feat(knowledge): KB Phase 2 — OpenClaw RAG 整合
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
_dual_engine_analyze 新增 _query_kb_context(): - Incident 分析前語意搜尋相關 KB 條目 (top-3, threshold=0.4) - 將 KB context 注入 expert_context.diagnosis_context 傳給 LLM - 失敗時靜默降級,不影響主分析流程 - dual_engine_llm_win log 新增 kb_rag 欄位,可觀測 RAG 命中率 架構: _query_kb_context 透過 get_knowledge_service() 呼叫 Service 層 符合 leWOOOgo 積木化 — decision_manager 不直接存取 DB/pgvector Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -548,17 +548,56 @@ class DecisionManager:
|
||||
_push_decision_to_telegram(incident, token.proposal_data)
|
||||
)
|
||||
|
||||
async def _query_kb_context(self, incident: Incident) -> str:
|
||||
"""
|
||||
KB Phase 2: 語意搜尋相關 KB 條目,組裝為 LLM context 字串
|
||||
2026-04-04 Claude Code: KB RAG 整合
|
||||
|
||||
失敗時靜默降級,不影響主分析流程
|
||||
"""
|
||||
try:
|
||||
from src.services.knowledge_service import get_knowledge_service
|
||||
query_parts = list(incident.affected_services)
|
||||
if incident.signals:
|
||||
query_parts.insert(0, getattr(incident.signals[0], "alert_name", ""))
|
||||
query = " ".join(filter(None, query_parts))
|
||||
|
||||
svc = get_knowledge_service()
|
||||
results = await svc.semantic_search(query, limit=3, threshold=0.4)
|
||||
if not results:
|
||||
return ""
|
||||
|
||||
lines = ["## 📚 Knowledge Base 相關條目 (KB RAG)"]
|
||||
for entry, score in results:
|
||||
lines.append(
|
||||
f"\n### [{entry.entry_type}] {entry.title} (similarity={score:.2f})"
|
||||
)
|
||||
lines.append(entry.content[:500])
|
||||
if len(entry.content) > 500:
|
||||
lines.append("... (truncated)")
|
||||
|
||||
logger.info(
|
||||
"kb_rag_context_injected",
|
||||
incident_id=incident.incident_id,
|
||||
kb_hits=len(results),
|
||||
)
|
||||
return "\n".join(lines)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning("kb_rag_failed", incident_id=incident.incident_id, error=str(e))
|
||||
return ""
|
||||
|
||||
async def _dual_engine_analyze(
|
||||
self,
|
||||
incident: Incident,
|
||||
) -> dict[str, Any]:
|
||||
"""
|
||||
三軌決策分析 (Phase 7.5 升級)
|
||||
三軌決策分析 (Phase 7.5 升級 + KB Phase 2 RAG 整合)
|
||||
|
||||
策略:
|
||||
1. 先檢查 Playbook 是否有高度匹配 (similarity >= 85%)
|
||||
2. Playbook 命中則直接使用 (最快、經驗驗證)
|
||||
3. 否則 LLM + Expert System 雙軌
|
||||
3. 否則 LLM + Expert System 雙軌 + KB RAG context 注入
|
||||
|
||||
優先順序: Playbook > LLM > Expert System
|
||||
"""
|
||||
@@ -570,16 +609,29 @@ class DecisionManager:
|
||||
# Expert System 同步執行 (立即可用)
|
||||
expert_result = expert_analyze(incident)
|
||||
|
||||
# KB Phase 2: 語意搜尋相關知識條目 (失敗時靜默降級)
|
||||
# 2026-04-04 Claude Code: KB RAG 整合,提升 LLM 決策品質
|
||||
kb_context = await self._query_kb_context(incident)
|
||||
|
||||
# LLM 非同步執行 (Phase 22: OpenClaw + Nemotron 協作)
|
||||
# 2026-03-31 Claude Code: 使用 _with_tools 方法啟用雙軌協作
|
||||
try:
|
||||
signals_dict = [s.model_dump() for s in incident.signals]
|
||||
|
||||
# 將 KB context 注入 expert_context 傳給 LLM
|
||||
llm_expert_context: dict[str, Any] = {**expert_result} if expert_result else {}
|
||||
if kb_context:
|
||||
existing = str(llm_expert_context.get("diagnosis_context", ""))
|
||||
llm_expert_context["diagnosis_context"] = (
|
||||
f"{kb_context}\n\n{existing}" if existing else kb_context
|
||||
)
|
||||
|
||||
llm_result, provider, success = await self._openclaw.generate_incident_proposal_with_tools(
|
||||
incident_id=incident.incident_id,
|
||||
severity=incident.severity.value,
|
||||
signals=signals_dict,
|
||||
affected_services=incident.affected_services,
|
||||
expert_context=llm_expert_context if llm_expert_context else None,
|
||||
)
|
||||
|
||||
if success and llm_result:
|
||||
@@ -587,6 +639,7 @@ class DecisionManager:
|
||||
"dual_engine_llm_win",
|
||||
incident_id=incident.incident_id,
|
||||
provider=provider,
|
||||
kb_rag=bool(kb_context),
|
||||
)
|
||||
return {
|
||||
**llm_result,
|
||||
|
||||
Reference in New Issue
Block a user