fix(api): align kb extractor ollama model
All checks were successful
CD Pipeline / tests (push) Successful in 1m23s
Code Review / ai-code-review (push) Successful in 14s
CD Pipeline / build-and-deploy (push) Successful in 3m35s
CD Pipeline / post-deploy-checks (push) Successful in 3m23s

This commit is contained in:
Your Name
2026-05-31 18:07:03 +08:00
parent 8f73058b93
commit 8699fe0c7f
4 changed files with 96 additions and 11 deletions

View File

@@ -4,7 +4,7 @@ Knowledge Extractor Service — KB Phase 2-A
Incident resolved 後自動萃取 KB 草稿。
設計原則:
- 使用 Ollama llama3.2:3b,依全域順序 GCP-A → GCP-B → 111 嘗試
- 使用 `settings.OLLAMA_TOOL_MODEL`,依全域順序 GCP-A → GCP-B → 111 嘗試
- fire-and-forget失敗不影響 resolve 主流程
- logger.exception 保留完整 Stack Trace 供 Prompt 調優
@@ -17,10 +17,19 @@ logger = structlog.get_logger(__name__)
# 2026-05-19 Codex: 統帥校正,全 Ollama workload 固定 GCP-A → GCP-B → 111。
def _get_ollama_endpoints():
from src.services.ollama_endpoint_resolver import resolve_ollama_order
from src.services.ollama_endpoint_circuit_breaker import (
resolve_ollama_order_with_cooldown,
)
return resolve_ollama_order_with_cooldown("hermes")
def _get_extract_model() -> str:
from src.core.config import settings
return str(getattr(settings, "OLLAMA_TOOL_MODEL", "hermes3:latest") or "hermes3:latest")
return resolve_ollama_order("deep_rca")
_EXTRACT_MODEL = "llama3.2:3b"
_EXTRACT_TIMEOUT = 30.0 # 秒,容忍慢速
# Linear / Nothing.tech 風格的 SRE KB Prompt
@@ -72,7 +81,7 @@ class KnowledgeExtractorService:
"""
Incident → KB 草稿自動萃取器
使用 Ollama llama3.2:3b 本地推理,產生 Markdown 格式的 SRE 知識條目。
使用目前配置的 Ollama tool model 產生 Markdown 格式的 SRE 知識條目。
"""
async def extract_from_incident(self, incident) -> bool:
@@ -103,11 +112,12 @@ class KnowledgeExtractorService:
# 2. 呼叫 Ollama直接 HTTP不走 AIRouter 避免路由邏輯開銷)
markdown_content = await self._call_ollama(prompt)
model = _get_extract_model()
if not markdown_content:
logger.warning(
"kb_extract_empty_response",
incident_id=incident.incident_id,
model=_EXTRACT_MODEL,
model=model,
)
return False
@@ -142,7 +152,7 @@ class KnowledgeExtractorService:
incident_id=incident.incident_id,
title=title,
category=category,
model=_EXTRACT_MODEL,
model=model,
)
return True
@@ -165,6 +175,7 @@ class KnowledgeExtractorService:
import httpx
endpoints = _get_ollama_endpoints()
model = _get_extract_model()
async with httpx.AsyncClient(timeout=_EXTRACT_TIMEOUT) as client:
for endpoint in endpoints:
if not endpoint.url:
@@ -173,7 +184,7 @@ class KnowledgeExtractorService:
r = await client.post(
f"{endpoint.url}/api/generate",
json={
"model": _EXTRACT_MODEL,
"model": model,
"prompt": prompt,
"stream": False,
"options": {
@@ -188,15 +199,25 @@ class KnowledgeExtractorService:
if text:
logger.info(
"kb_ollama_call_success",
model=_EXTRACT_MODEL,
model=model,
provider=endpoint.provider_name,
base=endpoint.url,
)
from src.services.ollama_endpoint_circuit_breaker import (
record_ollama_endpoint_success,
)
record_ollama_endpoint_success(endpoint.url)
return text
except Exception as e:
from src.services.ollama_endpoint_circuit_breaker import (
record_ollama_endpoint_failure,
)
record_ollama_endpoint_failure(endpoint.url)
logger.warning(
"kb_ollama_call_failed",
model=_EXTRACT_MODEL,
model=model,
provider=endpoint.provider_name,
base=endpoint.url,
error=str(e),
@@ -204,7 +225,7 @@ class KnowledgeExtractorService:
logger.error(
"kb_ollama_all_endpoints_failed",
model=_EXTRACT_MODEL,
model=model,
attempted=[endpoint.provider_name for endpoint in endpoints],
)
return None