目 录CONTENT

文章目录

超越提示词工程:检测和缓解 LLM 幻觉的 5 种实用技术

Administrator
2026-03-26 / 0 评论 / 0 点赞 / 0 阅读 / 0 字

📣 转载信息

原文链接:https://machinelearningmastery.com/5-practical-techniques-to-detect-and-mitigate-llm-hallucinations-beyond-prompt-engineering/

原文作者:Shittu Olumide


本文将帮助你了解大型语言模型(LLM)为何会产生幻觉,以及如何通过超越提示词工程的系统级技术来减少它们。

我们将涵盖的主题包括:

  • 大型语言模型中产生幻觉的原因。
  • 用于检测和缓解生产系统中幻觉输出的五种实用技术。
  • 如何通过简单的示例和实际的设计模式来实现这些技术。

让我们开始吧。

5 Practical Techniques to Detect and Mitigate LLM Hallucinations Beyond Prompt Engineering

5 种超越提示词工程来检测和缓解 LLM 幻觉的实用技术
图片由编辑提供

引言

我的一个朋友,他是一名开发者,曾经让一个 LLM 为一个支付 API 生成文档。生成的回复看起来很完美。它有清晰的结构、恰当的语气,甚至还有示例接口。唯一的问题是,这个 API 根本不存在。模型自信地编造了接口、参数和响应,这些信息看起来足够真实,能够通过快速审查。直到有人尝试集成时才发现问题,一切都无法正常工作。

这就是幻觉在实践中的样子。模型凭空捏造信息,并将其作为事实呈现,却没有任何错误信号。

这并非罕见的边缘案例。它以微妙的方式出现在各种生产系统中。研究工具中的虚假引文。不正确的法律参考。客户支持回复中不存在的产品功能。孤立来看,这些可能只是小错误。但大规模出现时,它们就会成为严重的问题。

其影响不仅限于准确性。当用户无法依赖输出时,信任就开始瓦解。许多早期解决方案都专注于提示词工程:改进指令、加强措辞和明确约束。这有所帮助,但仅限于一定程度。提示词可以指导模型,但它们不会从根本上改变其生成答案的方式。当系统缺乏正确信息时,它仍然会试图产生某种结果。

这就是为什么团队开始将幻觉视为一个系统问题,而不仅仅是提示词问题。与其仅仅依赖更好的输入,他们正在围绕模型构建层,以检测、验证和控制输出内容。

LLM 幻觉的成因

在探讨如何解决幻觉问题之前,了解它们为何会发生很有帮助。其原因并不神秘,但当输出听起来令人信服时,它们很容易被忽视。

第一个问题是缺乏基础信息。大多数语言模型如果没有明确连接到实时或已验证的数据源,就无法直接访问它们。它们基于训练过程中学到的模式生成响应,而不是通过实时来源核查事实。当缺少确切答案时,模型会填补空白。

还有过度泛化的问题。这些模型在庞大而多样的数据集上进行训练,这意味着它们学习的是广泛的模式,而不是精确的真相。当面对特定问题时,它们可能会将相似信息的片段组合起来,形成听起来正确但实际上不准确的内容。

另一个因素是内置的“总是需要给出答案”的压力。语言模型被设计成乐于助人和响应迅速。它们通常不会回答“我不知道”,而是生成它们认为最合理的响应。这种倾向在对话中很有用,但在准确性至关重要时却存在风险。

技术 1: 检索增强生成 (RAG)

减少幻觉最有效的方法之一,其原理很简单。停止仅依赖模型记忆中的内容,而是在需要回答时为其提供实时数据的访问权限。

这就是检索增强生成 (RAG) 的作用。你不是让模型仅凭其内部训练来生成响应,而是首先从外部源检索相关信息,然后将这些信息作为上下文传递给模型。流程很简单:用户提出问题,系统搜索知识库以查找相关内容,然后模型根据检索到的数据生成答案。

这改变了模型的行为。没有检索时,它依赖模式和概率,这是幻觉的来源。有了检索,它就有具体的内容可供参考。它不再猜测什么可能是真实的,而是基于提供的信息进行工作。

