首页 / 文章 / 无需微调即可减少幻觉的十种方法

无需微调即可减少幻觉的十种方法

用于减少生成答案中虚构事实的约束、检索及评估循环。

2855 词

本指南将逐步构建从原始材料到可运行系统的完整流程,内容为《无需微调模型即可减少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. 先检索再生成

  1. “在生成之前先获取数据”这一方法在被视为可度量的指标时效果最佳。在扩大范围之前,先记录一份理想的输出样本、一个失败案例以及回滚说明。 将配置信息置于应用程序代码之外。环境文件、密钥存储和功能开关应集中存放于一个位置,这样操作人员无需查看整个系统结构即可进行审核。 为每轮对话和每次会话设定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. 减少上下文干扰

  1. 将“减少上下文噪声”视为可度量的指标时效果最佳。在扩大范围之前,先记录一份理想的处理结果、一个失败案例以及回滚说明。同时记录正常流程和恢复流程的文档。重试机制、人工审核环节以及错误处理都是产品本身的一部分,而非后续需要补充的内容。为每轮对话和每次会话设定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. 使用知识图谱存储结构化事实

  1. 将结构化事实存储在知识图中时,若能将其视为可度量的对象,效果最佳。在扩大范围之前,先记录一份标准范本、一个故障案例以及回滚说明。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某一步骤出现故障时,故障原因应能明确指向某个具体责任方,而非复杂的流程链。 需为每轮对话和每次会话设定token预算。智能工具往往会大量消耗上下文资源,设置上限可避免演示过程突然产生额外费用。
  2. 将结构化事实存储在知识图中时,若能将其视为可度量的对象,效果最佳。在扩大范围之前,先记录一份标准范本、一个故障案例以及回滚说明。 除了功能结果外,还需记录执行时间以及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的批处理说明:不要将提供者密钥放入代码仓库,为每个会话设置令牌上限,并将转录内容存储在评估测试用例的旁边,以便后续更换模型时仍能保持可比性。