feat: migrate to reasoning models (openai/gpt-oss-120b primary + openai/gpt-oss-20b fallback + qwen router fallback)
Browse files- config.py +3 -1
- services/groq_service.py +33 -8
config.py
CHANGED
|
@@ -5,7 +5,9 @@ load_dotenv()
|
|
| 5 |
|
| 6 |
GROQ_API_KEY = os.environ.get("GROQ_API_KEY", "")
|
| 7 |
GROQ_ROUTE_MODEL = os.environ.get("GROQ_ROUTE_MODEL", "openai/gpt-oss-20b")
|
| 8 |
-
|
|
|
|
|
|
|
| 9 |
SUPABASE_URL = os.environ.get("SUPABASE_URL", "")
|
| 10 |
SUPABASE_KEY = os.environ.get("SUPABASE_KEY", "")
|
| 11 |
|
|
|
|
| 5 |
|
| 6 |
GROQ_API_KEY = os.environ.get("GROQ_API_KEY", "")
|
| 7 |
GROQ_ROUTE_MODEL = os.environ.get("GROQ_ROUTE_MODEL", "openai/gpt-oss-20b")
|
| 8 |
+
GROQ_FALLBACK_ROUTE_MODEL = os.environ.get("GROQ_FALLBACK_ROUTE_MODEL", "qwen/qwen3.6-27b")
|
| 9 |
+
GROQ_SYNTHESIS_MODEL = os.environ.get("GROQ_SYNTHESIS_MODEL", "openai/gpt-oss-120b")
|
| 10 |
+
GROQ_FALLBACK_SYNTHESIS_MODEL = os.environ.get("GROQ_FALLBACK_SYNTHESIS_MODEL", "openai/gpt-oss-20b")
|
| 11 |
SUPABASE_URL = os.environ.get("SUPABASE_URL", "")
|
| 12 |
SUPABASE_KEY = os.environ.get("SUPABASE_KEY", "")
|
| 13 |
|
services/groq_service.py
CHANGED
|
@@ -321,14 +321,39 @@ async def process_chat_message(
|
|
| 321 |
router_messages.extend(session_history[session_id][-4:])
|
| 322 |
router_messages.append({"role": "user", "content": user_query})
|
| 323 |
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 332 |
|
| 333 |
if isinstance(routing, list) and len(routing) > 0:
|
| 334 |
routing = routing[0]
|
|
|
|
| 321 |
router_messages.extend(session_history[session_id][-4:])
|
| 322 |
router_messages.append({"role": "user", "content": user_query})
|
| 323 |
|
| 324 |
+
try:
|
| 325 |
+
router_res = groq_client.chat.completions.create(
|
| 326 |
+
model=GROQ_ROUTE_MODEL,
|
| 327 |
+
messages=router_messages,
|
| 328 |
+
temperature=0.0,
|
| 329 |
+
max_tokens=600,
|
| 330 |
+
response_format={"type": "json_object"},
|
| 331 |
+
)
|
| 332 |
+
routing = json.loads(router_res.choices[0].message.content)
|
| 333 |
+
except Exception as router_err:
|
| 334 |
+
logger.warning(f"Router model {GROQ_ROUTE_MODEL} failed: {router_err}. Trying fallback {GROQ_FALLBACK_ROUTE_MODEL}...")
|
| 335 |
+
try:
|
| 336 |
+
router_res = groq_client.chat.completions.create(
|
| 337 |
+
model=GROQ_FALLBACK_ROUTE_MODEL,
|
| 338 |
+
messages=router_messages,
|
| 339 |
+
temperature=0.0,
|
| 340 |
+
max_tokens=600,
|
| 341 |
+
)
|
| 342 |
+
raw_content = router_res.choices[0].message.content
|
| 343 |
+
cleaned_content = re.sub(r'<think>.*?</think>', '', raw_content, flags=re.DOTALL).strip()
|
| 344 |
+
# If JSON parseable, load it; otherwise extract tag directly
|
| 345 |
+
try:
|
| 346 |
+
routing = json.loads(cleaned_content)
|
| 347 |
+
except Exception:
|
| 348 |
+
for tag in ["OUT_OF_SCOPE", "PATH_A", "PATH_B", "BOTH", "GREETING", "COMMERCIAL_HANDOFF"]:
|
| 349 |
+
if tag in cleaned_content:
|
| 350 |
+
routing = {"classification": tag, "reason": "Fallback extracted"}
|
| 351 |
+
break
|
| 352 |
+
else:
|
| 353 |
+
routing = {"classification": "PATH_A"}
|
| 354 |
+
except Exception as fb_err:
|
| 355 |
+
logger.error(f"Fallback router {GROQ_FALLBACK_ROUTE_MODEL} also failed: {fb_err}. Defaulting to PATH_A.")
|
| 356 |
+
routing = {"classification": "PATH_A"}
|
| 357 |
|
| 358 |
if isinstance(routing, list) and len(routing) > 0:
|
| 359 |
routing = routing[0]
|