feat: 完成 issue #74 [Ti-1] 报警解释 Prompt 模板与 RAG 接入
This commit is contained in:
@@ -19,7 +19,7 @@ from typing import Callable, Dict, List, Optional
|
||||
from llm_gateway.gateway import GatewayResult, LLMGateway
|
||||
from llm_gateway.prompts import PromptRegistry
|
||||
from llm_gateway.router import SensitivityRouter
|
||||
from rag_kb import RagKnowledgeBase, load_kb_config
|
||||
from rag_kb import KnowledgeSourceKind, RagKnowledgeBase, load_kb_config
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 场景配置资产路径
|
||||
@@ -41,6 +41,12 @@ def scenarios_config_path() -> str:
|
||||
return os.path.join(_scenarios_dir(), "config", "scenarios.template.yaml")
|
||||
|
||||
|
||||
def alarm_config_path() -> str:
|
||||
"""报警解释场景配置资产(alarm_explain.template.yaml)路径。"""
|
||||
return os.path.join(_scenarios_dir(), "config",
|
||||
"alarm_explain.template.yaml")
|
||||
|
||||
|
||||
def prompts_config_path() -> str:
|
||||
"""复用 llm-gateway 提示词版本库资产路径。"""
|
||||
return os.path.join(_repo_root(), "core", "llm-gateway", "config",
|
||||
@@ -110,6 +116,7 @@ class TiScenarioRunner:
|
||||
prompts: Optional[PromptRegistry] = None,
|
||||
router: Optional[SensitivityRouter] = None,
|
||||
kb_loader: Callable[[str], str] = demo_kb_loader,
|
||||
alarm_config: Optional[dict] = None,
|
||||
) -> None:
|
||||
prompts = prompts or PromptRegistry.from_template_config(prompts_config_path())
|
||||
kb = kb or RagKnowledgeBase.from_template_config(
|
||||
@@ -117,6 +124,8 @@ class TiScenarioRunner:
|
||||
)
|
||||
router = router or SensitivityRouter.from_template_config(router_config_path())
|
||||
self.kb = kb
|
||||
# 报警解释场景配置(issue #74:sop 类目检索 + 检索阈值)
|
||||
self.alarm_cfg = alarm_config or self._load_alarm_config()
|
||||
if gateway is not None:
|
||||
# 注入 gateway:由调用方负责 prompt_name / 高利害配置
|
||||
self._gateways = {
|
||||
@@ -141,12 +150,35 @@ class TiScenarioRunner:
|
||||
|
||||
# -- 场景 1:报警根因解释(高利害) -----------------------------------
|
||||
|
||||
@staticmethod
|
||||
def _load_alarm_config() -> dict:
|
||||
"""加载报警解释场景配置资产(issue #74)。"""
|
||||
import yaml
|
||||
|
||||
with open(alarm_config_path(), "r", encoding="utf-8") as fh:
|
||||
return (yaml.safe_load(fh) or {}).get("alarm_explain", {})
|
||||
|
||||
def explain_alarm(self, alarm: str, confidence: float = 1.0,
|
||||
top_k: int = 3) -> GatewayResult:
|
||||
"""解释一条报警的可能原因与处置建议(RAG 检索异常处置 SOP)。"""
|
||||
hits = self.kb.search(alarm, top_k=top_k,
|
||||
categories=None)
|
||||
sources = [h.source for h in hits]
|
||||
top_k: Optional[int] = None) -> GatewayResult:
|
||||
"""解释一条报警的可能原因与处置建议。
|
||||
|
||||
RAG 接入(issue #74):只检索 **sop 知识域**(异常处置 SOP),
|
||||
并按 min_score 过滤——低于阈值视为未命中,降级提示人工确认
|
||||
(高利害场景宁缺毋滥,避免无据回答)。
|
||||
"""
|
||||
rag = self.alarm_cfg.get("rag", {}) or {}
|
||||
cat_names = rag.get("categories")
|
||||
categories = ([KnowledgeSourceKind(c) for c in cat_names]
|
||||
if cat_names else None)
|
||||
top_k = top_k or int(rag.get("top_k", 3))
|
||||
min_score = float(rag.get("min_score", 0.0))
|
||||
hits = self.kb.search(alarm, top_k=top_k, categories=categories)
|
||||
hits = [h for h in hits if h.score >= min_score]
|
||||
if hits:
|
||||
sources = [h.source for h in hits]
|
||||
else:
|
||||
# 未检索到 SOP:降级提示人工确认(来源占位,阻断无据回答)
|
||||
sources = ["未检索到相关 SOP,请人工确认"]
|
||||
return self._gateways["alarm_explain"].ask(
|
||||
alarm, rag_context=sources, confidence=confidence,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user