首页 / 文章

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

十项系统级改进可减少电商智能体中的大语言模型幻觉问题:通过优化上下文、检索、图结构、工具以及验证与评估机制,且无需进行微调。

发布者:REACTAPP.TOP阅读约 9 分钟2156 词

来源: 10 Ways to Reduce AI Hallucinations Without Fine-Tuning Your Model

当客服助手告诉客户“您的退款已处理”,但实际上并无退款时,问题通常出在系统而非模型本身。系统存在漏洞,模型便用猜测来填补这一空缺。订单状态缺失、数据检索返回错误信息、上下文混乱、工具调用未经过验证,此前的成功案例也被遗忘。

无需修改模型的权重,就能大幅减少幻觉现象。这里的示例是一个电商客服助手,负责查询订单、处理退款及更新配送信息,我们将逐层增强其稳定性。

简单版本

有客户询问:“我的订单#48291在哪儿?”初始版本的应用只是将问题转发出去:

const response = await client.responses.create({
  model: "gpt-5",
  input: `
    Where is order #48291?
  `
});

console.log(response.output_text);

模型可能会回复“您的订单已安排配送,今天就能送达。”听起来不错,但它根本不知道订单48291在哪儿。它只是根据训练数据中的模式生成了一句看似合理的句子,这其实是一种幻觉。

您想要的回复应该更像这样:

Customer
   ↓
AI Agent
   ↓
Order System
   ↓
Actual Order State
   ↓
AI Agent
   ↓
Response

模型应当查询现实信息,而非凭空编造。

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. 先检索,再生成

又有客户询问在节日促销中购买的电子产品的退换货政策。该答案并不存在于模型中,而是在您的政策数据库、产品文档、促销规则以及地区条款中。因此,在生成内容之前先获取这些信息。一个基本的RAG流程如下:

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
);

这里质量比数量更重要。向模型提供30份文档并不会让它变得更聪明。如果只有3份文档真正重要,那么其余27份不过是冗余信息。

3. 去除噪音

想象一下助手收到这一大堆文档的场景:

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. 使用知识图谱处理结构化事实

RAG适用于处理文档类数据,但许多电子商务相关问题其实与文档无关,而是涉及各种关系:哪个仓库负责处理该订单、哪笔付款用于支付该订单、哪些产品属于促销活动、某个仓库宕机时哪些订单会受到影响。这些都是图结构问题。以下是一个简化的图示:

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. 为智能体提供工具,而非让其猜测

有时最好的预防措施就是根本不让大语言模型回答。如果客户询问退款是否已处理,可提供查询功能:

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

与其给出含糊的“退款应在5到7天内到账”这样的说法,客服人员应该说明退款已于昨日启动但仍在处理中,因为这实际上是可以查证的。如果现实情况能够给出答案,那就去询问现实情况。

7. 验证工具的输入与输出

仅仅调用工具并不足以保证客服人员的可靠性。模型仍可能生成格式错误的请求。例如有客户要求为订单48291退款100美元,而模型输出的却是:

{
  "orderId": "48291",
  "amount": "one hundred",
  "currency": "dollars"
}

但你的支付 API 要求:

{
  "orderId": "48291",
  "amount": 100,
  "currency": "USD"
}

添加模式验证,例如使用 Zod:

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. 将事实与推理分开

一个巧妙且有效的办法是将系统已知的信息与模型得出的结论分开存储:

{
  "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. 从实际运行中学习,而非训练中学习

让我们让智能体在无需微调的情况下不断改进。有客户要求取消订单48291,智能体随即检查该订单:

{
  "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. 评估每一项变更

最后,要衡量这些变更是否有效。假设你改变了检索方法,但“答案看起来更好了”并不能作为证据。应当构建一个评估集:

[
  {
    "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

注意那些没有发生的事情:模型并未经过微调,而是其周围的系统得到了改进。

在指责模型之前应先思考的问题

面对幻觉现象,人们的第一反应往往是需要更好的模型。有时这确实没错,但首先应逐一检查以下事项。

  1. 是否提供了正确的上下文?
  2. 是否检索到了正确的信息?
  3. 是否去除了无关内容?
  4. 结构化知识能否确定性地回答该问题?
  5. 是否有工具能够读取系统的实际状态?
  6. 模型的输出是否经过验证?
  7. 事实与推理是否被分开处理?
  8. 系统是否从之前的运行中学习了经验?
  9. 是否有证据支持?
  10. 结果是否有量化衡量?

这些检查通常能找到比模型微调更经济、更安全且更易控制的方法。

模型只是其中一个组成部分

一张有用的图片:

              ┌───────────────────┐
              │ Knowledge + RAG   │
              └─────────┬─────────┘
                        ↓
Customer → Context → LLM → Tools → Real World
            ↑         ↓      ↓
          Memory   Reasoning Validation
            ↑         ↓
            └──── Feedback
                    ↓
                Evaluation

大语言模型能够生成各种可能性。它周围的一切——事实、背景信息、约束条件、工具、验证机制、记忆内容以及反馈——共同构成了让整个系统具备可靠性的基础。

幻觉问题往往更多是系统设计层面的问题,而非模型本身的问题。更好的背景信息、更丰富的知识储备、更完善的工具、经过验证的输出结果,以及从实际发生的情况中学习,这些比单纯重新训练更能带来进步。实际问题已从“该使用哪种模型”转变为“模型应该掌握什么知识、能够完成什么任务,以及如何判断它是否做对了”。