大语言模型智能体可靠性提升:置信度驱动的“我不知道”过滤器设计与实现

📅 2026/8/24 3:20:49
大语言模型智能体可靠性提升:置信度驱动的“我不知道”过滤器设计与实现
1. 项目概述当AI学会说“我不知道”在构建基于大语言模型的智能体时我们常常面临一个尴尬的局面模型表现得过于“自信”。你让它调用一个函数去查询天气它可能在你根本没提供天气API的情况下凭空编造一个“晴转多云25摄氏度”的结果。或者你要求它根据用户输入计算一个复杂的数学公式它明明不具备精确计算能力却会给你一个看似合理但完全错误的答案。这种“幻觉”或“胡编乱造”在需要精确执行动作的智能体场景中是致命的。这就是“The ‘I Don‘t Know’ Filter”要解决的核心问题。这个项目的本质是为基于函数调用Function Calling的智能体系统增加一层“不确定性感知”与“可靠性增强”的过滤机制。其目标不是让模型变得更聪明而是让它变得更“诚实”和“可靠”——在它没有足够把握正确调用函数或生成答案时能够主动承认“我不知道”并采取更安全的备选策略比如向用户澄清、请求更多信息或者转交控制权。想象一下你有一个客服机器人它可以调用“查询订单状态”、“处理退款”、“转接人工”等函数。一个鲁莽的智能体可能会在用户模糊地说“我的东西有问题”时直接调用“处理退款”函数造成误操作。而一个配备了“I Don‘t Know”过滤器的智能体则会先分析“用户的问题指向‘产品故障’还是‘退款需求’我现有的信息足够明确触发‘退款’函数吗”如果置信度不足它会选择先调用“请求用户提供订单号”或“澄清具体问题”的函数甚至直接“转接人工”。这极大地提升了系统的安全性和用户体验。这个项目紧密关联着当前AI研究的热点Agentic Reliability智能体可靠性和如何减少Hallucinations幻觉。它不仅仅是给API调用加个“开关”而是涉及对模型内部不确定性进行量化、制定决策阈值、设计降级处理流程等一系列工程与策略问题。接下来我将拆解实现这样一个过滤器的核心思路、技术细节与实操经验。2. 核心设计思路从“盲目执行”到“置信度驱动”传统的函数调用流程是线性的用户输入 - 模型理解意图 - 模型选择并填充函数参数 - 执行函数。在这个过程中模型通常只输出一个最可能的选项缺乏对自身决策可信度的评估。“I Don‘t Know”过滤器的核心就是在这个流程中插入一个置信度评估层。2.1 置信度的来源不止于概率为函数调用决策赋予一个置信度分数是过滤器的基石。这个分数可以从多个维度综合计算意图识别置信度模型对用户意图的理解有多确定例如用户说“定个明天上午的会议室”意图是“预约会议”这通常置信度很高。但如果用户说“帮我安排一下和团队的那个事情”意图就模糊了。函数匹配置信度在众多可用函数中当前选中的函数是否是最佳匹配是否存在其他相似函数造成混淆例如同时存在get_weather_current获取当前天气和get_weather_forecast获取天气预报时对于“明天会下雨吗”这个问题匹配后者的置信度应该更高。参数填充置信度函数所需的参数是否都能从用户输入或上下文中明确、完整地提取例如book_flight(destination, date)函数用户提供了“去上海”和“下周一”那么destination“上海”的置信度可能很高但date需要解析“下周一”为具体日期这个解析过程的置信度需要评估。上下文一致性置信度本次函数调用是否与对话历史、领域知识一致例如在电商场景中用户刚刚查询了订单A紧接着说“取消它”那么调用cancel_order(order_idA)的置信度就很高。但如果对话历史为空突然来一句“取消它”置信度就极低。实操心得不要只依赖模型输出的原始概率如logits。对于许多商用API你拿不到token级别的概率分布。此时可以通过提示工程让模型“自我评估”。例如在要求模型输出函数调用JSON的同时要求它额外输出一个confidence_score字段并给出评分标准如0.9-1.0非常确定0.7-0.9比较确定0.5-0.7大致确定但需确认0.5以下不确定。虽然这仍是模型“自己说的”但通过精心设计的提示语可以在一定程度上提高其自我评估的准确性。2.2 阈值策略如何定义“知道”与“不知道”得到了置信度分数后我们需要一个阈值来决定是执行还是触发“我不知道”流程。这个阈值不是固定的而应该是一个动态的、可配置的策略。静态全局阈值最简单的方式如设定confidence_score 0.8则执行否则触发过滤器。但这种方式不够灵活因为不同函数的风险等级不同。基于函数风险的动态阈值为每个函数定义一个“风险系数”。高风险函数如transfer_money,delete_database需要更高的置信度阈值如0.95低风险函数如search_knowledge_base,get_current_time可以容忍较低的阈值如0.7。基于场景的阈值在严谨的医疗、法律咨询场景阈值全面提高在休闲聊天场景阈值可以降低。我们可以设计一个阈值表来管理函数名称风险等级建议执行阈值触发“IDK”后的建议动作process_refund高0.92请求人工审核或让用户二次确认schedule_meeting中0.85向用户澄清模糊参数时间、参会人query_faq低0.75提供多个可能答案并标注“根据X信息推测最相关的答案是...”get_news_summary低0.70直接执行即使置信度一般后果也可接受2.3 “我不知道”之后降级处理流程触发过滤器后系统不应简单地报错而应执行一套优雅的降级处理流程。这体现了智能体的“可靠性”。主动澄清向用户提问以获取更明确的信息。例如“您想查询哪个城市的天气”、“您说的‘尽快’是指今天内还是本周内”提供选项当意图模糊时提供几个最可能的选项让用户选择。例如“您是想‘查询订单状态’还是‘申请售后’”缩小范围建议用户提供更具体的信息。例如“要为您预订航班需要知道目的地和出行日期。”安全默认动作对于高风险操作默认转向一个安全动作。例如当无法确定是否应该执行“删除”时默认执行“移动到回收站”或“标记为待删除”。移交控制权最终手段坦诚告知能力边界并建议用户联系人工客服或尝试其他方式。设计这个流程的关键在于要让用户感觉是系统在“协作”解决问题而不是“推卸”责任。3. 技术实现拆解构建置信度评估层理论说完了我们来看看具体怎么实现。一个完整的“I Don‘t Know”过滤器可以集成在智能体的决策循环中主要包含以下几个模块。3.1 模块一增强型函数调用提示工程这是最前线的工作。我们需要修改给大语言模型的提示词Prompt使其输出包含置信度评估。基础函数调用提示模板你是一个智能助手可以调用以下工具 {tools_description} 用户输入{user_input} 请根据对话历史和分析决定是否需要调用工具以及调用哪个工具。如果需要请以JSON格式输出包含 function_name 和 parameters。增强版提示模板加入自我评估你是一个谨慎可靠的智能助手可以调用以下工具 {tools_description} 用户输入{user_input} 请按以下步骤思考 1. 分析用户意图并判断是否需要调用工具。 2. 如果需要选择最匹配的工具。 3. 评估你此次决策的总体置信度0.0到1.0考虑意图清晰度、工具匹配度、参数完整性。 4. 如果置信度低于0.8请在 action 字段中输出 clarify并在 clarification_question 中提出一个最有助于厘清问题的问题。 5. 如果置信度高于等于0.8请在 action 字段中输出 call并填写完整的 function_name 和 parameters。 请输出JSON格式 { reasoning: 你的思考过程..., confidence_score: 0.95, action: call | clarify, function_name: xxx, // 当action为call时必填 parameters: {...}, // 当action为call时必填 clarification_question: ... // 当action为clarify时必填 }注意事项让模型在JSON中输出reasoning思考链非常关键。这不仅是可解释性的要求我们还可以事后分析这段文本来验证其置信度评分是否合理甚至可以用一个更小的模型来对这段“思考过程”进行二次置信度评估作为交叉验证。3.2 模块二外部验证器与一致性检查仅靠模型自我评估是不够的我们需要引入外部验证机制。参数格式与范围验证在调用函数前对模型提取的参数进行强校验。例如日期格式是否正确、邮箱地址是否有效、数字是否在合理范围内如年龄不能为负数。如果校验失败直接判定此次调用置信度为0触发过滤器。业务规则验证结合业务逻辑检查。例如用户要求“取消订单”验证器需要检查该订单是否存在、是否属于当前用户、是否已过可取消期限。这需要查询外部数据库或服务。多模型投票或验证对于极高风险的决策可以采用“委员会”机制。将同一个问题发给两个不同的大模型或同一模型的不同提示比较它们输出的函数调用决策。如果一致则提高置信度如果不一致则触发过滤器进入人工或更复杂的裁决流程。3.3 模块三置信度融合与决策引擎这是过滤器的大脑它接收来自各方的信号做出最终决策。输入信号C_self: 模型自我评估的置信度分数。C_validator: 外部验证器的评分如格式验证通过为1.0失败为0业务规则验证根据复杂程度给出0-1分。C_consistency: 上下文一致性分数可通过将当前对话片段与历史嵌入向量计算相似度得到。融合算法简单的做法是加权平均C_final w1*C_self w2*C_validator w3*C_consistency。更复杂的可以采用基于规则或机器学习的小型分类器来融合。决策执行将C_final与为该函数预设的动态阈值进行比较。高于阈值则执行函数调用低于阈值则根据预设的降级处理流程执行澄清、提供选项等动作。这个决策引擎可以设计成一个独立的微服务它维护着函数风险表、阈值配置和降级处理策略方便运营人员后期调整。3.4 模块四反馈学习与阈值优化一个优秀的系统应该能自我进化。我们可以记录每一次决策的日志request_id,user_input,predicted_function,predicted_params,C_final,decision(执行/过滤),fallback_action(如果被过滤)。对于最终执行了函数调用的请求我们可以通过用户后续的满意反馈如完成任务、正面评价或失败反馈如用户纠正、操作错误来作为“真实标签”。定期分析这些日志可以校准置信度评分如果发现模型自我评估的C_self普遍虚高而实际失败率高可以调整提示词或对C_self施加一个衰减系数。优化阈值对于某个函数如果发现很多C_final在0.85左右的决策都成功了而阈值是0.9那么可以考虑适当降低该函数的阈值以提高系统的灵活性减少不必要的澄清。发现模糊场景集中分析那些被频繁触发过滤器的用户输入这些是系统当前的“认知盲区”。我们可以针对这些场景专门设计澄清话术或者考虑是否需要增加新的、功能更细分的函数。4. 实操部署与核心环节实现让我们以一个具体的场景——智能邮件助手来串联整个实现过程。这个助手可以帮助用户“发送邮件”、“查询未读邮件”、“标记邮件为重要”。4.1 环境准备与工具定义首先定义我们的函数工具集tools [ { type: function, function: { name: send_email, description: 向指定的收件人发送一封电子邮件, parameters: { type: object, properties: { recipient: {type: string, description: 收件人邮箱地址}, subject: {type: string, description: 邮件主题}, body: {type: string, description: 邮件正文内容} }, required: [recipient, subject, body] } } }, { type: function, function: { name: get_unread_emails, description: 获取当前用户的未读邮件列表支持按发件人或关键词筛选, parameters: { type: object, properties: { sender_filter: {type: string, description: 按发件人邮箱过滤可选}, keyword_filter: {type: string, description: 按主题或正文关键词过滤可选}, max_results: {type: integer, description: 返回的最大邮件数量默认10} }, required: [] } } } ]4.2 实现增强型调用与决策引擎我们使用一个伪代码框架来展示核心循环class IDKFilterAgent: def __init__(self, llm_client, function_registry, threshold_policy): self.llm llm_client self.functions function_registry # 包含函数定义和风险等级 self.policy threshold_policy # 阈值策略 def process_query(self, user_input, conversation_history): # 1. 构建增强型Prompt prompt self._build_enhanced_prompt(user_input, conversation_history) # 2. 调用LLM获取包含置信度的结构化输出 llm_response self.llm.generate(prompt) # 解析出action, confidence, function_name, parameters, clarification_q # 3. 外部验证 validation_score self._validate_parameters(llm_response.function_name, llm_response.parameters) # 4. 上下文一致性检查简化示例检查函数是否与历史连贯 consistency_score self._check_consistency(llm_response.function_name, conversation_history) # 5. 置信度融合 final_confidence self._fuse_confidence( llm_response.confidence, validation_score, consistency_score ) # 6. 获取该函数的动态阈值 function_risk self.functions.get_risk(llm_response.function_name) threshold self.policy.get_threshold(function_risk, user_input) # 7. 决策 if llm_response.action call and final_confidence threshold: # 执行函数调用 result self._execute_function(llm_response.function_name, llm_response.parameters) return {action: executed, result: result, confidence: final_confidence} else: # 触发降级流程 fallback_action self._determine_fallback( final_confidence, llm_response.function_name, llm_response.clarification_question ) return {action: fallback, type: fallback_action, message: self._generate_fallback_message(fallback_action)} def _fuse_confidence(self, c_self, c_val, c_con): # 简单的加权平均权重可根据经验调整 weights {self: 0.5, validator: 0.3, consistency: 0.2} return weights[self] * c_self weights[validator] * c_val weights[consistency] * c_con def _determine_fallback(self, confidence, func_name, model_clarification_q): if confidence 0.5: # 置信度极低可能是完全误解建议重述或转人工 return escalate_to_human elif func_name send_email and confidence 0.8: # 发送邮件风险较高优先使用模型自己生成的澄清问题 return clarify_with_question else: # 其他情况提供选项或安全默认动作 return suggest_options4.3 一个完整的交互示例用户输入“给Alex回个邮件说资料收到了谢谢。”LLM增强输出{ reasoning: 用户想发送一封感谢邮件。需要调用send_email函数。收件人‘Alex’不明确可能是名字需要邮箱地址。主题和正文内容相对明确。总体置信度中等因为关键参数‘recipient’缺失。, confidence_score: 0.65, action: clarify, function_name: send_email, parameters: {subject: 关于资料的确认, body: 资料已收到谢谢}, clarification_question: 请问收件人Alex的完整邮箱地址是什么 }外部验证参数中recipient缺失验证器评分c_val 0.2因为必填参数缺失。一致性检查对话历史为空无法连贯性检查c_con 0.5中性。置信度融合c_final 0.5*0.65 0.3*0.2 0.2*0.5 0.485。决策send_email函数风险等级为“高”阈值设为0.85。0.485 0.85触发过滤器。降级处理由于confidence 0.5且函数风险高决策引擎选择escalate_to_human标记待人工处理或输出一个非常保守的回应“我需要Alex的邮箱地址才能发送邮件。同时为了确保信息准确您是否需要我先草拟邮件内容给您确认”这个例子展示了过滤器如何阻止了一次参数不全的邮件发送避免了可能发生的“邮件发错人”的事故。5. 常见问题与避坑指南实录在实际开发和部署“I Don‘t Know”过滤器的过程中我遇到了不少坑也总结了一些经验。5.1 置信度评分不准模型总是“过于自信”这是最常见的问题。即使你在提示词里要求模型保守一点它给出的confidence_score可能依然普遍在0.9以上。解决方案一校准提示词。在提示词中加入具体的、例子驱动的评分标准。例如“0.9-1.0分你100%确定所有参数都明确无误如‘查询北京今天天气’。0.6-0.8分意图清楚但个别参数需要常规推断如‘定个明天下午的会’需要推断具体时间。0.6分以下意图模糊或参数关键信息缺失。”解决方案二后处理惩罚。对模型自评分数进行全局性惩罚比如adjusted_score raw_score * 0.8。这个系数可以通过历史数据的错误分析得到。解决方案三引入不确定性探测提示。在主要思考提示之外单独设计一个问题让模型评估不确定性。例如在得到函数调用决策后再问模型一个问题“请列出可能导致这个决策错误的三个潜在原因。”如果模型能轻易列出原因说明它其实“心里没底”此时应降低置信度。5.2 阈值难以设定要么太严要么太松一开始没有数据阈值全靠猜结果不是过滤太多用户觉得机器人很笨就是过滤太少没起到防错作用。解决方案采用分阶段上线和A/B测试。影子模式初期让过滤器运行在“只记录不拦截”的模式。收集大量(C_final, 是否真的应该执行)的数据对。分析数据绘制ROC曲线找到理想的风险收益平衡点。对于高风险函数可以容忍一定的“误拦”False Positive但要极力避免“误放”False Negative。小流量实验先对1%的流量开启过滤观察用户反馈和问题发生率逐步调整阈值。动态阈值根据时间如业务高峰期、用户群体新用户/老用户、渠道APP/网页微调阈值。5.3 降级处理体验生硬用户感到烦躁简单的“我不明白”或者不断追问会让用户体验变差。解决方案设计智能且多样的降级策略。猜测并确认不要只问“你要做什么”而是说“您是想‘发送邮件’对吗请提供收件人邮箱。”这利用了模型猜测的意图减少了用户思考负担。提供结构化选项对于模糊意图提供按钮或快捷选项。例如“您可能想1. 发送新邮件 2. 回复某封邮件 3. 查询邮件”。记住上下文在一次对话中如果用户针对同一个模糊点被追问两次系统应该自动切换到更简单的处理方式或直接转人工避免陷入死循环。个性化对于老用户可以根据其历史行为适当放宽阈值或调整澄清方式。5.4 系统复杂度与延迟增加增加了置信度评估、外部验证、决策引擎等多个环节必然增加系统延迟和运维复杂度。解决方案优化与异步处理。并行化外部验证如格式校验和一致性检查可以并行进行。缓存对常见的、高置信度的请求-响应对进行缓存直接绕过复杂计算。降级开关在系统高负载时可以动态调低过滤器的严格程度如全局提高阈值优先保障核心功能的可用性。关键路径与非关键路径分离将置信度评估的日志记录、反馈学习等非实时关键任务通过消息队列异步处理不影响主请求的响应时间。5.5 如何处理模型的“创造性”误用有时模型会“创造性”地组合函数或试图调用一个不存在的函数来完成目标这同样危险。解决方案严格的功能边界与参数约束。在函数描述中明确其边界和前置条件。例如在transfer_money的描述中强调“仅当用户明确指示金额和收款人时使用”。在外部验证器中加入更严格的业务逻辑校验。例如即使模型提取了amount和to_account验证器也要检查单笔转账限额、收款账户是否在白名单内等。对于高风险领域考虑采用“白名单”机制。模型只能从经过严格审核的、有限的函数列表中选择彻底杜绝其调用未知或危险操作的可能性。实现“The ‘I Don‘t Know’ Filter”不是一个一蹴而就的功能而是一个需要持续迭代、精心调校的系统工程。它的价值在于将智能体从“黑盒执行者”转变为“透明协作伙伴”。当你的AI学会在适当的时候说“我不知道”并优雅地寻求帮助时用户获得的不仅仅是准确的结果更是一种可信赖、可预期的交互体验。这或许是迈向真正可靠、实用的AI应用的关键一步。从我自己的实践来看引入这套机制后智能体在生产环境中的误操作率下降了超过70%而用户的满意度却因为交互变得更加顺畅和“聪明”而有所提升。这其中的平衡艺术正是AI工程化落地的精髓所在。