Spaces:
Sleeping
Sleeping
Integrate TxAgent into CPS API: add TxAgent files, update requirements, fix imports and database collections
Browse files- api/__init__.py +64 -1
- api/routes/txagent.py +0 -53
api/__init__.py
CHANGED
|
@@ -17,7 +17,11 @@ def get_router():
|
|
| 17 |
from .routes.pdf import pdf
|
| 18 |
from .routes.appointments import router as appointments
|
| 19 |
from .routes.messaging import router as messaging
|
| 20 |
-
from .routes.txagent import router as txagent
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
# Include sub-routers with correct prefixes
|
| 23 |
router.include_router(patients, tags=["patients"]) # Remove prefix since routes already have /patients
|
|
@@ -27,6 +31,65 @@ def get_router():
|
|
| 27 |
router.include_router(messaging, tags=["messaging"])
|
| 28 |
router.include_router(txagent, tags=["txagent"])
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
return router
|
| 31 |
|
| 32 |
# Export the router
|
|
|
|
| 17 |
from .routes.pdf import pdf
|
| 18 |
from .routes.appointments import router as appointments
|
| 19 |
from .routes.messaging import router as messaging
|
| 20 |
+
from .routes.txagent import router as txagent, get_txagent, ChatRequest
|
| 21 |
+
from fastapi import Depends, HTTPException
|
| 22 |
+
from core.security import get_current_user
|
| 23 |
+
import asyncio
|
| 24 |
+
from fastapi.responses import StreamingResponse
|
| 25 |
|
| 26 |
# Include sub-routers with correct prefixes
|
| 27 |
router.include_router(patients, tags=["patients"]) # Remove prefix since routes already have /patients
|
|
|
|
| 31 |
router.include_router(messaging, tags=["messaging"])
|
| 32 |
router.include_router(txagent, tags=["txagent"])
|
| 33 |
|
| 34 |
+
# Add the chat-stream endpoint at the root level
|
| 35 |
+
@router.post("/chat-stream")
|
| 36 |
+
async def chat_stream(
|
| 37 |
+
request: ChatRequest,
|
| 38 |
+
current_user: dict = Depends(get_current_user)
|
| 39 |
+
):
|
| 40 |
+
"""Streaming chat endpoint for TxAgent"""
|
| 41 |
+
import logging
|
| 42 |
+
logger = logging.getLogger(__name__)
|
| 43 |
+
|
| 44 |
+
try:
|
| 45 |
+
if not any(role in current_user.get('roles', []) for role in ['doctor', 'admin']):
|
| 46 |
+
raise HTTPException(status_code=403, detail="Only doctors and admins can use TxAgent")
|
| 47 |
+
|
| 48 |
+
# Get TxAgent instance
|
| 49 |
+
txagent = get_txagent()
|
| 50 |
+
|
| 51 |
+
if txagent is None:
|
| 52 |
+
# Fallback response if TxAgent is not available
|
| 53 |
+
response_text = f"TxAgent is currently unavailable. Please try again later. Your message was: {request.message}"
|
| 54 |
+
else:
|
| 55 |
+
# Get real response from TxAgent
|
| 56 |
+
try:
|
| 57 |
+
response_text = txagent.chat(
|
| 58 |
+
message=request.message,
|
| 59 |
+
temperature=request.temperature,
|
| 60 |
+
max_new_tokens=request.max_new_tokens
|
| 61 |
+
)
|
| 62 |
+
except Exception as e:
|
| 63 |
+
logger.error(f"TxAgent chat failed: {e}")
|
| 64 |
+
response_text = f"Sorry, I encountered an error processing your request: {request.message}. Please try again."
|
| 65 |
+
|
| 66 |
+
# Create streaming response
|
| 67 |
+
async def generate():
|
| 68 |
+
# Split response into sentences for more natural streaming
|
| 69 |
+
sentences = response_text.split('. ')
|
| 70 |
+
|
| 71 |
+
for i, sentence in enumerate(sentences):
|
| 72 |
+
if sentence.strip():
|
| 73 |
+
# Add period back except for the last sentence
|
| 74 |
+
chunk = sentence + ('. ' if i < len(sentences) - 1 else '')
|
| 75 |
+
yield f"data: {chunk}\n\n"
|
| 76 |
+
await asyncio.sleep(0.2) # Natural delay between sentences
|
| 77 |
+
|
| 78 |
+
yield "data: [DONE]\n\n"
|
| 79 |
+
|
| 80 |
+
return StreamingResponse(
|
| 81 |
+
generate(),
|
| 82 |
+
media_type="text/plain",
|
| 83 |
+
headers={
|
| 84 |
+
"Cache-Control": "no-cache",
|
| 85 |
+
"Connection": "keep-alive",
|
| 86 |
+
"Content-Type": "text/event-stream"
|
| 87 |
+
}
|
| 88 |
+
)
|
| 89 |
+
except Exception as e:
|
| 90 |
+
logger.error(f"Error in chat stream: {e}")
|
| 91 |
+
raise HTTPException(status_code=500, detail="Failed to process chat stream")
|
| 92 |
+
|
| 93 |
return router
|
| 94 |
|
| 95 |
# Export the router
|
api/routes/txagent.py
CHANGED
|
@@ -265,57 +265,4 @@ async def get_chats(current_user: dict = Depends(get_current_user)):
|
|
| 265 |
logger.error(f"Error getting chats: {e}")
|
| 266 |
raise HTTPException(status_code=500, detail="Failed to get chats")
|
| 267 |
|
| 268 |
-
@router.post("/chat-stream")
|
| 269 |
-
async def chat_stream(
|
| 270 |
-
request: ChatRequest,
|
| 271 |
-
current_user: dict = Depends(get_current_user)
|
| 272 |
-
):
|
| 273 |
-
"""Streaming chat endpoint for TxAgent"""
|
| 274 |
-
try:
|
| 275 |
-
if not any(role in current_user.get('roles', []) for role in ['doctor', 'admin']):
|
| 276 |
-
raise HTTPException(status_code=403, detail="Only doctors and admins can use TxAgent")
|
| 277 |
|
| 278 |
-
# Get TxAgent instance
|
| 279 |
-
txagent = get_txagent()
|
| 280 |
-
|
| 281 |
-
if txagent is None:
|
| 282 |
-
# Fallback response if TxAgent is not available
|
| 283 |
-
response_text = f"TxAgent is currently unavailable. Please try again later. Your message was: {request.message}"
|
| 284 |
-
else:
|
| 285 |
-
# Get real response from TxAgent
|
| 286 |
-
try:
|
| 287 |
-
response_text = txagent.chat(
|
| 288 |
-
message=request.message,
|
| 289 |
-
temperature=request.temperature,
|
| 290 |
-
max_new_tokens=request.max_new_tokens
|
| 291 |
-
)
|
| 292 |
-
except Exception as e:
|
| 293 |
-
logger.error(f"TxAgent chat failed: {e}")
|
| 294 |
-
response_text = f"Sorry, I encountered an error processing your request: {request.message}. Please try again."
|
| 295 |
-
|
| 296 |
-
# Create streaming response
|
| 297 |
-
async def generate():
|
| 298 |
-
# Split response into sentences for more natural streaming
|
| 299 |
-
sentences = response_text.split('. ')
|
| 300 |
-
|
| 301 |
-
for i, sentence in enumerate(sentences):
|
| 302 |
-
if sentence.strip():
|
| 303 |
-
# Add period back except for the last sentence
|
| 304 |
-
chunk = sentence + ('. ' if i < len(sentences) - 1 else '')
|
| 305 |
-
yield f"data: {chunk}\n\n"
|
| 306 |
-
await asyncio.sleep(0.2) # Natural delay between sentences
|
| 307 |
-
|
| 308 |
-
yield "data: [DONE]\n\n"
|
| 309 |
-
|
| 310 |
-
return StreamingResponse(
|
| 311 |
-
generate(),
|
| 312 |
-
media_type="text/plain",
|
| 313 |
-
headers={
|
| 314 |
-
"Cache-Control": "no-cache",
|
| 315 |
-
"Connection": "keep-alive",
|
| 316 |
-
"Content-Type": "text/event-stream"
|
| 317 |
-
}
|
| 318 |
-
)
|
| 319 |
-
except Exception as e:
|
| 320 |
-
logger.error(f"Error in chat stream: {e}")
|
| 321 |
-
raise HTTPException(status_code=500, detail="Failed to process chat stream")
|
|
|
|
| 265 |
logger.error(f"Error getting chats: {e}")
|
| 266 |
raise HTTPException(status_code=500, detail="Failed to get chats")
|
| 267 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|