Upload patch_models.py

#13
by bep40 - opened
Files changed (1) hide show
  1. patch_models.py +51 -71
patch_models.py CHANGED
@@ -1,4 +1,4 @@
1
- """Patch backend: replace AVAILABLE_MODELS with OpenRouter models + routing."""
2
 
3
  import ast
4
  import os
@@ -6,61 +6,36 @@ import re
6
 
7
  AGENT_FILE = "/app/backend/routes/agent.py"
8
  LLM_PARAMS_FILE = "/app/agent/core/llm_params.py"
9
-
10
- # === Step 1: Patch model_ids.py ===
11
  IDS_FILE = "/app/agent/core/model_ids.py"
 
12
  with open(IDS_FILE) as f:
13
  content = f.read()
14
 
15
- # --- Remove any previous NO_TOOLS_MODELS addition first (clean slate) ---
16
  if "NO_TOOLS_MODELS" in content:
17
  content = re.sub(r'NO_TOOLS_MODELS\s*=\s*\{[^}]*\}\n?', '', content)
18
  print("OK: Removed old NO_TOOLS_MODELS")
19
 
20
- # Swap out old model definitions for new ones
21
  content = content.replace(
22
  'KIMI_K27_CODE_MODEL_ID = "moonshotai/Kimi-K2.7-Code:novita"',
23
- 'KIMI_K27_CODE_MODEL_ID = "deepseek-ai/DeepSeek-V4-Pro"',
24
  )
25
  content = content.replace(
26
  'MINIMAX_M3_MODEL_ID = "MiniMaxAI/MiniMax-M3:novita"',
27
- 'MINIMAX_M3_MODEL_ID = "deepseek-ai/DeepSeek-V4-Flash"',
28
  )
29
  content = content.replace(
30
  'GLM_52_MODEL_ID = "zai-org/GLM-5.2:novita"',
31
- 'GLM_52_MODEL_ID = "openai/deepseek/deepseek-v4-flash"',
32
  )
33
  content = content.replace(
34
  'DEEPSEEK_V4_PRO_MODEL_ID = "deepseek-ai/DeepSeek-V4-Pro:novita"',
35
- 'DEEPSEEK_V4_PRO_MODEL_ID = "nvidia/nemotron-3-super-120b-a12b:free"',
36
- )
37
-
38
- # Replace all existing deepseek model IDs with 0731 version
39
- content = content.replace(
40
- '~deepseek/deepseek-v4-flash-latest',
41
- '~deepseek/deepseek-v4-flash-0731'
42
- )
43
- content = content.replace(
44
- 'deepseek/deepseek-v4-flash-latest',
45
- '~deepseek/deepseek-v4-flash-0731'
46
- )
47
- content = content.replace(
48
- 'deepseek/deepseek-v4-flash',
49
- 'deepseek/deepseek-v4-flash' # keep as-is
50
  )
51
 
52
- # Add missing model ID constants if not present
53
- if "GEMMA_4_31B_FREE_MODEL_ID" not in content:
54
- # Find where model constants end (after DEEPSEEK_V4_PRO_MODEL_ID)
55
- pos = content.find('DEEPSEEK_V4_PRO_MODEL_ID')
56
- if pos >= 0:
57
- # Find the next line break after this constant definition
58
- next_newline = content.find('\n', pos)
59
- if next_newline >= 0:
60
- before = content[:next_newline + 1]
61
- after = content[next_newline + 1:]
62
- new_constants = '''
63
- TENCENT_HY3_FREE_MODEL_ID = "openai/tencent/hy3:free"
64
  GEMMA_4_31B_FREE_MODEL_ID = "openai/google/gemma-4-31b-it:free"
65
  LLAMA_3_3_70B_FREE_MODEL_ID = "openai/meta-llama/llama-3.3-70b-instruct:free"
66
  LLAMA_3_1_8B_MODEL_ID = "openai/meta-llama/llama-3.1-8b-instruct"
@@ -69,21 +44,20 @@ LAGUNA_S21_FREE_MODEL_ID = "openai/poolside/laguna-s-2.1:free"
69
  NEX_N2_MINI_MODEL_ID = "openai/nex-agi/nex-n2-mini"
70
  LING_3_0_FLASH_FREE_MODEL_ID = "openai/inclusionai/ling-3.0-flash:free"
71
  '''
72
- content = before + new_constants + after
 
 
 
 
 
73
 
74
  with open(IDS_FILE, "w") as f:
75
  f.write(content)
76
  print("OK: model_ids.py patched")
77
 
