LLM-Cookbook 学习——搭建基于 ChatGPT 的问答系统>评估输入——检查结果 Check Outputs

发布时间:2026/8/20 13:02:04
LLM-Cookbook 学习——搭建基于 ChatGPT 的问答系统>评估输入——检查结果 Check Outputs 一、前言在前面的学习中我们已经了解了如何对用户的输入进行分类、Moderation 内容审核、思维链推理以及 Prompt 链式处理。但是在一个真正的大模型应用中只检查用户的输入是不够的。因为即使用户的问题本身没有问题大语言模型最终生成的答案仍然可能存在不安全或者不合适的内容回答与用户问题无关没有充分回答用户的问题引用了知识库中不存在的信息出现模型“幻觉Hallucination”。因此在模型生成答案之后、真正把答案展示给用户之前我们还可以增加一个Output Checking输出检查这一节主要介绍两种输出检查方法使用 Moderation 对模型生成结果进行安全审核使用另一个 LLM 调用对生成结果的正确性和相关性进行评价。课程中的 Check Outputs 正是在前几节客服系统的基础上增加“输出质量控制”这一环节。二、为什么还需要检查模型输出一个典型的大模型问答系统可以简单理解为用户输入 ↓ 输入检查 ↓ 检索相关信息 ↓ LLM 生成回答 ↓ 输出检查 ↓ 返回给用户这里有一个非常重要的思想LLM 生成答案并不意味着这个答案就应该直接展示给用户。模型首先负责“生成”系统还应该负责“验证”。比如一个商品客服系统中知识库告诉模型SmartX ProPhone - 6.1 英寸屏幕 - 128GB 存储 - 12MP 双摄像头 - 支持 5G如果模型最后回答SmartX ProPhone 配备 512GB 存储空间。这句话语言上完全正常但实际上已经脱离提供给模型的商品资料。这种情况下语言通顺 ≠ 内容正确所以需要增加额外的检查机制。三、方法一使用 Moderation 检查模型输出前面学习 Moderation 时我们主要用它检查用户输入实际上同样的思路也可以用来检查模型输出也就是说在把模型生成的回答发送给用户之前先进行一次内容审核。课程给出的示例就是将final_response_to_customer再送入 Moderation。例如final_response_to_customer SmartX ProPhone has a 6.1-inch display, 128GB storage, 12MP dual camera and 5G. 此时response openai.Moderation.create( inputfinal_response_to_customer )这里的逻辑非常简单模型生成的回答 ↓ Moderation ↓ 判断回答是否包含风险内容然后取出检测结果moderation_output response[results][0] print(moderation_output)四、Moderation 返回结果怎么看课程示例中的结果大致可以理解成{ categories: { ... }, category_scores: { ... }, flagged: False }这里重点理解三个字段。1. categoriescategories表示文本是否属于某种风险类别。可以简单理解成文本属于什么风险类型每个类别通常对应True或者False如果全部为 False说明没有检测到对应类型的风险内容。2. category_scorescategory_scores可以理解为模型认为文本属于某种风险类别的程度。通常数值越高说明文本越可能属于相应类别。因此categories更像最终判断结果而category_scores则提供了更细致的评分信息。3. flaggedflagged: False可以简单理解为False → 未被系统整体判定为需要拦截 True → 内容触发审核条件因此在真正的系统中可以写类似逻辑if moderation_output[flagged]: # 不把原回答直接发送给用户 ... else: # 返回正常回答 ...于是系统结构变成LLM生成答案 ↓ Moderation审核 ↓ ┌───────────────┐ │ │ 通过 不通过 │ │ ↓ ↓ 返回用户 拦截/重新生成这相当于在大模型输出之后增加了一道“安全闸门”。五、但是 Moderation 解决不了所有问题Moderation 更擅长解决这段内容安全吗但是它不能直接解决另外一个很重要的问题这个回答到底对不对例如用户 SmartX ProPhone 的内存是多少 模型 SmartX ProPhone 有 512GB 存储空间。这句话没有违法内容 没有攻击内容 没有暴力内容 语言也很正常所以安全审核可能没有问题。但是如果知识库里写的是128GB那么这个回答仍然是错误的。所以我们还需要第二种检查检查答案是否真正基于提供的信息生成。六、方法二让 LLM 检查 LLM这一节比较重要的思想是不仅可以让 LLM 回答问题还可以让 LLM 充当“评审员”。也就是说第一次调用LLM → 生成答案第二次调用LLM → 检查刚刚生成的答案可以理解为┌───────────┐ 用户问题 ───────→ │ 生成模型 │ └─────┬─────┘ │ 回答 │ ↓ ┌───────────┐ 商品资料 ───────→ │ 评审模型 │ 用户问题 ───────→ │ │ └─────┬─────┘ │ Y / N课程中的评审 Prompt 主要检查两件事情1. 回答是否正确使用了提供的产品信息 2. 回答是否充分回答了用户的问题两项都满足才输出Y否则输出N。七、system_message 在这里起什么作用课程中会先定义一个system_message它的大概思想是system_message 你是一个负责评估客服回答质量的助手。 你需要检查 1. 客服是否充分回答用户的问题 2. 客服引用的产品信息是否正确。 如果两个条件都满足输出 Y。 否则输出 N。 只输出一个字母。 这个 Prompt 非常值得学习。因为这里已经不是让 LLM回答问题而是让它按照规则评价另一个回答也就是说LLM 的角色发生了变化第一次 LLM Answer Generator 答案生成器第二次LLM Evaluator / Judge 评审器八、为什么要求只输出 Y 或 N这里还有一个很值得学习的 Prompt Engineering 技巧。课程没有让模型回答“请详细分析这个回答好不好。”而是直接规定Y或者N这样做的原因是程序最需要的是稳定、容易判断的结构化结果。如果让模型自由回答它可能输出这个回答总体来说不错不过还有一些可以改进的地方……程序就很难判断到底通过还是不通过但是如果规定Y / N代码就非常容易处理if response Y: ... else: ...九、q_a_pair 是什么课程中还有一个变量q_a_pair第一次看到这个名字可能比较奇怪。实际上q Question a Answer pair 一对因此q_a_pair就是Question-Answer Pair问题和回答组成的一组数据。例如q_a_pair f Customer message: {customer_message} Product information: {product_information} Agent response: {final_response_to_customer} Does the response use the retrieved information correctly? Does the response sufficiently answer the question? Output Y or N. 这里实际上一次把三类信息交给评审模型① 用户问了什么 ② 知识库提供了什么 ③ 模型最终回答了什么然后让模型判断③ 是否根据②正确回答了①这个结构非常重要。十、为什么使用 把内容包起来例如Customer message: {customer_message}三个反引号在这里相当于分隔符 Delimiter告诉模型这里是用户问题 ---------------- 这里是商品信息 ---------------- 这里是客服回答避免不同类型的内容混在一起。因此 Prompt 的结构更加清晰Customer message: 用户问题 Product information: 商品资料 Agent response: 模型回答模型就更容易理解哪些是“事实依据” 哪些是“待检查的答案”这也是前面课程反复出现的一个 Prompt Engineering 技巧使用清晰的分隔符把不同信息块分开。十一、messages 是如何工作的接下来messages [ { role: system, content: system_message }, { role: user, content: q_a_pair } ]这里可以理解成System 你现在是一名回答质量检查员 按照 Y/N 规则检查回答。 User 这里有用户问题、产品资料和客服回答 请开始检查。也就是说system_message负责定义规则而q_a_pair负责提供需要检查的数据这是一个非常典型的大模型应用结构System Prompt ↓ 规定模型“应该怎么做” User Prompt ↓ 告诉模型“这次具体处理什么数据”十二、max_tokens1 为什么只设置为 1课程中还有这样一行response get_completion_from_messages( messages, max_tokens1 )为什么max_tokens1就够了因为我们明确要求模型只返回Y或者N根本不需要模型生成一大段文本。所以这里实际上进一步限制了模型输出长度。整个思路就是任务只是分类 ↓ 不需要生成长文本 ↓ 限制输出空间 ↓ 只输出 Y / N这也是一种比较典型的“把生成模型当分类器使用”的方式。十三、正常回答的检测结果假设用户问介绍一下 SmartX ProPhone、 FotoSnap DSLR Camera 另外介绍一下你们的电视。系统提供了对应的商品资料。然后客服回答确实根据资料进行了回答。评审模型得到用户问题 商品资料 客服回答检查之后输出Y也就是回答充分回答了问题 AND 回答正确使用了商品资料 ↓ Y课程示例中正常客服回答通过了这种检查。十四、故意给一个错误回答例如another_response life is like a box of chocolates意思是生活就像一盒巧克力。用户明明问的是手机 相机 电视结果客服突然回答生活就像一盒巧克力。显然完全答非所问。然后把这个回答再次送给评审模型q_a_pair f Customer message: {customer_message} Product information: {product_information} Agent response: {another_response} Does the response use the retrieved information correctly? Does the response sufficiently answer the question? Output Y or N 最终模型输出N因为这个回答既没有使用商品信息也没有回答用户的问题。课程仓库中也专门包含了这个another_response示例。十五、这和“幻觉”有什么关系LLM 中非常重要的一个问题就是Hallucination即幻觉可以简单理解成模型生成了看起来很合理但没有事实依据的内容。例如知识库写SmartX ProPhone 存储128GB模型却回答SmartX ProPhone 提供 512GB 存储。语法没有问题而且听起来非常自然。但知识库128GB 模型回答512GB明显发生了事实错误。因此我们可以把用户问题 知识库信息 模型回答一起交给评审模型要求它判断回答中的事实是否真的能够从知识库中得到支持这就是一种降低幻觉风险的思路。需要注意的是输出检查能够降低问题出现的概率但不能理解成可以绝对消除所有幻觉。十六、完整的大模型系统流程把前面的几节连起来之后一个比较完整的客服系统已经逐渐形成。可以简单表示为用户输入 │ ↓ ┌─────────────────┐ │ 1. 输入安全检查 │ └────────┬────────┘ │ ↓ ┌─────────────────┐ │ 2. 理解用户意图 │ └────────┬────────┘ │ ↓ ┌─────────────────┐ │ 3. 查找相关商品 │ └────────┬────────┘ │ ↓ ┌─────────────────┐ │ 4. 获取商品信息 │ └────────┬────────┘ │ ↓ ┌─────────────────┐ │ 5. LLM生成回答 │ └────────┬────────┘ │ ↓ ┌─────────────────┐ │ 6. 输出安全检查 │ └────────┬────────┘ │ ↓ ┌─────────────────┐ │ 7. 回答质量检查 │ └────────┬────────┘ │ ┌────┴────┐ │ │ Y N │ │ ↓ ↓ 返回用户 重新生成/ 人工处理到这里我觉得已经能明显体会到真正的大模型应用并不是调用一次 API 就结束而是多个检查、检索、生成和判断模块共同组成一个系统。十七、两个“检查”不要混淆这一节最容易搞混的是Moderation 检查和LLM 质量检查它们解决的问题不同。检查方式主要检查的问题Moderation这个回答是否包含不安全、不合适的内容LLM Evaluator这个回答是否正确、相关、充分可以简单记成Moderation “这句话能不能说”而LLM Evaluator “这句话说得对不对”因此两者并不是替代关系而是可以组合使用。十八、这种方式是不是所有回答都必须检查不一定。如果每产生一个答案都再额外调用一次甚至多次大模型进行检查那么意味着一次用户请求可能变成生成回答 → 1 次模型调用 检查回答 → 再调用 1 次模型 甚至重新生成 → 再调用模型这样会带来更高的 API 调用成本 更大的响应延迟课程相关笔记也特别指出额外的输出评估会增加 latency 和 cost因此是否采用需要根据应用对错误率、成本和响应速度的要求权衡。因此真正做项目时需要考虑业务风险有多高 ↓ 是否值得增加额外检查例如一些普通问答场景可能不需要每次都进行复杂的二次评价但是在对答案可靠性要求比较高的业务中就可能值得增加更多检查机制。十九、这一节给我的最大启发给评审模型清晰的评价标准不能只是说帮我检查一下这个回答好不好。因为“好不好”这个标准太模糊。最好明确告诉模型标准1是否回答用户问题 标准2事实是否来自给定资料 标准3是否存在不安全内容 标准4是否符合要求的语气也就是说评价标准越明确模型越容易稳定地完成评价任务。尽量让检查结果结构化比如Y / N比“这个回答我觉得整体还可以……”更适合程序处理。进一步还可以设计成{ relevant: true, factually_correct: true, safe: true, passed: true }对于真正的工程系统这种结构化结果通常会更加方便。