模型记忆和外部知识之间的区别在这里很重要。模型记忆是静态的。它反映了模型训练时所学的内容,这些内容可能过时、不完整或过于笼统。外部知识是动态的。它可以被更新、整理并针对特定领域进行定制。RAG 将真理的来源从模型转移到你的数据。

在实践中,这通常通过向量数据库来实现。文档被转换为嵌入并以允许语义搜索的方式存储。当收到查询时,系统会查找最相关的文本片段,并将它们注入提示词中,然后再生成响应。

这是一个简单的 Python 示例,用于说明其流程:

from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
from openai import OpenAI

# Step 1: Load embedding model
embedder = SentenceTransformer("all-MiniLM-L6-v2")

# Step 2: Sample knowledge base
documents = [
    "Our refund policy allows returns within 30 days.",
    "Shipping takes 3 to 5 business days.",
    "You can track your order using the tracking link sent via email."
]

# Step 3: Convert documents to embeddings
doc_embeddings = embedder.encode(documents).astype("float32")

# Step 4: Store embeddings in FAISS index
index = faiss.IndexFlatL2(doc_embeddings.shape[1])
index.add(doc_embeddings)

# Step 5: Query
query = "How long does delivery take?"
query_embedding = embedder.encode([query]).astype("float32")

# Step 6: Retrieve most relevant document
_, indices = index.search(query_embedding, k=1)
retrieved_doc = documents[indices[0][0]]

# Step 7: Generate response using retrieved context
client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "Answer using the provided context only."},
        {"role": "user", "content": f"Context: {retrieved_doc}\n\nQuestion: {query}"}
    ]
)

print(response.choices[0].message.content)

代码的功能:

  • 嵌入模型将文档和查询转换为向量,以便进行有意义的比较
  • FAISS 用于高效地存储和搜索这些向量
  • 收到查询时,系统会检索最相关的文档
  • 该文档作为上下文被注入模型,指导响应生成
  • “仅使用提供的上下文进行回答”的指令进一步降低了幻觉的可能性

这种方法之所以有效,是因为它将模型的响应锚定在真实信息上。它不是从头开始生成,而是在约束下进行生成。

即便如此,RAG 也并非完美解决方案。如果检索步骤失败,模型就又回到了猜测的状态。索引质量不高、文档不相关或数据缺失仍可能导致幻觉输出。换句话说,答案的质量很大程度上取决于你检索内容的质量。

RAG 并不能完全消除幻觉,但通过提供一个可靠的真实信息来源供模型参考,可以显著减少幻觉的发生。

技术 2: 输出验证和事实核查层

使用 LLM 时,最容易犯的错误之一就是将第一次响应视为最终结果。它读起来很流畅,听起来很自信,在很多情况下,它看起来也很正确。这正是幻觉得以混入的原因。

更可靠的方法是将每次输出都视为未经核实的草稿。这就是验证层的用武之地。你引入额外的步骤来检查、验证或质疑生成的内容,然后再将其传递给用户,而不是依赖单一的模型响应。

一种常见的方法是使用第二个模型进行验证。第一个模型生成答案,第二个模型进行审查。审查者可以检查事实一致性,标记未经支持的声明,甚至将答案与已知来源进行比较。这创建了一个简单的但有效的生成与验证分离。

另一种方法是将输出与可信数据源进行交叉检查。例如,如果一个响应包含统计数据、引文或技术细节,系统可以与数据库、API 或内部知识库进行核实。如果信息无法确认,系统可以拒绝该响应或要求澄清。

还有一种称为自洽性的技术。不是只问模型一次,而是多次提问,有时会轻微修改提示词。如果答案趋于一致,则更有可能是正确的。如果它们存在显著差异,这表明模型不确定或在猜测。

以下是一个简单的实现示例:

from openai import OpenAI

client = OpenAI()

def ask_model(question):
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": question}]
    )
    return response.choices[0].message.content.strip()

question = "What is the capital of Australia?"

# Ask the same question multiple times
answers = [ask_model(question) for _ in range(3)]

print("Model Answers:")
for i, ans in enumerate(answers, start=1):
    print(f"{i}. {ans}")

