openfree commited on
Commit
fba7498
·
verified ·
1 Parent(s): 75e8c43

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -45
app.py CHANGED
@@ -82,10 +82,14 @@ class InitResponse(BaseModel):
82
  session_id: str
83
  status: str
84
 
85
- # Simple HTML interface (API key input form removed)
86
  @app.get("/", response_class=HTMLResponse)
87
  async def root():
88
- """Root endpoint with a simple HTML interface"""
 
 
 
 
89
  html_content = f"""
90
  <!DOCTYPE html>
91
  <html>
@@ -94,7 +98,7 @@ async def root():
94
  <style>
95
  body {{
96
  font-family: Arial, sans-serif;
97
- max-width: 800px;
98
  margin: 0 auto;
99
  padding: 20px;
100
  line-height: 1.6;
@@ -133,19 +137,36 @@ async def root():
133
  button:hover {{
134
  background-color: #45a049;
135
  }}
136
- #response {{
137
  white-space: pre-wrap;
138
  background-color: #f5f5f5;
139
  padding: 15px;
140
  border-radius: 4px;
141
- margin-top: 20px;
142
  min-height: 100px;
143
  }}
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  .log {{
145
  margin-top: 20px;
146
  font-size: 0.9em;
147
  color: #666;
148
  }}
 
 
 
 
 
149
  </style>
150
  </head>
151
  <body>
@@ -154,7 +175,6 @@ async def root():
154
  <div id="init-form">
155
  <h2>1. Initialize Chat</h2>
156
 
157
- <!-- API key input removed -->
158
  <label for="model">Model:</label>
159
  <input type="text" id="model" value="mistralai/mistral-small-3.1-24b-instruct:free">
160
 
@@ -181,12 +201,22 @@ async def root():
181
  <button onclick="resetChat()" style="background-color: #f44336;">Reset</button>
182
  </div>
183
 
184
- <div id="response-container" style="display: none;">
185
- <h2>3. Response</h2>
186
- <div id="response">The response will appear here...</div>
187
- <div class="log">
188
- <h3>Thinking Process Log:</h3>
189
- <div id="thinking-log"></div>
 
 
 
 
 
 
 
 
 
 
190
  </div>
191
  </div>
192
  </div>
@@ -198,7 +228,8 @@ async def root():
198
 
199
  <script>
200
  let currentSessionId = null;
201
-
 
202
  async function initializeChat() {{
203
  const model = document.getElementById('model').value;
204
  const temperature = parseFloat(document.getElementById('temperature').value);
@@ -222,7 +253,10 @@ async def root():
222
  document.getElementById('session-id').textContent = currentSessionId;
223
  document.getElementById('init-form').style.display = 'none';
224
  document.getElementById('chat-form').style.display = 'block';
225
- document.getElementById('response-container').style.display = 'block';
 
 
 
226
  }} else {{
227
  alert('Initialization failed: ' + (data.detail || 'Unknown error'));
228
  }}
@@ -230,7 +264,71 @@ async def root():
230
  alert('An error occurred: ' + error.message);
231
  }}
232
  }}
233
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  async function sendMessage() {{
235
  if (!currentSessionId) {{
236
  alert('Please initialize a chat session first.');
@@ -246,51 +344,55 @@ async def root():
246
  return;
247
  }}
248
 
249
- document.getElementById('response').textContent = 'Processing...';
 
 
250
  document.getElementById('thinking-log').textContent = '';
251
-
 
 
252
  try {{
253
- const response = await fetch('/api/send_message', {{
254
  method: 'POST',
255
  headers: {{
256
  'Content-Type': 'application/json',
257
  }},
258
  body: JSON.stringify({{
259
  session_id: currentSessionId,
260
- message: message,
261
- thinking_rounds: thinkingRounds ? parseInt(thinkingRounds) : null,
262
- alternatives_per_round: alternatives ? parseInt(alternatives) : 3
263
  }}),
264
  }});
265
-
266
- const data = await response.json();
267
-
268
- if (response.ok) {{
269
- document.getElementById('response').textContent = data.response;
270
-
271
- // Display thinking history
272
- let thinkingLogHTML = '';
273
- data.thinking_history.forEach(item => {{
274
- const selected = item.selected ? ' ✓ Selected' : '';
275
- thinkingLogHTML += "<p><strong>Round " + item.round + selected + ":</strong> ";
276
-
277
- if (item.explanation && item.selected) {{
278
- thinkingLogHTML += "<br><em>Reason for selection: " + item.explanation + "</em>";
279
- }}
280
- thinkingLogHTML += "</p>";
281
- }});
282
-
283
- document.getElementById('thinking-log').innerHTML = thinkingLogHTML;
284
  }} else {{
285
- document.getElementById('response').textContent = 'Error: ' + (data.detail || 'Unknown error');
286
  }}
287
  }} catch (error) {{
288
- document.getElementById('response').textContent = 'An error occurred: ' + error.message;
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  }}
290
  }}
291
 
292
  function resetChat() {{
293
  currentSessionId = null;
 
 
 
 
294
  document.getElementById('init-form').style.display = 'block';
295
  document.getElementById('chat-form').style.display = 'none';
296
  document.getElementById('response-container').style.display = 'none';
@@ -317,7 +419,7 @@ async def initialize_chat(config: ChatConfig):
317
  # Generate a session ID
318
  session_id = f"session_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:8]}"
319
 
320
- # If the environment variable is missing, raise an error (or warning)
321
  if not API_KEY:
322
  raise HTTPException(status_code=400, detail="The OPENROUTE_API environment variable is not set.")
323
 
@@ -338,9 +440,29 @@ async def initialize_chat(config: ChatConfig):
338
  logger.error(f"Error initializing chat: {str(e)}")
339
  raise HTTPException(status_code=500, detail=f"Failed to initialize chat: {str(e)}")
340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  @app.post("/api/send_message")
342
  async def send_message(request: MessageRequest):
343
- """Send a message and get a response with the thinking process"""
344
  try:
345
  if request.session_id not in chat_instances:
346
  raise HTTPException(status_code=404, detail="Session not found")
@@ -558,7 +680,7 @@ async def websocket_endpoint(websocket: WebSocket, session_id: str):
558
  "message": "Starting recursive thinking process..."
559
  })
560
 
561
- # Process the message
562
  result = chat.think_and_respond(message_data["content"], verbose=True)
563
  processing_time = (datetime.now() - start_time).total_seconds()
564
 
 
82
  session_id: str
83
  status: str
84
 
85
+ # Simple HTML interface
86
  @app.get("/", response_class=HTMLResponse)
87
  async def root():
88
+ """
89
+ Root endpoint with a simple HTML interface.
90
+ Modified to display side-by-side "Original" vs. "Chain-of-Thought" outputs,
91
+ and to show real-time "thinking in progress" messages.
92
+ """
93
  html_content = f"""
