Spaces:
Running on Zero
Running on Zero
atakan Claude Sonnet 5 commited on
Commit ·
80cc518
1
Parent(s): f971ecf
fix: Serialize inference requests to prevent concurrent llama.cpp crashes
Browse filesllama_cpp's Llama object isn't safe for concurrent generation calls --
two simultaneous requests hitting the same model instance corrupted
its state and crashed the worker (observed live: two overlapping chat
requests both failed with a stream INTERNAL_ERROR and the container
restarted). A single lock now serializes every request through the
shared model instance; concurrent users queue instead of crashing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
app.py
CHANGED
|
@@ -6,6 +6,7 @@ import json
|
|
| 6 |
import os
|
| 7 |
import shutil
|
| 8 |
import sys
|
|
|
|
| 9 |
import time
|
| 10 |
from contextlib import asynccontextmanager
|
| 11 |
from pathlib import Path
|
|
@@ -65,6 +66,9 @@ if STATIC_DIR.exists():
|
|
| 65 |
|
| 66 |
# Initialize Agent
|
| 67 |
agent_instance: ControlAIAgent | None = None
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
|
| 70 |
def get_agent() -> ControlAIAgent:
|
|
@@ -181,8 +185,9 @@ async def chat_stream_endpoint(req: ChatRequest):
|
|
| 181 |
|
| 182 |
def event_generator():
|
| 183 |
try:
|
| 184 |
-
|
| 185 |
-
|
|
|
|
| 186 |
except Exception as exc:
|
| 187 |
yield f"data: {json.dumps({'type': 'error', 'error': str(exc)}, ensure_ascii=False)}\n\n"
|
| 188 |
|
|
@@ -205,7 +210,8 @@ async def chat_endpoint(req: ChatRequest) -> ChatResponse:
|
|
| 205 |
t0 = time.time()
|
| 206 |
try:
|
| 207 |
agent = get_agent()
|
| 208 |
-
|
|
|
|
| 209 |
elapsed = time.time() - t0
|
| 210 |
|
| 211 |
# Collect tool traces
|
|
|
|
| 6 |
import os
|
| 7 |
import shutil
|
| 8 |
import sys
|
| 9 |
+
import threading
|
| 10 |
import time
|
| 11 |
from contextlib import asynccontextmanager
|
| 12 |
from pathlib import Path
|
|
|
|
| 66 |
|
| 67 |
# Initialize Agent
|
| 68 |
agent_instance: ControlAIAgent | None = None
|
| 69 |
+
# llama.cpp's Llama object is not safe for concurrent generation calls from
|
| 70 |
+
# multiple threads; serialize every request through the single model instance.
|
| 71 |
+
inference_lock = threading.Lock()
|
| 72 |
|
| 73 |
|
| 74 |
def get_agent() -> ControlAIAgent:
|
|
|
|
| 185 |
|
| 186 |
def event_generator():
|
| 187 |
try:
|
| 188 |
+
with inference_lock:
|
| 189 |
+
for event in agent.run_stream(req.message.strip(), history=req.history):
|
| 190 |
+
yield f"data: {json.dumps(event, ensure_ascii=False)}\n\n"
|
| 191 |
except Exception as exc:
|
| 192 |
yield f"data: {json.dumps({'type': 'error', 'error': str(exc)}, ensure_ascii=False)}\n\n"
|
| 193 |
|
|
|
|
| 210 |
t0 = time.time()
|
| 211 |
try:
|
| 212 |
agent = get_agent()
|
| 213 |
+
with inference_lock:
|
| 214 |
+
result = agent.run(req.message.strip(), history=req.history, verbose=False)
|
| 215 |
elapsed = time.time() - t0
|
| 216 |
|
| 217 |
# Collect tool traces
|