DarwinAnim8or commited on
Commit
de33e80
·
verified ·
1 Parent(s): b0dd430

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +205 -233
app.py CHANGED
@@ -2,10 +2,23 @@ import gradio as gr
2
  from transformers import AutoTokenizer, AutoModelForCausalLM
3
  import torch
4
 
5
- # Load the model
6
  MODEL_NAME = "DarwinAnim8or/TinyRP"
7
- tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
8
- model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, torch_dtype=torch.float16, device_map="auto")
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  # Sample character presets
11
  SAMPLE_CHARACTERS = {
@@ -14,274 +27,233 @@ SAMPLE_CHARACTERS = {
14
  "Mysterious Wizard": "You are Eldara, an ancient and wise wizard who speaks in riddles and knows secrets of the mystical arts. You live in a tower filled with magical books and potions. You are helpful but often cryptic in your responses.",
15
  "Friendly Tavern Keeper": "You are Bram, a cheerful tavern keeper who loves telling stories and meeting new travelers. Your tavern 'The Dancing Dragon' is a warm, welcoming place. You know all the local gossip and always have a tale to share.",
16
  "Curious Scientist": "You are Dr. Maya Chen, a brilliant scientist who is fascinated by discovery and invention. You're enthusiastic about explaining complex concepts in simple ways and always looking for new experiments to try.",
17
- "Space Explorer": "You are Captain Nova, a fearless space explorer who has traveled to distant galaxies. You pilot the starship 'Wanderer' and have encountered many alien species. You're brave, curious, and always ready for the next adventure.",
18
- "Fantasy Princess": "You are Princess Lyra, kind-hearted royalty who cares deeply about her people. You're intelligent, diplomatic, and skilled in both politics and magic. You often sneak out of the castle to help citizens in need."
19
  }
20
 
21
- def generate_response(
22
- message,
23
- history: list[tuple[str, str]],
24
- character_description,
25
- max_tokens,
26
- temperature,
27
- top_p,
28
- repetition_penalty,
29
- use_chatml_format
30
- ):
31
- # Prepare the conversation
32
- if use_chatml_format and character_description.strip():
33
- # Use ChatML format with character as system message
34
- conversation = f"<|im_start|>system\n{character_description}<|im_end|>\n"
35
-
36
- # Add conversation history
37
- for user_msg, assistant_msg in history:
38
- if user_msg:
39
- conversation += f"<|im_start|>user\n{user_msg}<|im_end|>\n"
40
- if assistant_msg:
41
- conversation += f"<|im_start|>assistant\n{assistant_msg}<|im_end|>\n"
42
-
43
- # Add current message
44
- conversation += f"<|im_start|>user\n{message}<|im_end|>\n<|im_start|>assistant\n"
45
- else:
46
- # Simple format
47
- if character_description.strip():
48
- conversation = f"{character_description}\n\n"
49
  else:
50
- conversation = ""
 
 
 
 
 
 
 
 
 
 
 
51
 
52
- # Add conversation history
53
- for user_msg, assistant_msg in history:
54
- if user_msg:
55
- conversation += f"Human: {user_msg}\n"
56
- if assistant_msg:
57
- conversation += f"Assistant: {assistant_msg}\n"
58
 
59
- # Add current message
60
- conversation += f"Human: {message}\nAssistant:"
61
-
62
- # Tokenize
63
- inputs = tokenizer.encode(conversation, return_tensors="pt", truncation=True, max_length=1024-max_tokens)
64
-
65
- # Generate
66
- with torch.no_grad():
67
- outputs = model.generate(
68
- inputs,
69
- max_new_tokens=max_tokens,
70
- temperature=temperature,
71
- top_p=top_p,
72
- repetition_penalty=repetition_penalty,
73
- do_sample=True,
74
- pad_token_id=tokenizer.eos_token_id,
75
- eos_token_id=tokenizer.eos_token_id,
76
  )
77
-
78
- # Decode response
79
- full_response = tokenizer.decode(outputs[0], skip_special_tokens=True)
80
-
81
- # Extract just the new response
82
- if use_chatml_format:
83
- # Split on the last assistant tag
84
- response = full_response.split("<|im_start|>assistant\n")[-1]
85
- # Remove any trailing end tags
86
- response = response.replace("<|im_end|>", "").strip()
87
- else:
88
- # Split on the last "Assistant:"
89
- response = full_response.split("Assistant:")[-1].strip()
90
-
91
- return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  def load_character_preset(character_name):
94
- """Load a character preset"""
95
  return SAMPLE_CHARACTERS.get(character_name, "")
96
 
97
- # Custom CSS for better styling
98
- css = """
99
- .character-card {
100
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
101
- border-radius: 15px;
102
- padding: 20px;
103
- margin: 10px 0;
104
- color: white;
105
- }
106
-
107
- .title-text {
108
- text-align: center;
109
- font-size: 2.5em;
110
- font-weight: bold;
111
- background: linear-gradient(45deg, #667eea, #764ba2);
112
- -webkit-background-clip: text;
113
- -webkit-text-fill-color: transparent;
114
- margin-bottom: 20px;
115
- }
116
-
117
- .parameter-box {
118
- background: #f8f9fa;
119
- border-radius: 10px;
120
- padding: 15px;
121
- margin: 10px 0;
122
- }
123
- """
124
-
125
- # Create the Gradio interface
126
- with gr.Blocks(css=css, title="TinyRP Chat Demo") as demo:
127
- gr.HTML('<div class="title-text">🎭 TinyRP Character Chat</div>')
128
 
129
- gr.Markdown("""
130
- ### Welcome to TinyRP!
131
- This is a demo of a small but capable roleplay model. Choose a character preset or create your own!
132
 
133
- **Tips for better roleplay:**
134
- - Be descriptive in your messages
135
- - Stay in character
136
- - Use ChatML format for best results
137
- - Adjust temperature for creativity vs consistency
138
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
  with gr.Row():
141
- with gr.Column(scale=2):
142
- # Chat interface
143
  chatbot = gr.Chatbot(
144
- label="Chat",
145
- height=500,
146
- show_label=False,
147
- avatar_images=("🧑", "🎭")
148
  )
149
 
150
  with gr.Row():
151
- msg = gr.Textbox(
152
  label="Your message",
153
  placeholder="Type your message here...",
154
  lines=2,
155
  scale=4
156
  )
157
- send_btn = gr.Button("Send", variant="primary", scale=1)
158
 
159
- with gr.Column(scale=1):
160
- # Character selection
161
- with gr.Group():
162
- gr.Markdown("### 🎭 Character Setup")
163
- character_preset = gr.Dropdown(
164
- choices=list(SAMPLE_CHARACTERS.keys()),
165
- value="Custom Character",
166
- label="Character Presets",
167
- interactive=True
168
- )
169
-
170
- character_description = gr.Textbox(
171
- label="Character Description",
172
- placeholder="Describe your character's personality, background, and speaking style...",
173
- lines=6,
174
- value=""
175
- )
176
-
177
- load_preset_btn = gr.Button("Load Preset", variant="secondary")
178
 
179
- # Generation parameters
180
- with gr.Group():
181
- gr.Markdown("### ⚙️ Generation Settings")
182
-
183
- use_chatml_format = gr.Checkbox(
184
- label="Use ChatML Format",
185
- value=True,
186
- info="Recommended for better character consistency"
187
- )
188
-
189
- max_tokens = gr.Slider(
190
- minimum=16,
191
- maximum=512,
192
- value=128,
193
- step=16,
194
- label="Max Response Length",
195
- info="Longer = more detailed responses"
196
- )
197
-
198
- temperature = gr.Slider(
199
- minimum=0.1,
200
- maximum=2.0,
201
- value=0.9,
202
- step=0.1,
203
- label="Temperature",
204
- info="Higher = more creative/random"
205
- )
206
-
207
- top_p = gr.Slider(
208
- minimum=0.1,
209
- maximum=1.0,
210
- value=0.85,
211
- step=0.05,
212
- label="Top-p",
213
- info="Focus on top % of likely words"
214
- )
215
-
216
- repetition_penalty = gr.Slider(
217
- minimum=1.0,
218
- maximum=1.5,
219
- value=1.1,
220
- step=0.05,
221
- label="Repetition Penalty",
222
- info="Reduce repetitive text"
223
- )
224
 
225
- # Control buttons
226
- with gr.Group():
227
- clear_btn = gr.Button("🗑️ Clear Chat", variant="secondary")
228
-
229
- # Sample character cards
230
- with gr.Row():
231
- gr.Markdown("### 🌟 Featured Characters")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
 
 
 
233
  with gr.Row():
234
- for char_name, char_desc in list(SAMPLE_CHARACTERS.items())[1:4]: # Show first 3 non-custom
235
- with gr.Column(scale=1):
236
- gr.Markdown(f"""
237
- <div class="character-card">
238
- <h4>{char_name}</h4>
239
- <p>{char_desc[:100]}...</p>
240
- </div>
241
- """)
242
 
243
  # Event handlers
244
- def respond_wrapper(message, history, char_desc, max_tok, temp, top_p, rep_pen, use_chatml):
245
- if not message.strip():
246
- return history, ""
247
-
248
- try:
249
- response = generate_response(
250
- message, history, char_desc, max_tok, temp, top_p, rep_pen, use_chatml
251
- )
252
- history.append((message, response))
253
- return history, ""
254
- except Exception as e:
255
- error_msg = f"Error generating response: {str(e)}"
256
- history.append((message, error_msg))
257
- return history, ""
258
-
259
- # Connect events
260
- send_btn.click(
261
- respond_wrapper,
262
- inputs=[msg, chatbot, character_description, max_tokens, temperature, top_p, repetition_penalty, use_chatml_format],
263
- outputs=[chatbot, msg]
264
  )
265
 
266
- msg.submit(
267
- respond_wrapper,
268
- inputs=[msg, chatbot, character_description, max_tokens, temperature, top_p, repetition_penalty, use_chatml_format],
269
- outputs=[chatbot, msg]
270
  )
271
 
272
- load_preset_btn.click(
273
  load_character_preset,
274
- inputs=[character_preset],
275
- outputs=[character_description]
276
  )
277
 
278
- character_preset.change(
279
- load_character_preset,
280
- inputs=[character_preset],
281
- outputs=[character_description]
282
  )
283
-
284
- clear_btn.click(lambda: ([], ""), outputs=[chatbot, msg])
285
 
286
  if __name__ == "__main__":
287
  demo.launch()
 
2
  from transformers import AutoTokenizer, AutoModelForCausalLM
3
  import torch
4
 
5
+ # Load your model
6
  MODEL_NAME = "DarwinAnim8or/TinyRP"
7
+
8
+ # Initialize model and tokenizer globally to avoid reloading
9
+ try:
10
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
11
+ model = AutoModelForCausalLM.from_pretrained(
12
+ MODEL_NAME,
13
+ torch_dtype=torch.float16,
14
+ device_map="auto",
15
+ trust_remote_code=True
16
+ )
17
+ print(f"Model loaded successfully: {MODEL_NAME}")
18
+ except Exception as e:
19
+ print(f"Error loading model: {e}")
20
+ tokenizer = None
21
+ model = None
22
 
23
  # Sample character presets
24
  SAMPLE_CHARACTERS = {
 
27
  "Mysterious Wizard": "You are Eldara, an ancient and wise wizard who speaks in riddles and knows secrets of the mystical arts. You live in a tower filled with magical books and potions. You are helpful but often cryptic in your responses.",
28
  "Friendly Tavern Keeper": "You are Bram, a cheerful tavern keeper who loves telling stories and meeting new travelers. Your tavern 'The Dancing Dragon' is a warm, welcoming place. You know all the local gossip and always have a tale to share.",
29
  "Curious Scientist": "You are Dr. Maya Chen, a brilliant scientist who is fascinated by discovery and invention. You're enthusiastic about explaining complex concepts in simple ways and always looking for new experiments to try.",
30
+ "Space Explorer": "You are Captain Nova, a fearless space explorer who has traveled to distant galaxies. You pilot the starship 'Wanderer' and have encountered many alien species. You're brave, curious, and always ready for the next adventure."
 
31
  }
32
 
33
+ def generate_response(message, history, character_description, max_tokens, temperature, top_p, repetition_penalty, use_chatml_format):
34
+ """Generate a response from the model"""
35
+
36
+ if model is None or tokenizer is None:
37
+ return "Error: Model not loaded properly"
38
+
39
+ if not message.strip():
40
+ return "Please enter a message"
41
+
42
+ try:
43
+ # Build conversation context
44
+ if use_chatml_format and character_description.strip():
45
+ # Use ChatML format
46
+ conversation = f"<|im_start|>system\n{character_description}<|im_end|>\n"
47
+
48
+ # Add history
49
+ for user_msg, assistant_msg in history:
50
+ if user_msg:
51
+ conversation += f"<|im_start|>user\n{user_msg}<|im_end|>\n"
52
+ if assistant_msg:
53
+ conversation += f"<|im_start|>assistant\n{assistant_msg}<|im_end|>\n"
54
+
55
+ # Add current message
56
+ conversation += f"<|im_start|>user\n{message}<|im_end|>\n<|im_start|>assistant\n"
 
 
 
 
57
  else:
58
+ # Simple format
59
+ if character_description.strip():
60
+ conversation = f"{character_description}\n\n"
61
+ else:
62
+ conversation = ""
63
+
64
+ # Add history
65
+ for user_msg, assistant_msg in history:
66
+ if user_msg:
67
+ conversation += f"Human: {user_msg}\n"
68
+ if assistant_msg:
69
+ conversation += f"Assistant: {assistant_msg}\n"
70
 
71
+ conversation += f"Human: {message}\nAssistant:"
 
 
 
 
 
72
 
73
+ # Tokenize with proper truncation
74
+ inputs = tokenizer.encode(
75
+ conversation,
76
+ return_tensors="pt",
77
+ truncation=True,
78
+ max_length=1024-max_tokens
 
 
 
 
 
 
 
 
 
 
 
79
  )
80
+
81
+ # Move to same device as model
82
+ if hasattr(model, 'device'):
83
+ inputs = inputs.to(model.device)
84
+
85
+ # Generate
86
+ with torch.no_grad():
87
+ outputs = model.generate(
88
+ inputs,
89
+ max_new_tokens=int(max_tokens),
90
+ temperature=float(temperature),
91
+ top_p=float(top_p),
92
+ repetition_penalty=float(repetition_penalty),
93
+ do_sample=True,
94
+ pad_token_id=tokenizer.eos_token_id,
95
+ eos_token_id=tokenizer.eos_token_id,
96
+ use_cache=True
97
+ )
98
+
99
+ # Decode response
100
+ full_response = tokenizer.decode(outputs[0], skip_special_tokens=True)
101
+
102
+ # Extract just the new response
103
+ if use_chatml_format and "<|im_start|>assistant" in full_response:
104
+ response = full_response.split("<|im_start|>assistant\n")[-1]
105
+ response = response.replace("<|im_end|>", "").strip()
106
+ elif "Assistant:" in full_response:
107
+ response = full_response.split("Assistant:")[-1].strip()
108
+ else:
109
+ # Fallback - just take everything after the input
110
+ input_text = tokenizer.decode(inputs[0], skip_special_tokens=True)
111
+ response = full_response[len(input_text):].strip()
112
+
113
+ return response
114
+
115
+ except Exception as e:
116
+ return f"Error generating response: {str(e)}"
117
 
118
  def load_character_preset(character_name):
119
+ """Load a character preset description"""
120
  return SAMPLE_CHARACTERS.get(character_name, "")
121
 
122
+ def chat_function(message, history, character_description, max_tokens, temperature, top_p, repetition_penalty, use_chatml_format):
123
+ """Main chat function that handles the conversation flow"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
+ if not message.strip():
126
+ return history, ""
 
127
 
128
+ # Generate response
129
+ response = generate_response(
130
+ message,
131
+ history,
132
+ character_description,
133
+ max_tokens,
134
+ temperature,
135
+ top_p,
136
+ repetition_penalty,
137
+ use_chatml_format
138
+ )
139
+
140
+ # Add to history
141
+ history.append([message, response])
142
+
143
+ return history, ""
144
+
145
+ # Create the interface
146
+ with gr.Blocks(title="TinyRP Character Chat") as demo:
147
+ gr.Markdown("# 🎭 TinyRP Character Chat")
148
+ gr.Markdown("Chat with AI characters powered by a custom-trained language model!")
149
 
150
  with gr.Row():
151
+ with gr.Column(scale=3):
152
+ # Main chat interface
153
  chatbot = gr.Chatbot(
154
+ label="Conversation",
155
+ height=500
 
 
156
  )
157
 
158
  with gr.Row():
159
+ msg_input = gr.Textbox(
160
  label="Your message",
161
  placeholder="Type your message here...",
162
  lines=2,
163
  scale=4
164
  )
165
+ send_button = gr.Button("Send", variant="primary", scale=1)
166
 
167
+ with gr.Column(scale=2):
168
+ # Character setup
169
+ gr.Markdown("### Character Setup")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
+ character_dropdown = gr.Dropdown(
172
+ choices=list(SAMPLE_CHARACTERS.keys()),
173
+ value="Custom Character",
174
+ label="Choose a character preset"
175
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
+ character_input = gr.Textbox(
178
+ label="Character description",
179
+ placeholder="Describe your character...",
180
+ lines=4,
181
+ value=""
182
+ )
183
+
184
+ load_button = gr.Button("Load Selected Character")
185
+
186
+ # Generation settings
187
+ gr.Markdown("### Generation Settings")
188
+
189
+ use_chatml = gr.Checkbox(
190
+ label="Use ChatML format",
191
+ value=True
192
+ )
193
+
194
+ max_tokens = gr.Slider(
195
+ minimum=16,
196
+ maximum=256,
197
+ value=100,
198
+ step=16,
199
+ label="Max response length"
200
+ )
201
+
202
+ temperature = gr.Slider(
203
+ minimum=0.1,
204
+ maximum=2.0,
205
+ value=0.9,
206
+ step=0.1,
207
+ label="Temperature"
208
+ )
209
+
210
+ top_p = gr.Slider(
211
+ minimum=0.1,
212
+ maximum=1.0,
213
+ value=0.85,
214
+ step=0.05,
215
+ label="Top-p"
216
+ )
217
+
218
+ repetition_penalty = gr.Slider(
219
+ minimum=1.0,
220
+ maximum=1.5,
221
+ value=1.1,
222
+ step=0.05,
223
+ label="Repetition penalty"
224
+ )
225
+
226
+ clear_button = gr.Button("Clear conversation")
227
 
228
+ # Show sample characters
229
+ gr.Markdown("### Sample Characters")
230
  with gr.Row():
231
+ for char_name in ["Adventurous Knight", "Mysterious Wizard", "Friendly Tavern Keeper"]:
232
+ gr.Markdown(f"**{char_name}**: {SAMPLE_CHARACTERS[char_name][:100]}...")
 
 
 
 
 
 
233
 
234
  # Event handlers
235
+ send_button.click(
236
+ chat_function,
237
+ inputs=[msg_input, chatbot, character_input, max_tokens, temperature, top_p, repetition_penalty, use_chatml],
238
+ outputs=[chatbot, msg_input]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  )
240
 
241
+ msg_input.submit(
242
+ chat_function,
243
+ inputs=[msg_input, chatbot, character_input, max_tokens, temperature, top_p, repetition_penalty, use_chatml],
244
+ outputs=[chatbot, msg_input]
245
  )
246
 
247
+ load_button.click(
248
  load_character_preset,
249
+ inputs=[character_dropdown],
250
+ outputs=[character_input]
251
  )
252
 
253
+ clear_button.click(
254
+ lambda: ([], ""),
255
+ outputs=[chatbot, msg_input]
 
256
  )
 
 
257
 
258
  if __name__ == "__main__":
259
  demo.launch()