Shrijanagain commited on
Commit
69f786a
·
verified ·
1 Parent(s): 44f811b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -73
app.py CHANGED
@@ -1,54 +1,136 @@
1
  import os
2
  import torch
 
3
  import gradio as gr
4
  from transformers import AutoTokenizer, AutoModelForCausalLM
5
 
6
- # =====================================================
7
  # CONFIG
8
- # =====================================================
9
 
10
  MODEL_ID = os.getenv("MODEL_ID", "WeiboAI/VibeThinker-3B")
11
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
12
 
13
  print("=" * 60)
14
- print("X-RUDRA MODEL SPACE")
15
  print("MODEL:", MODEL_ID)
16
  print("DEVICE:", DEVICE)
17
  print("=" * 60)
18
 
19
- # =====================================================
20
- # LOAD TOKENIZER & MODEL
21
- # =====================================================
22
 
23
  print("Loading tokenizer...")
24
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
25
 
 
 
 
 
26
  print("Loading model...")
27
  model = AutoModelForCausalLM.from_pretrained(
28
  MODEL_ID,
 
29
  device_map="auto",
30
- torch_dtype=torch.float16 if DEVICE == "cuda" else torch.float32,
31
  trust_remote_code=True,
32
  )
33
  model.eval()
34
  print("MODEL READY")
35
 
36
- # =====================================================
37
- # GENERATION (unchanged)
38
- # =====================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- def generate(prompt, max_tokens, temperature):
41
- if not prompt.strip():
42
- return "Please enter a prompt."
 
 
 
 
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  inputs = tokenizer(
45
- prompt,
46
  return_tensors="pt",
47
  truncation=True,
48
- max_length=4096
 
49
  )
50
  inputs = {k: v.to(model.device) for k, v in inputs.items()}
51
- input_length = inputs["input_ids"].shape[-1]
 
52
 
53
  with torch.no_grad():
54
  outputs = model.generate(
@@ -60,76 +142,58 @@ def generate(prompt, max_tokens, temperature):
60
  top_k=50,
61
  repetition_penalty=1.15,
62
  no_repeat_ngram_size=3,
 
63
  eos_token_id=tokenizer.eos_token_id,
64
- pad_token_id=tokenizer.eos_token_id,
65
  )
66
 
67
- result = tokenizer.decode(outputs[0][input_length:], skip_special_tokens=True)
68
- return result.strip()
69
-
70
- # =====================================================
71
- # CONVERSATION FORMATTER
72
- # =====================================================
73
-
74
- def format_conversation(history):
75
- """Convert history (list of dicts) into a single prompt string."""
76
- prompt = ""
77
- for turn in history:
78
- if turn["role"] == "user":
79
- prompt += f"User: {turn['content']}\n"
80
- elif turn["role"] == "assistant":
81
- prompt += f"Assistant: {turn['content']}\n"
82
- # Append the final assistant prompt to continue the conversation
83
- prompt += "Assistant:"
84
- return prompt
85
-
86
- # =====================================================
87
- # CHAT FUNCTION (FIXED)
88
- # =====================================================
89
-
90
- def chat(message, history, max_tokens, temperature):
91
- history = history or []
92
-
93
- # Append the new user message to history
94
- history.append({"role": "user", "content": message})
95
 
96
- # Build the full conversation prompt
97
- full_prompt = format_conversation(history)
98
-
99
- # Generate assistant response from the full context
100
- answer = generate(full_prompt, max_tokens, temperature)
101
 
102
- # Append assistant response to history
103
- history.append({"role": "assistant", "content": answer})
104
 
105
- return "", history
 
 
106
 
107
- # =====================================================
108
- # UI (unchanged)
109
- # =====================================================
 
 
 
 
 
110
 
111
- with gr.Blocks(title="X-RUDRA") as demo:
112
- gr.Markdown(f"""
113
- # ⚡ X-RUDRA
114
- Model: `{MODEL_ID}`
115
- Device: `{DEVICE}`
116
- """)
117
 
118
- chatbot = gr.Chatbot(type="messages", height=600, label="Chat")
119
  with gr.Row():
120
- message = gr.Textbox(placeholder="Ask anything...", scale=8)
121
  send = gr.Button("Send", variant="primary", scale=1)
122
 
123
  with gr.Row():
124
- max_tokens = gr.Slider(minimum=64, maximum=2048, value=512, step=64, label="Max Tokens")
125
- temperature = gr.Slider(minimum=0.1, maximum=1.2, value=0.7, step=0.1, label="Temperature")
126
-
127
- send.click(fn=chat, inputs=[message, chatbot, max_tokens, temperature], outputs=[message, chatbot])
128
- message.submit(fn=chat, inputs=[message, chatbot, max_tokens, temperature], outputs=[message, chatbot])
 
 
 
 
 
 
 
 
 
129
 
130
- # =====================================================
131
- # START SERVER
132
- # =====================================================
133
 
134
  if __name__ == "__main__":
135
- demo.launch(server_name="0.0.0.0", server_port=7860, show_error=True)
 
1
  import os
2
  import torch
3
+ import spaces
4
  import gradio as gr
5
  from transformers import AutoTokenizer, AutoModelForCausalLM
6
 
7
+ # ============================================================
8
  # CONFIG
9
+ # ============================================================
10
 
11
  MODEL_ID = os.getenv("MODEL_ID", "WeiboAI/VibeThinker-3B")
12
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
13
 
14
  print("=" * 60)
15
+ print("X-RUDRA M2 (CHAT)")
16
  print("MODEL:", MODEL_ID)
17
  print("DEVICE:", DEVICE)
18
  print("=" * 60)
19
 
20
+ # ============================================================
21
+ # LOAD MODEL
22
+ # ============================================================
23
 
24
  print("Loading tokenizer...")
25
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
26
 
27
+ # Ensure pad_token is set (some tokenizers don't have one)
28
+ if tokenizer.pad_token is None:
29
+ tokenizer.pad_token = tokenizer.eos_token
30
+
31
  print("Loading model...")
32
  model = AutoModelForCausalLM.from_pretrained(
33
  MODEL_ID,
34
+ dtype=torch.float16 if DEVICE == "cuda" else torch.float32, # FIXED: use dtype
35
  device_map="auto",
 
36
  trust_remote_code=True,
37
  )
38
  model.eval()
39
  print("MODEL READY")
40
 
41
+ # ============================================================
42
+ # HELPERS: CONVERSATION FORMATTING
43
+ # ============================================================
44
+
45
+ def format_conversation(history):
46
+ """
47
+ Convert history (list of tuples [(user, assistant), ...]) into a single prompt.
48
+ Uses the tokenizer's chat template if available, else a simple User/Assistant format.
49
+ """
50
+ # Try to use the tokenizer's built-in chat template (if any)
51
+ if hasattr(tokenizer, "apply_chat_template") and tokenizer.chat_template is not None:
52
+ # Convert history to list of dicts
53
+ messages = []
54
+ for user_msg, assistant_msg in history:
55
+ messages.append({"role": "user", "content": user_msg})
56
+ if assistant_msg:
57
+ messages.append({"role": "assistant", "content": assistant_msg})
58
+ # Add the final user message placeholder? Actually we'll append the new user message separately.
59
+ # But we are calling this before adding the new user message? We'll design it to include the new user message.
60
+ # Better to handle in generate_response: we'll pass the full history including the new user message.
61
+ # So we'll restructure: generate_response will build the messages list and then call apply_chat_template.
62
+ # We'll move this logic into generate_response directly.
63
+ # So this function will only be used as fallback.
64
+ pass
65
+
66
+ # Fallback: simple User/Assistant format
67
+ prompt = ""
68
+ for user_msg, assistant_msg in history:
69
+ prompt += f"User: {user_msg}\n"
70
+ if assistant_msg:
71
+ prompt += f"Assistant: {assistant_msg}\n"
72
+ # We will append the new user message outside this function
73
+ return prompt
74
+
75
+ # ============================================================
76
+ # GENERATION (with chat history)
77
+ # ============================================================
78
 
79
+ @spaces.GPU
80
+ def generate_response(message, history, max_tokens, temperature):
81
+ """
82
+ Takes the current message and history (list of tuples), generates a response,
83
+ and returns (new_message, updated_history) – new_message is always '' to clear the input.
84
+ """
85
+ history = history or []
86
 
