FrederickSundeep commited on
Commit
311fd07
·
1 Parent(s): 8cc8f94

commit 000000239

Browse files
Files changed (1) hide show
  1. app.py +29 -20
app.py CHANGED
@@ -2,8 +2,7 @@ import os
2
  import time
3
  import torch
4
  import re
5
- from fastapi import FastAPI, Request
6
- from fastapi.responses import StreamingResponse
7
  from fastapi.staticfiles import StaticFiles
8
  from fastapi.templating import Jinja2Templates
9
  from pydantic import BaseModel
@@ -24,15 +23,15 @@ app = FastAPI(
24
  title="ChatMate Real-Time API",
25
  description="LangChain + DuckDuckGo + Phi-4",
26
  version="1.0",
27
- docs_url="/apidocs", # Swagger UI at /apidocs
28
- redoc_url="/redoc" # ReDoc at /redoc
29
  )
30
 
31
  # ✅ Static + templates
32
  app.mount("/static", StaticFiles(directory="static"), name="static")
33
  templates = Jinja2Templates(directory="templates")
34
 
35
- # Enable CORS (important for browser clients)
36
  app.add_middleware(
37
  CORSMiddleware,
38
  allow_origins=["*"],
@@ -94,24 +93,38 @@ class ChatRequest(BaseModel):
94
  message: str
95
  history: list = []
96
 
97
- # ---------------- FastAPI route ----------------
98
  # ---------------- Routes ----------------
99
  @app.get("/", summary="Serve homepage")
100
  async def home(request: Request):
101
  return templates.TemplateResponse("index.html", {"request": request})
102
 
103
- @app.post("/chat-stream", summary="Stream assistant reply", tags=["Chat"])
104
- async def chat_stream(body: ChatRequest):
105
  """
106
- Stream the AI assistant's reply token-by-token.
107
  """
108
- def generate():
109
- reply = generate_full_reply(body.message, body.history)
110
- for token in reply:
111
- yield token
112
- time.sleep(0.05)
 
 
 
 
113
 
114
- return StreamingResponse(generate(), media_type="text/plain")
 
 
 
 
 
 
 
 
 
 
 
115
 
116
  # ---------------- Startup warm-up ----------------
117
  @app.on_event("startup")
@@ -120,10 +133,6 @@ async def warmup_model():
120
  _ = generate_full_reply("Hello", [])
121
 
122
  # ---------------- Run with Uvicorn ----------------
123
- # In Hugging Face Spaces, just run: uvicorn app:app --host 0.0.0.0 --port 7860
124
  if __name__ == "__main__":
125
- # Hugging Face Spaces usually expects port 7860
126
  port = int(os.environ.get("PORT", 7860))
127
-
128
- # Run using uvicorn for FastAPI/Flask with ASGI wrapper
129
- uvicorn.run("app:app", host="0.0.0.0", port=port, reload=False)
 
2
  import time
3
  import torch
4
  import re
5
+ from fastapi import FastAPI, Request, WebSocket, WebSocketDisconnect
 
6
  from fastapi.staticfiles import StaticFiles
7
  from fastapi.templating import Jinja2Templates
8
  from pydantic import BaseModel
 
23
  title="ChatMate Real-Time API",
24
  description="LangChain + DuckDuckGo + Phi-4",
25
  version="1.0",
26
+ docs_url="/apidocs",
27
+ redoc_url="/redoc"
28
  )
29
 
30
  # ✅ Static + templates
31
  app.mount("/static", StaticFiles(directory="static"), name="static")
32
  templates = Jinja2Templates(directory="templates")
33
 
34
+ # Enable CORS
35
  app.add_middleware(
36
  CORSMiddleware,
37
  allow_origins=["*"],
 
93
  message: str
94
  history: list = []
95
 
 
96
  # ---------------- Routes ----------------
97
  @app.get("/", summary="Serve homepage")
98
  async def home(request: Request):
99
  return templates.TemplateResponse("index.html", {"request": request})
100
 
101
+ @app.websocket("/chat-stream")
102
+ async def chat_stream_ws(websocket: WebSocket):
103
  """
104
+ WebSocket endpoint to stream tokens to the client.
105
  """
106
+ await websocket.accept()
107
+ try:
108
+ while True:
109
+ data = await websocket.receive_text()
110
+ try:
111
+ req = ChatRequest.parse_raw(data)
112
+ except Exception as e:
113
+ await websocket.send_text(f"[Error] Invalid request: {str(e)}")
114
+ continue
115
 
116
+ reply = generate_full_reply(req.message, req.history)
117
+
118
+ # Stream token by token
119
+ for token in reply:
120
+ await websocket.send_text(token)
121
+ await asyncio.sleep(0.05)
122
+
123
+ # Optional: send special marker to indicate completion
124
+ await websocket.send_text("[END]")
125
+
126
+ except WebSocketDisconnect:
127
+ print("Client disconnected from WebSocket.")
128
 
129
  # ---------------- Startup warm-up ----------------
130
  @app.on_event("startup")
 
133
  _ = generate_full_reply("Hello", [])
134
 
135
  # ---------------- Run with Uvicorn ----------------
 
136
  if __name__ == "__main__":
 
137
  port = int(os.environ.get("PORT", 7860))
138
+ uvicorn.run("app:app", host="0.0.0.0", port=port, reload=False)