Space-Mutiverse-Control / patch_models.py
bep40's picture
Upload patch_models.py
adf5f36 verified
Raw
History Blame
9.51 kB
"""Patch backend: replace AVAILABLE_MODELS (remove old 6, add 18 new) + OpenRouter routing."""
import ast
import os
import re
AGENT_FILE = "/app/backend/routes/agent.py"
LLM_PARAMS_FILE = "/app/agent/core/llm_params.py"
# === Step 1: Replace _available_models() to return ONLY new models ===
with open(AGENT_FILE) as f:
content = f.read()
# Make DEFAULT_MODEL_ID point to our default
content = content.replace(
"DEFAULT_MODEL_ID = GLM_52_MODEL_ID",
'DEFAULT_MODEL_ID = "deepseek-ai/DeepSeek-V4-Pro:novita"'
)
content = content.replace(
"DEFAULT_GPT_MODEL_ID = GPT_55_MODEL_ID",
'DEFAULT_GPT_MODEL_ID = "openai/gpt-oss-120b"'
)
# Find and replace the _available_models() function using regex
func_pattern = re.compile(
r'def _available_models\(\) -> list\[dict\[str, Any\]\]:\s*\n'
r'\s+models\s*=\s*\[.*?\]\s*\n\s+return models',
re.DOTALL
)
new_func = '''def _available_models() -> list[dict[str, Any]]:
models = [
{
"id": "openai/openrouter/owl-alpha",
"label": "Owl Alpha",
"provider": "openrouter",
"tier": "free",
"recommended": True,
},
{
"id": "deepseek-ai/DeepSeek-V4-Pro:novita",
"label": "DeepSeek V4 Pro",
"provider": "huggingface",
"tier": "free",
"recommended": True,
},
{
"id": "deepseek-ai/DeepSeek-V4-Flash:novita",
"label": "DeepSeek V4 Flash",
"provider": "huggingface",
"tier": "free",
},
{
"id": "openai/gpt-oss-120b",
"label": "gpt-oss-120b",
"provider": "openrouter",
"tier": "free",
},
{
"id": "Qwen/Qwen3-Coder-Next:novita",
"label": "Qwen3 Coder Next",
"provider": "huggingface",
"tier": "free",
"recommended": True,
},
{
"id": "google/gemma-3-1b-it:novita",
"label": "Gemma 3 1B",
"provider": "huggingface",
"tier": "free",
"recommended": True,
},
{
"id": "openai/google/gemini-2.0-flash-001",
"label": "Gemini 2.0 Flash",
"provider": "openrouter",
"tier": "free",
},
{
"id": "openai/deepseek/deepseek-v4-flash",
"label": "DeepSeek V4 Flash (OR)",
"provider": "openrouter",
"tier": "paid",
},
{
"id": "openai/google/gemma-4-9b-it:free",
"label": "Gemma 4 9B",
"provider": "openrouter",
"tier": "free",
"recommended": True,
},
{
"id": "openai/google/gemma-4-31b-it:free",
"label": "Gemma 4 31B",
"provider": "openrouter",
"tier": "free",
"recommended": True,
},
{
"id": "openai/tencent/hy3-preview",
"label": "Hy3 Preview",
"provider": "openrouter",
"tier": "paid",
"recommended": True,
},
{
"id": "openai/cohere/north-mini-code:free",
"label": "north-mini-code:free",
"provider": "openrouter",
"tier": "free",
"recommended": True,
},
{
"id": "openai/nvidia/nemotron-3-super-120b-a12b:free",
"label": "Nemotron 3 Super 120B",
"provider": "openrouter",
"tier": "free",
},
{
"id": "openai/nvidia/nemotron-3-ultra-550b-a55b:free",
"label": "Nemotron 3 Ultra 550B",
"provider": "openrouter",
"tier": "free",
"recommended": True,
},
{
"id": "openai/poolside/laguna-m.1:free",
"label": "Laguna M.1",
"provider": "openrouter",
"tier": "free",
"recommended": True,
},
{
"id": "openai/poolside/laguna-xs.2:free",
"label": "Laguna XS.2",
"provider": "openrouter",
"tier": "free",
},
{
"id": "openai/qwen/qwen3.7-flash",
"label": "Qwen3.7 Flash",
"provider": "openrouter",
"tier": "free",
},
{
"id": "openai/inclusionai/ling-2.6-flash",
"label": "Ling 2.6 Flash",
"provider": "openrouter",
"tier": "free",
},
]
return models'''
func_match = func_pattern.search(content)
if func_match:
content = content[:func_match.start()] + new_func + content[func_match.end():]
print("OK: Replaced _available_models() with 18 new models via regex")
else:
print("WARN: Could not find _available_models() via regex, trying extend approach...")
target = "AVAILABLE_MODELS = _available_models()\n"
if target in content:
content = content.replace(
target,
target + "AVAILABLE_MODELS.clear()\n" +
"AVAILABLE_MODELS.extend([\n"
' {"id": "openai/openrouter/owl-alpha", "label": "Owl Alpha", "provider": "openrouter", "tier": "free", "recommended": True},\n'
' {"id": "deepseek-ai/DeepSeek-V4-Pro:novita", "label": "DeepSeek V4 Pro", "provider": "huggingface", "tier": "free", "recommended": True},\n'
' {"id": "deepseek-ai/DeepSeek-V4-Flash:novita", "label": "DeepSeek V4 Flash", "provider": "huggingface", "tier": "free"},\n'
' {"id": "openai/gpt-oss-120b", "label": "gpt-oss-120b", "provider": "openrouter", "tier": "free"},\n'
' {"id": "Qwen/Qwen3-Coder-Next:novita", "label": "Qwen3 Coder Next", "provider": "huggingface", "tier": "free", "recommended": True},\n'
' {"id": "google/gemma-3-1b-it:novita", "label": "Gemma 3 1B", "provider": "huggingface", "tier": "free", "recommended": True},\n'
' {"id": "openai/google/gemini-2.0-flash-001", "label": "Gemini 2.0 Flash", "provider": "openrouter", "tier": "free"},\n'
' {"id": "openai/deepseek/deepseek-v4-flash", "label": "DeepSeek V4 Flash (OR)", "provider": "openrouter", "tier": "paid"},\n'
' {"id": "openai/google/gemma-4-9b-it:free", "label": "Gemma 4 9B", "provider": "openrouter", "tier": "free", "recommended": True},\n'
' {"id": "openai/google/gemma-4-31b-it:free", "label": "Gemma 4 31B", "provider": "openrouter", "tier": "free", "recommended": True},\n'
' {"id": "openai/tencent/hy3-preview", "label": "Hy3 Preview", "provider": "openrouter", "tier": "paid", "recommended": True},\n'
' {"id": "openai/cohere/north-mini-code:free", "label": "north-mini-code:free", "provider": "openrouter", "tier": "free", "recommended": True},\n'
' {"id": "openai/nvidia/nemotron-3-super-120b-a12b:free", "label": "Nemotron 3 Super 120B", "provider": "openrouter", "tier": "free"},\n'
' {"id": "openai/nvidia/nemotron-3-ultra-550b-a55b:free", "label": "Nemotron 3 Ultra 550B", "provider": "openrouter", "tier": "free", "recommended": True},\n'
' {"id": "openai/poolside/laguna-m.1:free", "label": "Laguna M.1", "provider": "openrouter", "tier": "free", "recommended": True},\n'
' {"id": "openai/poolside/laguna-xs.2:free", "label": "Laguna XS.2", "provider": "openrouter", "tier": "free"},\n'
' {"id": "openai/qwen/qwen3.7-flash", "label": "Qwen3.7 Flash", "provider": "openrouter", "tier": "free"},\n'
' {"id": "openai/inclusionai/ling-2.6-flash", "label": "Ling 2.6 Flash", "provider": "openrouter", "tier": "free"},\n'
"])\n"
'DEFAULT_FREE_MODEL_ID = "openai/openrouter/owl-alpha"\n'
)
print("OK: Used extend approach")
else:
print("FAIL: Cannot patch agent.py!")
import sys
sys.exit(1)
try:
ast.parse(content)
print("OK: agent.py syntax OK")
except SyntaxError as e:
print(f"FAIL: Syntax error in agent.py: {e}")
raise
with open(AGENT_FILE, "w") as f:
f.write(content)
# === Step 2: Patch _resolve_llm_params for OpenRouter routing ===
with open(LLM_PARAMS_FILE) as f:
llm_content = f.read()
# Insert the OpenRouter routing before the params block
api_key_match = re.search(r'api_key\s*=\s*_resolve_hf_router_token\(session_hf_token\)', llm_content)
if api_key_match:
line_end = llm_content.find('\n', api_key_match.end()) + 1
if line_end > 0:
routing_insert = ''' # === PATCH: Route ALL openai/-prefixed models to OpenRouter ===
if normalized_model.startswith("openai/"):
return {
"model": normalized_model,
"api_base": "https://openrouter.ai/api/v1",
"api_key": os.environ.get("OPENROUTER_API_KEY") or api_key or "",
}
# === END PATCH ===
'''
llm_content = llm_content[:line_end] + routing_insert + llm_content[line_end:]
print("OK: Patched _resolve_llm_params (catch-all openai/ -> OR)")
else:
print("OK: Could not find end of api_key line")
else:
print("OK: api_key line not found, may already be patched")
try:
ast.parse(llm_content)
print("OK: llm_params.py syntax OK")
except SyntaxError as e:
print(f"FAIL: Syntax error in llm_params.py: {e}")
raise
with open(LLM_PARAMS_FILE, "w") as f:
f.write(llm_content)
print("OK: Backend patched - 18 models, ALL openai/ -> OR")