87
+ # Build the full conversation prompt
88
+ # If the tokenizer has a chat template, use it
89
+ if hasattr(tokenizer, "apply_chat_template") and tokenizer.chat_template is not None:
90
+ # Convert history (tuples) to messages list
91
+ messages = []
92
+ for user_msg, assistant_msg in history:
93
+ messages.append({"role": "user", "content": user_msg})
94
+ if assistant_msg:
95
+ messages.append({"role": "assistant", "content": assistant_msg})
96
+ # Add the new user message
97
+ messages.append({"role": "user", "content": message})
98
+ # Apply the template
99
+ try:
100
+ full_prompt = tokenizer.apply_chat_template(
101
+ messages,
102
+ tokenize=False,
103
+ add_generation_prompt=True
104
+ )
105
+ except Exception as e:
106
+ print("Chat template failed, falling back to manual format:", e)
107
+ full_prompt = None
108
+ else:
109
+ full_prompt = None
110
+
111
+ # If template failed or not available, use manual format
112
+ if full_prompt is None:
113
+ # Build from history + new message
114
+ prompt = ""
115
+ for user_msg, assistant_msg in history:
116
+ prompt += f"User: {user_msg}\n"
117
+ if assistant_msg:
118
+ prompt += f"Assistant: {assistant_msg}\n"
119
+ # Add the new user message
120
+ prompt += f"User: {message}\nAssistant:"
121
+ full_prompt = prompt
122
+
123
+ # Tokenize
124
  inputs = tokenizer(
125
+ full_prompt,
126
  return_tensors="pt",
127
  truncation=True,
128
+ max_length=4096, # adjust if needed
129
+ padding=True,
130
  )
131
  inputs = {k: v.to(model.device) for k, v in inputs.items()}
132
+
133
+ input_len = inputs["input_ids"].shape[-1]
134
 
135
  with torch.no_grad():
136
  outputs = model.generate(
 
142
  top_k=50,
143
  repetition_penalty=1.15,
144
  no_repeat_ngram_size=3,
145
+ pad_token_id=tokenizer.pad_token_id,
146
  eos_token_id=tokenizer.eos_token_id,
 
147
  )
148
 
149
+ # Decode only new tokens
150
+ new_tokens = outputs[0][input_len:]
151
+ answer = tokenizer.decode(new_tokens, skip_special_tokens=True).strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
+ # Update history: add (user, assistant) tuple
154
+ history.append((message, answer))
 
 
 
155
 
156
+ return "", history # clear input, return updated history
 
157
 
158
+ # ============================================================
159
+ # UI (Chat Interface – using tuples for Gradio 3.x)
160
+ # ============================================================
161
 
162
+ with gr.Blocks(title="X-RUDRA M2") as demo:
163
+ gr.Markdown(
164
+ f"""
165
+ # ⚡ X-RUDRA M2 – Chat
166
+ **Model:** `{MODEL_ID}`
167
+ **Device:** `{DEVICE}`
168
+ """
169
+ )
170
 
171
+ # Chatbot component – no 'type' argument
172
+ chatbot = gr.Chatbot(height=600, label="Conversation")
 
 
 
 
173
 
 
174
  with gr.Row():
175
+ msg = gr.Textbox(placeholder="Ask anything...", scale=8)
176
  send = gr.Button("Send", variant="primary", scale=1)
177
 
178
  with gr.Row():
179
+ max_tokens = gr.Slider(64, 2048, value=512, step=64, label="Max Tokens")
180
+ temperature = gr.Slider(0.1, 1.5, value=0.7, step=0.1, label="Temperature")
181
+
182
+ # When Send is clicked or Enter is pressed
183
+ send.click(
184
+ fn=generate_response,
185
+ inputs=[msg, chatbot, max_tokens, temperature],
186
+ outputs=[msg, chatbot]
187
+ )
188
+ msg.submit(
189
+ fn=generate_response,
190
+ inputs=[msg, chatbot, max_tokens, temperature],
191
+ outputs=[msg, chatbot]
192
+ )
193
 
194
+ # ============================================================
195
+ # START
196
+ # ============================================================
197
 
198
  if __name__ == "__main__":
199
+ demo.launch(server_name="0.0.0.0", server_port=7860)