【AI-agent】让 AI 输出可依赖:LLM 工程化的四道防线

目录

  • [1. 一个「格式漂移」的故事](#1. 一个「格式漂移」的故事)
  • [2. LLM 会怎么「出错」:失败模式全景](#2. LLM 会怎么「出错」:失败模式全景)
  • [3. 第一道防线:让「一次调用」可靠](#3. 第一道防线:让「一次调用」可靠)
    • [3.1 Prompt 约束(软约束)](#3.1 Prompt 约束(软约束))
    • [3.2 后处理规范化(硬校正)](#3.2 后处理规范化(硬校正))
    • [3.3 结构化兜底(不依赖 LLM)](#3.3 结构化兜底(不依赖 LLM))
  • [4. 第二道防线:让「流程」可控](#4. 第二道防线:让「流程」可控)
    • [4.1 把 LLM 服务当成一个「会宕机的组件」来对待](#4.1 把 LLM 服务当成一个「会宕机的组件」来对待)
  • [5. 第三道防线:让「质量」收敛](#5. 第三道防线:让「质量」收敛)
    • [5.1 失败模式测试矩阵](#5.1 失败模式测试矩阵)
  • [6. 第四道防线:让「效果」可评估](#6. 第四道防线:让「效果」可评估)
    • [6.1 评估就像「考试」](#6.1 评估就像「考试」)
    • [6.2 评估闭环](#6.2 评估闭环)
  • [7. 完整收敛路径](#7. 完整收敛路径)
  • [8. 总结](#8. 总结)

1. 一个「格式漂移」的故事

巡检系统上线了 AI 智能诊断:把巡检发现的问题交给大模型,让它结合历史经验库,自动生成「初步诊断」,展示在报告里。

有一天,用户翻开报告,发现同样都是「没有历史记录」的问题,诊断却出现了三种写法:

plain 复制代码
① [暂无历史记录] 多块磁盘 IO 短时飙升,疑似定时备份......
② [历史判定] 暂无历史记录。诊断:缓存命中率长期偏低......
③ [历史判定] : 当前节点 CPU 均值偏高,符合该模式......

三种写法,语义几乎相同,却把「历史判定」字段渲染得参差不齐。用户问:为什么会出现这种现象?能不能统一?

这个问题引出了 LLM 工程化的核心问题--格式漂移。而「格式漂移」,其实只是冰山一角------真正的水面之下,LLM 会以更多、更隐蔽的方式「出错」。


2. LLM 会怎么「出错」:失败模式全景

把 LLM 想象成一个「聪明但偶尔走神的学生」,它交上来的答案,可能出四类问题:

失败模式 类比 表现 能否靠后处理修复
格式漂移 字写得潦草 [暂无历史记录] / [历史判定] 暂无历史记录 混用 ✅ 能,正则归一
截断 考试时间到,最后几题没写完 响应体被掐断,JSON 缺尾括号 ⚠️ 部分能,补全尾括号
幻觉 没背到就瞎编 编造一个不存在的工单号、编造根因 ❌ 难,需校验真实性
语义错误 答非所问 格式全对,但诊断结论与现象对不上 ❌ 不能,只能评估后打回

关键认知 :格式漂移、截断是「形式 」问题,能用代码修;幻觉、语义错误是「内容」问题,代码救不了------只能靠「评估」发现、靠「打回重试」收敛。

因此,LLM 工程化不能只有「约束」,还要有「评估」。完整的解法是四道防线,层层递进:
#mermaid-svg-Dmy8LQpPvn9XNLly{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Dmy8LQpPvn9XNLly .error-icon{fill:#552222;}#mermaid-svg-Dmy8LQpPvn9XNLly .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Dmy8LQpPvn9XNLly .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Dmy8LQpPvn9XNLly .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Dmy8LQpPvn9XNLly .marker.cross{stroke:#333333;}#mermaid-svg-Dmy8LQpPvn9XNLly svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Dmy8LQpPvn9XNLly p{margin:0;}#mermaid-svg-Dmy8LQpPvn9XNLly .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Dmy8LQpPvn9XNLly .cluster-label text{fill:#333;}#mermaid-svg-Dmy8LQpPvn9XNLly .cluster-label span{color:#333;}#mermaid-svg-Dmy8LQpPvn9XNLly .cluster-label span p{background-color:transparent;}#mermaid-svg-Dmy8LQpPvn9XNLly .label text,#mermaid-svg-Dmy8LQpPvn9XNLly span{fill:#333;color:#333;}#mermaid-svg-Dmy8LQpPvn9XNLly .node rect,#mermaid-svg-Dmy8LQpPvn9XNLly .node circle,#mermaid-svg-Dmy8LQpPvn9XNLly .node ellipse,#mermaid-svg-Dmy8LQpPvn9XNLly .node polygon,#mermaid-svg-Dmy8LQpPvn9XNLly .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Dmy8LQpPvn9XNLly .rough-node .label text,#mermaid-svg-Dmy8LQpPvn9XNLly .node .label text,#mermaid-svg-Dmy8LQpPvn9XNLly .image-shape .label,#mermaid-svg-Dmy8LQpPvn9XNLly .icon-shape .label{text-anchor:middle;}#mermaid-svg-Dmy8LQpPvn9XNLly .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Dmy8LQpPvn9XNLly .rough-node .label,#mermaid-svg-Dmy8LQpPvn9XNLly .node .label,#mermaid-svg-Dmy8LQpPvn9XNLly .image-shape .label,#mermaid-svg-Dmy8LQpPvn9XNLly .icon-shape .label{text-align:center;}#mermaid-svg-Dmy8LQpPvn9XNLly .node.clickable{cursor:pointer;}#mermaid-svg-Dmy8LQpPvn9XNLly .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Dmy8LQpPvn9XNLly .arrowheadPath{fill:#333333;}#mermaid-svg-Dmy8LQpPvn9XNLly .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Dmy8LQpPvn9XNLly .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Dmy8LQpPvn9XNLly .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Dmy8LQpPvn9XNLly .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Dmy8LQpPvn9XNLly .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Dmy8LQpPvn9XNLly .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Dmy8LQpPvn9XNLly .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Dmy8LQpPvn9XNLly .cluster text{fill:#333;}#mermaid-svg-Dmy8LQpPvn9XNLly .cluster span{color:#333;}#mermaid-svg-Dmy8LQpPvn9XNLly div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Dmy8LQpPvn9XNLly .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Dmy8LQpPvn9XNLly rect.text{fill:none;stroke-width:0;}#mermaid-svg-Dmy8LQpPvn9XNLly .icon-shape,#mermaid-svg-Dmy8LQpPvn9XNLly .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Dmy8LQpPvn9XNLly .icon-shape p,#mermaid-svg-Dmy8LQpPvn9XNLly .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Dmy8LQpPvn9XNLly .icon-shape .label rect,#mermaid-svg-Dmy8LQpPvn9XNLly .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Dmy8LQpPvn9XNLly .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Dmy8LQpPvn9XNLly .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Dmy8LQpPvn9XNLly :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} LLM 输出

(概率正确)
① 约束

让格式对
② 编排

让流程可控
③ 收敛

让质量达标
④ 评估

让效果可验证
确定可用


3. 第一道防线:让「一次调用」可靠

先解决「一次 LLM 调用」的可靠性。按「从软到硬」排布三层:
#mermaid-svg-nphQdv4XAojm6PMD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nphQdv4XAojm6PMD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nphQdv4XAojm6PMD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nphQdv4XAojm6PMD .error-icon{fill:#552222;}#mermaid-svg-nphQdv4XAojm6PMD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nphQdv4XAojm6PMD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nphQdv4XAojm6PMD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nphQdv4XAojm6PMD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nphQdv4XAojm6PMD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nphQdv4XAojm6PMD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nphQdv4XAojm6PMD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nphQdv4XAojm6PMD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nphQdv4XAojm6PMD .marker.cross{stroke:#333333;}#mermaid-svg-nphQdv4XAojm6PMD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nphQdv4XAojm6PMD p{margin:0;}#mermaid-svg-nphQdv4XAojm6PMD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nphQdv4XAojm6PMD .cluster-label text{fill:#333;}#mermaid-svg-nphQdv4XAojm6PMD .cluster-label span{color:#333;}#mermaid-svg-nphQdv4XAojm6PMD .cluster-label span p{background-color:transparent;}#mermaid-svg-nphQdv4XAojm6PMD .label text,#mermaid-svg-nphQdv4XAojm6PMD span{fill:#333;color:#333;}#mermaid-svg-nphQdv4XAojm6PMD .node rect,#mermaid-svg-nphQdv4XAojm6PMD .node circle,#mermaid-svg-nphQdv4XAojm6PMD .node ellipse,#mermaid-svg-nphQdv4XAojm6PMD .node polygon,#mermaid-svg-nphQdv4XAojm6PMD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nphQdv4XAojm6PMD .rough-node .label text,#mermaid-svg-nphQdv4XAojm6PMD .node .label text,#mermaid-svg-nphQdv4XAojm6PMD .image-shape .label,#mermaid-svg-nphQdv4XAojm6PMD .icon-shape .label{text-anchor:middle;}#mermaid-svg-nphQdv4XAojm6PMD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nphQdv4XAojm6PMD .rough-node .label,#mermaid-svg-nphQdv4XAojm6PMD .node .label,#mermaid-svg-nphQdv4XAojm6PMD .image-shape .label,#mermaid-svg-nphQdv4XAojm6PMD .icon-shape .label{text-align:center;}#mermaid-svg-nphQdv4XAojm6PMD .node.clickable{cursor:pointer;}#mermaid-svg-nphQdv4XAojm6PMD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nphQdv4XAojm6PMD .arrowheadPath{fill:#333333;}#mermaid-svg-nphQdv4XAojm6PMD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nphQdv4XAojm6PMD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nphQdv4XAojm6PMD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nphQdv4XAojm6PMD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nphQdv4XAojm6PMD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nphQdv4XAojm6PMD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nphQdv4XAojm6PMD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nphQdv4XAojm6PMD .cluster text{fill:#333;}#mermaid-svg-nphQdv4XAojm6PMD .cluster span{color:#333;}#mermaid-svg-nphQdv4XAojm6PMD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nphQdv4XAojm6PMD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nphQdv4XAojm6PMD rect.text{fill:none;stroke-width:0;}#mermaid-svg-nphQdv4XAojm6PMD .icon-shape,#mermaid-svg-nphQdv4XAojm6PMD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nphQdv4XAojm6PMD .icon-shape p,#mermaid-svg-nphQdv4XAojm6PMD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nphQdv4XAojm6PMD .icon-shape .label rect,#mermaid-svg-nphQdv4XAojm6PMD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nphQdv4XAojm6PMD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nphQdv4XAojm6PMD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nphQdv4XAojm6PMD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 问题
① Prompt 约束

软约束:明确期望
② 后处理规范化

硬校正:统一变体
③ 结构化兜底

不依赖 LLM:可靠补
确定可用的输出

3.1 Prompt 约束(软约束)

在 system prompt 里写清格式模板、枚举分支、强调「只输出 JSON」「控制 N 字内」。

作用 :让模型「大多数时候」输出正确格式。局限:软约束,无法保证 100% 精确。

3.2 后处理规范化(硬校正)

用确定性代码做「格式归一」,且必须幂等------对已规范的输出保持不变,只纠正不规范变体:

python 复制代码
def normalize_verdict(text: str) -> str:
    # ① [暂无历史记录] → [历史判定] 暂无历史记录。
    text = re.sub(r'^\s*\[暂无历史记录\]\s*[::]?\s*', '[历史判定] 暂无历史记录。', text)
    # ③ [历史判定] :(内容为空)→ 补"暂无历史记录"
    text = re.sub(r'^\s*\[历史判定\]\s*[::]\s*', '[历史判定] 暂无历史记录。', text)
    return text

3.3 结构化兜底(不依赖 LLM)

关键信息根本不该交给 LLM 去「写全」,而应由代码从结构化数据「可靠补充」。例如工单号:

python 复制代码
def ensure_ticket_ref(problem: dict) -> str:
    diagnosis = problem.get("diagnosis", "")
    match = first_known_history(problem)          # 从结构化 KB 里取
    if match and match.ticket not in diagnosis:
        ref = f"[历史判定] 参考历史问题 {match.ticket}(根因:{match.cause})"
        return f"{ref}。{diagnosis}"
    return diagnosis

关于结构化输出 :现在更优的「源头治理」手段是 function calling / JSON mode / structured output------让模型直接从 API 层输出结构化对象。但它解决的是「格式 」,不解决「内容 」。所以定位是:结构化输出管源头,三层防线做兜底,两者配合,而不是二选一。


4. 第二道防线:让「流程」可控

三层防线解决「单次调用」,但诊断涉及「多个问题、多个步骤、多个依赖」时,需要把 LLM 调用编排成确定性工作流,而不是黑盒调用。

核心理念:确定性步骤和概率性步骤分离,LLM 只出现在它必须出现的地方。
#mermaid-svg-O52yx4JpK0QsodVX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-O52yx4JpK0QsodVX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-O52yx4JpK0QsodVX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-O52yx4JpK0QsodVX .error-icon{fill:#552222;}#mermaid-svg-O52yx4JpK0QsodVX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-O52yx4JpK0QsodVX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-O52yx4JpK0QsodVX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-O52yx4JpK0QsodVX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-O52yx4JpK0QsodVX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-O52yx4JpK0QsodVX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-O52yx4JpK0QsodVX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-O52yx4JpK0QsodVX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-O52yx4JpK0QsodVX .marker.cross{stroke:#333333;}#mermaid-svg-O52yx4JpK0QsodVX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-O52yx4JpK0QsodVX p{margin:0;}#mermaid-svg-O52yx4JpK0QsodVX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-O52yx4JpK0QsodVX .cluster-label text{fill:#333;}#mermaid-svg-O52yx4JpK0QsodVX .cluster-label span{color:#333;}#mermaid-svg-O52yx4JpK0QsodVX .cluster-label span p{background-color:transparent;}#mermaid-svg-O52yx4JpK0QsodVX .label text,#mermaid-svg-O52yx4JpK0QsodVX span{fill:#333;color:#333;}#mermaid-svg-O52yx4JpK0QsodVX .node rect,#mermaid-svg-O52yx4JpK0QsodVX .node circle,#mermaid-svg-O52yx4JpK0QsodVX .node ellipse,#mermaid-svg-O52yx4JpK0QsodVX .node polygon,#mermaid-svg-O52yx4JpK0QsodVX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-O52yx4JpK0QsodVX .rough-node .label text,#mermaid-svg-O52yx4JpK0QsodVX .node .label text,#mermaid-svg-O52yx4JpK0QsodVX .image-shape .label,#mermaid-svg-O52yx4JpK0QsodVX .icon-shape .label{text-anchor:middle;}#mermaid-svg-O52yx4JpK0QsodVX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-O52yx4JpK0QsodVX .rough-node .label,#mermaid-svg-O52yx4JpK0QsodVX .node .label,#mermaid-svg-O52yx4JpK0QsodVX .image-shape .label,#mermaid-svg-O52yx4JpK0QsodVX .icon-shape .label{text-align:center;}#mermaid-svg-O52yx4JpK0QsodVX .node.clickable{cursor:pointer;}#mermaid-svg-O52yx4JpK0QsodVX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-O52yx4JpK0QsodVX .arrowheadPath{fill:#333333;}#mermaid-svg-O52yx4JpK0QsodVX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-O52yx4JpK0QsodVX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-O52yx4JpK0QsodVX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O52yx4JpK0QsodVX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-O52yx4JpK0QsodVX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O52yx4JpK0QsodVX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-O52yx4JpK0QsodVX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-O52yx4JpK0QsodVX .cluster text{fill:#333;}#mermaid-svg-O52yx4JpK0QsodVX .cluster span{color:#333;}#mermaid-svg-O52yx4JpK0QsodVX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-O52yx4JpK0QsodVX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-O52yx4JpK0QsodVX rect.text{fill:none;stroke-width:0;}#mermaid-svg-O52yx4JpK0QsodVX .icon-shape,#mermaid-svg-O52yx4JpK0QsodVX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-O52yx4JpK0QsodVX .icon-shape p,#mermaid-svg-O52yx4JpK0QsodVX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-O52yx4JpK0QsodVX .icon-shape .label rect,#mermaid-svg-O52yx4JpK0QsodVX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-O52yx4JpK0QsodVX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-O52yx4JpK0QsodVX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-O52yx4JpK0QsodVX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 收集问题
① KB 匹配

确定性:结构化检索
② 分批 LLM 生成

概率性:每批 ≤N 个
③ 归一化匹配

确定性:把诊断对齐回问题
④ 后处理规范化

确定性:统一格式
⑤ 结构化兜底

确定性:补工单号
输出

每个阶段职责单一、可独立失败隔离

阶段 性质 失败时的处理
KB 匹配 确定性 匹配不到 → 走「暂无历史记录」分支
分批 LLM 生成 概率性 某批失败 → 只该批降级,不影响其他批
归一化匹配 确定性 匹配不上 → 跳过,不硬塞(防诊断错位)
后处理规范化 确定性 幂等,无副作用
结构化兜底 确定性 无匹配 → 原样返回

为什么「分批」是关键一环 :一次塞十几个问题,响应体过长、截断概率高,会导致整批诊断丢失。拆成每批 ≤N 个,缩短响应体、把失败隔离在批内。

为什么「归一化匹配」不能省:LLM 返回的描述常与原描述有细微差异(丢空格、拼现象),按位置硬塞会把诊断错位赋给下一个问题。必须先做「去空白后的前缀/子串匹配」,匹配不上的宁可跳过。

4.1 把 LLM 服务当成一个「会宕机的组件」来对待

工作流里,还有一个 DFX 视角不能漏:LLM 服务本身也是需要可靠性工程的组件 。它可能超时、可能限流、可能连续失败。于是需要一条降级链
#mermaid-svg-KH9zdgDFFfQOsmPT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KH9zdgDFFfQOsmPT .error-icon{fill:#552222;}#mermaid-svg-KH9zdgDFFfQOsmPT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KH9zdgDFFfQOsmPT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KH9zdgDFFfQOsmPT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KH9zdgDFFfQOsmPT .marker.cross{stroke:#333333;}#mermaid-svg-KH9zdgDFFfQOsmPT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KH9zdgDFFfQOsmPT p{margin:0;}#mermaid-svg-KH9zdgDFFfQOsmPT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KH9zdgDFFfQOsmPT .cluster-label text{fill:#333;}#mermaid-svg-KH9zdgDFFfQOsmPT .cluster-label span{color:#333;}#mermaid-svg-KH9zdgDFFfQOsmPT .cluster-label span p{background-color:transparent;}#mermaid-svg-KH9zdgDFFfQOsmPT .label text,#mermaid-svg-KH9zdgDFFfQOsmPT span{fill:#333;color:#333;}#mermaid-svg-KH9zdgDFFfQOsmPT .node rect,#mermaid-svg-KH9zdgDFFfQOsmPT .node circle,#mermaid-svg-KH9zdgDFFfQOsmPT .node ellipse,#mermaid-svg-KH9zdgDFFfQOsmPT .node polygon,#mermaid-svg-KH9zdgDFFfQOsmPT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KH9zdgDFFfQOsmPT .rough-node .label text,#mermaid-svg-KH9zdgDFFfQOsmPT .node .label text,#mermaid-svg-KH9zdgDFFfQOsmPT .image-shape .label,#mermaid-svg-KH9zdgDFFfQOsmPT .icon-shape .label{text-anchor:middle;}#mermaid-svg-KH9zdgDFFfQOsmPT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KH9zdgDFFfQOsmPT .rough-node .label,#mermaid-svg-KH9zdgDFFfQOsmPT .node .label,#mermaid-svg-KH9zdgDFFfQOsmPT .image-shape .label,#mermaid-svg-KH9zdgDFFfQOsmPT .icon-shape .label{text-align:center;}#mermaid-svg-KH9zdgDFFfQOsmPT .node.clickable{cursor:pointer;}#mermaid-svg-KH9zdgDFFfQOsmPT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KH9zdgDFFfQOsmPT .arrowheadPath{fill:#333333;}#mermaid-svg-KH9zdgDFFfQOsmPT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KH9zdgDFFfQOsmPT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KH9zdgDFFfQOsmPT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KH9zdgDFFfQOsmPT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KH9zdgDFFfQOsmPT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KH9zdgDFFfQOsmPT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KH9zdgDFFfQOsmPT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KH9zdgDFFfQOsmPT .cluster text{fill:#333;}#mermaid-svg-KH9zdgDFFfQOsmPT .cluster span{color:#333;}#mermaid-svg-KH9zdgDFFfQOsmPT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KH9zdgDFFfQOsmPT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KH9zdgDFFfQOsmPT rect.text{fill:none;stroke-width:0;}#mermaid-svg-KH9zdgDFFfQOsmPT .icon-shape,#mermaid-svg-KH9zdgDFFfQOsmPT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KH9zdgDFFfQOsmPT .icon-shape p,#mermaid-svg-KH9zdgDFFfQOsmPT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KH9zdgDFFfQOsmPT .icon-shape .label rect,#mermaid-svg-KH9zdgDFFfQOsmPT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KH9zdgDFFfQOsmPT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KH9zdgDFFfQOsmPT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KH9zdgDFFfQOsmPT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 成功
超时/失败


命中
未命中
调用 LLM 生成诊断
调用是否成功

且格式合法
进入后处理
重试是否耗尽
降级到「仅 KB 匹配」
K B 是否命中
输出 KB 诊断
降级到「默认诊断模板」

这条链保证了巡检流程永不卡死:LLM 挂了,就退到 KB 匹配;KB 也没命中,就退到默认模板。每一级降级,都让「有诊断可用」比「诊断最精确」更重要。


5. 第三道防线:让「质量」收敛

工作流保证「流程可控」,还差一步------怎么知道 LLM 这次输出「达标」了? 用代码定义「质量判据」,不达标就进 loop 重试,直到收敛或降级。
#mermaid-svg-reSskuZpG3oahMCn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-reSskuZpG3oahMCn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-reSskuZpG3oahMCn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-reSskuZpG3oahMCn .error-icon{fill:#552222;}#mermaid-svg-reSskuZpG3oahMCn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-reSskuZpG3oahMCn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-reSskuZpG3oahMCn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-reSskuZpG3oahMCn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-reSskuZpG3oahMCn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-reSskuZpG3oahMCn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-reSskuZpG3oahMCn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-reSskuZpG3oahMCn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-reSskuZpG3oahMCn .marker.cross{stroke:#333333;}#mermaid-svg-reSskuZpG3oahMCn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-reSskuZpG3oahMCn p{margin:0;}#mermaid-svg-reSskuZpG3oahMCn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-reSskuZpG3oahMCn .cluster-label text{fill:#333;}#mermaid-svg-reSskuZpG3oahMCn .cluster-label span{color:#333;}#mermaid-svg-reSskuZpG3oahMCn .cluster-label span p{background-color:transparent;}#mermaid-svg-reSskuZpG3oahMCn .label text,#mermaid-svg-reSskuZpG3oahMCn span{fill:#333;color:#333;}#mermaid-svg-reSskuZpG3oahMCn .node rect,#mermaid-svg-reSskuZpG3oahMCn .node circle,#mermaid-svg-reSskuZpG3oahMCn .node ellipse,#mermaid-svg-reSskuZpG3oahMCn .node polygon,#mermaid-svg-reSskuZpG3oahMCn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-reSskuZpG3oahMCn .rough-node .label text,#mermaid-svg-reSskuZpG3oahMCn .node .label text,#mermaid-svg-reSskuZpG3oahMCn .image-shape .label,#mermaid-svg-reSskuZpG3oahMCn .icon-shape .label{text-anchor:middle;}#mermaid-svg-reSskuZpG3oahMCn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-reSskuZpG3oahMCn .rough-node .label,#mermaid-svg-reSskuZpG3oahMCn .node .label,#mermaid-svg-reSskuZpG3oahMCn .image-shape .label,#mermaid-svg-reSskuZpG3oahMCn .icon-shape .label{text-align:center;}#mermaid-svg-reSskuZpG3oahMCn .node.clickable{cursor:pointer;}#mermaid-svg-reSskuZpG3oahMCn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-reSskuZpG3oahMCn .arrowheadPath{fill:#333333;}#mermaid-svg-reSskuZpG3oahMCn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-reSskuZpG3oahMCn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-reSskuZpG3oahMCn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-reSskuZpG3oahMCn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-reSskuZpG3oahMCn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-reSskuZpG3oahMCn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-reSskuZpG3oahMCn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-reSskuZpG3oahMCn .cluster text{fill:#333;}#mermaid-svg-reSskuZpG3oahMCn .cluster span{color:#333;}#mermaid-svg-reSskuZpG3oahMCn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-reSskuZpG3oahMCn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-reSskuZpG3oahMCn rect.text{fill:none;stroke-width:0;}#mermaid-svg-reSskuZpG3oahMCn .icon-shape,#mermaid-svg-reSskuZpG3oahMCn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-reSskuZpG3oahMCn .icon-shape p,#mermaid-svg-reSskuZpG3oahMCn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-reSskuZpG3oahMCn .icon-shape .label rect,#mermaid-svg-reSskuZpG3oahMCn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-reSskuZpG3oahMCn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-reSskuZpG3oahMCn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-reSskuZpG3oahMCn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 达标
不达标


生成诊断
质量校验

确定性判据
输出
重试次数

是否耗尽
补充上下文 / 调整参数
降级到默认诊断

python 复制代码
def diagnose_with_loop(problem, max_retry=2):
    for attempt in range(max_retry + 1):
        text = llm_generate(problem)               # 概率性
        text = recover_truncated_json(text)        # 确定性:截断恢复
        if passes_quality_check(text, problem):    # 确定性:判据
            return text
        problem.hint = refine_hint(attempt)        # 补充上下文,下一轮
    return default_diagnosis(problem)              # 确定性:降级

三条原则:

  • 截断恢复在前:被截断时先补全 JSON 尾括号、挽救已生成内容,而不是丢弃重来。
  • 质量判据要可判定:如「是否含历史判定前缀」「是否含工单号」「JSON 是否可解析」,不能靠「感觉差不多」。
  • 兜底永远在 :重试耗尽后降级到默认诊断,保证流程永不中断------这是生产系统与 demo 的分水岭。

5.1 失败模式测试矩阵

作为测试视角,把各种失败模式做成一张可执行的测试矩阵------每种失败一个用例、一个断言,就能把「loop 收敛」从玄学变成可验证:

用例 输入 期望断言
格式漂移 LLM 返回 [暂无历史记录] 归一后 == [历史判定] 暂无历史记录。
截断 JSON 缺尾括号 截断恢复后能正常解析
空响应 返回空串 降级到默认诊断,不抛异常
幻觉 编造不存在的工单号 结构化兜底校验工单号真实性
语义错误 诊断与现象不符 评估阶段打回,进 loop 重试

6. 第四道防线:让「效果」可评估

前面三道防线都在「约束 」和「收敛 」,但它们回答不了最关键的问题:这个诊断到底「对不对」?

格式对 ≠ 内容对。幻觉和语义错误,代码后处理救不了------只能靠「评估」发现。

6.1 评估就像「考试」

把 LLM 的诊断当成学生的答卷,评估就是老师批改:

  • golden dataset(标准答案) :把一批「人工确认过正确」的诊断沉淀下来。它们不是让 LLM 抄,而是改 prompt、换模型后,用来回归------新版本跑一遍标准答案,看关键点有没有答到。
  • 语义断言(阅卷规则):不要求 LLM 输出和标准答案一模一样(那不现实,也太苛刻),而是检查「关键点答到了没有」------必须包含某关键词、必须引用某工单号、结论方向是否正确。
python 复制代码
def semantic_assert(generated: str, reference: dict) -> bool:
    """不追求逐字一致,只校验关键点是否命中"""
    if reference.ticket and reference.ticket not in generated:
        return False          # 该引用的工单号没引用
    for kw in reference.keywords:
        if kw not in generated:
            return False      # 该命中的关键词没命中
    return True

6.2 评估闭环

评估不是一次性动作,而是一个持续闭环:
#mermaid-svg-qlh86DL8q1mOAmq5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qlh86DL8q1mOAmq5 .error-icon{fill:#552222;}#mermaid-svg-qlh86DL8q1mOAmq5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qlh86DL8q1mOAmq5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qlh86DL8q1mOAmq5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qlh86DL8q1mOAmq5 .marker.cross{stroke:#333333;}#mermaid-svg-qlh86DL8q1mOAmq5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qlh86DL8q1mOAmq5 p{margin:0;}#mermaid-svg-qlh86DL8q1mOAmq5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qlh86DL8q1mOAmq5 .cluster-label text{fill:#333;}#mermaid-svg-qlh86DL8q1mOAmq5 .cluster-label span{color:#333;}#mermaid-svg-qlh86DL8q1mOAmq5 .cluster-label span p{background-color:transparent;}#mermaid-svg-qlh86DL8q1mOAmq5 .label text,#mermaid-svg-qlh86DL8q1mOAmq5 span{fill:#333;color:#333;}#mermaid-svg-qlh86DL8q1mOAmq5 .node rect,#mermaid-svg-qlh86DL8q1mOAmq5 .node circle,#mermaid-svg-qlh86DL8q1mOAmq5 .node ellipse,#mermaid-svg-qlh86DL8q1mOAmq5 .node polygon,#mermaid-svg-qlh86DL8q1mOAmq5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qlh86DL8q1mOAmq5 .rough-node .label text,#mermaid-svg-qlh86DL8q1mOAmq5 .node .label text,#mermaid-svg-qlh86DL8q1mOAmq5 .image-shape .label,#mermaid-svg-qlh86DL8q1mOAmq5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-qlh86DL8q1mOAmq5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qlh86DL8q1mOAmq5 .rough-node .label,#mermaid-svg-qlh86DL8q1mOAmq5 .node .label,#mermaid-svg-qlh86DL8q1mOAmq5 .image-shape .label,#mermaid-svg-qlh86DL8q1mOAmq5 .icon-shape .label{text-align:center;}#mermaid-svg-qlh86DL8q1mOAmq5 .node.clickable{cursor:pointer;}#mermaid-svg-qlh86DL8q1mOAmq5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qlh86DL8q1mOAmq5 .arrowheadPath{fill:#333333;}#mermaid-svg-qlh86DL8q1mOAmq5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qlh86DL8q1mOAmq5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qlh86DL8q1mOAmq5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qlh86DL8q1mOAmq5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qlh86DL8q1mOAmq5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qlh86DL8q1mOAmq5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qlh86DL8q1mOAmq5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qlh86DL8q1mOAmq5 .cluster text{fill:#333;}#mermaid-svg-qlh86DL8q1mOAmq5 .cluster span{color:#333;}#mermaid-svg-qlh86DL8q1mOAmq5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qlh86DL8q1mOAmq5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qlh86DL8q1mOAmq5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-qlh86DL8q1mOAmq5 .icon-shape,#mermaid-svg-qlh86DL8q1mOAmq5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qlh86DL8q1mOAmq5 .icon-shape p,#mermaid-svg-qlh86DL8q1mOAmq5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qlh86DL8q1mOAmq5 .icon-shape .label rect,#mermaid-svg-qlh86DL8q1mOAmq5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qlh86DL8q1mOAmq5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qlh86DL8q1mOAmq5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qlh86DL8q1mOAmq5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 通过
不通过
确认错误
确认正确
新诊断
语义断言
上线
人工复核
修正 prompt / 补充 KB
沉淀进 golden dataset

这个闭环的价值在于:每一次「评估发现的问题」,要么修正系统,要么扩充标准答案,让下一轮评估更准。golden dataset 越滚越大,系统越跑越稳------这正是「AI 应用工程」与「普通后端工程」最本质的区别:普通后端靠单测保正确,AI 应用靠「评估闭环」保正确。


7. 完整收敛路径

把四道防线串起来,AI 诊断的完整收敛路径:
#mermaid-svg-J5CLy7fW9jZcYbCJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-J5CLy7fW9jZcYbCJ .error-icon{fill:#552222;}#mermaid-svg-J5CLy7fW9jZcYbCJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-J5CLy7fW9jZcYbCJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .marker.cross{stroke:#333333;}#mermaid-svg-J5CLy7fW9jZcYbCJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-J5CLy7fW9jZcYbCJ p{margin:0;}#mermaid-svg-J5CLy7fW9jZcYbCJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .cluster-label text{fill:#333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .cluster-label span{color:#333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .cluster-label span p{background-color:transparent;}#mermaid-svg-J5CLy7fW9jZcYbCJ .label text,#mermaid-svg-J5CLy7fW9jZcYbCJ span{fill:#333;color:#333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .node rect,#mermaid-svg-J5CLy7fW9jZcYbCJ .node circle,#mermaid-svg-J5CLy7fW9jZcYbCJ .node ellipse,#mermaid-svg-J5CLy7fW9jZcYbCJ .node polygon,#mermaid-svg-J5CLy7fW9jZcYbCJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-J5CLy7fW9jZcYbCJ .rough-node .label text,#mermaid-svg-J5CLy7fW9jZcYbCJ .node .label text,#mermaid-svg-J5CLy7fW9jZcYbCJ .image-shape .label,#mermaid-svg-J5CLy7fW9jZcYbCJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-J5CLy7fW9jZcYbCJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-J5CLy7fW9jZcYbCJ .rough-node .label,#mermaid-svg-J5CLy7fW9jZcYbCJ .node .label,#mermaid-svg-J5CLy7fW9jZcYbCJ .image-shape .label,#mermaid-svg-J5CLy7fW9jZcYbCJ .icon-shape .label{text-align:center;}#mermaid-svg-J5CLy7fW9jZcYbCJ .node.clickable{cursor:pointer;}#mermaid-svg-J5CLy7fW9jZcYbCJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .arrowheadPath{fill:#333333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-J5CLy7fW9jZcYbCJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-J5CLy7fW9jZcYbCJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-J5CLy7fW9jZcYbCJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-J5CLy7fW9jZcYbCJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-J5CLy7fW9jZcYbCJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-J5CLy7fW9jZcYbCJ .cluster text{fill:#333;}#mermaid-svg-J5CLy7fW9jZcYbCJ .cluster span{color:#333;}#mermaid-svg-J5CLy7fW9jZcYbCJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-J5CLy7fW9jZcYbCJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-J5CLy7fW9jZcYbCJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-J5CLy7fW9jZcYbCJ .icon-shape,#mermaid-svg-J5CLy7fW9jZcYbCJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-J5CLy7fW9jZcYbCJ .icon-shape p,#mermaid-svg-J5CLy7fW9jZcYbCJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-J5CLy7fW9jZcYbCJ .icon-shape .label rect,#mermaid-svg-J5CLy7fW9jZcYbCJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-J5CLy7fW9jZcYbCJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-J5CLy7fW9jZcYbCJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-J5CLy7fW9jZcYbCJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 评估
收敛
编排
约束
超时/失败
达标
不达标
重试耗尽
通过
不通过
Prompt 约束
后处理规范化
结构化兜底
KB 匹配
分批 LLM
归一化匹配
降级链:KB 兜底 / 默认模板
质量校验
输出
重试 / 补上下文
默认诊断兜底
语义断言 / golden 回归
交付
修正 prompt / 补充 KB

四道防线各司其职:

  • 约束 ------让「一次调用」的格式对;
  • 编排 ------让「多次调用」的流程可控、可降级;
  • 收敛 ------让「最终输出」的质量达标、有兜底;
  • 评估 ------让「整体效果」的正确性可验证、可持续改进。

8. 总结

AI Native 系统的核心矛盾是:LLM 提供了强大的生成能力,但它是概率系统,输出天然不稳定。

工程化的解法,是把不确定性关进笼子,而且要用四道防线逐层关紧:

  1. 约束------Prompt 约束「尽量」守规矩,后处理规范化「纠正」格式漂移,结构化兜底「补全」关键信息;
  2. 编排------把 LLM 编排成确定性工作流,确定性步骤与概率性步骤分离,配降级链保证永不卡死;
  3. 收敛------用确定性判据做质量校验,不达标就 loop 重试,重试耗尽就降级兜底;
  4. 评估------用 golden dataset + 语义断言做回归,把「格式对」推进到「内容对」。

一句话总结:

先相信 LLM 能做,但永远用代码兜底;

把 LLM 关进确定性工作流的笼子里,用 loop 逼它收敛,再用评估证明它对。

让 LLM 做它擅长的事(分析、生成、概括),把「确定性」和「正确性」交给工程手段------这样,AI 的输出才真正「可依赖」。

相关推荐
2501_9269783343 分钟前
AGI封锁的物理边界:发现模式决定封锁可行性
人工智能·经验分享·笔记·ai写作·agi
tech讯息44 分钟前
企业 AI Agent 对接外部服务如何安全集成?—— 多租户业务场景优先选用 WebSocket 方案
人工智能·websocket·安全
过去式的美好1 小时前
阿里云 2 核 2G 服务器搭建 AI 知识库:从 0 到可用(附踩坑实录)
服务器·人工智能·阿里云
薛定谔的悦1 小时前
储能系统CAN通信抽象层解读
人工智能·能源·储能
江畔柳前堤1 小时前
AgentScope 设计与原理全解:从消息原语到分布式智能体工程底座
大数据·人工智能·分布式·目标检测·机器学习·语言模型·架构
Yiran_G1 小时前
低功耗 Zigbee 模组怎么选?基于 CC2340R53 的 WS8823 设计实践
人工智能·物联网·智能家居
Elastic 中国社区官方博客1 小时前
跳过有状态的 OTel Collector:Elasticsearch 9.5 原生存储两种指标时间类型
大数据·人工智能·elasticsearch·搜索引擎·重构·全文检索
show4331 小时前
2026小程序端AI智能优化技术实践:转文字后自动纠错+润色+分段算法分析
人工智能·算法·小程序
今天AI了吗1 小时前
Agent & AI 名词大扫盲
数据库·人工智能·python·sql·rust