moonlantern1 commited on
Commit
fc5961e
·
verified ·
1 Parent(s): 5cd4a32

Add OpenRouter backup key failover

Browse files
Files changed (1) hide show
  1. src/humeo/layout_vision.py +47 -30
src/humeo/layout_vision.py CHANGED
@@ -35,11 +35,11 @@ from humeo.env import (
35
  OPENROUTER_BASE_URL,
36
  current_llm_provider,
37
  model_name_for_provider,
38
- openrouter_default_headers,
39
- resolve_gemini_api_key,
40
- resolve_llm_provider,
41
- resolve_openrouter_api_key,
42
- )
43
  from humeo.gemini_generate import gemini_generate_config
44
 
45
  logger = logging.getLogger(__name__)
@@ -1337,31 +1337,48 @@ def _call_vision_json(keyframe_path: str, model_name: str, prompt: str) -> dict[
1337
  raise RuntimeError("Gemini vision returned empty response")
1338
  return _json_object_from_vision_response(response.text)
1339
 
1340
- client = OpenAI(
1341
- api_key=resolve_openrouter_api_key(),
1342
- base_url=OPENROUTER_BASE_URL,
1343
- default_headers=openrouter_default_headers(),
1344
- )
1345
- data_url = f"data:{mime};base64,{base64.b64encode(data).decode('ascii')}"
1346
- response = client.chat.completions.create(
1347
- model=resolved_model,
1348
- messages=[
1349
- {"role": "system", "content": prompt},
1350
- {
1351
- "role": "user",
1352
- "content": [
1353
- {"type": "text", "text": "Analyze this keyframe and return only JSON."},
1354
- {"type": "image_url", "image_url": {"url": data_url}},
1355
- ],
1356
- },
1357
- ],
1358
- temperature=0.2,
1359
- response_format={"type": "json_object"},
1360
- )
1361
- text = _openai_message_text(response.choices[0].message.content)
1362
- if not text:
1363
- raise RuntimeError("OpenRouter vision returned empty response")
1364
- return _json_object_from_vision_response(text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1365
 
1366
 
1367
  def _call_gemini_vision(keyframe_path: str, model_name: str) -> dict[str, Any]:
 
35
  OPENROUTER_BASE_URL,
36
  current_llm_provider,
37
  model_name_for_provider,
38
+ openrouter_default_headers,
39
+ resolve_gemini_api_key,
40
+ resolve_llm_provider,
41
+ resolve_openrouter_api_keys,
42
+ )
43
  from humeo.gemini_generate import gemini_generate_config
44
 
45
  logger = logging.getLogger(__name__)
 
1337
  raise RuntimeError("Gemini vision returned empty response")
1338
  return _json_object_from_vision_response(response.text)
1339
 
1340
+ data_url = f"data:{mime};base64,{base64.b64encode(data).decode('ascii')}"
1341
+ keys = resolve_openrouter_api_keys()
1342
+ last_error: Exception | None = None
1343
+ for key_idx, api_key in enumerate(keys, start=1):
1344
+ try:
1345
+ client = OpenAI(
1346
+ api_key=api_key,
1347
+ base_url=OPENROUTER_BASE_URL,
1348
+ default_headers=openrouter_default_headers(),
1349
+ )
1350
+ response = client.chat.completions.create(
1351
+ model=resolved_model,
1352
+ messages=[
1353
+ {"role": "system", "content": prompt},
1354
+ {
1355
+ "role": "user",
1356
+ "content": [
1357
+ {"type": "text", "text": "Analyze this keyframe and return only JSON."},
1358
+ {"type": "image_url", "image_url": {"url": data_url}},
1359
+ ],
1360
+ },
1361
+ ],
1362
+ temperature=0.2,
1363
+ response_format={"type": "json_object"},
1364
+ )
1365
+ text = _openai_message_text(response.choices[0].message.content)
1366
+ if not text:
1367
+ raise RuntimeError("OpenRouter vision returned empty response")
1368
+ if key_idx > 1:
1369
+ logger.info("OpenRouter vision succeeded with fallback key %d/%d", key_idx, len(keys))
1370
+ return _json_object_from_vision_response(text)
1371
+ except Exception as exc:
1372
+ last_error = exc
1373
+ if key_idx < len(keys):
1374
+ logger.warning(
1375
+ "OpenRouter vision failed with key %d/%d: %s; trying fallback",
1376
+ key_idx,
1377
+ len(keys),
1378
+ exc,
1379
+ )
1380
+ assert last_error is not None
1381
+ raise last_error
1382
 
1383
 
1384
  def _call_gemini_vision(keyframe_path: str, model_name: str) -> dict[str, Any]: