Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
"""
|
| 2 |
Sixfinger Backend API - FRONTEND UYUMLU VERSİYON
|
| 3 |
Ultra-fast AI Chat Backend with Multi-Model Support
|
| 4 |
-
Supports: Groq, LLM7.io
|
| 5 |
"""
|
| 6 |
|
| 7 |
import os
|
|
@@ -21,6 +21,9 @@ from openai import OpenAI
|
|
| 21 |
# ========== CONFIGURATION ==========
|
| 22 |
API_VERSION = "1.1.0"
|
| 23 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY", "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")
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
# ========== API PROVIDERS ==========
|
| 26 |
PROVIDERS = {
|
|
@@ -35,6 +38,13 @@ PROVIDERS = {
|
|
| 35 |
"base_url": "https://api.llm7.io/v1",
|
| 36 |
"api_key": "unused",
|
| 37 |
"requires_key": False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
}
|
| 39 |
}
|
| 40 |
|
|
@@ -65,6 +75,28 @@ MODELS = {
|
|
| 65 |
"plans": ["free", "starter", "pro", "plus"],
|
| 66 |
"daily_limit": 300
|
| 67 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
# ============ STARTER PLAN MODELS ============
|
| 70 |
|
|
@@ -137,6 +169,39 @@ MODELS = {
|
|
| 137 |
"plans": ["starter", "pro", "plus"],
|
| 138 |
"daily_limit": 1000
|
| 139 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 140 |
|
| 141 |
# ============ PRO PLAN MODELS ============
|
| 142 |
|
|
@@ -172,6 +237,14 @@ DEFAULT_MODELS = {
|
|
| 172 |
"plus": "gpt-oss-120b"
|
| 173 |
}
|
| 174 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
# ========== LOGGING ==========
|
| 176 |
logging.basicConfig(
|
| 177 |
level=logging.INFO,
|
|
@@ -208,6 +281,12 @@ llm7_client = OpenAI(
|
|
| 208 |
api_key=PROVIDERS["llm7"]["api_key"]
|
| 209 |
)
|
| 210 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
# ========== PYDANTIC MODELS ==========
|
| 212 |
class ChatRequest(BaseModel):
|
| 213 |
prompt: str = Field(..., description="User's message")
|
|
@@ -258,9 +337,17 @@ def build_messages(prompt: str, system_prompt: Optional[str], history: Optional[
|
|
| 258 |
messages.append(msg)
|
| 259 |
|
| 260 |
messages.append({"role": "user", "content": prompt})
|
| 261 |
-
|
| 262 |
return messages
|
| 263 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
# ========== PROVIDER-SPECIFIC API CALLS ==========
|
| 265 |
|
| 266 |
def call_groq_api(
|
|
@@ -312,6 +399,36 @@ def call_llm7_api(
|
|
| 312 |
logger.error(f"LLM7 API error: {e}")
|
| 313 |
raise HTTPException(status_code=500, detail=f"LLM7 API error: {str(e)}")
|
| 314 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
def call_api(
|
| 316 |
provider: str,
|
| 317 |
model_id: str,
|
|
@@ -326,6 +443,8 @@ def call_api(
|
|
| 326 |
return call_groq_api(model_id, messages, max_tokens, temperature, top_p, stream)
|
| 327 |
elif provider == "llm7":
|
| 328 |
return call_llm7_api(model_id, messages, max_tokens, temperature, top_p, stream)
|
|
|
|
|
|
|
| 329 |
else:
|
| 330 |
raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")
|
| 331 |
|
|
@@ -340,7 +459,8 @@ def health_check():
|
|
| 340 |
"timestamp": datetime.now().isoformat(),
|
| 341 |
"providers": {
|
| 342 |
"groq": bool(GROQ_API_KEY),
|
| 343 |
-
"llm7": True
|
|
|
|
| 344 |
}
|
| 345 |
}
|
| 346 |
|
|
@@ -371,48 +491,62 @@ def chat(
|
|
| 371 |
request.history
|
| 372 |
)
|
| 373 |
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
provider=provider,
|
| 377 |
-
model_id=model_id,
|
| 378 |
-
messages=messages,
|
| 379 |
-
max_tokens=request.max_tokens,
|
| 380 |
-
temperature=request.temperature,
|
| 381 |
-
top_p=request.top_p,
|
| 382 |
-
stream=False
|
| 383 |
-
)
|
| 384 |
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
"
|
| 407 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 408 |
}
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
|
|
|
|
|
|
| 416 |
|
| 417 |
@app.post("/api/chat/stream")
|
| 418 |
def chat_stream(
|
|
@@ -499,12 +633,42 @@ def chat_stream(
|
|
| 499 |
except Exception as e:
|
| 500 |
logger.error(f"LLM7 stream error: {e}")
|
| 501 |
yield f"data: {json.dumps({'error': str(e)})}\n\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 502 |
|
| 503 |
# Provider'a göre generator seç
|
| 504 |
if provider == "groq":
|
| 505 |
generator = generate_groq()
|
| 506 |
elif provider == "llm7":
|
| 507 |
generator = generate_llm7()
|
|
|
|
|
|
|
| 508 |
else:
|
| 509 |
raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")
|
| 510 |
|
|
|
|
| 1 |
"""
|
| 2 |
Sixfinger Backend API - FRONTEND UYUMLU VERSİYON
|
| 3 |
Ultra-fast AI Chat Backend with Multi-Model Support
|
| 4 |
+
Supports: Groq, LLM7.io, OpenRouter
|
| 5 |
"""
|
| 6 |
|
| 7 |
import os
|
|
|
|
| 21 |
# ========== CONFIGURATION ==========
|
| 22 |
API_VERSION = "1.1.0"
|
| 23 |
GROQ_API_KEY = os.getenv("GROQ_API_KEY", "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")
|
| 24 |
+
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY") or os.getenv("openrouter_api_key")
|
| 25 |
+
OPENROUTER_SITE_URL = os.getenv("OPENROUTER_SITE_URL", "https://sfapi.pythonanywhere.com")
|
| 26 |
+
OPENROUTER_SITE_NAME = os.getenv("OPENROUTER_SITE_NAME", "Sixfinger Backend")
|
| 27 |
|
| 28 |
# ========== API PROVIDERS ==========
|
| 29 |
PROVIDERS = {
|
|
|
|
| 38 |
"base_url": "https://api.llm7.io/v1",
|
| 39 |
"api_key": "unused",
|
| 40 |
"requires_key": False
|
| 41 |
+
},
|
| 42 |
+
"openrouter": {
|
| 43 |
+
"name": "OpenRouter",
|
| 44 |
+
"type": "openai_compatible",
|
| 45 |
+
"base_url": "https://openrouter.ai/api/v1",
|
| 46 |
+
"api_key": OPENROUTER_API_KEY,
|
| 47 |
+
"requires_key": True
|
| 48 |
}
|
| 49 |
}
|
| 50 |
|
|
|
|
| 75 |
"plans": ["free", "starter", "pro", "plus"],
|
| 76 |
"daily_limit": 300
|
| 77 |
},
|
| 78 |
+
"stepfun/step-3.5-flash:free": {
|
| 79 |
+
"provider": "openrouter",
|
| 80 |
+
"model_id": "stepfun/step-3.5-flash:free",
|
| 81 |
+
"display_name": "Step 3.5 Flash (Free)",
|
| 82 |
+
"size": "Unknown",
|
| 83 |
+
"language": "Multilingual",
|
| 84 |
+
"speed": "⚡⚡⚡",
|
| 85 |
+
"description": "OpenRouter uzerinden hizli StepFun modeli",
|
| 86 |
+
"plans": ["free", "starter", "pro", "plus"],
|
| 87 |
+
"daily_limit": 1000
|
| 88 |
+
},
|
| 89 |
+
"nvidia/nemotron-3-super-120b-a12b:free": {
|
| 90 |
+
"provider": "openrouter",
|
| 91 |
+
"model_id": "nvidia/nemotron-3-super-120b-a12b:free",
|
| 92 |
+
"display_name": "Nemotron 3 Super 120B A12B (Free)",
|
| 93 |
+
"size": "120B",
|
| 94 |
+
"language": "Multilingual",
|
| 95 |
+
"speed": "⚡⚡",
|
| 96 |
+
"description": "OpenRouter uzerinden NVIDIA Nemotron modeli",
|
| 97 |
+
"plans": ["free", "starter", "pro", "plus"],
|
| 98 |
+
"daily_limit": 1000
|
| 99 |
+
},
|
| 100 |
|
| 101 |
# ============ STARTER PLAN MODELS ============
|
| 102 |
|
|
|
|
| 169 |
"plans": ["starter", "pro", "plus"],
|
| 170 |
"daily_limit": 1000
|
| 171 |
},
|
| 172 |
+
"z-ai/glm-4.5-air:free": {
|
| 173 |
+
"provider": "openrouter",
|
| 174 |
+
"model_id": "z-ai/glm-4.5-air:free",
|
| 175 |
+
"display_name": "GLM 4.5 Air (Free)",
|
| 176 |
+
"size": "Unknown",
|
| 177 |
+
"language": "Multilingual",
|
| 178 |
+
"speed": "⚡⚡",
|
| 179 |
+
"description": "OpenRouter uzerinden GLM 4.5 Air modeli",
|
| 180 |
+
"plans": ["starter", "pro", "plus"],
|
| 181 |
+
"daily_limit": 1000
|
| 182 |
+
},
|
| 183 |
+
"qwen/qwen3-coder:free": {
|
| 184 |
+
"provider": "openrouter",
|
| 185 |
+
"model_id": "qwen/qwen3-coder:free",
|
| 186 |
+
"display_name": "Qwen3 Coder (Free)",
|
| 187 |
+
"size": "Unknown",
|
| 188 |
+
"language": "Multilingual",
|
| 189 |
+
"speed": "⚡⚡",
|
| 190 |
+
"description": "OpenRouter uzerinden kod odakli Qwen modeli",
|
| 191 |
+
"plans": ["starter", "pro", "plus"],
|
| 192 |
+
"daily_limit": 1000
|
| 193 |
+
},
|
| 194 |
+
"liquid/lfm-2.5-1.2b-thinking:free": {
|
| 195 |
+
"provider": "openrouter",
|
| 196 |
+
"model_id": "liquid/lfm-2.5-1.2b-thinking:free",
|
| 197 |
+
"display_name": "LFM 2.5 1.2B Thinking (Free)",
|
| 198 |
+
"size": "1.2B",
|
| 199 |
+
"language": "Multilingual",
|
| 200 |
+
"speed": "⚡⚡⚡",
|
| 201 |
+
"description": "OpenRouter uzerinden hizli dusunme odakli model",
|
| 202 |
+
"plans": ["starter", "pro", "plus"],
|
| 203 |
+
"daily_limit": 1000
|
| 204 |
+
},
|
| 205 |
|
| 206 |
# ============ PRO PLAN MODELS ============
|
| 207 |
|
|
|
|
| 237 |
"plus": "gpt-oss-120b"
|
| 238 |
}
|
| 239 |
|
| 240 |
+
# Primary provider başarısız olursa kullanılacak fallback modeli
|
| 241 |
+
# Key: birincil provider adı, Value: fallback olarak denenecek model key'i
|
| 242 |
+
PROVIDER_FALLBACK = {
|
| 243 |
+
"groq": "gpt4-nano", # Groq hata verirse → LLM7 üzerinden gpt4-nano
|
| 244 |
+
"llm7": "llama-8b-instant", # LLM7 hata verirse → Groq üzerinden llama-8b-instant
|
| 245 |
+
"openrouter": "llama-8b-instant"
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
# ========== LOGGING ==========
|
| 249 |
logging.basicConfig(
|
| 250 |
level=logging.INFO,
|
|
|
|
| 281 |
api_key=PROVIDERS["llm7"]["api_key"]
|
| 282 |
)
|
| 283 |
|
| 284 |
+
# OpenRouter Client
|
| 285 |
+
openrouter_client = OpenAI(
|
| 286 |
+
base_url=PROVIDERS["openrouter"]["base_url"],
|
| 287 |
+
api_key=PROVIDERS["openrouter"]["api_key"]
|
| 288 |
+
) if OPENROUTER_API_KEY else None
|
| 289 |
+
|
| 290 |
# ========== PYDANTIC MODELS ==========
|
| 291 |
class ChatRequest(BaseModel):
|
| 292 |
prompt: str = Field(..., description="User's message")
|
|
|
|
| 337 |
messages.append(msg)
|
| 338 |
|
| 339 |
messages.append({"role": "user", "content": prompt})
|
| 340 |
+
|
| 341 |
return messages
|
| 342 |
|
| 343 |
+
def _chat_candidates(primary_key: str, primary_config: dict):
|
| 344 |
+
"""Primary provider'ı dene, başarısız olursa fallback'i yield et."""
|
| 345 |
+
yield primary_key, primary_config, False
|
| 346 |
+
|
| 347 |
+
fallback_key = PROVIDER_FALLBACK.get(primary_config["provider"])
|
| 348 |
+
if fallback_key and fallback_key != primary_key and fallback_key in MODELS:
|
| 349 |
+
yield fallback_key, MODELS[fallback_key], True
|
| 350 |
+
|
| 351 |
# ========== PROVIDER-SPECIFIC API CALLS ==========
|
| 352 |
|
| 353 |
def call_groq_api(
|
|
|
|
| 399 |
logger.error(f"LLM7 API error: {e}")
|
| 400 |
raise HTTPException(status_code=500, detail=f"LLM7 API error: {str(e)}")
|
| 401 |
|
| 402 |
+
def call_openrouter_api(
|
| 403 |
+
model_id: str,
|
| 404 |
+
messages: list,
|
| 405 |
+
max_tokens: int,
|
| 406 |
+
temperature: float,
|
| 407 |
+
top_p: float,
|
| 408 |
+
stream: bool = False
|
| 409 |
+
):
|
| 410 |
+
"""OpenRouter API'ye istek at"""
|
| 411 |
+
if not openrouter_client:
|
| 412 |
+
raise HTTPException(status_code=500, detail="OpenRouter API key not configured")
|
| 413 |
+
|
| 414 |
+
try:
|
| 415 |
+
response = openrouter_client.chat.completions.create(
|
| 416 |
+
model=model_id,
|
| 417 |
+
messages=messages,
|
| 418 |
+
max_tokens=max_tokens,
|
| 419 |
+
temperature=temperature,
|
| 420 |
+
top_p=top_p,
|
| 421 |
+
stream=stream,
|
| 422 |
+
extra_headers={
|
| 423 |
+
"HTTP-Referer": OPENROUTER_SITE_URL,
|
| 424 |
+
"X-OpenRouter-Title": OPENROUTER_SITE_NAME
|
| 425 |
+
}
|
| 426 |
+
)
|
| 427 |
+
return response
|
| 428 |
+
except Exception as e:
|
| 429 |
+
logger.error(f"OpenRouter API error: {e}")
|
| 430 |
+
raise HTTPException(status_code=500, detail=f"OpenRouter API error: {str(e)}")
|
| 431 |
+
|
| 432 |
def call_api(
|
| 433 |
provider: str,
|
| 434 |
model_id: str,
|
|
|
|
| 443 |
return call_groq_api(model_id, messages, max_tokens, temperature, top_p, stream)
|
| 444 |
elif provider == "llm7":
|
| 445 |
return call_llm7_api(model_id, messages, max_tokens, temperature, top_p, stream)
|
| 446 |
+
elif provider == "openrouter":
|
| 447 |
+
return call_openrouter_api(model_id, messages, max_tokens, temperature, top_p, stream)
|
| 448 |
else:
|
| 449 |
raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")
|
| 450 |
|
|
|
|
| 459 |
"timestamp": datetime.now().isoformat(),
|
| 460 |
"providers": {
|
| 461 |
"groq": bool(GROQ_API_KEY),
|
| 462 |
+
"llm7": True,
|
| 463 |
+
"openrouter": bool(OPENROUTER_API_KEY)
|
| 464 |
}
|
| 465 |
}
|
| 466 |
|
|
|
|
| 491 |
request.history
|
| 492 |
)
|
| 493 |
|
| 494 |
+
attempts = 0
|
| 495 |
+
last_error = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 496 |
|
| 497 |
+
for attempt_model_key, attempt_model_config, is_fallback in _chat_candidates(model_key, model_config):
|
| 498 |
+
attempts += 1
|
| 499 |
+
attempt_provider = attempt_model_config["provider"]
|
| 500 |
+
attempt_model_id = attempt_model_config["model_id"]
|
| 501 |
+
|
| 502 |
+
if is_fallback:
|
| 503 |
+
logger.warning(f"Primary provider failed, retrying with fallback: {attempt_model_key} via {attempt_provider}")
|
| 504 |
+
|
| 505 |
+
try:
|
| 506 |
+
response = call_api(
|
| 507 |
+
provider=attempt_provider,
|
| 508 |
+
model_id=attempt_model_id,
|
| 509 |
+
messages=messages,
|
| 510 |
+
max_tokens=request.max_tokens,
|
| 511 |
+
temperature=request.temperature,
|
| 512 |
+
top_p=request.top_p,
|
| 513 |
+
stream=False
|
| 514 |
+
)
|
| 515 |
+
|
| 516 |
+
content = response.choices[0].message.content
|
| 517 |
+
usage = {
|
| 518 |
+
"prompt_tokens": getattr(response.usage, 'prompt_tokens', 0),
|
| 519 |
+
"completion_tokens": getattr(response.usage, 'completion_tokens', 0),
|
| 520 |
+
"total_tokens": getattr(response.usage, 'total_tokens', 0)
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
elapsed = time.time() - start_time
|
| 524 |
+
logger.info(f"Chat completed: provider={attempt_provider}, model={attempt_model_key}, tokens={usage['total_tokens']}, time={elapsed:.2f}s, attempts={attempts}")
|
| 525 |
+
|
| 526 |
+
return {
|
| 527 |
+
"response": content,
|
| 528 |
+
"model": attempt_model_id,
|
| 529 |
+
"model_key": attempt_model_key,
|
| 530 |
+
"model_size": attempt_model_config["size"],
|
| 531 |
+
"model_language": attempt_model_config["language"],
|
| 532 |
+
"fallback_used": is_fallback,
|
| 533 |
+
"attempts": attempts,
|
| 534 |
+
"usage": usage,
|
| 535 |
+
"parameters": {
|
| 536 |
+
"max_tokens": request.max_tokens,
|
| 537 |
+
"temperature": request.temperature,
|
| 538 |
+
"top_p": request.top_p
|
| 539 |
+
}
|
| 540 |
}
|
| 541 |
+
|
| 542 |
+
except HTTPException as e:
|
| 543 |
+
last_error = e
|
| 544 |
+
logger.error(f"Provider {attempt_provider} failed (attempt {attempts}): {e.detail}")
|
| 545 |
+
except Exception as e:
|
| 546 |
+
last_error = HTTPException(status_code=500, detail=str(e))
|
| 547 |
+
logger.error(f"Provider {attempt_provider} error (attempt {attempts}): {e}")
|
| 548 |
+
|
| 549 |
+
raise last_error or HTTPException(status_code=500, detail="All providers failed")
|
| 550 |
|
| 551 |
@app.post("/api/chat/stream")
|
| 552 |
def chat_stream(
|
|
|
|
| 633 |
except Exception as e:
|
| 634 |
logger.error(f"LLM7 stream error: {e}")
|
| 635 |
yield f"data: {json.dumps({'error': str(e)})}\n\n"
|
| 636 |
+
|
| 637 |
+
def generate_openrouter():
|
| 638 |
+
"""OpenRouter streaming generator"""
|
| 639 |
+
try:
|
| 640 |
+
yield f"data: {json.dumps({'info': f'Using {model_key} via OpenRouter'})}\n\n"
|
| 641 |
+
|
| 642 |
+
stream = call_openrouter_api(
|
| 643 |
+
model_id=model_id,
|
| 644 |
+
messages=messages,
|
| 645 |
+
max_tokens=request.max_tokens,
|
| 646 |
+
temperature=request.temperature,
|
| 647 |
+
top_p=request.top_p,
|
| 648 |
+
stream=True
|
| 649 |
+
)
|
| 650 |
+
|
| 651 |
+
total_completion_tokens = 0
|
| 652 |
+
|
| 653 |
+
for chunk in stream:
|
| 654 |
+
if chunk.choices and chunk.choices[0].delta and chunk.choices[0].delta.content:
|
| 655 |
+
text = chunk.choices[0].delta.content
|
| 656 |
+
yield f"data: {json.dumps({'text': text})}\n\n"
|
| 657 |
+
total_completion_tokens += 1
|
| 658 |
+
|
| 659 |
+
yield f"data: {json.dumps({'done': True, 'model_key': model_key, 'provider': 'openrouter', 'attempts': 1, 'usage': {'prompt_tokens': 0, 'completion_tokens': total_completion_tokens, 'total_tokens': total_completion_tokens}})}\n\n"
|
| 660 |
+
|
| 661 |
+
except Exception as e:
|
| 662 |
+
logger.error(f"OpenRouter stream error: {e}")
|
| 663 |
+
yield f"data: {json.dumps({'error': str(e)})}\n\n"
|
| 664 |
|
| 665 |
# Provider'a göre generator seç
|
| 666 |
if provider == "groq":
|
| 667 |
generator = generate_groq()
|
| 668 |
elif provider == "llm7":
|
| 669 |
generator = generate_llm7()
|
| 670 |
+
elif provider == "openrouter":
|
| 671 |
+
generator = generate_openrouter()
|
| 672 |
else:
|
| 673 |
raise HTTPException(status_code=400, detail=f"Unknown provider: {provider}")
|
| 674 |
|