94
  <!DOCTYPE html>
95
  <html>
 
98
  <style>
99
  body {{
100
  font-family: Arial, sans-serif;
101
+ max-width: 1000px;
102
  margin: 0 auto;
103
  padding: 20px;
104
  line-height: 1.6;
 
137
  button:hover {{
138
  background-color: #45a049;
139
  }}
140
+ #original-response, #chain-response {{
141
  white-space: pre-wrap;
142
  background-color: #f5f5f5;
143
  padding: 15px;
144
  border-radius: 4px;
 
145
  min-height: 100px;
146
  }}
147
+ .responses-container {{
148
+ display: flex;
149
+ gap: 20px;
150
+ margin-top: 20px;
151
+ }}
152
+ .response-column {{
153
+ flex: 1;
154
+ display: flex;
155
+ flex-direction: column;
156
+ }}
157
+ .column-title {{
158
+ margin-top: 0;
159
+ }}
160
  .log {{
161
  margin-top: 20px;
162
  font-size: 0.9em;
163
  color: #666;
164
  }}
165
+ .thinking-progress {{
166
+ margin-top: 10px;
167
+ font-style: italic;
168
+ color: #555;
169
+ }}
170
  </style>
171
  </head>
172
  <body>
 
175
  <div id="init-form">
176
  <h2>1. Initialize Chat</h2>
177
 
 
178
  <label for="model">Model:</label>
179
  <input type="text" id="model" value="mistralai/mistral-small-3.1-24b-instruct:free">
180
 
 
201
  <button onclick="resetChat()" style="background-color: #f44336;">Reset</button>
202
  </div>
203
 
