Aaravkumar commited on
Commit
8698bda
·
verified ·
1 Parent(s): ec9c3cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -35
app.py CHANGED
@@ -1,5 +1,6 @@
1
  from fastapi import HTTPException, FastAPI, File, UploadFile
2
  from fastapi.middleware.cors import CORSMiddleware
 
3
  from fastapi.responses import StreamingResponse
4
  from pydantic import BaseModel, Field
5
  import aiofiles
@@ -100,6 +101,8 @@ async def upload_file(file: UploadFile = File(...)):
100
  if tmp_path and os.path.exists(tmp_path):
101
  os.unlink(tmp_path)
102
 
 
 
103
  @app.post("/chat")
104
  async def chat(chat_req: ChatRequest):
105
  hf_token = os.environ.get("HF_TOKEN")
@@ -121,8 +124,7 @@ async def chat(chat_req: ChatRequest):
121
 
122
  if not context_chunks:
123
  async def empty_stream():
124
- ymsg = "I couldn't find relevant information in the document."
125
- yield f"data: {json.dumps({'token': ymsg})}\n\n"
126
  yield "data: [DONE]\n\n"
127
  return StreamingResponse(empty_stream(), media_type="text/event-stream")
128
 
@@ -132,47 +134,51 @@ async def chat(chat_req: ChatRequest):
132
  messages.extend(chat_req.history)
133
  messages.append({"role": "user", "content": f"Context:\n{context_text}\n\nQuestion: {chat_req.message}"})
134
 
135
- def generate_tokens():
136
- """Synchronous generator that yields SSE formatted tokens"""
137
- for model in MODELS:
138
- success = False
139
- try:
140
- client = InferenceClient(model, token=hf_token)
141
- for chunk in client.chat_completion(messages=messages, max_tokens=512, stream=True):
142
- text = chunk.choices[0].delta.content
143
- if text:
144
- yield f"data: {json.dumps({'token': text})}\n\n"
145
- success = True
146
-
147
- yield "data: [DONE]\n\n"
148
- return
149
- except Exception as e:
150
- if success:
151
- yield "data: [DONE]\n\n"
152
  return
153
- continue
154
- # All models failed
155
- yield f"data: {json.dumps({'token': 'Sorry, all models are currently unavailable. Try again later.'})}\n\n"
156
- yield "data: [DONE]\n\n"
 
 
 
 
 
 
 
 
 
 
 
157
 
158
  async def stream_wrapper():
159
- """Safe async wrapper for the generator"""
160
  try:
161
- # Use a safer way to iterate over the generator in a thread
162
- gen = generate_tokens()
163
  while True:
164
- try:
165
- chunk = await asyncio.to_thread(next, gen)
166
- yield chunk
167
- except StopIteration:
168
- break
169
- except Exception as e:
170
- yield f"data: {json.dumps({'token': 'Error occurred during streaming.'})}\n\n"
171
- yield "data: [DONE]\n\n"
172
  break
 
 
173
  except Exception:
174
- yield f"data: {json.dumps({'token': 'Unexpected error in response generation.'})}\n\n"
175
  yield "data: [DONE]\n\n"
 
 
176
 
177
  return StreamingResponse(stream_wrapper(), media_type="text/event-stream")
178
 
 
1
  from fastapi import HTTPException, FastAPI, File, UploadFile
2
  from fastapi.middleware.cors import CORSMiddleware
3
+ from asyncio import Queue, create_task
4
  from fastapi.responses import StreamingResponse
5
  from pydantic import BaseModel, Field
6
  import aiofiles
 
101
  if tmp_path and os.path.exists(tmp_path):
102
  os.unlink(tmp_path)
103
 
104
+ from asyncio import Queue, create_task
105
+
106
  @app.post("/chat")
107
  async def chat(chat_req: ChatRequest):
108
  hf_token = os.environ.get("HF_TOKEN")
 
124
 
125
  if not context_chunks:
126
  async def empty_stream():
127
+ yield f"data: {json.dumps({'token': 'I couldn't find relevant information in the document.'})}\n\n"
 
128
  yield "data: [DONE]\n\n"
129
  return StreamingResponse(empty_stream(), media_type="text/event-stream")
130
 
 
134
  messages.extend(chat_req.history)
135
  messages.append({"role": "user", "content": f"Context:\n{context_text}\n\nQuestion: {chat_req.message}"})
136
 
137
+
138
+ queue: Queue = Queue()
139
+
140
+ async def consumer():
141
+ try:
142
+ for model in MODELS:
143
+ success = False
144
+ try:
145
+ client = InferenceClient(model, token=hf_token)
146
+ for chunk in client.chat_completion(messages=messages, max_tokens=512, stream=True):
147
+ text = chunk.choices[0].delta.content
148
+ if text:
149
+ await queue.put(f"data: {json.dumps({'token': text})}\n\n")
150
+ success = True
151
+ await queue.put("data: [DONE]\n\n")
 
 
152
  return
153
+ except Exception:
154
+ if success:
155
+ await queue.put("data: [DONE]\n\n")
156
+ return
157
+ continue
158
+ await queue.put(f"data: {json.dumps({'token': 'Sorry, all models are currently unavailable.'})}\n\n")
159
+ await queue.put("data: [DONE]\n\n")
160
+ except Exception as e:
161
+ await queue.put(f"data: {json.dumps({'token': 'Error generating response.'})}\n\n")
162
+ await queue.put("data: [DONE]\n\n")
163
+ finally:
164
+ await queue.put(None)
165
+
166
+
167
+ task = create_task(consumer())
168
 
169
  async def stream_wrapper():
 
170
  try:
 
 
171
  while True:
172
+ item = await queue.get()
173
+ if item is None:
 
 
 
 
 
 
174
  break
175
+ yield item
176
+ queue.task_done()
177
  except Exception:
178
+ yield f"data: {json.dumps({'token': 'Streaming error occurred.'})}\n\n"
179
  yield "data: [DONE]\n\n"
180
+ finally:
181
+ task.cancel()
182
 
183
  return StreamingResponse(stream_wrapper(), media_type="text/event-stream")
184