# Simple consistency check
if len(set(answers)) == 1:
    print("\nHigher confidence: answers are consistent.")
else:
    print("\nLower confidence: answers differ, so this result needs verification.")

代码的功能:

  • 同一问题被发送给模型多次
  • 收集并比较响应
  • 如果所有答案都匹配,系统会认为结果更可靠
  • 如果答案不同,系统会标记结果以供进一步检查或人工审核

这是一个基本示例,但在生产系统中,这个想法可以进一步扩展。你可以重新措辞问题、使用不同的模型或引入评分系统来评估一致性。

关键思想很简单:不要依赖单次尝试。在生成和交付之间增加摩擦。验证层确实会增加额外的成本和延迟,但它们显著提高了可靠性。在许多情况下,这种权衡是值得的,尤其是在准确性至关重要的系统中。

技术 3: 约束生成(结构化输出)

许多幻觉源于一个简单的现实:模型在如何响应方面拥有过多的自由度。当你提出一个开放式问题并允许自由文本输出时,模型会随意填补空白。这种灵活性有利于创造力,但也为不正确或虚构的信息留下了空间。

约束生成采取了相反的方法。它限制了模型响应的方式。你不是要求一个段落,而是定义一个结构。这可以是一个 JSON schema、一组固定的字段,甚至是受控的可接受值列表。模型不再可以自由生成任何它想要的东西。它必须将其答案放入预定义的格式中。

这行得通,因为它消除了歧义。如果一个字段需要一个数字,模型就不能返回一个故事。如果一个值必须来自固定列表,它就不能发明一个新选项。结构本身就成为了一个护栏。

实现此目的的一种常见方法是使用 JSON schema。你精确定义输出应有的样子,包括必需字段和允许的值。

这是一个简单的示例:

import json
from jsonschema import validate
from openai import OpenAI

client = OpenAI()

schema = {
    "type": "object",
    "properties": {
        "product_name": {"type": "string"},
        "price": {"type": "number"},
        "availability": {
            "type": "string",
            "enum": ["in_stock", "out_of_stock"]
        }
    },
    "required": ["product_name", "price", "availability"]
}

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "Extract product details in JSON format only."},
        {"role": "user", "content": "The iPhone 13 costs $799 and is currently available."}
    ],
    response_format={"type": "json_object"}
)

result = json.loads(response.choices[0].message.content)
validate(instance=result, schema=schema)

print(result)

代码的功能:

  • Schema 定义了预期的输出结构
  • 模型被指示仅返回 JSON
  • 生成的 JSON 在生成后会根据 schema 进行验证
  • availability这样的字段被限制在特定值内
  • 这减少了意外格式或不支持值出现在输出中的可能性

除了 JSON,约束生成还体现在函数调用和工具使用中。模型不是直接生成答案,而是从预定义的动作中进行选择。例如,它可以调用一个函数来获取数据,而不是猜测结果。这减少了幻觉,因为模型不再需要独自负责生成最终答案。

受控词汇将这一点进一步推向了极致。在某些系统中,模型被限制在一组固定的术语、标签或类别中。这在一致性比灵活性更重要的分类任务中很常见。

这种方法之所以有效,原因很简单。幻觉通常源于模型在开放式场景中试图提供帮助。通过缩小可能的输出范围,你可以减少它偏离轨道的机会。

技术 4: 置信度评分与不确定性处理

LLM 更危险的特性之一不是它们会出错,而是它们毫不犹豫地出错。正确答案和完全捏造的答案在语气和自信度上可能看起来完全一样。

如果你想减少幻觉,就需要一种方法来判断模型何时可能在猜测。置信度评分引入了这种信号。系统在接受每个响应之前会评估其可靠性,而不是照单全收。

在最低层面,这可以通过词元概率来完成。模型在生成每个词元时,都会为其分配一个概率。当这些概率很高且一致时,通常意味着模型在熟悉模式内运行。当它们下降或波动时,它们可能表示不确定性。虽然这个信号并不完美,但它提供了一个有用的基线。

除了原始概率,校准技术有助于使这些信号更有意义。例如,你可以比较多次运行的输出,以查看...

0

评论区