Chrunos commited on
Commit
ebb5e1e
·
verified ·
1 Parent(s): b855f82

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -41
app.py CHANGED
@@ -168,65 +168,58 @@ async def direct_chat(payload: ChatPayload):
168
  raise HTTPException(status_code=500, detail="Custom API key not configured.")
169
 
170
  async def custom_api_streamer():
171
- executor = ThreadPoolExecutor(max_workers=1)
172
  client = None
173
-
174
  try:
175
  logger.info("Sending request to Custom API for /chat.")
176
 
177
- def create_stream():
178
- nonlocal client
179
- client = openai.OpenAI(
180
- api_key=custom_api_key_secret,
181
- base_url=custom_api_base_url,
182
- timeout=30.0
183
- )
184
- return client.chat.completions.create(
185
- model=custom_api_model,
186
- temperature=payload.temperature,
187
- messages=[{"role": "user", "content": payload.message}],
188
- stream=True
189
- )
190
 
191
- # Run the blocking call in a thread
192
- stream = await asyncio.get_event_loop().run_in_executor(executor, create_stream)
 
 
 
 
193
 
194
- def process_chunk():
195
  try:
196
- for chunk in stream:
197
- content_to_yield = None
198
- if hasattr(chunk.choices[0].delta, "reasoning_content") and chunk.choices[0].delta.reasoning_content:
199
- content_to_yield = chunk.choices[0].delta.reasoning_content
200
- elif chunk.choices[0].delta and chunk.choices[0].delta.content:
201
- content_to_yield = chunk.choices[0].delta.content
202
 
203
- if content_to_yield:
204
- yield content_to_yield
 
205
  except Exception as e:
206
- logger.error(f"Error processing stream chunk: {e}")
207
- yield f"Error processing stream: {str(e)}"
208
-
209
- # Process chunks in the thread pool
210
- loop = asyncio.get_event_loop()
211
- chunks = await loop.run_in_executor(executor, lambda: list(process_chunk()))
212
-
213
- for chunk in chunks:
214
- yield chunk
215
-
216
  except Exception as e:
217
  logger.error(f"Error during Custom API call for /chat: {e}", exc_info=True)
218
- yield f"Error processing with Custom API: {str(e)}"
 
 
 
 
 
 
219
  finally:
220
- # Cleanup
221
  if client:
222
  try:
223
- client.close()
224
  except Exception as cleanup_error:
225
  logger.warning(f"Error closing OpenAI client: {cleanup_error}")
226
- executor.shutdown(wait=False)
227
 
228
  return StreamingResponse(
229
- custom_api_streamer(),
230
  media_type="text/plain",
231
  headers={
232
  "Cache-Control": "no-cache",
 
168
  raise HTTPException(status_code=500, detail="Custom API key not configured.")
169
 
170
  async def custom_api_streamer():
 
171
  client = None
 
172
  try:
173
  logger.info("Sending request to Custom API for /chat.")
174
 
175
+ # Use AsyncOpenAI with proper configuration
176
+ from openai import AsyncOpenAI
177
+ client = AsyncOpenAI(
178
+ api_key=custom_api_key_secret,
179
+ base_url=custom_api_base_url,
180
+ timeout=60.0 # Longer timeout for gemma3:27b model
181
+ )
 
 
 
 
 
 
182
 
183
+ stream = await client.chat.completions.create(
184
+ model=custom_api_model,
185
+ temperature=payload.temperature,
186
+ messages=[{"role": "user", "content": payload.message}],
187
+ stream=True
188
+ )
189
 
190
+ async for chunk in stream:
191
  try:
192
+ # Exact same logic as your working code
193
+ if hasattr(chunk.choices[0].delta, "reasoning_content") and chunk.choices[0].delta.reasoning_content:
194
+ yield chunk.choices[0].delta.reasoning_content
195
+ elif chunk.choices[0].delta.content is not None: # Handle None explicitly
196
+ yield chunk.choices[0].delta.content
 
197
 
198
+ except (IndexError, AttributeError) as e:
199
+ # Skip malformed chunks silently (some APIs send empty chunks)
200
+ continue
201
  except Exception as e:
202
+ logger.warning(f"Skipping chunk due to error: {e}")
203
+ continue
204
+
 
 
 
 
 
 
 
205
  except Exception as e:
206
  logger.error(f"Error during Custom API call for /chat: {e}", exc_info=True)
207
+
208
+ # Handle specific connection errors with retry suggestion
209
+ if "peer closed connection" in str(e) or "incomplete chunked read" in str(e):
210
+ yield "Connection interrupted. Please try again."
211
+ else:
212
+ yield f"Error processing with Custom API: {str(e)}"
213
+
214
  finally:
 
215
  if client:
216
  try:
217
+ await client.close()
218
  except Exception as cleanup_error:
219
  logger.warning(f"Error closing OpenAI client: {cleanup_error}")
 
220
 
221
  return StreamingResponse(
222
+ custom_api_streamer(),
223
  media_type="text/plain",
224
  headers={
225
  "Cache-Control": "no-cache",