204
+ <div class="responses-container" id="response-container" style="display: none;">
205
+ <!-- Original Response Column -->
206
+ <div class="response-column">
207
+ <h2 class="column-title">Original (No Chain-of-Thought)</h2>
208
+ <div id="original-response">The original LLM response will appear here...</div>
209
+ </div>
210
+
211
+ <!-- Chain-of-Thought Response Column -->
212
+ <div class="response-column">
213
+ <h2 class="column-title">Chain-of-Thought</h2>
214
+ <div id="chain-thinking-progress" class="thinking-progress"></div>
215
+ <div id="chain-response">The chain-of-thought response will appear here...</div>
216
+ <div class="log">
217
+ <h3>Thinking Process Log:</h3>
218
+ <div id="thinking-log"></div>
219
+ </div>
220
  </div>
221
  </div>
222
  </div>
 
228
 
229
  <script>
230
  let currentSessionId = null;
231
+ let ws = null; // WebSocket for Chain-of-Thought
232
+
233
  async function initializeChat() {{
234
  const model = document.getElementById('model').value;
235
  const temperature = parseFloat(document.getElementById('temperature').value);
 
253
  document.getElementById('session-id').textContent = currentSessionId;
254
  document.getElementById('init-form').style.display = 'none';
255
  document.getElementById('chat-form').style.display = 'block';
256
+ document.getElementById('response-container').style.display = 'flex';
257
+
258
+ // Connect to WebSocket for chain-of-thought streaming
259
+ connectWebSocket();
260
  }} else {{
261
  alert('Initialization failed: ' + (data.detail || 'Unknown error'));
262
  }}
 
264
  alert('An error occurred: ' + error.message);
265
  }}
266
  }}
267
+
268
+ function connectWebSocket() {{
269
+ if (!currentSessionId) {{
270
+ return;
271
+ }}
272
+ const loc = window.location;
273
+ let wsUrl = '';
274
+ if (loc.protocol === 'https:') {{
275
+ wsUrl = 'wss:';
276
+ }} else {{
277
+ wsUrl = 'ws:';
278
+ }}
279
+ wsUrl += '//' + loc.host + '/ws/' + currentSessionId;
280
+ ws = new WebSocket(wsUrl);
281
+
282
+ ws.onopen = function() {{
283
+ console.log('WebSocket connection opened for chain-of-thought.');
284
+ }};
285
+
286
+ ws.onmessage = function(event) {{
287
+ const data = JSON.parse(event.data);
288
+
289
+ if (data.type === 'status') {{
290
+ // Show "thinking in progress" messages
291
+ document.getElementById('chain-thinking-progress').textContent = data.message;
292
+ }} else if (data.type === 'chunk') {{
293
+ // In this example code, "chunk" is not truly partial, but let's append anyway
294
+ document.getElementById('chain-thinking-progress').textContent += '\\n' + data.content;
295
+ }} else if (data.type === 'final') {{
296
+ // Final answer
297
+ document.getElementById('chain-thinking-progress').textContent = '';
298
+ document.getElementById('chain-response').textContent = data.response;
299
+
300
+ // Display thinking history
301
+ const thinkingLog = document.getElementById('thinking-log');
302
+ thinkingLog.innerHTML = '';
303
+ data.thinking_history.forEach(item => {{
304
+ const selected = item.selected ? ' ✓ Selected' : '';
305
+ let logEntry = document.createElement('p');
306
+ logEntry.innerHTML = '<strong>Round ' + item.round + selected + ':</strong> ';
307
+ if (item.explanation && item.selected) {{
308
+ logEntry.innerHTML += '<br><em>Reason for selection: ' + item.explanation + '</em>';
309
+ }}
310
+ thinkingLog.appendChild(logEntry);
311
+ }});
312
+ }} else if (data.type === 'error') {{
313
+ document.getElementById('chain-thinking-progress').textContent = '';
314
+ document.getElementById('chain-response').textContent = 'Error: ' + data.error;
315
+ }} else if (data.error) {{
316
+ // Session not found or other errors
317
+ document.getElementById('chain-thinking-progress').textContent = '';
318
+ document.getElementById('chain-response').textContent = 'Error: ' + data.error;
319
+ }}
320
+ }};
321
+
322
+ ws.onerror = function(error) {{
323
+ console.error('WebSocket error:', error);
324
+ document.getElementById('chain-thinking-progress').textContent = 'WebSocket error. Check console.';
325
+ }};
326
+
327
+ ws.onclose = function() {{
328
+ console.log('WebSocket closed.');
329
+ }};
330
+ }}
331
+
332
  async function sendMessage() {{
333
  if (!currentSessionId) {{
334
  alert('Please initialize a chat session first.');
 
344
  return;
345
  }}
346
 
347
+ // Clear out previous responses/log
348
+ document.getElementById('original-response').textContent = 'Loading original response...';
349
+ document.getElementById('chain-response').textContent = '';
350
  document.getElementById('thinking-log').textContent = '';
351
+ document.getElementById('chain-thinking-progress').textContent = 'Thinking...';
352
+
353
+ // 1) Get Original Response via standard fetch
354
  try {{
355
+ const originalRes = await fetch('/api/send_message_original', {{
356
  method: 'POST',
357
  headers: {{
358
  'Content-Type': 'application/json',
359
  }},
360
  body: JSON.stringify({{
361
  session_id: currentSessionId,
362
+ message: message
 
 
363
  }}),
364
  }});
365
+
366
+ const originalData = await originalRes.json();
367
+ if (originalRes.ok) {{
368
+ document.getElementById('original-response').textContent = originalData.response;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  }} else {{
370
+ document.getElementById('original-response').textContent = 'Error: ' + (originalData.detail || 'Unknown error');
371
  }}
372
  }} catch (error) {{
373
+ document.getElementById('original-response').textContent = 'Error: ' + error.message;
374
+ }}
375
+
376
+ // 2) Send message to WebSocket for chain-of-thought
377
+ if (ws && ws.readyState === WebSocket.OPEN) {{
378
+ const payload = {{
379
+ type: 'message',
380
+ content: message,
381
+ thinking_rounds: thinkingRounds ? parseInt(thinkingRounds) : null,
382
+ alternatives_per_round: alternatives ? parseInt(alternatives) : 3
383
+ }};
384
+ ws.send(JSON.stringify(payload));
385
+ }} else {{
386
+ document.getElementById('chain-thinking-progress').textContent = 'WebSocket not connected. Unable to get chain-of-thought response.';
387
  }}
388
  }}
