openfree commited on
Commit
72d096e
·
verified ·
1 Parent(s): 2624ce9

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -713
app.py DELETED
@@ -1,713 +0,0 @@
1
- from fastapi import FastAPI, WebSocket, HTTPException, WebSocketDisconnect
2
- from fastapi.responses import JSONResponse, HTMLResponse
3
- from fastapi.staticfiles import StaticFiles
4
- from fastapi.middleware.cors import CORSMiddleware
5
- from pydantic import BaseModel, Field
6
- import uvicorn
7
- import json
8
- import os
9
- import asyncio
10
- from datetime import datetime
11
- from typing import List, Dict, Optional, Any
12
- import logging
13
- import uuid
14
-
15
- # If the module does not exist, try to import from the current directory
16
- try:
17
- from recursive_thinking_ai import EnhancedRecursiveThinkingChat
18
- except ModuleNotFoundError:
19
- # The file recursive_thinking_ai.py must exist in the current directory
20
- import sys
21
- sys.path.append('.')
22
- from recursive_thinking_ai import EnhancedRecursiveThinkingChat
23
-
24
- # Set up logging
25
- logging.basicConfig(
26
- level=logging.INFO,
27
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
28
- )
29
- logger = logging.getLogger(__name__)
30
-
31
- app = FastAPI(
32
- title="Chain-of-Recursive-Thoughts: TEST",
33
- description="https://github.com/PhialsBasement/Chain-of-Recursive-Thoughts",
34
- version="1.0.0"
35
- )
36
-
37
- # Add CORS middleware
38
- app.add_middleware(
39
- CORSMiddleware,
40
- allow_origins=["*"], # In production, replace with specific origins
41
- allow_credentials=True,
42
- allow_methods=["*"],
43
- allow_headers=["*"],
44
- )
45
-
46
- # Create a dictionary to store chat instances
47
- chat_instances = {}
48
-
49
- # Retrieve API key from environment variable
50
- API_KEY = os.getenv("OPENROUTE_API")
51
- if not API_KEY:
52
- logger.warning("The OPENROUTE_API environment variable is not set. Some features may not work.")
53
-
54
- # Pydantic models for request/response validation
55
- class ChatConfig(BaseModel):
56
- model: str = "mistralai/mistral-small-3.1-24b-instruct:free"
57
- temperature: Optional[float] = Field(default=0.7, ge=0.0, le=1.0)
58
-
59
- class MessageRequest(BaseModel):
60
- session_id: str
61
- message: str
62
- thinking_rounds: Optional[int] = Field(default=None, ge=1, le=10)
63
- alternatives_per_round: Optional[int] = Field(default=3, ge=1, le=5)
64
- temperature: Optional[float] = Field(default=None, ge=0.0, le=1.0)
65
-
66
- class SaveRequest(BaseModel):
67
- session_id: str
68
- filename: Optional[str] = None
69
- full_log: bool = False
70
-
71
- class SessionInfo(BaseModel):
72
- session_id: str
73
- message_count: int
74
- created_at: str
75
- model: str
76
-
77
- class SessionResponse(BaseModel):
78
- sessions: List[SessionInfo]
79
-
80
- class InitResponse(BaseModel):
81
- session_id: str
82
- status: str
83
-
84
- @app.get("/", response_class=HTMLResponse)
85
- async def root():
86
- """
87
- Root endpoint with a simple HTML interface.
88
- Modified to display side-by-side "Original" vs. "Chain-of-Thought" outputs,
89
- and to show real-time "thinking in progress" messages.
90
- """
91
- html_content = f"""
92
- <!DOCTYPE html>
93
- <html>
94
- <head>
95
- <title>Chain-of-Recursive-Thoughts: TEST</title>
96
- <style>
97
- body {{
98
- font-family: Arial, sans-serif;
99
- max-width: 1000px;
100
- margin: 0 auto;
101
- padding: 20px;
102
- line-height: 1.6;
103
- }}
104
- h1 {{
105
- color: #333;
106
- border-bottom: 1px solid #eee;
107
- padding-bottom: 10px;
108
- }}
109
- .container {{
110
- background-color: #f9f9f9;
111
- border-radius: 5px;
112
- padding: 20px;
113
- margin-top: 20px;
114
- }}
115
- label {{
116
- display: block;
117
- margin-bottom: 5px;
118
- font-weight: bold;
119
- }}
120
- input, textarea, select {{
121
- width: 100%;
122
- padding: 8px;
123
- margin-bottom: 10px;
124
- border: 1px solid #ddd;
125
- border-radius: 4px;
126
- }}
127
- button {{
128
- background-color: #4CAF50;
129
- color: white;
130
- padding: 10px 15px;
131
- border: none;
132
- border-radius: 4px;
133
- cursor: pointer;
134
- }}
135
- button:hover {{
136
- background-color: #45a049;
137
- }}
138
- #original-response, #chain-response {{
139
- white-space: pre-wrap;
140
- background-color: #f5f5f5;
141
- padding: 15px;
142
- border-radius: 4px;
143
- min-height: 100px;
144
- }}
145
- .responses-container {{
146
- display: flex;
147
- gap: 20px;
148
- margin-top: 20px;
149
- }}
150
- .response-column {{
151
- flex: 1;
152
- display: flex;
153
- flex-direction: column;
154
- }}
155
- .column-title {{
156
- margin-top: 0;
157
- }}
158
- .log {{
159
- margin-top: 20px;
160
- font-size: 0.9em;
161
- color: #666;
162
- }}
163
- .thinking-progress {{
164
- margin-top: 10px;
165
- font-style: italic;
166
- color: #555;
167
- }}
168
- </style>
169
- </head>
170
- <body>
171
- <h1>Chain-of-Recursive-Thoughts: TEST</h1>
172
- <div class="container">
173
- <div id="init-form">
174
- <h2>1. Initialize Chat</h2>
175
-
176
- <label for="model">Model:</label>
177
- <input type="text" id="model" value="mistralai/mistral-small-3.1-24b-instruct:free">
178
-
179
- <label for="temperature">Temperature:</label>
180
- <input type="number" id="temperature" min="0" max="1" step="0.1" value="0.7">
181
-
182
- <button onclick="initializeChat()">Initialize</button>
183
- </div>
184
-
185
- <div id="chat-form" style="display: none;">
186
- <h2>2. Send Message</h2>
187
- <p>Session ID: <span id="session-id"></span></p>
188
-
189
- <label for="message">Message:</label>
190
- <textarea id="message" rows="4" placeholder="Enter your message"></textarea>
191
-
192
- <label for="thinking-rounds">Thinking Rounds (optional):</label>
193
- <input type="number" id="thinking-rounds" min="1" max="10" placeholder="Auto">
194
-
195
- <label for="alternatives">Number of Alternatives (optional):</label>
196
- <input type="number" id="alternatives" min="1" max="5" value="3">
197
-
198
- <button onclick="sendMessage()">Send</button>
199
- <button onclick="resetChat()" style="background-color: #f44336;">Reset</button>
200
- </div>
201
-
202
- <div class="responses-container" id="response-container" style="display: none;">
203
- <!-- Original Response Column -->
204
- <div class="response-column">
205
- <h2 class="column-title">Original (No Chain-of-Thought)</h2>
206
- <div id="original-response">The original LLM response will appear here...</div>
207
- </div>
208
-
209
- <!-- Chain-of-Thought Response Column -->
210
- <div class="response-column">
211
- <h2 class="column-title">Chain-of-Thought</h2>
212
- <div id="chain-thinking-progress" class="thinking-progress"></div>
213
- <div id="chain-response">The chain-of-thought response will appear here...</div>
214
- <div class="log">
215
- <h3>Thinking Process Log:</h3>
216
- <div id="thinking-log"></div>
217
- </div>
218
- </div>
219
- </div>
220
- </div>
221
-
222
- <div style="margin-top: 30px;">
223
- <p>Repo: https://github.com/PhialsBasement/Chain-of-Recursive-Thoughts</p>
224
- <p>Community: https://discord.gg/openfreeai</p>
225
- </div>
226
-
227
- <script>
228
- let currentSessionId = null;
229
- let ws = null; // WebSocket for Chain-of-Thought
230
-
231
- async function initializeChat() {{
232
- const model = document.getElementById('model').value;
233
- const temperature = parseFloat(document.getElementById('temperature').value);
234
-
235
- try {{
236
- const response = await fetch('/api/initialize', {{
237
- method: 'POST',
238
- headers: {{
239
- 'Content-Type': 'application/json',
240
- }},
241
- body: JSON.stringify({{
242
- model: model,
243
- temperature: temperature
244
- }}),
245
- }});
246
-
247
- const data = await response.json();
248
-
249
- if (response.ok) {{
250
- currentSessionId = data.session_id;
251
- document.getElementById('session-id').textContent = currentSessionId;
252
- document.getElementById('init-form').style.display = 'none';
253
- document.getElementById('chat-form').style.display = 'block';
254
- document.getElementById('response-container').style.display = 'flex';
255
-
256
- // Connect to WebSocket for chain-of-thought streaming
257
- connectWebSocket();
258
- }} else {{
259
- alert('Initialization failed: ' + (data.detail || 'Unknown error'));
260
- }}
261
- }} catch (error) {{
262
- alert('An error occurred: ' + error.message);
263
- }}
264
- }}
265
-
266
- function connectWebSocket() {{
267
- if (!currentSessionId) {{
268
- return;
269
- }}
270
- const loc = window.location;
271
- let wsUrl = '';
272
- if (loc.protocol === 'https:') {{
273
- wsUrl = 'wss:';
274
- }} else {{
275
- wsUrl = 'ws:';
276
- }}
277
- wsUrl += '//' + loc.host + '/ws/' + currentSessionId;
278
- ws = new WebSocket(wsUrl);
279
-
280
- ws.onopen = function() {{
281
- console.log('WebSocket connection opened for chain-of-thought.');
282
- }};
283
-
284
- ws.onmessage = function(event) {{
285
- const data = JSON.parse(event.data);
286
-
287
- if (data.type === 'status') {{
288
- // Show "thinking in progress" messages
289
- document.getElementById('chain-thinking-progress').textContent = data.message;
290
- }} else if (data.type === 'chunk') {{
291
- // In this example code, "chunk" is not truly partial, but let's append anyway
292
- document.getElementById('chain-thinking-progress').textContent += '\\n' + data.content;
293
- }} else if (data.type === 'final') {{
294
- // Final answer
295
- document.getElementById('chain-thinking-progress').textContent = '';
296
- document.getElementById('chain-response').textContent = data.response;
297
-
298
- // Display thinking history
299
- const thinkingLog = document.getElementById('thinking-log');
300
- thinkingLog.innerHTML = '';
301
- data.thinking_history.forEach(item => {{
302
- const selected = item.selected ? ' ✓ Selected' : '';
303
- let logEntry = document.createElement('p');
304
- logEntry.innerHTML = '<strong>Round ' + item.round + selected + ':</strong> ';
305
- if (item.explanation && item.selected) {{
306
- logEntry.innerHTML += '<br><em>Reason for selection: ' + item.explanation + '</em>';
307
- }}
308
- thinkingLog.appendChild(logEntry);
309
- }});
310
- }} else if (data.type === 'error') {{
311
- document.getElementById('chain-thinking-progress').textContent = '';
312
- document.getElementById('chain-response').textContent = 'Error: ' + data.error;
313
- }} else if (data.error) {{
314
- // Session not found or other errors
315
- document.getElementById('chain-thinking-progress').textContent = '';
316
- document.getElementById('chain-response').textContent = 'Error: ' + data.error;
317
- }}
318
- }};
319
-
320
- ws.onerror = function(error) {{
321
- console.error('WebSocket error:', error);
322
- document.getElementById('chain-thinking-progress').textContent = 'WebSocket error. Check console.';
323
- }};
324
-
325
- ws.onclose = function() {{
326
- console.log('WebSocket closed.');
327
- }};
328
- }}
329
-
330
- async function sendMessage() {{
331
- if (!currentSessionId) {{
332
- alert('Please initialize a chat session first.');
333
- return;
334
- }}
335
-
336
- const message = document.getElementById('message').value;
337
- const thinkingRounds = document.getElementById('thinking-rounds').value;
338
- const alternatives = document.getElementById('alternatives').value;
339
-
340
- if (!message) {{
341
- alert('Please enter a message.');
342
- return;
343
- }}
344
-
345
- // Clear out previous responses/log
346
- document.getElementById('original-response').textContent = 'Loading original response...';
347
- document.getElementById('chain-response').textContent = '';
348
- document.getElementById('thinking-log').textContent = '';
349
- document.getElementById('chain-thinking-progress').textContent = 'Thinking...';
350
-
351
- // 1) Get Original Response via standard fetch
352
- try {{
353
- const originalRes = await fetch('/api/send_message_original', {{
354
- method: 'POST',
355
- headers: {{
356
- 'Content-Type': 'application/json',
357
- }},
358
- body: JSON.stringify({{
359
- session_id: currentSessionId,
360
- message: message
361
- }}),
362
- }});
363
-
364
- const originalData = await originalRes.json();
365
- if (originalRes.ok) {{
366
- document.getElementById('original-response').textContent = originalData.response;
367
- }} else {{
368
- document.getElementById('original-response').textContent = 'Error: ' + (originalData.detail || 'Unknown error');
369
- }}
370
- }} catch (error) {{
371
- document.getElementById('original-response').textContent = 'Error: ' + error.message;
372
- }}
373
-
374
- // 2) Send message to WebSocket for chain-of-thought
375
- if (ws && ws.readyState === WebSocket.OPEN) {{
376
- const payload = {{
377
- type: 'message',
378
- content: message,
379
- thinking_rounds: thinkingRounds ? parseInt(thinkingRounds) : null,
380
- alternatives_per_round: alternatives ? parseInt(alternatives) : 3
381
- }};
382
- ws.send(JSON.stringify(payload));
383
- }} else {{
384
- document.getElementById('chain-thinking-progress').textContent = 'WebSocket not connected. Unable to get chain-of-thought response.';
385
- }}
386
- }}
387
-
388
- function resetChat() {{
389
- currentSessionId = null;
390
- if (ws) {{
391
- ws.close();
392
- ws = null;
393
- }}
394
- document.getElementById('init-form').style.display = 'block';
395
- document.getElementById('chat-form').style.display = 'none';
396
- document.getElementById('response-container').style.display = 'none';
397
- document.getElementById('message').value = '';
398
- document.getElementById('thinking-rounds').value = '';
399
- document.getElementById('alternatives').value = '3';
400
- }}
401
- </script>
402
- </body>
403
- </html>
404
- """
405
- return HTMLResponse(content=html_content)
406
-
407
- @app.get("/health")
408
- async def health_check():
409
- """Health check endpoint"""
410
- return {"status": "healthy", "timestamp": datetime.now().isoformat()}
411
-
412
- @app.post("/api/initialize", response_model=InitResponse)
413
- async def initialize_chat(config: ChatConfig):
414
- """Initialize a new chat session using the environment API key"""
415
- try:
416
- # Generate a session ID
417
- session_id = f"session_{datetime.now().strftime('%Y%m%d%H%M%S')}_{uuid.uuid4().hex[:8]}"
418
-
419
- if not API_KEY:
420
- raise HTTPException(status_code=400, detail="The OPENROUTE_API environment variable is not set.")
421
-
422
- chat = EnhancedRecursiveThinkingChat(
423
- api_key=API_KEY,
424
- model=config.model,
425
- temperature=config.temperature
426
- )
427
- chat_instances[session_id] = {
428
- "chat": chat,
429
- "created_at": datetime.now().isoformat(),
430
- "model": config.model
431
- }
432
- return {"session_id": session_id, "status": "initialized"}
433
- except Exception as e:
434
- logger.error(f"Error initializing chat: {str(e)}")
435
- raise HTTPException(status_code=500, detail=f"Failed to initialize chat: {str(e)}")
436
-
437
- @app.post("/api/send_message_original")
438
- async def send_message_original(request: MessageRequest):
439
- """
440
- Return a direct LLM response without applying the chain-of-thought logic.
441
- """
442
- if request.session_id not in chat_instances:
443
- raise HTTPException(status_code=404, detail="Session not found")
444
-
445
- chat = chat_instances[request.session_id]["chat"]
446
- try:
447
- # Make a direct call to the LLM without recursion logic
448
- messages = [{"role": "user", "content": request.message}]
449
- response_data = chat._call_api(messages, temperature=chat.temperature, stream=False)
450
-
451
- # The structure of response_data depends on the underlying LLM.
452
- # We'll try to handle both "message" and "text" keys as possible.
453
- if isinstance(response_data, dict) and "choices" in response_data:
454
- first_choice = response_data["choices"][0]
455
- if "message" in first_choice and "content" in first_choice["message"]:
456
- original_text = first_choice["message"]["content"]
457
- elif "text" in first_choice:
458
- original_text = first_choice["text"]
459
- else:
460
- original_text = str(first_choice)
461
- else:
462
- # If for some reason the response is not in the expected format, just convert to string
463
- original_text = str(response_data)
464
-
465
- return {"response": original_text.strip()}
466
- except Exception as e:
467
- logger.error(f"Error getting original response: {str(e)}")
468
- raise HTTPException(status_code=500, detail=str(e))
469
-
470
- @app.post("/api/send_message")
471
- async def send_message(request: MessageRequest):
472
- """
473
- Send a message and get a response with the chain-of-thought process (HTTP-based, not streaming).
474
- Primarily left here for completeness, but the user-facing code calls the WebSocket for streaming.
475
- """
476
- try:
477
- if request.session_id not in chat_instances:
478
- raise HTTPException(status_code=404, detail="Session not found")
479
-
480
- chat = chat_instances[request.session_id]["chat"]
481
-
482
- original_thinking_fn = chat._determine_thinking_rounds
483
- original_alternatives_fn = chat._generate_alternatives
484
- original_temperature = getattr(chat, "temperature", 0.7)
485
-
486
- if request.thinking_rounds is not None:
487
- chat._determine_thinking_rounds = lambda _: request.thinking_rounds
488
-
489
- if request.alternatives_per_round is not None:
490
- def modified_generate_alternatives(base_response, prompt, num_alternatives=3):
491
- return original_alternatives_fn(base_response, prompt, request.alternatives_per_round)
492
- chat._generate_alternatives = modified_generate_alternatives
493
-
494
- if request.temperature is not None:
495
- setattr(chat, "temperature", request.temperature)
496
-
497
- logger.info(f"Processing message for session {request.session_id}")
498
- start_time = datetime.now()
499
- result = chat.think_and_respond(request.message, verbose=True)
500
- processing_time = (datetime.now() - start_time).total_seconds()
501
- logger.info(f"Message processed in {processing_time:.2f} seconds")
502
-
503
- # Restore original
504
- chat._determine_thinking_rounds = original_thinking_fn
505
- chat._generate_alternatives = original_alternatives_fn
506
- if request.temperature is not None:
507
- setattr(chat, "temperature", original_temperature)
508
-
509
- return {
510
- "session_id": request.session_id,
511
- "response": result["response"],
512
- "thinking_rounds": result["thinking_rounds"],
513
- "thinking_history": result["thinking_history"],
514
- "processing_time": processing_time
515
- }
516
- except Exception as e:
517
- logger.error(f"Error processing message: {str(e)}")
518
- raise HTTPException(status_code=500, detail=f"Failed to process message: {str(e)}")
519
-
520
- @app.post("/api/save")
521
- async def save_conversation(request: SaveRequest):
522
- """Save the conversation or the full thinking log."""
523
- try:
524
- if request.session_id not in chat_instances:
525
- raise HTTPException(status_code=404, detail="Session not found")
526
-
527
- chat = chat_instances[request.session_id]["chat"]
528
-
529
- filename = request.filename
530
- if filename is None:
531
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
532
- log_type = "full_log" if request.full_log else "conversation"
533
- filename = f"recthink_{log_type}_{timestamp}.json"
534
-
535
- os.makedirs("logs", exist_ok=True)
536
- file_path = os.path.join("logs", filename)
537
-
538
- if request.full_log:
539
- chat.save_full_log(file_path)
540
- else:
541
- chat.save_conversation(file_path)
542
-
543
- return {"status": "saved", "filename": filename, "path": file_path}
544
- except Exception as e:
545
- logger.error(f"Error saving conversation: {str(e)}")
546
- raise HTTPException(status_code=500, detail=f"Failed to save conversation: {str(e)}")
547
-
548
- @app.get("/api/sessions", response_model=SessionResponse)
549
- async def list_sessions():
550
- """List all active chat sessions."""
551
- sessions = []
552
- for session_id, session_data in chat_instances.items():
553
- chat = session_data["chat"]
554
- message_count = len(chat.conversation_history) // 2
555
- sessions.append(SessionInfo(
556
- session_id=session_id,
557
- message_count=message_count,
558
- created_at=session_data["created_at"],
559
- model=session_data["model"]
560
- ))
561
- return {"sessions": sessions}
562
-
563
- @app.get("/api/sessions/{session_id}")
564
- async def get_session(session_id: str):
565
- """Get details for a specific chat session."""
566
- if session_id not in chat_instances:
567
- raise HTTPException(status_code=404, detail="Session not found")
568
-
569
- session_data = chat_instances[session_id]
570
- chat = session_data["chat"]
571
-
572
- conversation = []
573
- for i in range(0, len(chat.conversation_history), 2):
574
- if i+1 < len(chat.conversation_history):
575
- conversation.append({
576
- "user": chat.conversation_history[i],
577
- "assistant": chat.conversation_history[i+1]
578
- })
579
-
580
- return {
581
- "session_id": session_id,
582
- "created_at": session_data["created_at"],
583
- "model": session_data["model"],
584
- "message_count": len(conversation),
585
- "conversation": conversation
586
- }
587
-
588
- @app.delete("/api/sessions/{session_id}")
589
- async def delete_session(session_id: str):
590
- """Delete a chat session."""
591
- if session_id not in chat_instances:
592
- raise HTTPException(status_code=404, detail="Session not found")
593
- del chat_instances[session_id]
594
- return {"status": "deleted", "session_id": session_id}
595
-
596
- class ConnectionManager:
597
- def __init__(self):
598
- self.active_connections: Dict[str, WebSocket] = {}
599
-
600
- async def connect(self, session_id: str, websocket: WebSocket):
601
- await websocket.accept()
602
- self.active_connections[session_id] = websocket
603
-
604
- def disconnect(self, session_id: str):
605
- if session_id in self.active_connections:
606
- del self.active_connections[session_id]
607
-
608
- async def send_json(self, session_id: str, data: dict):
609
- if session_id in self.active_connections:
610
- await self.active_connections[session_id].send_json(data)
611
-
612
- manager = ConnectionManager()
613
-
614
- @app.websocket("/ws/{session_id}")
615
- async def websocket_endpoint(websocket: WebSocket, session_id: str):
616
- try:
617
- await manager.connect(session_id, websocket)
618
-
619
- if session_id not in chat_instances:
620
- await websocket.send_json({"error": "Session not found"})
621
- await websocket.close()
622
- return
623
-
624
- chat = chat_instances[session_id]["chat"]
625
- original_call_api = chat._call_api
626
-
627
- async def stream_callback(chunk):
628
- await manager.send_json(session_id, {"type": "chunk", "content": chunk})
629
-
630
- def ws_call_api(messages, temperature=0.7, stream=True):
631
- result = original_call_api(messages, temperature, stream)
632
- if stream:
633
- asyncio.create_task(stream_callback(result))
634
- return result
635
-
636
- chat._call_api = ws_call_api
637
-
638
- while True:
639
- data = await websocket.receive_text()
640
- message_data = json.loads(data)
641
-
642
- if message_data["type"] == "message":
643
- start_time = datetime.now()
644
-
645
- try:
646
- thinking_rounds = message_data.get("thinking_rounds", None)
647
- alternatives_per_round = message_data.get("alternatives_per_round", None)
648
- temperature = message_data.get("temperature", None)
649
-
650
- original_thinking_fn = chat._determine_thinking_rounds
651
- original_alternatives_fn = chat._generate_alternatives
652
- original_temperature = getattr(chat, "temperature", 0.7)
653
-
654
- if thinking_rounds is not None:
655
- chat._determine_thinking_rounds = lambda _: thinking_rounds
656
-
657
- if alternatives_per_round is not None:
658
- def modified_generate_alternatives(base_response, prompt, num_alternatives=3):
659
- return original_alternatives_fn(base_response, prompt, alternatives_per_round)
660
- chat._generate_alternatives = modified_generate_alternatives
661
-
662
- if temperature is not None:
663
- setattr(chat, "temperature", temperature)
664
-
665
- await manager.send_json(session_id, {
666
- "type": "status",
667
- "status": "processing",
668
- "message": "Starting recursive thinking process..."
669
- })
670
-
671
- result = chat.think_and_respond(message_data["content"], verbose=True)
672
- processing_time = (datetime.now() - start_time).total_seconds()
673
-
674
- chat._determine_thinking_rounds = original_thinking_fn
675
- chat._generate_alternatives = original_alternatives_fn
676
- if temperature is not None:
677
- setattr(chat, "temperature", original_temperature)
678
-
679
- await manager.send_json(session_id, {
680
- "type": "final",
681
- "response": result["response"],
682
- "thinking_rounds": result["thinking_rounds"],
683
- "thinking_history": result["thinking_history"],
684
- "processing_time": processing_time
685
- })
686
-
687
- except Exception as e:
688
- error_msg = str(e)
689
- logger.error(f"Error in WebSocket message processing: {error_msg}")
690
- await manager.send_json(session_id, {
691
- "type": "error",
692
- "error": error_msg
693
- })
694
- except WebSocketDisconnect:
695
- logger.info(f"WebSocket disconnected: {session_id}")
696
- manager.disconnect(session_id)
697
- except Exception as e:
698
- error_msg = str(e)
699
- logger.error(f"WebSocket error: {error_msg}")
700
- try:
701
- await websocket.send_json({"type": "error", "error": error_msg})
702
- except:
703
- pass
704
- finally:
705
- if 'chat' in locals() and 'original_call_api' in locals():
706
- chat._call_api = original_call_api
707
-
708
- manager.disconnect(session_id)
709
-
710
- if __name__ == "__main__":
711
- port = 7860
712
- print(f"Starting server on port {port}")
713
- uvicorn.run("app:app", host="0.0.0.0", port=port)