无需微调即可减少幻觉的十种方法
用于减少生成答案中虚构事实的约束、检索及评估循环。
本指南将逐步构建从原始材料到可运行系统的完整流程,内容为《无需微调模型即可减少AI幻觉的10种方法》。重点在于可操作的步骤、明确的检查点,以及可直接放入代码库的代码,无需猜测其用途。 在修改代码之前,应先明确输入参数、各步骤的负责人以及完成标准。操作人员应能够从已知的检查点重新运行相应步骤,而无需推测隐藏状态。 除了功能结果外,还需记录执行时间以及Token或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。
基本问题
在处理“基本问题”时,首先写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一个位置,这样操作人员无需查看整个系统结构即可进行审计。 缓存系统中稳定的指令和工具架构。重复发送相同的开头信息是导致资源浪费的常见原因。
const response = await client.responses.create({
model: "gpt-5",
input: `
Where is order #48291?
`
});
console.log(response.output_text);
Customer
↓
AI Agent
↓
Order System
↓
Actual Order State
↓
AI Agent
↓
Response
1. 为模型提供更好的上下文
在完成“1.为模型提供更好上下文”这一任务时,首先需列出相关规范:所需输入、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 同时记录正常流程与异常恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续需要补充的功能。 缓存系统中稳定的指令和工具结构。重复发送相同的开头信息是导致资源浪费的常见原因。
{
"orderId": "48291",
"status": "SHIPPED",
"carrier": "FedEx",
"trackingNumber": "784512963",
"estimatedDelivery": "2026-08-25"
}
const context = {
order: {
id: "48291",
status: "SHIPPED",
carrier: "FedEx",
trackingNumber: "784512963",
estimatedDelivery: "2026-08-25"
}
};
const response = await client.responses.create({
model: "gpt-5",
input: `
Answer the customer using only the supplied order information.
Context:
${JSON.stringify(context, null, 2)}
Customer:
Where is my order #48291?
`
});
模式
在处理该模式时,首先写下接口规范:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 优先选择小型、可测试的单元,而非庞大的脚本。当某个步骤失败时,故障应指向单一的责任模块,而非复杂的流程链。 缓存稳定的系统指令和工具结构。重复发送相同的开头信息是导致资源浪费的常见原因。
Bad:
Customer → LLM → Answer
Better:
Customer
↓
Retrieve state
↓
Build context
↓
LLM
↓
Answer
在处理该模式时,首先写下接口规范:所需的输入参数、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 在功能结果旁记录执行时间以及令牌或查询的成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。
2. 先检索再生成
- “在生成之前先获取数据”这一方法在被视为可度量的指标时效果最佳。在扩大范围之前,先记录一份理想的输出样本、一个失败案例以及回滚说明。 将配置信息置于应用程序代码之外。环境文件、密钥存储和功能开关应集中存放于一个位置,这样操作人员无需查看整个系统结构即可进行审核。 为每轮对话和每次会话设定token预算。智能工具往往会过度扩展上下文,设置上限可避免演示过程变成意外的费用账单。
Customer Question
↓
Retrieve
↓
Rank
↓
Build Context
↓
LLM
↓
Answer
const results = await vectorStore.search({
query: customerQuestion,
topK: 10
});
const relevant = results
.filter(item => item.score > 0.8)
.slice(0, 5);
const context = relevant
.map(item => item.content)
.join("\n\n");
const answer = await generateAnswer(
customerQuestion,
context
);
3. 减少上下文干扰
- 将“减少上下文噪声”视为可度量的指标时效果最佳。在扩大范围之前,先记录一份理想的处理结果、一个失败案例以及回滚说明。同时记录正常流程和恢复流程的文档。重试机制、人工审核环节以及错误处理都是产品本身的一部分,而非后续需要补充的内容。为每轮对话和每次会话设定token预算。智能工具会大量消耗上下文资源,设置上限可避免演示过程变成意外的费用账单。
20 retrieved documents
+
15 previous messages
+
10 previous tool responses
+
customer profile
+
product catalog
+
order history
+
promotion metadata
Available Information
↓
Relevance Filtering
↓
Metadata Filtering
↓
Ranking
↓
Deduplication
↓
Context Compression
↓
LLM
const context = results
.filter(x => x.score >= 0.82)
.filter(x => x.metadata.category === "returns")
.filter(x => x.metadata.region === customer.region)
.sort((a, b) => b.score - a.score)
.slice(0, 5)
.map(x => x.content);
4. 使用知识图谱存储结构化事实
- 将结构化事实存储在知识图中时,若能将其视为可度量的对象,效果最佳。在扩大范围之前,先记录一份标准范本、一个故障案例以及回滚说明。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某一步骤出现故障时,故障原因应能明确指向某个具体责任方,而非复杂的流程链。 需为每轮对话和每次会话设定token预算。智能工具往往会大量消耗上下文资源,设置上限可避免演示过程突然产生额外费用。
- 将结构化事实存储在知识图中时,若能将其视为可度量的对象,效果最佳。在扩大范围之前,先记录一份标准范本、一个故障案例以及回滚说明。 除了功能结果外,还需记录执行时间以及token或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外账单。
Customer
│
└── PLACED → Order
│
├── CONTAINS → Product
│
├── PAID_BY → Payment
│
├── FULFILLED_BY → Warehouse
│
└── SHIPPED_BY → Carrier
Order #48291
↓
FULFILLED_BY
↓
Warehouse #17
MATCH (o:Order {id: "48291"})
-[:FULFILLED_BY]->
(w:Warehouse)
RETURN w.id, w.name, w.location;
{
"orderId": "48291",
"warehouse": {
"id": "WH-17",
"name": "Delhi Fulfillment Center",
"location": "Delhi"
}
}
Without structured knowledge:
User → LLM
↓
Guess
With Knowledge Graph:
User
↓
Entity Identification
↓
Graph Traversal
↓
Verified Relationship
↓
Context
↓
LLM
5. 基于证据的确定性答案
在处理“基于证据的确定性答案”时,应在修改代码之前明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 配置信息应置于应用程序代码之外。环境文件、密钥存储以及功能标志应集中存放于一个位置,以便操作人员无需查看整个流程即可进行审核。 当下一步操作为代码执行或工具调用时,应优先使用具有架构验证的结构化输出,而非自由形式的文本描述。
{
"answer": "Your order is being fulfilled by Warehouse WH-17.",
"confidence": 0.98,
"evidence": [
{
"type": "order_record",
"source": "orders_db",
"orderId": "48291"
},
{
"type": "warehouse_relationship",
"source": "knowledge_graph",
"warehouseId": "WH-17"
}
]
}
For every factual claim:
1. Identify supporting evidence.
2. Use only available evidence.
3. Never invent a source.
4. If evidence is unavailable, say so.
5. Clearly distinguish facts from inference.
if (result.confidence < 0.7) {
return escalateToHuman(result);
}
LLM → Answer
LLM
↓
Answer
↓
Evidence
↓
Confidence
↓
Decision
6. 为智能体提供工具而非让其猜测
对于第6点:不要让系统猜测,而应为其提供工具支持,在修改代码之前明确输入内容、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误处理都是产品的一部分,而非后续需要补充的功能。 当下一步操作是代码执行或工具调用时,应优先使用具有结构化格式且经过模式验证的输出,而非自由形式的文本。
const tools = [{
name: "get_refund_status",
description: "Retrieve the current refund status for an order",
parameters: {
type: "object",
properties: {
orderId: {
type: "string"
}
},
required: ["orderId"]
}
}];
Customer
↓
LLM
↓
get_refund_status()
↓
Payment System
↓
Actual Refund State
↓
LLM
↓
Customer
7. 验证工具的输入与输出
对于第7点:在修改代码之前,需验证工具的输入与输出,明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。相比冗长的脚本,更应采用小型、可测试的单元。当某个步骤失败时,故障原因应能明确指向单一责任方,而非复杂的流程链。如果后续步骤是代码或工具调用,相比自由形式的文本,更应使用具有结构化格式且经过模式验证的输出。对于第7点:在修改代码之前,需验证工具的输入与输出,明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。除了功能结果外,还需记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。
{
"orderId": "48291",
"amount": "one hundred",
"currency": "dollars"
}
{
"orderId": "48291",
"amount": 100,
"currency": "USD"
}
import { z } from "zod";
const RefundRequest = z.object({
orderId: z.string(),
amount: z.number().positive(),
currency: z.enum(["USD", "EUR", "GBP", "INR"])
});
const refundRequest = RefundRequest.parse(
modelOutput
);
if (refundRequest.amount > order.total) {
throw new Error(
"Refund amount exceeds order total"
);
}
LLM
↓
Schema Validation
↓
Business Validation
↓
Permission Check
↓
Execute
↓
Response Validation
↓
Accept / Retry / Escalate
8. 将事实与推理分开
在处理“8. 将事实与推理分开”这一部分时,首先写下相关契约:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 应将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一个位置,这样操作人员无需查看整个系统结构即可进行审计。 缓存系统中稳定的指令和工具架构。重复发送相同的前置数据是导致资源浪费的常见原因。
{
"facts": [
"Order 48291 is shipped",
"Order 48291 is fulfilled by Warehouse WH-17",
"Warehouse WH-17 is currently operating"
],
"reasoning": [
"The order is likely to remain on schedule"
],
"conclusion": "The order is currently expected to arrive on time."
}
Was the fact wrong?
OR
Was the reasoning wrong?
FACT
→ Order shipped
FACT
→ Estimated delivery: Aug 25
INFERENCE
→ Delivery is currently expected on schedule
9. 从成功与失败的执行中学习
在学习“9. 从成功与失败的执行中汲取经验”时,首先需写下契约内容:所需输入、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 同时记录正常流程与恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续的优化工作。 缓存稳定的系统指令和工具架构。重复发送相同的报文头是导致资源浪费的常见原因。
{
"orderId": "48291",
"status": "PROCESSING",
"cancelable": true
}
cancel_order(48291)
{
"success": true,
"cancellationId": "CAN-83921"
}
{
"task": "Cancel order",
"orderState": "PROCESSING",
"action": "cancel_order",
"result": "SUCCESS",
"cancellationId": "CAN-83921"
}
New Request
↓
Find Similar Successful Execution
↓
Retrieve Relevant Pattern
↓
Check Current Order State
↓
Generate Action
↓
Validate
↓
Execute
Attempt 1
↓
cancel_order()
↓
Rejected: Order already shipped
↓
Agent retrieves shipping information
↓
Explains cancellation is unavailable
Execute
↓
Observe
↓
Evaluate
↓
Store Experience
↓
Improve Future Context
10. 评估每一项变更
在完成“10. 评估每一项变更”这一环节时,首先需明确合同条款:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码变更透明可溯。 相较于庞大的脚本,应优先选择小型且易于测试的单元。当某个步骤失败时,故障应指向单一责任模块,而非复杂的流程链。 对稳定的系统指令和工具结构进行缓存。重复发送相同的开头信息是导致资源浪费的常见原因。 在完成“10. 评估每一项变更”这一环节时,首先需明确合同条款:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码变更透明可溯。 在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在代码从演示环境转向共享环境时出现意外费用。
[
{
"question": "Where is order 48291?",
"expected": "SHIPPED"
},
{
"question": "Which warehouse fulfills order 48291?",
"expected": "WH-17"
},
{
"question": "Can order 48291 be cancelled?",
"expected": false
}
]
Answer Accuracy
Groundedness
Retrieval Precision
Tool Selection Accuracy
Tool Success Rate
Task Success Rate
Recovery Rate
Hallucination Rate
Latency
Cost
Before After
Answer Accuracy 72% 95%
Groundedness 69% 97%
Tool Success 81% 98%
Hallucination Rate 17% 3%
Change
↓
Test
↓
Measure
↓
Compare
↓
Improve
整合所有要素
将“整合所有要素”视为一个可度量的整体效果最佳。在扩大范围之前,先记录一份优秀的示例文本、一个失败案例以及回滚说明。 将配置置于应用程序代码之外。环境文件、密钥存储和功能开关应集中存放,这样操作人员无需查看整个系统结构即可进行审计。 为每轮对话和每次会话设定令牌预算。智能工具往往会大量消耗上下文资源,设置上限可避免演示过程变成意外的费用账单。
┌──────────────────┐
│ Knowledge Graph │
└────────┬─────────┘
│
┌────────▼─────────┐
│ RAG / Search │
└────────┬─────────┘
│
Customer → Intent → Context Engine → LLM
↑ │
│ ▼
Memory Tool Selection
↑ │
│ ▼
│ Validation
│ │
│ ▼
│ Real Systems
│ │
│ ▼
└─────── Feedback
│
▼
Evaluation
更深层的启示
“更大层面的教训”这一方法在被视为可度量的指标时效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。同时将正常流程和恢复流程都记录下来。重试机制、人工审核环节以及错误处理都是产品本身的一部分,而非后续需要补充的内容。为每轮对话和每次会话设定token预算——智能工具往往会大量消耗上下文,设置上限可以避免演示过程变成意外的费用账单。
大语言模型只是系统的一部分
“大语言模型只是系统的一部分”,只有将其视为可测量的对象时才能发挥最佳作用。在扩大范围之前,先记录一份理想的操作日志、一个故障案例以及回滚说明。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某一步骤出现故障时,故障原因应能明确指向某个具体责任方,而非复杂的流程链。 需为每轮对话和每次会话设定token预算。智能代理工具会大量消耗上下文资源,设置上限可避免演示过程变成意外的费用账单。 “大语言模型只是系统的一部分”,只有将其视为可测量的对象时才能发挥最佳作用。在扩大范围之前,先记录一份理想的操作日志、一个故障案例以及回滚说明。 除了功能结果外,还需记录处理时间以及token或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外账单。
┌───────────────────┐
│ Knowledge + RAG │
└─────────┬─────────┘
↓
Customer → Context → LLM → Tools → Real World
↑ ↓ ↓
Memory Reasoning Validation
↑ ↓
└──── Feedback
↓
Evaluation
最后思考
最后需要强调的是,在修改代码之前,务必明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。配置信息应置于应用程序代码之外,环境文件、密钥存储以及功能开关都应集中存放于一个位置,这样操作人员无需查看整个流程即可进行审核。当后续步骤为代码执行或工具调用时,优先使用具有结构化格式且经过模式验证的输出,而非自由形式的文本。
操作检查清单
将操作检查清单视为可衡量的标准,才能发挥其最大作用。在扩大范围之前,需记录一份最佳操作范例、一个故障案例以及回滚说明。应将此阶段视为输入参数与经过验证的输出之间的契约,为相关成果命名、明确成功标准,并杜绝默许的半完成状态。
每轮及每次会话的预算令牌数。智能工具会大量扩展上下文;设置上限可避免演示变成意外的账单。
在预算允许的情况下,使用测试数据而非真实的付费 API,在持续集成中加入用于检测关键路径的烟雾测试。
在功能结果旁记录耗时以及令牌或查询成本。提前了解成本情况,可防止从演示环境过渡到共享环境时出现意外账单。
每轮及每次会话的预算令牌数。智能工具会大量扩展上下文;设置上限可避免演示变成意外的账单。
在推广该技术栈之前,应冻结版本、为关键路径保存标准记录,并确认回滚步骤。共享环境需要速率限制、租户验证,以及明确的密钥轮换负责人。与其追求巧妙的单次演示,不如注重扎实的可靠性。
d3bfab080c19的批处理说明:不要将提供者密钥放入代码仓库,为每个会话设置令牌上限,并将转录内容存储在评估测试用例的旁边,以便后续更换模型时仍能保持可比性。