fix(api): route direct ollama callers through ordered fallback
This commit is contained in:
@@ -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
|
||||
# 呼叫 Ollama(GCP-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
|
||||
|
||||
Reference in New Issue
Block a user