78
- # Validate syntax
79
- try:
80
- ast.parse(content)
81
- print("OK: model_ids.py syntax OK")
82
- except SyntaxError as e:
83
- print(f"FAIL: model_ids.py syntax error: {e}")
84
- raise
85
 
86
- # === Step 2: Patch agent.py ===
87
  with open(AGENT_FILE) as f:
88
  content = f.read()
89
 
@@ -96,7 +70,7 @@ content = content.replace(
96
  "DEFAULT_GPT_MODEL_ID = LAGUNA_S21_FREE_MODEL_ID"
97
  )
98
 
99
- # Replace import block
100
  old_import = (
101
  "from agent.core.model_ids import (\n"
102
  " CLAUDE_OPUS_48_MODEL_ID,\n"
@@ -128,25 +102,24 @@ new_import = (
128
  )
129
  content = content.replace(old_import, new_import)
130
 
131
- # Replace _available_models function
132
- new_func = (
133
- "def _available_models() -> list[dict[str, Any]]:\n"
134
- " models = [\n"
135
- ' {"id": TENCENT_HY3_FREE_MODEL_ID, "label": "Tencent HY3:free", "recommended": True},\n'
136
- ' {"id": GEMMA_4_31B_FREE_MODEL_ID, "label": "Gemma 4 31B:free", "recommended": True},\n'
137
- ' {"id": LLAMA_3_3_70B_FREE_MODEL_ID, "label": "Llama 3.3 70B:free", "recommended": True},\n'
138
- ' {"id": LAGUNA_M1_FREE_MODEL_ID, "label": "Laguna M.1:free", "recommended": True},\n'
139
- ' {"id": DEFAULT_GPT_MODEL_ID, "label": "Laguna S 2.1:free", "recommended": True},\n'
140
- ' {"id": NEX_N2_MINI_MODEL_ID, "label": "nex-agi/nex-n2-mini", "recommended": True},\n'
141
- ' {"id": LING_3_0_FLASH_FREE_MODEL_ID, "label": "inclusionai/ling-3.0-flash:free", "recommended": True},\n'
142
- ' {"id": LLAMA_3_1_8B_MODEL_ID, "label": "Llama 3.1 8B"},\n'
143
- ' {"id": KIMI_K27_CODE_MODEL_ID, "label": "DeepSeek V4 Pro"},\n'
144
- ' {"id": MINIMAX_M3_MODEL_ID, "label": "DeepSeek V4 Flash"},\n'
145
- ' {"id": DEFAULT_MODEL_ID, "label": "DeepSeek V4 Flash"},\n'
146
- ' {"id": DEEPSEEK_V4_PRO_MODEL_ID, "label": "Nemotron 3 Super 120B"},\n'
147
- " ]\n"
148
- " return models"
149
- )
150
 
151
  func_match = re.search(
152
  r"def _available_models\(\)\s*->\s*list\[dict\[str,\s*Any\]\]:.*?return models",
@@ -154,7 +127,7 @@ func_match = re.search(
154
  )
155
  if func_match:
156
  content = content[:func_match.start()] + new_func + content[func_match.end():]
157
- print("OK: Replaced _available_models()")
158
  else:
159
  old_func = (
160
  "def _available_models() -> list[dict[str, Any]]:\n"
@@ -172,15 +145,16 @@ else:
172
  content = content.replace(old_func, new_func)
173
  print("OK: String replace of _available_models()")
174
  else:
175
- print("WARN: Cannot find _available_models(), skipping")
 
 
 
176
 
177
- # Update title gen model
178
  content = content.replace(
179
  '"openai/gpt-oss-120b:cerebras",',
180
  '"huggingface/deepseek-ai/DeepSeek-V4-Pro",'
181
  )
182
 
183
- # Validate syntax
184
  try:
185
  ast.parse(content)
186
  print("OK: agent.py syntax OK")
@@ -190,9 +164,8 @@ except SyntaxError as e:
190
 
191
  with open(AGENT_FILE, "w") as f:
192
  f.write(content)
193
- print("OK: agent.py patched")
194
 
195
- # === Step 3: Patch _resolve_llm_params ===
196
  with open(LLM_PARAMS_FILE) as f:
197
  llm_content = f.read()
198
 
@@ -201,6 +174,13 @@ if "normalized_model.startswith" not in llm_content:
201
  if api_key_find in llm_content:
202
  line_end = llm_content.find("\n", llm_content.find(api_key_find) + len(api_key_find)) + 1
203
  routing_insert = (
 
 
 
 
 
 
 
204
  ' # Route openai/-prefixed models to OpenRouter\n'
205
  ' if normalized_model.startswith("openai/"):\n'
206
  ' return {\n'
@@ -210,7 +190,7 @@ if "normalized_model.startswith" not in llm_content:
210
  ' }\n\n'
211
  )
212
  llm_content = llm_content[:line_end] + routing_insert + llm_content[line_end:]
213
- print("OK: Patched _resolve_llm_params")
214
  else:
215
  print("WARN: Could not find api_key line")
216
  else:
 
1
+ """Patch backend: OpenRouter routing + DeepSeek V4 Flash 0731."""
2
 
3
  import ast
4
  import os
 
6
 
7
  AGENT_FILE = "/app/backend/routes/agent.py"
8
  LLM_PARAMS_FILE = "/app/agent/core/llm_params.py"
 
 
9
  IDS_FILE = "/app/agent/core/model_ids.py"
10
+
11
  with open(IDS_FILE) as f:
12
  content = f.read()
13
 
14
+ # Remove NO_TOOLS_MODELS if present from previous patches
15
  if "NO_TOOLS_MODELS" in content:
16
  content = re.sub(r'NO_TOOLS_MODELS\s*=\s*\{[^}]*\}\n?', '', content)
17
  print("OK: Removed old NO_TOOLS_MODELS")
18
 
19
+ # Fix model IDs for OpenRouter
20
  content = content.replace(
21
  'KIMI_K27_CODE_MODEL_ID = "moonshotai/Kimi-K2.7-Code:novita"',
22
+ 'KIMI_K27_CODE_MODEL_ID = "deepseek-ai/DeepSeek-V4-Pro"'
23
  )
24
  content = content.replace(
25
  'MINIMAX_M3_MODEL_ID = "MiniMaxAI/MiniMax-M3:novita"',
26
+ 'MINIMAX_M3_MODEL_ID = "deepseek-ai/DeepSeek-V4-Flash"'
27
  )
28
  content = content.replace(
29
  'GLM_52_MODEL_ID = "zai-org/GLM-5.2:novita"',
30
+ 'GLM_52_MODEL_ID = "openai/deepseek/deepseek-v4-flash"'
31
  )
32
  content = content.replace(
33
  'DEEPSEEK_V4_PRO_MODEL_ID = "deepseek-ai/DeepSeek-V4-Pro:novita"',
34
+ 'DEEPSEEK_V4_PRO_MODEL_ID = "nvidia/nemotron-3-super-120b-a12b:free"'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  )
36
 
37
+ # Add missing constants before DEEPSEEK_V4_PRO_MODEL_ID line
38
+ insert_before = '''TENCENT_HY3_FREE_MODEL_ID = "openai/tencent/hy3:free"
 
 
 
 
 
 
 
 
 
 
39
  GEMMA_4_31B_FREE_MODEL_ID = "openai/google/gemma-4-31b-it:free"
40
  LLAMA_3_3_70B_FREE_MODEL_ID = "openai/meta-llama/llama-3.3-70b-instruct:free"
41
  LLAMA_3_1_8B_MODEL_ID = "openai/meta-llama/llama-3.1-8b-instruct"
 
44
  NEX_N2_MINI_MODEL_ID = "openai/nex-agi/nex-n2-mini"
45
  LING_3_0_FLASH_FREE_MODEL_ID = "openai/inclusionai/ling-3.0-flash:free"
46
  '''
47
+ if "TENCENT_HY3_FREE_MODEL_ID" not in content:
48
+ content = content.replace('DEEPSEEK_V4_PRO_MODEL_ID', insert_before + 'DEEPSEEK_V4_PRO_MODEL_ID')
49
+
50
+ # Replace all references to latest deepseek models with 0731 version
51
+ content = content.replace('"~deepseek/deepseek-v4-flash-latest"', '"deepseek/deepseek-v4-flash-0731"')
52
+ content = content.replace('"~deepseek/deepseek-v4-flash-0731"', '"deepseek/deepseek-v4-flash-0731"')
53
 
54
  with open(IDS_FILE, "w") as f:
55
  f.write(content)
56
  print("OK: model_ids.py patched")
57
 
58
+ ast.parse(content) # validate syntax
59
+ print("OK: model_ids.py syntax OK")
 
 
 
 
 
60
 
 
61
  with open(AGENT_FILE) as f:
62
  content = f.read()
63
 
 
70
  "DEFAULT_GPT_MODEL_ID = LAGUNA_S21_FREE_MODEL_ID"
71
  )
72
 
73
+ # Update imports
74
  old_import = (
75
  "from agent.core.model_ids import (\n"
76
  " CLAUDE_OPUS_48_MODEL_ID,\n"
 
102
  )
103
  content = content.replace(old_import, new_import)
104
 
105
+ # Update _available_models to include DeepSeek V4 Flash 0731
106
+ new_func = '''def _available_models() -> list[dict[str, Any]]:
107
+ models = [
108
+ {"id": TENCENT_HY3_FREE_MODEL_ID, "label": "Tencent HY3:free", "recommended": True},
109
+ {"id": GEMMA_4_31B_FREE_MODEL_ID, "label": "Gemma 4 31B:free", "recommended": True},
110
+ {"id": LLAMA_3_3_70B_FREE_MODEL_ID, "label": "Llama 3.3 70B:free", "recommended": True},
111
+ {"id": LAGUNA_M1_FREE_MODEL_ID, "label": "Laguna M.1:free", "recommended": True},
112
+ {"id": DEFAULT_GPT_MODEL_ID, "label": "Laguna S 2.1:free", "recommended": True},
113
+ {"id": NEX_N2_MINI_MODEL_ID, "label": "nex-agi/nex-n2-mini", "recommended": True},
114
+ {"id": LING_3_0_FLASH_FREE_MODEL_ID, "label": "inclusionai/ling-3.0-flash:free", "recommended": True},
115
+ {"id": LLAMA_3_1_8B_MODEL_ID, "label": "Llama 3.1 8B"},
116
+ {"id": KIMI_K27_CODE_MODEL_ID, "label": "DeepSeek V4 Pro"},
117
+ {"id": MINIMAX_M3_MODEL_ID, "label": "DeepSeek V4 Flash"},
118
+ {"id": DEFAULT_MODEL_ID, "label": "DeepSeek V4 Flash"},
119
+ {"id": DEEPSEEK_V4_PRO_MODEL_ID, "label": "Nemotron 3 Super 120B"},
120
+ {"id": "deepseek/deepseek-v4-flash-0731", "label": "DeepSeek V4 Flash 0731", "recommended": True},
121
+ ]
122
+ return models'''
 
123
 
124
  func_match = re.search(
125
  r"def _available_models\(\)\s*->\s*list\[dict\[str,\s*Any\]\]:.*?return models",
 
127
  )
128
  if func_match:
129
  content = content[:func_match.start()] + new_func + content[func_match.end():]
130
+ print("OK: Replaced _available_models() with DeepSeek V4 Flash 0731")
131
  else:
132
  old_func = (
133
  "def _available_models() -> list[dict[str, Any]]:\n"
 
145
  content = content.replace(old_func, new_func)
146
  print("OK: String replace of _available_models()")
147
  else:
148
+ print("WARN: Could not find _available_models() pattern, searching...")
149
+ idx = content.find("def _available_models")
150
+ if idx >= 0:
151
+ print(f"Found at index {idx}, context: {content[idx:idx+400]}")
152
 
 
153
  content = content.replace(
154
  '"openai/gpt-oss-120b:cerebras",',
155
  '"huggingface/deepseek-ai/DeepSeek-V4-Pro",'
156
  )
157
 
 
158
  try:
159
  ast.parse(content)
160
  print("OK: agent.py syntax OK")
 
164
 
165
  with open(AGENT_FILE, "w") as f:
166
  f.write(content)
 
167
 
168
+ # Patch llm_params for OpenRouter routing
169
  with open(LLM_PARAMS_FILE) as f:
170
  llm_content = f.read()
171
 
 
174
  if api_key_find in llm_content:
175
  line_end = llm_content.find("\n", llm_content.find(api_key_find) + len(api_key_find)) + 1
176
  routing_insert = (
177
+ ' # Route deepseek/ models to OpenRouter\n'
178
+ ' if normalized_model.startswith("deepseek/"):\n'
179
+ ' return {\n'
180
+ ' "model": normalized_model,\n'
181
+ ' "api_base": "https://openrouter.ai/api/v1",\n'
182
+ ' "api_key": os.environ.get("OPENROUTER_API_KEY") or api_key or "",\n'
183
+ ' }\n\n'
184
  ' # Route openai/-prefixed models to OpenRouter\n'
185
  ' if normalized_model.startswith("openai/"):\n'
186
  ' return {\n'
 
190
  ' }\n\n'
191
  )
192
  llm_content = llm_content[:line_end] + routing_insert + llm_content[line_end:]
193
+ print("OK: Patched _resolve_llm_params with deepseek/ routing")
194
  else:
195
  print("WARN: Could not find api_key line")
196
  else: