AI Agent 开发讨论记录
20260407
话题 1:混合检索中 BM25 与向量检索的融合与权重设定
核心问题
在 RAG 系统的混合检索中,BM25(词法匹配)和向量检索(语义匹配)如何融合?权重如何设定?
要点摘要
为什么要混合:BM25 擅长精确关键词/专有名词匹配,向量检索擅长同义词/语义意图理解。两者信号正交互补。
三种融合方式:
- Score-level 加权融合:
final = α × norm(bm25) + (1-α) × norm(vector),需要分数归一化(Min-Max 或 Z-score) - RRF(Reciprocal Rank Fusion):
score = Σ 1/(k + rank_i),k 通常取 60。不依赖分数分布,是工业界最稳方案 - Learned 融合:BM25 top-K ∪ Vector top-K → Cross-Encoder Rerank,权重由模型隐式学习
权重设定方法:
- 经验起点:α ∈ [0.3, 0.5](BM25 权重),语义占主导
- Grid Search:有标注数据时在验证集上扫 α
- RRF:无标注数据时的最佳选择,对超参不敏感
- Query-adaptive:按 query 类型动态调权(关键词型 → BM25 高,自然语言型 → 向量高)
- Cross-Encoder Rerank:latency 允许时(+50~100ms)几乎总是最优
关键结论:
- RRF 是"懒人最优解",主流向量数据库(Elasticsearch 8.x、Qdrant、Weaviate)都内置支持
- α 最优值高度依赖 query 分布,无万能值
- 如果精度要求高且 latency 允许,Cross-Encoder Rerank 是最终答案
话题 2:Agent 循环终止条件设计,避免死循环
核心问题
Agent 执行过程中如何设计循环终止条件?有哪些真实 case?
根因分类
- 工具幻觉循环:反复调用同一工具但输出不变,无限 retry
- 目标漂移循环:每轮生成新子目标,永远无法收敛
- 自我验证循环:修复 → 验证失败 → 再修复,陷入振荡
四层防御体系
- 硬性计数器:MAX_STEPS / MAX_TOOL_CALLS / MAX_SAME_TOOL,兜底红线,不可软化
- 语义去重检测:对 (action, observation) 哈希或 embedding 相似度检测重复状态,连续 3 步相似度 > 0.95 → 强制打断
- 目标收敛性验证:每 N 步让 LLM 自评进展是否有效,stuck → replanning(不是 retry)
- 时间熔断:SIGALRM 或 asyncio.timeout,超时返回 partial_result 而非空结果
真实 Case:代码修复 Agent 的振荡死循环
模式:修复 test_A → 破坏 test_B → 修复 test_B → 破坏 test_A → 无限循环
问题:每步都有 action,计数器不会及时触发,但系统在两个状态间振荡
解法:引入变更集去重——检测文件版本的回滚模式(v0 → v1 → v0),一旦检测到,强制从"单点修复"升级为"全量依赖图分析"策略
设计原则
- 硬限制不可协商,MAX_STEPS 是红线不是建议
- stuck ≠ retry,stuck = replan(换方向,不是加力推同一面墙)
- 语义层面去重比计数更有效
- 熔断时返回 partial_result,优于空手而回
话题 3:Agent 安全护栏设计与模型选型
核心问题
Agent 的安全护栏怎么做?如果用模型做安全检测,如何选型和调用?
分层防御架构(从低成本到高成本)
| 层级 | 手段 | 延迟 | 防御目标 |
|---|---|---|---|
| L0 | 正则/关键词黑名单 | <1ms | 低成本批量攻击 |
| L1 | 轻量分类器(Llama Guard / DistilBERT) | 5~20ms | 毒性/有害意图分类 |
| L2 | 主模型 System Prompt 安全指令 | 0(内嵌) | 行为边界定义 |
| L3 | 输出审查(小模型分类或主模型自审) | 20ms~2s | 有害输出/幻觉/信息泄露 |
| L4 | 工具调用审计 | 按需 | Agent 最关键层:拦截危险操作 |
安全模型选型
- FastText:<1ms,精度 ~85%,适合超高 QPS + 预算紧
- Llama Guard 3 (1B):~20ms GPU,精度 ~95%,推荐方案——专为安全分类训练,对齐 MLCommons 标准
- OpenAI Moderation API:~100ms,精度 ~93%,不想自建模型时用
- 主模型自审:+500ms~2s,语境理解最深,适合高风险领域(医疗/金融)
关键设计原则
- 每一层独立防御,不依赖其他层
- 安全模型必须和主模型异构——同模型做审查,被 jailbreak 后审查也失效
- 输入审查 + 输出审查缺一不可——安全输入可能产生不安全输出
- Agent 最大风险不是"说错话"而是**“做错事”**——工具调用审计(L4)是 Agent 区别于 chatbot 的最关键安全层
- 未知工具默认最高风险级别
常见踩坑
- 只靠 System Prompt = 裸奔(Prompt injection 技术已有现成工具包)
- 做了输入审查但漏了输出审查
- 工具调用没有独立审计通道
- 安全模型和主模型用同一个(同源 jailbreak 风险)
话题 4:工具调用失败时的优雅降级与用户反馈
核心问题
Agent 调用工具失败、超时或返回空值时,如何通过 Prompt 和工程手段实现优雅降级?
失败类型拆分(不同类型策略不同)
- 硬失败(500/异常):重试 → 降级备选 → 告知用户
- 超时:取消 → 降级 → 部分结果返回
- 空值(查无数据):不是错误,不应重试,应改查询策略或如实反馈
- 格式异常:日志 + 降级
降级方式
- 换备选工具
- 缩小目标:拿不到完整数据,就返回已确认的部分数据
- 改用已有信息回答:如果工具查不到就坦白“查不到”,并基于上下文给出有限回答
- 改查询策略再试一次:换参数、改关键词、改过滤条件、改检索方式
工程侧关键设计
- 结构化错误返回:ToolResult 包含 status/error_message/fallback_hint/retry_allowed,给 LLM 可操作的降级提示
- 分级重试策略:RetryPolicy 按工具配置 max_retries + 指数退避 + fallback 工具链
- 幂等性保障:有副作用的操作(send_email/delete/write)绝不重试,或引入幂等键防重复执行
Prompt 侧关键设计
- 在 System Prompt 中预编程降级行为,不让 LLM 临场发挥
- 硬失败:最多重试 2 次 → 尝试备选工具 → 坦诚告知 + 基于已有信息回答
- 空值:不重试同参数,先改写查询再试一次,仍空则如实反馈
- 部分成功:使用已有数据,标注哪些已验证/哪些是推测
用户反馈话术原则
- 坦诚 + 降级推理 + 标注置信度 + 给用户替代方案
- 禁止:空洞的"无法完成"、把锅甩给用户、静默跳过假装没用工具
最重要的坑
- 把"空值"当"失败"处理 → 导致无意义重试循环
- 非幂等操作重试 → 重复发邮件/重复下单等真实事故
话题 5:材料领域 RAG 系统的 Prompt 设计
项目背景
材料科学领域的知识抽取 + 混合检索 + RAG 问答端到端系统。
知识抽取与摘要生成 Prompt
- 角色设定:锚定"材料科学数据工程师",嵌入领域硬约束(化学式精度、单位有效数字、测试条件不可省略、缺失值标注"未报告"而非编造)
- 结构化输出:JSON Schema 约束抽取粒度(material/synthesis/performance),关键设计是
raw_sentence字段保留原文用于溯源 - Few-shot 选样策略:覆盖材料类别多样性 + 包含"未报告"场景 + 包含多步合成路径;token 紧张时优先砍检索结果数量,不砍 few-shot
RAG 问答 Prompt
- 检索结果注入:带来源编号的模板,要求引用数据必须标注 [来源 X]
- 查询改写:用户自然语言 → 三路查询(semantic_query 走向量、structured_filters 走数据库精确过滤、must_contain_keywords 走 BM25),RRF 融合
- 反幻觉三规则:①数值必须可溯源 ②条件不同禁止直接对比 ③推测与事实用前缀分离
Prompt 组装顺序
System Prompt(角色+约束+反幻觉+降级策略)→ Few-shot(2~3个)→ Retrieved Context(带编号+metadata)→ User Query
Token 预算分配(8K context)
System+规则 ~15% | Few-shot ~20% | 检索结果 ~50% | 问题+输出 ~15%
话题 6:Agent 记忆系统设计——短期记忆与长期记忆
核心问题
Agent 体系中短期记忆和长期记忆分别怎么设计?各自存在哪里?如何做更新和清理?
记忆分层架构
| 层级 | 类比 | 载体 | 生命周期 | 容量 |
|---|---|---|---|---|
| 工作记忆 | CPU 寄存器 | LLM Context Window | 单轮推理 | 4K~200K tokens |
| 短期记忆 | RAM | 会话状态存储(Redis/内存) | 单次会话 | 数十轮对话 |
| 长期记忆 | 硬盘 | 向量数据库 + KV 存储 | 跨会话持久化 | 无上限 |
工作记忆(Context Window 管理)
- 滑动窗口:保留最近 N 轮,丢弃更早的,最简单但会丢关键上下文
- 摘要压缩:超过阈值时用 LLM 将旧对话压缩为摘要,压缩比约 5:1~10:1
- 分层注入:System Prompt(常驻)+ 摘要(半常驻)+ 最近 K 轮原文(滑动)+ 检索结果(按需)
短期记忆(Session Memory)
- 存储位置:简单方案用内存
List[Message],工程方案用 Redis/DynamoDB 以session_id为 key - Scratchpad(草稿板):Agent 内部推理区域,存放中间推理、子目标分解、工具调用计划,不返回给用户但参与下一轮推理(ReAct/CoT 的工程实现)
- 任务栈:跟踪当前任务、子任务、已完成步骤,防止 Agent 迷失方向
- 压缩触发:Token 计数 > 0.7 × context_window 或每 N 轮,两者取先
- 关键坑:压缩前必须做 fact extraction,将硬约束(用户偏好、已确认决策)单独存储,不参与压缩
长期记忆(Persistent Memory)
- 用户画像 → KV Store,精确查询
- 对话摘要 → 向量数据库,语义检索
- 事实记忆 → 结构化 DB + 向量索引,混合检索
- 技能/经验 → 向量数据库,语义检索
- 写入时机:会话结束时提取摘要+facts、用户显式指令、隐式学习(检测到反复纠正 → 提取经验规则)
- 检索注入:用户新消息 → 向量化 → 长期记忆检索 top-K → 注入 Context → LLM 推理
记忆更新与清理策略
- 覆盖更新:同一 key 新值覆盖旧值
- 矛盾检测:写入前检查新旧记忆是否矛盾,时间戳新的优先或标记冲突待确认
- TTL 过期:超过 T 天自动标记 stale(适合时效性信息)
- LRU 淘汰:满了淘汰最久未用的
- 重要度衰减:
importance = base_score × decay(t),平衡新鲜度和重要性 - 语义去重:embedding 相似度 > 0.95 的记忆合并
- LLM 主动整理:定期让 LLM 审查记忆库,合并/删除/更新(最灵活但成本最高)
工业界参考
- MemGPT/Letta:Context Window 类比虚拟内存,Agent 自主决定换入换出,“管理记忆"本身是一种工具调用
- LangGraph Checkpointer:短期用 thread_id 级状态持久化,长期用 Store 接口 + namespace 级 KV/向量检索
- 常见选型:短期 Redis(TTL)或 SQLite;长期 PostgreSQL+pgvector 或专用向量库
设计原则
- 记忆有成本——不是越多越好,每条都消耗检索时间和 Context 空间
- 写入要克制,检索要精准——低质量记忆污染检索
- 压缩 ≠ 丢弃——硬约束不能丢
- 矛盾检测必须有——否则 Agent 新旧信息冲突导致"精神分裂”
- 定期清理不可少——过时信息比没有信息更有害
常见踩坑
- 只做滑动窗口没做摘要压缩 → 早期关键信息丢失
- 长期记忆只写不清 → 过时/矛盾信息堆积,回答质量下降
- 压缩时没保留用户硬约束 → 用户说"不要 X",压缩后又推荐 X
- 所有记忆同等对待 → 应区分 facts/preferences/episodes,检索权重不同
- 记忆检索没有相关性阈值 → 不相关记忆注入 Context 干扰推理
话题 7:交叉编码器(Cross-Encoder)在 Rerank 中的作用
核心问题
Cross-Encoder 在 Rerank 中的作用是什么?相比双塔模型(Bi-Encoder),优势和代价分别是什么?
核心区别
- Bi-Encoder(双塔):Query 和 Doc 独立编码为向量,最后做点积/余弦相似度。Doc 向量可离线预计算,速度极快,但语义理解浅——所有信息压缩到一个向量,丢失细粒度交互
- Cross-Encoder(交叉编码器):Query 和 Doc 拼接后联合编码(
[CLS] Query [SEP] Doc [SEP]),每层 self-attention 都做 query-doc token 级交互。语义理解深,但每个 pair 都要完整 forward,不可预计算
Cross-Encoder 精度更高的根因
- Bi-Encoder 的信息瓶颈:所有语义压到一个 768d 向量,无法做词级对齐
- Cross-Encoder 无瓶颈:token 级全交叉注意力,能理解否定语义、条件约束、细粒度匹配
- 示例:查询"室温下抗拉强度超过 500MPa 的铝合金"时,Cross-Encoder 能区分温度条件不匹配的文档,Bi-Encoder 做不到
代价对比
| 指标 | Bi-Encoder | Cross-Encoder |
|---|---|---|
| 延迟 | ~5ms(ANN 检索百万文档) | ~50-100ms(重排 20-50 候选) |
| 可索引性 | 可预计算、可 ANN | 不可预计算、不可建索引 |
| 适用规模 | 全库检索(百万~十亿) | 仅候选精排(10~100 个) |
检索-重排 Pipeline
全库 → Stage 1 粗召回(BM25 + Bi-Encoder, top-100, ~5ms)→ Stage 2 精排(Cross-Encoder, top-10, ~50-100ms)→ Stage 3 业务规则/多样性过滤 → 最终 Top-K
模型选型参考
cross-encoder/ms-marco-MiniLM-L-6-v2(22M):~15ms/20docs,低延迟优先BAAI/bge-reranker-v2-m3(568M):~80ms/20docs,多语言/中文推荐Cohere Rerank v3(API):~100ms,不想自建时用
优化技巧
- 候选数控制:20~50 个是甜区,超 100 加轻量预排
- Batch 推理:各 pair 独立,天然可 GPU 并行
- 知识蒸馏:Cross-Encoder 做 teacher 训练更小的 Bi-Encoder(ColBERT 思路)
- Late Interaction(ColBERT):折中方案——Doc token 级向量可预计算,query-doc token 级 MaxSim 交互,精度接近 Cross-Encoder,速度接近 Bi-Encoder
材料领域特殊考量
- 化学式/晶体结构的细微差异需要 token 级精确匹配,Cross-Encoder 优势明显
- 温度、压力、成分比例等条件约束是查询核心,Bi-Encoder 的向量压缩容易丢失
- 材料领域 RAG 强烈推荐加 Cross-Encoder Rerank
话题 8:Rerank 效果评估——NDCG、MRR 及工程实践
核心问题
如何量化评估 Rerank 的效果?NDCG、MRR 等指标的含义、适用场景、以及在材料领域 RAG 中的实际应用。
核心指标对比
| 指标 | 相关性类型 | 关注重点 | RAG 适用度 |
|---|---|---|---|
| MRR | 二值 | 仅第一个相关结果位置 | 低——RAG 需多个文档 |
| MAP | 二值 | 所有相关结果的位置 | 中——二值标注太粗 |
| NDCG@K | 多级 | top-K 整体排序质量 | 高——RAG 首选 |
| Recall@K | 二值 | 相关文档是否被召回 | 高——评估召回阶段 |
NDCG@K 详解
DCG@K = Σ (2^rel_i - 1) / log₂(i+1),位置越靠前权重越大NDCG@K = DCG@K / IDCG@K,归一化到 [0,1],不同 query 可比- 支持多级相关性标注(0-3分),区分粒度远优于二值指标
评估数据集构建
- 人工标注(金标准):200~500 条 query,每条 top-50 候选,0-3 级打分
- LLM 辅助标注(降本):GPT-4 与人工 Cohen’s Kappa 可达 0.70.8,必须人工抽检 1020%
- 隐式反馈(零成本):用户点击行为,适合线上持续评估,噪声大
Rerank 前后 A/B 对比(典型提升幅度)
| 阶段 | NDCG@10 | MRR |
|---|---|---|
| BM25 only | ~0.35 | ~0.40 |
| + Vector hybrid | ~0.42 | ~0.48 |
| + Cross-Encoder Rerank | ~0.50 | ~0.58 |
- 使用 paired t-test 或 Wilcoxon signed-rank test 验证显著性(p < 0.05)
- 推荐工具:
ranx(30+ 指标 + 统计显著性检验)
端到端评估(线上)
离线排序指标好 ≠ 最终回答好。需同时评估:
- Answer Faithfulness / Relevance(LLM-as-Judge)
- Context Precision / Recall(标注 + 自动化)
- 推荐框架:
ragas(RAG 端到端质量评估)
材料领域评估特殊处理
- 标注相关性时必须考虑实验条件是否匹配,不能只看材料名称
- 分 query 类型统计:性能查询看 MRR,对比查询看 NDCG,综述查询看 Recall@K
- 数值精度和溯源性需单独评估
设计原则
- 没有标注数据 = 没有评估——构建标注集是第一优先级
- NDCG@K 是 RAG 检索评估首选——多级相关性 + 位置折扣
- 离线指标和线上效果必须同时看
- 统计显著性不能省——少于 200 条 query 的结论要打折扣
常见踩坑
- 只看整体均值不看分层表现 → 掩盖某类 query 效果恶化
- 用二值标注评估 Rerank → 粒度太粗,区分不出排序微调效果
- 标注集和检索系统同源 → 评估不同系统时产生偏差
- 忽略延迟-精度权衡 → NDCG 提升 2% 但延迟增加 3 倍,不值得上线
话题 9:召回效果测试与优化优先级
核心问题
如何系统测试召回效果?召回质量不好时,优先优化哪个环节?为什么?
召回测试指标
- Recall@K:top-K 覆盖了多少相关文档(召回阶段核心指标)
- Hit Rate@K:至少命中 1 个相关文档的 query 占比(最宽松通过率)
- 召回阶段追求 Recall(不漏),不是 Precision(不错)——漏召了 Rerank 救不回来
测试集构建(材料领域三类难度)
- 精确查询(“Al₂O₃ 在 1200°C 的热导率”)→ 关键词精确匹配
- 语义改写(“氧化铝高温导热性能” → 同一篇文档)→ 同义词理解
- 跨表述(“哪些陶瓷适合隔热” → 召回 Al₂O₃/ZrO₂)→ 泛化 + 领域知识
召回问题诊断(逐层排查)
原始文档 → 切分 → 编码 → 索引 → 检索策略,每层有对应诊断方法:
- 数据质量:抽样看原始文档(格式/OCR/表格丢失)
- 切分策略:检查被切断的 case
- Embedding 质量:相似 query-doc 的余弦相似度分布
- 索引配置:ANN vs 暴力搜索对比(overlap < 0.9 → 参数有问题)
- 检索策略:BM25/Vector 各自召回率对比
优化优先级(ROI 从高到低)
- Chunk 切分策略(ROI 最高):切分是后续所有步骤的基础,垃圾进垃圾出。推荐 512 tokens + 12.5% 重叠 + 结构感知切分(表格整表不切)
- Query 改写/扩展:同义词扩展(化学式↔中文↔英文)、HyDE(假想答案向量检索)、多路查询
- Embedding 模型升级:中文推荐 bge-large-zh-v1.5 或 bge-m3;领域微调用 5000~10000 对数据 + MultipleNegativesRankingLoss
- 索引参数调优:通常不是瓶颈,快速检查即可
验证闭环
发现问题 → 定位层级 → 针对性优化 → 用固定测试集回归测试 → 对比指标变化
设计原则
- Recall 是召回阶段唯一目标——漏召不可逆
- 先诊断再优化——不要上来就换模型
- 先修数据 → 再调策略 → 最后换模型——ROI 递减
- Bad Case 驱动优化——线上真实失败 case 最有价值
常见踩坑
- Recall@K 够高就不管 Precision → 不相关文档干扰 LLM 生成
- 只测 happy path → 漏了语义改写和跨表述难例
- 切分用固定字数不看内容 → 表格/公式/上下文被截断
- 换 embedding 模型没重建索引 → 新旧向量空间不兼容
- HyDE 不加验证直接用 → 假想答案幻觉反而带偏检索
话题 10:RAG 工程实战中的核心踩坑与解法
核心问题
真实业务中 RAG 最大的坑是什么?幻觉、召回偏差、延迟等问题如何系统性解决?
问题严重度排名(按 发现难度×后果 排序)
- 幻觉(拼接/推断/格式幻觉)——最致命,引用格式正确但内容失真,用户无法分辨
- 召回沉默失败——系统不报错但答案基于错误文档,比"我不知道"更危险
- 上下文污染——多文档矛盾时 LLM 随机选择或错误合并
- 延迟不可控——LLM 生成占 90%+ 延迟
- 数据新鲜度——知识库腐烂,返回过时信息
幻觉防御(三层)
- Prompt 硬约束:数值必须标注来源、不同来源数据禁止跨条件组合、缺数据回答"未收录"、近似值保持近似表述
- 结构化输出 + 溯源:每个声明关联 source_id + raw_sentence(原文原句),可自动比对一致性
- 输出校验:自动检查来源是否存在、原文是否在文档中、数值是否一致
召回沉默失败防御
- 检索结果整体相关性自检(max_sim < threshold → 触发"我不知道")
- Query-Doc 关键实体对齐(材料/性能类型/测试条件是否匹配)
- Prompt 中嵌入自检指令,不匹配时必须在开头指出
上下文污染防御
- 按来源/条件分组注入(不要平铺),标注各自测试条件
- Prompt 禁止取平均/最大/最小值,要求分别列出并解释差异原因
延迟优化
- Streaming 输出(必须做,感知延迟降 70%+)
- 分级策略:简单查询跳过 Rerank,复杂查询走全链路
- 检索缓存、异步预取、减少注入文档数
数据新鲜度
- 文档时间戳 + 检索时加权(时间衰减最多影响 30% 权重)
- 增量更新 Pipeline(新文档入库,旧版本标记不删除)
- 回答中标注数据时间
RAG 工程"铁三角"
数据质量(地基)→ 检索精度(管道)→ 生成可控性(龙头) 优先级永远是:数据 > 检索 > 生成——大部分团队在生成端调 Prompt 投入过多,回头修数据和检索的 ROI 高得多
话题 11:材料数据库 RAG 架构的实际坑位分析
核心问题
在"实验室数据 → JSON → LLM 生成摘要 → 向量检索 → Agent 决定是否追加 SQL"的实际架构中,通用 RAG 的哪些坑存在、哪些不存在?有哪些独有的坑?
架构链路
实验室上传半结构化数据 → 导出 JSON → LLM 生成摘要(第一层 LLM 介入)→ 摘要入向量库 → 用户查询 → 向量检索摘要 → Agent 判断是否追加 SQL → 综合回答
坑位对标
| 坑 | 是否存在 | 严重度 | 核心原因 |
|---|---|---|---|
| 幻觉 | ✅ 存在且加重 | ⭐⭐⭐⭐⭐ | 两层 LLM 介入,幻觉可叠加 |
| 召回沉默失败 | ✅ 形态变了 | ⭐⭐⭐ | 摘要有损压缩导致信息丢失 |
| 上下文污染 | ✅ 尤其突出 | ⭐⭐⭐⭐ | 多实验室命名/标准/单位不统一 |
| 延迟 | ⚠️ 可控 | ⭐⭐ | SQL 很快,Agent 判断可优化 |
| 数据新鲜度 | ❓ 视上传频率 | ⭐~⭐⭐⭐ | 增量 Pipeline 是否自动化 |
| 摘要单点故障(独有) | ✅ | ⭐⭐⭐⭐ | 摘要质量=系统天花板 |
| SQL/摘要矛盾(独有) | ✅ | ⭐⭐⭐ | 两个数据源优先级必须明确 |
幻觉(加重)
- 两层 LLM 幻觉叠加:摘要生成丢精度/遗漏条件 → 回答基于失真摘要继续推断
- 解法:摘要生成强制保留原始数值精度+完整条件、摘要生成后自动校验数值一致性、数值查询强制走 SQL 验证不依赖摘要
召回沉默失败(形态变了)
- 原始 JSON 有数据但摘要省略了 → 检索不到 → 误判为"未收录"
- 解法:摘要附带结构化 index_metadata(覆盖的性能类型、条件范围、源表 ID),即使摘要正文没提,metadata 能命中
上下文污染(尤其突出)
- 多实验室同材料异名(Ti-6Al-4V / TC4 / Ti64)、单位不统一、测试标准不同
- 解法:入库前材料名归一化+单位归一化+测试标准标注;摘要中强制标注来源实验室和标准
架构独有的防御优势
SQL 精确查询兜底——普通 RAG 没有这个条件
- 核心原则:摘要只做语义导航和上下文理解,不做数值依据;精确数值以 SQL 为准
- 数值类查询强制走 SQL,不给 Agent 选择权
- SQL 和摘要结果矛盾时,SQL 优先级更高
话题 12:多 Agent 协作架构设计
核心问题
多 Agent 协作中,任务如何拆分?Agent 之间如何通信?有哪些主流架构模式?
为什么需要多 Agent
单 Agent 面临职责过载(Prompt 塞满指令遵循率下降)、能力冲突(无法各领域都最优)、上下文溢出等瓶颈。拆成多 Agent 核心收益:每个 Agent 职责单一 → Prompt 精简 → 指令遵循率高。
任务拆分维度
- 按职能:Retriever / Reasoner / Validator
- 按阶段:Query理解 → 检索 → 排序 → 生成 → 审核
- 按领域:材料性能Agent / 合成工艺Agent / 测试标准Agent
- 按角色:Planner / Executor / Critic / Reporter
- 拆分甜区 3~5 个 Agent,超过 7 个要警惕通信开销 > 分工收益
四种协作架构
| 架构 | 通信方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 中心化编排 | Orchestrator 调度子 Agent | 控制流清晰,可控性最强 | Orchestrator 是单点瓶颈 | 生产系统首选 |
| 顺序流水线 | 上游输出=下游输入 | 最简单,环节独立可替换 | 不能并行/回退 | 流程固定的 Pipeline |
| 辩论对抗 | Agent 交替发言,Judge 仲裁 | 推理质量高 | 延迟×2~3,token 消耗高 | 高可靠性关键决策 |
| 去中心化自治 | Agent 间直接 handoff | 灵活可扩展 | 控制流不可预测 | 研究原型,不推荐生产 |
Agent 间通信设计
- Agent 间传递结构化消息(AgentMessage: sender/receiver/msg_type/task/payload/constraints),不传自由文本
- 上下文传递推荐共享状态池(SharedState):所有 Agent 读写同一状态对象,每个 Agent 只读需要的字段、只写负责的字段
- 共享状态优于消息传递:减少重复传递、方便调试
容错与降级
- 每个子 Agent 独立超时 + 降级策略,一个挂了不拖垮整个系统
- 检索和 SQL 可并行执行(asyncio.gather),任一失败则降级为另一路
- 调用深度计数器(MAX_DEPTH=3)防循环调用
- 结果矛盾时 Orchestrator 按优先级仲裁(SQL 优先)
多 Agent vs 单 Agent + 多工具
不是所有场景都需要多 Agent。工具 < 5 个、流程固定、同领域 → 单 Agent + 多工具足够。工具 > 10 个、需要交叉验证、中间结果多 → 多 Agent。
常见踩坑
- Agent 拆太细 → 通信开销 > 分工收益
- Agent 间传自由文本 → 信息失真、格式不可预测
- 没有容错机制 → 一个子 Agent 挂掉整体崩溃
- 协调逻辑写在 Prompt 里 → 条件判断/并行控制应写在代码里
- 去中心化架构用于生产 → 控制流不可预测,bug 无法复现
话题 13:Agent 系统的稳定性与可观测性工程
核心问题
从 Harness 角度,如何系统性提升 Agent 的稳定性和可观测性?
Agent 可观测性的特殊挑战
传统系统输入/逻辑/输出确定;Agent 系统四重不确定(输入×决策×工具调用×输出),“bug"不是代码报错而是决策质量下降,甚至不知道它在犯错。
可观测性三支柱 + Agent 扩展
Metrics(指标):
- 运维指标:延迟 p50/p95/p99、Token 消耗、工具调用次数和错误率、推理循环次数、单次成本
- 质量指标(Agent 专属):幻觉率、引用准确率、工具选择正确率、回答相关性、SQL 降级触发率、检索空结果率
Structured Event Log:
- 结构化事件序列(非文本日志),每个事件是 JSON(event_type/payload/duration_ms/token_count)
- 关键:
decision_made事件记录 Agent 每个决策点的推理和备选方案
Agent Trace(决策链追踪):
- 追踪完整思考和行动链:query_understanding → retrieval → decision_point → sql_query → answer_generation → validation
- 工具选型:LangSmith(LangChain 体系)、Phoenix/Arize(通用)、Langfuse(轻量开源)、OpenTelemetry(自建)
稳定性五道防线
- 输入防御:长度限制 + Prompt Injection 检测 + 速率限制 + 意图可行性预判
- 执行熔断:max_steps/max_tool_calls/max_llm_calls/max_tokens_total/timeout
- 输出校验:安全审查 + 幻觉检测(数值与 SQL 比对)+ 引用一致性 + 置信度标注
- 降级策略矩阵:LLM 不可用→缓存/降级模型,检索不可用→纯 SQL,SQL 不可用→纯检索+标注,全不可用→静态 FAQ
- 灰度发布 + 回滚:Prompt 版本管理,5% 流量灰度,指标异常一键回滚
告警设计
- 不只看"服务是否活着”,要看"Agent 是否在做正确的事"
- 质量级告警:幻觉率 spike → 自动切保守模式、检索空结果率 spike → 检查向量库、循环次数异常 → 检查 Prompt 变更
事后分析:Session Replay
- 完整复现某次会话的决策链:每个决策点的选择、理由、备选方案
- 价值:用户投诉时能复现"Agent 为什么这么决策"
可观测性成熟度模型
- L0 基础日志:“在运行吗?”
- L1 结构化事件+指标:“哪个环节慢?”
- L2 Agent Trace+决策审计:“为什么做了这个决策?”
- L3 质量指标+告警:“回答质量是否下降?”
- L4 Session Replay+根因分析:“为什么这个 case 错了?同类有多少?”
- 生产至少 L2,目标 L3,L4 是竞争优势
话题 14:大模型辅助开发的实际应用与效率提升
核心问题
日常开发中如何利用大模型提升效率?做过哪些实际项目或尝试?
使用场景 ROI 排序
- ⭐⭐⭐⭐⭐ 样板代码生成(数据类/CRUD/测试用例)5~10x
- ⭐⭐⭐⭐⭐ Debug 辅助(报错信息→修复方案)3~5x
- ⭐⭐⭐⭐ 代码理解(读陌生代码库)3~5x
- ⭐⭐⭐⭐ 文档/注释生成 3x
- ⭐⭐⭐ 架构讨论(当橡皮鸭)2x
- ⭐⭐ 复杂算法实现(框架可用但细节需审)1.5x
- ⭐ 核心业务逻辑(不理解业务上下文)1x 甚至负
高效使用模式
- Prompt 驱动代码生成:给现有代码风格+新需求→LLM 生成初版→review 修改。样板代码从 2h 降到 20min
- 报错信息直接喂 LLM:附带上下文(代码片段+环境+已试方案),比翻文档快 3 倍
- 代码审查辅助:让 LLM 重点关注边界条件、空值处理、并发安全
- 测试用例生成:给实现代码→生成覆盖 happy path + edge case 的测试,ROI 极高
- Meta-prompting:用 LLM 帮优化 Prompt——给"当前 Prompt+输入+实际输出+期望输出"让 LLM 分析缺陷
材料项目实际案例
- ETL Pipeline 加速:50+ 种格式的实验室数据解析,LLM 识别不规范数据结构并生成适配代码,每个解析器从 4h 降到 40min
- SQL 查询构造:LLM 生成 text-to-SQL 的 few-shot 示例+SQL 模板,几天压缩到一天
- 文档自动生成:从代码提取签名→API 参考,从 schema→数据字典,从 git log→CHANGELOG
教训和红线
- 盲信 LLM 代码是最大的坑——必须 100% review,尤其边界条件和并发
- LLM 做不了需要权衡的架构决策——它是执行工具不是决策者
- 上下文给太少 → 输出质量差;Prompt 太长 → LLM 选择性忽略;拆成多步更好
- 红线:安全代码、线上 DB 操作、不理解就用、替代人工审查
核心认知
- LLM 是放大器不是替代器——放大已有能力,不替代缺失知识
- ROI 最高:“结构清楚但写起来无聊"的代码
- ROI 最低:“需要深度领域知识和权衡判断"的工作
- 给够上下文是决定输出质量的关键
- LLM 生成的代码 = 初级工程师的初稿——需要 senior review
话题 15:Skill 开发方法论——边界设计决定 Agent 上限
核心观点
- Skill 本质是契约(输入契约、行为契约、输出契约),不是 Prompt 堆砌
- 决定 Agent 上限的是边界设计,不是步骤数量
- Agent 的强项是在约束内自主推理,不是机械执行步骤
五大设计原则
- 单一触发、单一职责:一个 Skill 做一件事,出问题能精确定位
- 触发条件可判定:像正则一样明确,不用"seems to need"这种模糊描述
- 显式声明 DO NOT:不做什么比做什么更重要,画围栏优先于堆功能
- 输出格式刚性约束:不写死格式,下游(人或 Agent)没法可靠消费
- 上下文最小充分:指导精准获取,不贪婪加载
开发工作流(四阶段)
- 用例故事先行:写 3-5 个正例+反例场景,反例定义边界
- 最小可用版本:先 20 行跑一遍,别上来就写 200 行
- 失败驱动迭代:根据症状(越界/漏触发/格式乱/质量波动/冲突)定位根因
- 反测试验证:喂不该触发的输入,验证确实不激活
六大常见误区
- God Skill:一个 Skill 包打天下 → 每个维度 60 分,没有 90 分
- 过度指令化:30 步状态机 → 第 15 步开始选择性忽略;应给目标和约束,不给实现路径
- 触发词重叠:多 Skill 抢触发 → 用层级化匹配或确保触发词不重叠
- 缺少接口协议:A 输出自然语言 B 期望 JSON → 像 API 一样定义数据契约
- 知识硬编码:规范写在 Skill 里 → 知识放 CLAUDE.md/rules,Skill 只放流程和约束
- 没有退出条件:无限循环 → 设 max iterations 和明确的 stop 条件
Skill 成熟度模型
- L0 原始:一段 Prompt → 输出不一致
- L1 结构化:有 When/Steps/Output → 边界模糊
- L2 边界清晰:有 DO/DO NOT、退出条件 → 可能与其他 Skill 冲突
- L3 可组合:接口协议明确 → 知识硬编码
- L4 生产级:知识外置、触发确定、有反测试 → 可长期维护
- 大多数卡在 L1→L2:因为画边界不如加功能有成就感
核心认知
- Skill 设计 = 微服务设计:高内聚、低耦合、显式契约、明确边界
- 唯一区别:微服务靠代码强制边界,Skill 靠语言描述——执行者是会自由发挥的 LLM,所以必须写得更精确
- Skill 的价值不在于能做多少事,而在于在多小的范围内能稳定做对事