389
 
390
  function resetChat() {{
391
  currentSessionId = null;
392
+ if (ws) {{
393
+ ws.close();
394
+ ws = null;
395
+ }}
396
  document.getElementById('init-form').style.display = 'block';
397
  document.getElementById('chat-form').style.display = 'none';
398
  document.getElementById('response-container').style.display = 'none';
 
419
  # Generate a session ID
420
  session_id = f"session_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:8]}"
421
 
422
+ # If the environment variable is missing, raise an error
423
  if not API_KEY:
424
  raise HTTPException(status_code=400, detail="The OPENROUTE_API environment variable is not set.")
425
 
 
440
  logger.error(f"Error initializing chat: {str(e)}")
441
  raise HTTPException(status_code=500, detail=f"Failed to initialize chat: {str(e)}")
442
 
443
+ @app.post("/api/send_message_original")
444
+ async def send_message_original(request: MessageRequest):
445
+ """
446
+ Return a direct LLM response without applying the chain-of-thought logic.
447
+ """
448
+ if request.session_id not in chat_instances:
449
+ raise HTTPException(status_code=404, detail="Session not found")
450
+
451
+ chat = chat_instances[request.session_id]["chat"]
452
+ try:
453
+ # Make a direct call to the LLM without recursion logic
454
+ messages = [{"role": "user", "content": request.message}]
455
+ response_data = chat._call_api(messages, temperature=chat.temperature, stream=False)
456
+ # Extract the text from the response
457
+ original_text = response_data["choices"][0]["message"]["content"]
458
+ return {"response": original_text.strip()}
459
+ except Exception as e:
460
+ logger.error(f"Error getting original response: {str(e)}")
461
+ raise HTTPException(status_code=500, detail=str(e))
462
+
463
  @app.post("/api/send_message")
464
  async def send_message(request: MessageRequest):
465
+ """Send a message and get a response with the chain-of-thought process (HTTP-based, not streaming)."""
466
  try:
467
  if request.session_id not in chat_instances:
468
  raise HTTPException(status_code=404, detail="Session not found")
 
680
  "message": "Starting recursive thinking process..."
681
  })
682
 
683
+ # Process the message with chain-of-thought
684
  result = chat.think_and_respond(message_data["content"], verbose=True)
685
  processing_time = (datetime.now() - start_time).total_seconds()
686