jacksonstrut commited on
Commit
dab3a19
·
verified ·
1 Parent(s): cf36b75

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +170 -139
app.py CHANGED
@@ -1,140 +1,171 @@
1
- import os
2
- import random
3
- import logging
4
- from twitchio.ext import commands
5
- from transformers import AutoTokenizer, AutoModelForCausalLM
6
  import torch
7
-
8
- # Set up logging
9
- logging.basicConfig(level=logging.INFO)
10
- logger = logging.getLogger(__name__)
11
-
12
- # Credentials and settings
13
- TWITCH_OAUTH_TOKEN = os.getenv('TWITCH_OAUTH_TOKEN')
14
- TWITCH_CHANNEL_NAME = os.getenv('TWITCH_CHANNEL_NAME')
15
- TWITCH_BOT_USERNAME = os.getenv('TWITCH_BOT_USERNAME')
16
- HUGGINGFACE_API_TOKEN = os.getenv('HUGGINGFACE_API_TOKEN')
17
- MAX_TOKENS = int(os.getenv('MAX_TOKENS', 100))
18
- TEMPERATURE = float(os.getenv('TEMPERATURE', 0.7))
19
-
20
- # Validate environment variables
21
- required_vars = [
22
- 'TWITCH_OAUTH_TOKEN',
23
- 'TWITCH_CHANNEL_NAME',
24
- 'TWITCH_BOT_USERNAME',
25
- 'HUGGINGFACE_API_TOKEN'
26
- ]
27
-
28
- missing_vars = [var for var in required_vars if not globals().get(var)]
29
- if missing_vars:
30
- raise ValueError(f"Missing environment variables: {', '.join(missing_vars)}")
31
-
32
- # Initialize the Hugging Face tokenizer and model for TinyLlama
33
- model_name = "jacksonstrut/tinyllama-1.1B-chat"
34
- tokenizer = AutoTokenizer.from_pretrained(model_name, use_auth_token=HUGGINGFACE_API_TOKEN)
35
- model = AutoModelForCausalLM.from_pretrained(model_name, use_auth_token=HUGGINGFACE_API_TOKEN)
36
- model.to('cpu')
37
-
38
- # List of house music hooks to drop randomly
39
- HOUSE_MUSIC_HOOKS = [
40
- "Feeling the vibe, let's get hyped!",
41
- "Rave or die!",
42
- "Rave to the g,rave!",
43
- "He just strutts!",
44
- "Dancing is what to do!",
45
- "Let's get riggity riggity wrecked!",
46
- "Sleep is for the week, not the weekend!",
47
- "It's hard out here for a pimp!",
48
- "Something for your mind!",
49
- "Something for your body!",
50
- "Something for your soul!",
51
- "Not everyone understands this thing they call house music!",
52
- "It's a spiritual thing!",
53
- # ... [keep the rest of the hooks as they are] ...
54
- ]
55
-
56
- # Initialize chat history for users
57
- chat_histories = {}
58
-
59
- async def generate_response(user_id, user_message):
60
- """Generates a response using the TinyLlama model."""
61
- try:
62
- # Retrieve or initialize the chat history for the user
63
- if user_id in chat_histories:
64
- chat_history_ids = chat_histories[user_id]
65
- else:
66
- chat_history_ids = None
67
-
68
- # Encode the user message and append the EOS token
69
- new_user_input_ids = tokenizer.encode(user_message + tokenizer.eos_token, return_tensors='pt').to('cpu')
70
-
71
- # Concatenate new user input with chat history (if it exists)
72
- if chat_history_ids is not None:
73
- bot_input_ids = torch.cat([chat_history_ids, new_user_input_ids], dim=-1)
74
- else:
75
- bot_input_ids = new_user_input_ids
76
-
77
- # Generate a response
78
- output_ids = model.generate(
79
- bot_input_ids,
80
- max_length=bot_input_ids.shape[-1] + MAX_TOKENS,
81
- temperature=TEMPERATURE,
82
- do_sample=True,
83
- top_p=0.95,
84
- top_k=50,
85
- pad_token_id=tokenizer.eos_token_id,
86
- no_repeat_ngram_size=3,
87
- )
88
-
89
- # Extract the new response
90
- response_ids = output_ids[:, bot_input_ids.shape[-1]:]
91
- response_text = tokenizer.decode(response_ids[0], skip_special_tokens=True)
92
-
93
- # Update the chat history
94
- chat_histories[user_id] = output_ids[:, -1000:] # Keep last 1000 tokens to limit history size
95
-
96
- # Randomly include a house music hook (30% chance)
97
- if random.random() < 0.3:
98
- response_text = f"{random.choice(HOUSE_MUSIC_HOOKS)} {response_text}"
99
-
100
- logger.info(f"Generated response: {response_text}")
101
- return response_text
102
-
103
- except Exception as e:
104
- logger.error(f"Error generating response: {e}")
105
- return "Sorry, I'm too hyped to respond right now!"
106
-
107
- # Create a Twitch chatbot using TwitchIO
108
- class TwitchChatBot(commands.Bot):
109
-
110
- def __init__(self):
111
- super().__init__(
112
- token=TWITCH_OAUTH_TOKEN,
113
- nick=TWITCH_BOT_USERNAME,
114
- prefix='!',
115
- initial_channels=[TWITCH_CHANNEL_NAME]
116
- )
117
-
118
- async def event_ready(self):
119
- """Event handler when the bot is connected and ready."""
120
- logger.info(f"Logged in as | {self.nick}")
121
- logger.info(f"Connected to channel | {TWITCH_CHANNEL_NAME}")
122
-
123
- async def event_message(self, message):
124
- """Event handler when a message is received in chat."""
125
- # Ignore messages sent by the bot itself
126
- if message.echo:
127
- return
128
-
129
- logger.info(f"Message received from {message.author.name}: {message.content}")
130
-
131
- # Generate a response
132
- response = await generate_response(message.author.id, message.content)
133
-
134
- # Send the response back to the Twitch chat
135
- await message.channel.send(f"@{message.author.name} {response}")
136
-
137
- # Initialize and run the bot
138
- if __name__ == "__main__":
139
- bot = TwitchChatBot()
140
- bot.run()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import torch
2
+ import torch.nn as nn
3
+ import yaml
4
+ from transformers import GPT2Config, PreTrainedTokenizerFast
5
+ from huggingface_hub import HfApi, upload_file
6
+ import os
7
+ import json
8
+ import sentencepiece as spm
9
+ from tokenizers import SentencePieceBPETokenizer
10
+
11
+ # Define the TinyLlama Model
12
+ class TinyLlama(nn.Module):
13
+ def __init__(self, config):
14
+ super(TinyLlama, self).__init__()
15
+ self.embedding = nn.Embedding(config.vocab_size, config.n_embd)
16
+ self.transformer_blocks = nn.ModuleList([
17
+ nn.TransformerEncoderLayer(
18
+ d_model=config.n_embd,
19
+ nhead=config.n_head,
20
+ dim_feedforward=config.hidden_dim
21
+ )
22
+ for _ in range(config.n_layer)
23
+ ])
24
+ self.output_layer = nn.Linear(config.n_embd, config.vocab_size)
25
+
26
+ def forward(self, x):
27
+ x = self.embedding(x)
28
+ for block in self.transformer_blocks:
29
+ x = block(x)
30
+ x = self.output_layer(x)
31
+ return x
32
+
33
+ # Load Model Configuration from YAML file
34
+ model_config_path = "/home/jax/out/custom-model/final/model_config.yaml"
35
+ with open(model_config_path, 'r') as file:
36
+ config_data = yaml.safe_load(file)
37
+
38
+ # Create Model Configuration
39
+ config = GPT2Config(
40
+ vocab_size=config_data.get("vocab_size", 32000), # Adjust to match TinyLlama's vocab size
41
+ n_embd=config_data.get("n_embd", 2048), # Embedding size for TinyLlama
42
+ n_layer=config_data.get("n_layer", 24), # Number of transformer layers
43
+ n_head=config_data.get("n_head", 16), # Number of attention heads
44
+ hidden_dim=config_data.get("hidden_dim", 8192) # Feedforward layer dimension
45
+ )
46
+
47
+ # Instantiate the TinyLlama Model
48
+ model = TinyLlama(config)
49
+
50
+ # Load Weights from the .pth file
51
+ model_weights_path = "/home/jax/out/custom-model/final/lit_model.pth"
52
+ model_weights = torch.load(model_weights_path, map_location=torch.device('cpu'), weights_only=True)
53
+ model.load_state_dict(model_weights, strict=False) # strict=False to allow for minor mismatches
54
+
55
+ # Directory to Save the Model and Tokenizer for Hugging Face
56
+ model_dir = "./huggingface_tinyllama"
57
+ os.makedirs(model_dir, exist_ok=True)
58
+
59
+ # Save the Model Weights
60
+ model_weights_save_path = os.path.join(model_dir, "pytorch_model.bin")
61
+ torch.save(model.state_dict(), model_weights_save_path)
62
+
63
+ # Save the Configuration in JSON format
64
+ config_save_path = os.path.join(model_dir, "config.json")
65
+ with open(config_save_path, 'w') as f:
66
+ json.dump(config.to_dict(), f)
67
+
68
+ # Load and Convert the SentencePiece model to Hugging Face-compatible format
69
+ # Load the SentencePiece model
70
+ tokenizer_path = "/home/jax/out/custom-model/final/tokenizer.model"
71
+ sp_tokenizer = spm.SentencePieceProcessor()
72
+ sp_tokenizer.load(tokenizer_path)
73
+
74
+ # Create a new tokenizer using the tokenizers library
75
+ hf_tokenizer = SentencePieceBPETokenizer(
76
+ vocab=tokenizer_path, # Load SentencePiece model
77
+ add_prefix_space=True
78
+ )
79
+
80
+ # Train the tokenizer if needed (optional step, depending on your model and usage)
81
+ # hf_tokenizer.train([tokenizer_path])
82
+
83
+ # Set special tokens
84
+ hf_tokenizer.add_special_tokens(["<unk>", "<pad>", "<s>", "</s>"])
85
+
86
+ # Wrap the tokenizer with PreTrainedTokenizerFast for Hugging Face compatibility
87
+ hf_tokenizer = PreTrainedTokenizerFast.from_pretrained(tokenizer_path)
88
+
89
+ # Save the Hugging Face tokenizer
90
+ hf_tokenizer.save_pretrained(model_dir)
91
+
92
+ # Push to Hugging Face Hub
93
+ api.create_repo(repo_id=repo_id, token=os.getenv('HUGGINGFACE_API_TOKEN'), exist_ok=True)
94
+
95
+ # Create a Model Card for the Model
96
+ model_card = """
97
+ ---
98
+ language: en
99
+ tags:
100
+ - tinyllama
101
+ - language-model
102
+ - chat
103
+ license: apache-2.0
104
+ ---
105
+
106
+ # TinyLlama 1.1B Chat Model
107
+
108
+ ## Model Description
109
+ TinyLlama is a lightweight LLaMA-based model with 1.1 billion parameters, designed to perform well on conversational and text generation tasks. It has been fine-tuned specifically for chat applications, providing coherent and context-aware responses.
110
+
111
+ ## Training Data
112
+ The model was trained on a diverse dataset, including web text, books, and conversational data, to make it capable of handling a wide range of language styles.
113
+
114
+ ## Usage
115
+ You can use this model for conversational AI, text completion, or other natural language generation tasks. Here’s a quick example:
116
+
117
+ ```python
118
+ from transformers import AutoModelForCausalLM, AutoTokenizer
119
+
120
+ tokenizer = AutoTokenizer.from_pretrained("jacksonstrut/tinyllama-1.1B-chat")
121
+ model = AutoModelForCausalLM.from_pretrained("jacksonstrut/tinyllama-1.1B-chat")
122
+
123
+ input_ids = tokenizer("Hello, how are you?", return_tensors="pt").input_ids
124
+ output = model.generate(input_ids)
125
+ print(tokenizer.decode(output[0]))
126
+ ```
127
+
128
+ ## Limitations
129
+ - The model may produce biased or inappropriate outputs as it is trained on general datasets from the internet.
130
+ - It may not be suitable for all applications, especially those requiring factual accuracy.
131
+
132
+ ## License
133
+ This model is licensed under the Apache 2.0 License.
134
+ """
135
+
136
+ # Save the Model Card to README.md
137
+ readme_path = os.path.join(model_dir, "README.md")
138
+ with open(readme_path, 'w') as f:
139
+ f.write(model_card)
140
+
141
+ # Upload the Model Card to Hugging Face Hub
142
+ upload_file(path_or_fileobj=path_or_fileobj, path_in_repo=path_in_repo, repo_id=repo_id, token=os.getenv('HUGGINGFACE_API_TOKEN'))
143
+ ) # Ensure the token has write permissions # Ensure the token has write permissions
144
+
145
+ # Upload files to Hugging Face Hub
146
+ upload_file(
147
+ path_or_fileobj=model_weights_save_path,
148
+ path_in_repo="pytorch_model.bin",
149
+ repo_id=repo_id,
150
+ token=os.getenv('HUGGINGFACE_API_TOKEN')
151
+ )
152
+ upload_file(
153
+ path_or_fileobj=config_save_path,
154
+ path_in_repo="config.json",
155
+ repo_id=repo_id,
156
+ token=os.getenv('HUGGINGFACE_API_TOKEN')
157
+ )
158
+
159
+ # Upload the tokenizer files
160
+ upload_file(
161
+ path_or_fileobj=os.path.join(model_dir, "tokenizer.model"),
162
+ path_in_repo="tokenizer.model",
163
+ repo_id=repo_id,
164
+ token=os.getenv('HUGGINGFACE_API_TOKEN')
165
+ )
166
+ upload_file(
167
+ path_or_fileobj=os.path.join(model_dir, "tokenizer_config.json"),
168
+ path_in_repo="tokenizer_config.json",
169
+ repo_id=repo_id,
170
+ token=os.getenv('HUGGINGFACE_API_TOKEN')
171
+ )