fix(api): route direct ollama callers through ordered fallback
All checks were successful
Code Review / ai-code-review (push) Successful in 23s
CD Pipeline / tests (push) Successful in 5m51s
CD Pipeline / build-and-deploy (push) Successful in 3m29s
CD Pipeline / post-deploy-checks (push) Successful in 1m14s

This commit is contained in:
Your Name
2026-05-19 12:56:13 +08:00
parent 8a0a3f89aa
commit 35fe37c82a
13 changed files with 579 additions and 384 deletions

View File

@@ -32,7 +32,7 @@ import httpx
import structlog
from src.services.model_registry import get_model_registry
from src.services.ollama_endpoint_resolver import resolve_ollama_endpoint
from src.services.ollama_endpoint_resolver import resolve_ollama_order
logger = structlog.get_logger(__name__)
@@ -546,27 +546,56 @@ class IntentClassifier:
# 取得模型配置
model_name = self.llm_model # qwen2.5:1b 或配置值
# 呼叫 Ollama
# 呼叫 OllamaGCP-A → GCP-B → 111
result_text = ""
last_error: Exception | None = None
async with httpx.AsyncClient() as client:
response = await client.post(
f"{resolve_ollama_endpoint('hermes')}/api/generate",
json={
"model": model_name,
"prompt": prompt,
"stream": False,
"format": "json",
"options": {
"num_predict": 128, # 意圖分類只需短回應
"temperature": 0.0, # 確定性輸出
"top_p": 0.9,
},
},
timeout=httpx.Timeout(5.0, connect=2.0), # 嚴格超時
)
for endpoint in resolve_ollama_order("hermes"):
if not endpoint.url:
continue
try:
response = await client.post(
f"{endpoint.url}/api/generate",
json={
"model": model_name,
"prompt": prompt,
"stream": False,
"format": "json",
"options": {
"num_predict": 128, # 意圖分類只需短回應
"temperature": 0.0, # 確定性輸出
"top_p": 0.9,
},
},
timeout=httpx.Timeout(5.0, connect=2.0), # 嚴格超時
)
response.raise_for_status()
data = response.json()
result_text = data.get("response", "")
response.raise_for_status()
data = response.json()
result_text = data.get("response", "")
break
except Exception as e:
last_error = e
logger.warning(
"intent_llm_endpoint_failed",
provider=endpoint.provider_name,
error=str(e),
error_type=type(e).__name__,
)
if not result_text:
_kw_result = self._keyword_classify(text)
return IntentResult(
intent=_kw_result.intent,
confidence=_kw_result.confidence,
method="llm_unavailable_keyword",
matched_keywords=_kw_result.matched_keywords,
detected_resources=_kw_result.detected_resources,
reasoning=(
f"LLM 全端點不可用({type(last_error).__name__ if last_error else 'no_endpoint'}"
f"{_kw_result.reasoning}"
),
)
# 解析 JSON 回應
elapsed_ms = (time.time() - start_time) * 1000