
在本系列的 第 1 部分 中,我们探讨了企业为何必须将模型集成到工作流中,以保持竞争优势并实现投资回报率(ROI)最大化。我们分析了从交易到欺诈检测的示例,强调了无所作为的潜在后果。然而,随着这些自主系统的规模扩大和新功能的引入,不可预见的副作用可能会呈指数级增长。在多代理线性系统中,如果一个代理的错误未得到纠正,可能会造成不可逆的损害。因此,我们确立了评估和护栏的基本原则,并强调了当模型负责后续操作或在多代理系统中运行时,这些原则的重要性。
第 2 部分展示了 LLM-as-Judge(大模型评审)的动手实践,这是一种利用一个大语言模型(LLM)来评估另一个 LLM 生成输出的模式。这种评估的主要目标是评定生成内容的质量、相关性和整体有效性,确保其符合标准并在定义的约束内运行。这种灵活的模式可以检测幻觉或错误响应等问题。一旦通过评估识别出问题,下一步就是确定适当的响应。在本篇博文中,我们将探索一种系统可以动态从错误中学习并在实时中自主纠正的模式。
评估工具帮助我们测量、评分并标记问题以供分析。我们可以将评估作为被动监控系统使用,即记录分数、发送到仪表板并进行离线审核,以指导未来的模型改进。我们也可以主动使用它们,将其视为可触发的操作事件,并将评估输出直接接入应用程序的控制流中。
模型可以生成置信度分数,并以此来调整应用程序的行为。例如:循环回溯并使用更安全的提示词或额外的检索过滤器重试上一步、拦截后续操作、转人工处理或回退到模板响应。这种模式被称为自我纠正(self correcting)或行为塑造(behavior shaping)——具体取决于模型是评估自身,还是使用另一个模型进行评估。
行为塑造:自适应安全网
行为塑造是一个三步循环:评分、反馈和纠正。
- 评分:首先,我们根据特定应用的评估标准对模型的响应进行评估。根据用例,这可能会检查幻觉、政策违规、语气不匹配或回答不完整。评估器生成一个分数,指示输出是可接受的还是需要纠正。
- 反馈:其次,基于评估结果,我们生成具体的纠正指南。如果模型编造了事实,我们就设计一个更严格的提示词,强调以上下文为基础。如果回答太啰嗦,我们就增加约束并指示其保持简洁。如果遗漏了关键信息,我们就明确指示其解决这些缺口。反馈是针对性的,包含精确的修复指令。
- 纠正:第三,我们使用更新后的提示词重试原始请求,在输出到达用户之前给模型第二次机会来生成更好的结果。
通过外部奖励服务增强评估
为了使评分步骤更强大,我们还可以使用外部奖励服务来引导评估。该服务可以包含定义应用程序高风险或最理想行为(如包含来源引用)的具体业务逻辑。
以基于 RAG 构建的自主客服机器人为例:用户提问,系统从向量数据库中检索相关的 FAQ,语言模型根据检索到的文档生成自然语言响应。现在我们需要评估该响应是否好到足以发送给用户。这就是评估器和奖励服务协同工作的地方。评估器接收三个输入:用户的原始问题、检索到的 FAQ 上下文以及机器人生成的响应。在给出最终评分之前,评估器会查询奖励服务并传递这些详细信息。
例如,奖励服务可以使用以下业务规则:
| 评估标准 | 得分 |
|---|---|
| 当用户意图模糊时,机器人是否进行了澄清提问? | +2 奖励 |
| 响应是否尝试给出超出批准 FAQ 范围的财务建议? | -5 高风险 |
| 响应是否包含来源引用? | +1 奖励 |
评估器整合这些外部信号以生成最终的、上下文感知的分数。这种架构清晰地将通用的评估任务与定义成功的、且经常变化的特定业务规则分离开来。
为什么这种模式很重要
行为塑造将 AI 应用中静态的护栏转化为自适应系统。与其用僵化的规则拦截每一个潜在的有问题输入,不如允许系统尝试任务、评估结果,并根据实际发生的情况调整方法。随着时间的推移,通过监控评估分数和成功率,你可以识别哪些纠正后的提示词能持续产生更好的输出。这些表现优异的提示词随后可以被提升为应用程序的新基准指令。
在模型根据检索上下文生成答案的 RAG 应用中,这种模式的需求尤为迫切。产生幻觉的 RAG 应用可能是危险的——特别是在高风险行业。想象一下医疗助手推断出笔记中不存在的剂量,或者金融助手编造申报截止日期。这些问题并不少见;它们代表了可能损害用户信任并产生真实法律责任的典型实施失败。
行为塑造对于处理多变外部状态(如市场波动、天气模式、API 健康状况或系统负载等快速且不可预测变化的现实条件)的应用也至关重要。在企业应用中,模型在生成响应时通常将这些外部信号作为输入。例如,交易机器人接收市场数据馈送和波动率指标来指导其买卖建议。然而,即使能访问正确的信号,模型也可能误读它们,应用错误的推理,或生成未能充分考虑当前风险水平的建议。这些条件直接影响模型的输出是否安全且适合执行。
假设一个交易机器人可以访问显示 VIX 指数为 42(极端市场压力)的市场波动率 API。机器人可能仍会生成激进的杠杆交易建议——也许它过重地考虑了历史模式,或者误解了当前波动的严重性。评估者的工作是根据这些相同的外部条件独立验证机器人的决策:“鉴于 VIX 为 42,这个交易建议合理吗?”如果不合理,它会被标记为高风险、在评分中受到重罚或完全被拦截。
同样,物流代理可能会获得显示严重风暴的天气数据,但由于优先考虑速度而非安全的优化逻辑,它仍建议走那条路线。评估器会重新检查天气状况,并在危险路线执行前发现错误。
评估器并不是引入新信号,而是提供一种常识检查,以确保模型正确解释了给定的外部状态。奖励服务可以通过集成相同的外部监控系统来编码这些验证规则:
- 运营约束:最大交易量、支出限制、执行超时
- API 安全:速率限制合规性、域名白名单、请求验证
- 外部状态监控:市场波动阈值、系统健康检查、依赖可用性
状态管理与回滚机制
在某些情况下,在错误输出到达用户之前拦截它就足够了。但在企业系统中,模型可能会执行影响系统状态的操作,例如写入数据库、调用外部 API、发起交易等。当这些操作使应用程序处于不理想状态时,仅仅防止未来的错误输出是不够的。你需要回滚机制来撤销已经完成的操作。
除了评分和为重试提供反馈外,评估器还可以被设计为具有直接触发回滚程序的权限。当它检测到模型的行为违反了安全约束或产生了错误结果时,它可以主动调用回滚机制将系统恢复到安全状态。
例如,如果评估器检测到金融交易以错误的金额执行,它可以自动触发补偿交易以撤销该操作。如果它发现多代理工作流传播了错误数据,它可以停止执行并回滚到目前为止所做的所有状态更改。这使得评估器不仅是一个测量工具,而且是一个有能力实时撤销损害的主动安全控制器。
灵活重配置
反馈循环可以在无需重新部署系统的情况下进行中途纠正。行为塑造并不是为了预先捕获每一个可能的故障,而是为了构建能够在问题发生时检测到问题、理解错误原因并在损害扩大前自动纠正方向的系统。我们已经讨论了可以引导 AI 系统实现预期结果的模式。让我们通过具体的实现来看看这在实践中是如何运作的。
实现示例
让我们构建一个具备幻觉检测和自动纠正功能的 RAG 系统。本示例演示了一个电子商务 FAQ 助手,客户在此咨询关于政策、物流和退货的问题。Weaviate 负责 RAG 功能,从知识库中检索相关的 FAQ 条目,并使用生成模型根据检索到的上下文创建自然语言答案。ArizeAI 的 幻觉评估器 会检查生成的答案是否与检索到的上下文一致,或者是否引入了未经验证的新信息。如果识别出幻觉,系统将自动启动重试,并使用专门设计用于对抗幻觉的提示词。
┌─────────────────┐ ┌────────────────────┐ ┌────────────────────┐
│ User query │ → │ Weaviate │ → │ Arize AI │
│ "return policy" │ │ RAG (retrieve │ │ evaluates │
│ │ │ + generate) │ │ hallucination │
└─────────────────┘ └────────────────────┘ └────────────────────┘
↑ │
│ ↓
│ hallucinated?
│ │
└───── retry with ──────┘
enhanced prompt
Weaviate 是一款通过 ISO27001 认证的开源向量数据库,具有内置的混合搜索、高级过滤和开箱即用的 RAG 能力。其特性包括灵活的即插即用模块、零停机备份、多租户、向量压缩以及用于安全、可扩展 ML 应用的租户隔离。
Arize AI 提供 AI 和代理工程平台,帮助企业开发、评估和观测其 LLM 应用。Arize AX——该公司的旗舰平台——提供 提示词优化、学习、追踪和 LLM 评估功能,并拥有针对幻觉和提示词有效性等内容的预测试 LLM 评估器 稳健库。
通过结合这些工具,可以创建一个自我纠正的 RAG 流水线,在幻觉到达用户之前捕获并修复它们。
先决条件
该示例使用 Python,并假设读者熟悉 RAG 架构 和 评估框架。如果你是这些工具的新手,建议先阅读 Weaviate 快速入门 和 Arize AX 文档。我们将使用 AWS Bedrock Titan 进行 Weaviate 内的 RAG 生成,并使用 OpenAI 在 ArizeAI 中评估 RAG 响应。
在开始之前,请确保具备以下条件:
- API 密钥:为您选择的 LLM 设置身份验证(用于嵌入和生成),并在环境中配置 API 密钥。
- Weaviate 设置:按照 Weaviate 快速入门指南 设置 Weaviate 实例。Weaviate 提供 多种部署选项 以满足您的特定用例。在下面的示例中,我们将连接到 Weaviate Serverless Cloud。
- Arize AX 账户:在此处注册 Arize AX 账户。
安装
安装所需的依赖项
%pip install -q arize-phoenix-evals openai weaviate-client datasets huggingface-hub
Weaviate 集合
Weaviate Cloud 快速入门 将帮助您设置云账户并在几分钟内开始使用。有关更多部署选项和连接教程,请参阅文档。
import weaviate
import weaviate.classes as wvc
weaviate_client = weaviate.connect_to_weaviate_cloud(
cluster_url=[WEAVIATE_CLOUD_URL],
auth_credentials=weaviate.auth.AuthApiKey([WEAVIATE_API_KEY]),
headers={
"X-AWS-Access-Key": [AWS_ACCESS_KEY],
"X-AWS-Secret-Key": [AWS_SECRET_KEY],
"X-OpenAI-Api-Key": [OPENAI_KEY],
}
)
接下来,我们创建一个使用 AWS Bedrock 模型进行向量化和 RAG 的集合。有关向量化器不同属性和特定模型的更多信息,请参阅此处文档 此处。同样,生成配置 文档将为您提供生成模型的更多配置选项。
from weaviate.classes.config import Configure, Property, DataType
weaviate_client.collections.create(
name='EcommerceFAQ',
vector_config=wvc.config.Configure.Vectors.text2vec_aws(
service="bedrock",
model="amazon.titan-embed-text-v2:0",
region="us-west-2",
vectorize_collection_name=False,
),
properties=[
Property(name="question", data_type=DataType.TEXT),
Property(name="answer", data_type=DataType.TEXT),
Property(name="category", data_type=DataType.TEXT),
Property(name="parent_category", data_type=DataType.TEXT),
Property(name="question_id", data_type=DataType.TEXT),
Property(name="category_id", data_type=DataType.TEXT),
],
generative_config=wvc.config.Configure.Generative.aws(
region="us-west-2",
service="bedrock",
model="amazon.titan-text-express-v1"
)
)
加载并导入 FAQ 数据
从 HuggingFace 加载 电子商务 FAQ 数据集并将其导入 Weaviate。
dataset = load_dataset("NebulaByte/E-Commerce_FAQs")
faq_data = dataset['train'].to_pandas()
print(f"Dataset loaded: {len(faq_data)} FAQ entries")
print("Importing FAQ data...")
with weaviate_client.batch.dynamic() as batch:
for idx, row in faq_data.iterrows():
batch.add_object(
collection=collection_name,
properties={
"question": row["question"],
"answer": row["answer"],
"category": row["category"],
"parent_category": row["parent_category"],
"question_id": str(row["question_id"]),
"category_id": str(row["category_id"])
}
)
Weaviate RAG
此函数处理核心 RAG 工作流——检索与用户查询相关的文档,然后在将检索到的文档保存到上下文后,要求 LLM 生成答案。它返回一个包含答案和上下文的字典,供 ArizeAI 中的评估器使用。
from weaviate.classes.config import Configure
from weaviate.classes.generate import GenerativeConfig
def weaviate_rag(question: str, generative_prompt: str, limit: int = 3) -> Dict:
try:
response = faq_collection.generate.hybrid(
query=question,
limit=limit,
grouped_task=generative_prompt,
return_metadata=["score"]
)
context_items = []
for obj in response.objects:
context_items.append(
f"Q: {obj.properties['question']}\n"
f"A: {obj.properties['answer']}\n"
f"Category: {obj.properties['category']}"
)
context = "\n\n---\n\n".join(context_items)
answer = response.generated if response.generated else ""
return {
"answer": answer,
"context": context
}
except Exception as e:
return {
"answer": f"Error occurred: {str(e)}",
"context": ""
}
幻觉评估器
设置 Arize 评估模型。
eval_judge_model = OpenAIModel(
model="gpt-4o",
temperature=0,
api_key=openai_key
)
创建一个幻觉检测模板,检查生成的答案是否基于提供的上下文。模板明确定义了什么是幻觉,什么是可接受的行为。
RAG_HALLUCINATION_TEMPLATE = '''
You are evaluating whether an AI assistant's response contains hallucinated information when answering a question based on provided context.
[BEGIN DATA]
************
[Question]: {question}
************
[Context]: {context}
************
[Response]: {answer}
[END DATA]
Evaluate if the response contains information that is NOT supported by the provided context.
Hallucination occurs when:
- The response includes facts, numbers, or details not found in the context
- The response makes claims that contradict the context
- The response invents specific information not mentioned in the context
NOT hallucination when:
- The response says it doesn't have enough information
- The response only uses information from the context
- The response makes reasonable inferences clearly based on the context
Your answer must be a single word: "hallucinated" or "factual".
'''
定义用于检查 Weaviate RAG 响应是否包含幻觉的函数。在此函数中,我们将用户的问题、Weaviate 的 RAG 答案以及 Weaviate 用于生成响应的上下文发送给评估模型。llm_classify 函数使用评估模型将每个响应分类为“幻觉”或“事实”,并提供其推理说明。
def evaluate_hallucination_in_RAG_response(question: str, answer: str, context: str) -> Dict:
user_query_df = pd.DataFrame({
"question": [question],
"answer": [answer],
"context": [context]
})
# Run hallucination evaluation using llm_classify
eval_result = llm_classify(
data=user_query_df,
template=RAG_HALLUCINATION_TEMPLATE,
model=eval_judge_model,
rails=["hallucinated", "factual"],
provide_explanation=True
)
result = eval_result.iloc[0].to_dict()
if 'explanation' in result:
print(f" Explanation: {result['explanation']}")
return result
行为塑造循环
这是我们检测幻觉并通过纠正提示词并重试来尝试修复它的地方。当 eval_result["label"] == "hallucinated" 时,我们不是返回失败的响应,而是构造一个新的提示词。retry_prompt 采用原始的 base_prompt 并添加一条警告,明确告诉模型其之前的响应因幻觉而被标记。然后,我们使用这个包含具体错误反馈的增强提示词再次调用 Weaviate RAG。重试后,我们再次运行幻觉评估器检查纠正是否奏效。如果新响应通过了评估,我们将其返回。如果达到 max_retries 后仍然失败,我们返回显示失败元数据的最后一次尝试。这样,你始终知道最终输出是否通过了幻觉检查。
def complete_rag_with_hallucination_check(question: str, max_retries: int = 1) -> Dict:
attempts = []
base_prompt = """
You are a helpful e-commerce customer service assistant. Answer the user's question based ONLY on the provided context from the FAQ database.
IMPORTANT RULES:
- Only use information from the provided FAQ context
- Be concise and helpful
- Don't make up information that's not in the context
"""
print(f"Attempt 1:")
# First attempt with base prompt
weaviate_result = weaviate_rag(question, base_prompt)
rag_result = {
"question": question,
"answer": weaviate_result["answer"],
"context": weaviate_result["context"]
}
print(f"Generated answer: {rag_result['answer']}")
print("Evaluating for hallucination...")
eval_result = evaluate_hallucination_in_RAG_response(
question=rag_result["question"],
answer=rag_result["answer"],
context=rag_result["context"]
)
attempts.append({
"attempt": 1,
"rag_result": rag_result,
"eval_result": eval_result
})
print(f"Evaluation result: {eval_result['label']}")
retry_count = 0
while eval_result["label"] == "hallucinated" and retry_count < max_retries:
retry_count += 1
print(f"\nHallucination detected! Retrying (Attempt {retry_count + 1})...")
# Anti-hallucination instruction to base prompt
retry_prompt = base_prompt + """
CRITICAL WARNING:
Your previous response was flagged as potentially containing hallucinated information.
Be EXTREMELY careful to only use information explicitly stated in the provided context.
If you cannot find the answer in the context, clearly state that you don't have enough information.
Do NOT add any information that is not directly mentioned in the context.
"""
# Retry with enhanced prompt
weaviate_result = weaviate_rag(question, retry_prompt)
rag_result = {
"question": question,
"answer": weaviate_result["answer"],
"context": weaviate_result["context"]
}
print(f"New answer: {rag_result['answer']}")
print("Re-evaluating for hallucination...")
eval_result = evaluate_hallucination_in_RAG_response(
question=rag_result["question"],
answer=rag_result["answer"],
context=rag_result["context"]
)
attempts.append({
"attempt": retry_count + 1,
"rag_result": rag_result,
"eval_result": eval_result
})
print(f"Re-evaluation result: {eval_result['label']}")
final_result = {
"question": question,
"final_answer": rag_result["answer"],
"final_evaluation": eval_result,
"total_attempts": len(attempts),
"hallucination_resolved": not eval_result["label"] == "hallucinated",
"all_attempts": attempts
}
if eval_result["label"] == "hallucinated":
print(f"\nFinal result: Hallucination still detected after {max_retries} retries")
else:
print(f"\nFinal result: Answer is factual (resolved in {len(attempts)} attempt{'s' if len(attempts) > 1 else ''})")
return final_result
系统测试
使用一些示例问题运行完整的工作流。测试套件包括应该在 FAQ 数据库中有良好匹配的正常问题,以及一个与电子商务完全无关的边缘案例(“航天计划”)。这测试了系统是否能正确区分“缺乏信息”和“产生幻觉”的情况。
test_questions = [
"What should I do if I missed my delivery?",
"Can I use my saved cards on mobile app?",
"How do I return a product?",
"What is your refund policy for electronics?",
"Can you tell me about your space program?" # Edge case: completely irrelevant
]
print("Testing RAG workflow with sample questions\n")
test_results = []
for i, question in enumerate(test_questions, 1):
print(f"\n{'='*60}")
print(f"Question {i}/{len(test_questions)}: {question}")
print('='*60)
result = complete_rag_with_hallucination_check(question)
test_results.append(result)
print(f"\nFinal Answer: {result['final_answer']}")
print(f"Factual: {result['final_evaluation']['label'] == 'factual'}")
print(f"Total Attempts: {result['total_attempts']}")
time.sleep(1)
print(f"\n\nCompleted {len(test_results)} tests")
结果与观察
运行时,你会看到三种模式:对于与 FAQ 数据库匹配良好的问题,第一次尝试通常立即通过评估。模型检索相关上下文并生成基于事实的答案,无需重试。当模型添加了检索上下文中没有的信息时,评估器会捕捉到它。使用抗幻觉提示词的重试会产生一个更保守的响应,严格遵循上下文。对于完全无关的问题(如在电商 FAQ 系统中询问航天计划),模型学会说“我没有关于那方面的信息”,而不是编造答案。
评估说明对于调试非常有用。你可以看到响应被标记的确切原因,以及在纠正提示词后模型输出的变化。以下输出显示 RAG 在问题 3 中产生了幻觉。在修复提示词并重试后,响应不再包含任何幻觉。
============================================================
Question 3/5: How do I return a product?
============================================================
Attempt 1:
Question: How can I return or exchange an item?
Generated answer: The model cannot find sufficient information to answer the question.
Evaluating for hallucination...
llm_classify |██████████| 1/1 (100.0%) | ⏳ 00:02<00:00 | 2.65s/it
Explanation: The response states that the model cannot find sufficient information to answer the question, which is not true. The context provides clear steps on how to return a product, including logging into the account, going to 'My Orders', selecting the item, and filling in the details to request a return. Therefore, the response is incorrect as it ignores the available information in the context.
Evaluation result: hallucinated
Hallucination detected! Retrying (Attempt 2)...
Question: How can I return or exchange an item?
New answer: You can raise a request to return your items with these simple steps: 1. Log into your Flipkart account 2. Go to My Orders 3. Click on 'Return' against the item you wish to return or exchange 4. Fill in the details and raise a return request Once you raise a request, you'll get an email and SMS confirming that your request is being processed. Based on the item, your request may be automatically approved or you may be contacted for more details. If the request is approved, the item will be picked up after which you will get a replacement or refund. You can also
Re-evaluating for hallucination...
llm_classify |██████████| 1/1 (100.0%) | ⏳ 00:02<00:00 | 2.22s/it
Explanation: The response is directly supported by the context provided. It outlines the steps to return an item, which are consistent with the information given in the context. The response does not introduce any new or contradictory information that is not present in the context.
Re-evaluation result: factual
Final result: Answer is factual (resolved in 2 attempts)
下方的截图显示了 OpenAI 评估器对每个 RAG 响应的回应。它告诉我们哪些响应是事实,哪些不是,尝试次数,以及其他几项审计指标。你还可以检查每次请求的成本。
评估器还为每次评估提供了解释。例如,在下方截图中,我们可以看到测试编号 3 的解释。机器人最初产生了幻觉,评估模型正确识别了这一点。解释如下所示。
在我们优化了提示词后,机器人生成了正确的答案,评估器表示满意,我们可以在下方截图中看到解释。
上述使用的完整工作代码可在该 GitHub 仓库 中找到。
上述示例专注于 RAG 系统中的幻觉,但相同的“评分-反馈-重试”模式适用于不同的企业用例。你的行业、用例和业务规则将决定你如何配置评估器和奖励服务(如果需要)。
客户服务:评估器检查语气和品牌合规性。如果响应听起来太随意或违反品牌指南,奖励服务将返回低分。系统使用强化正确语气的提示词重试。
交易系统:评估器根据风险参数和当前市场波动检查建议。如果交易违反了持仓限制或相对于外部条件过于激进,奖励服务会对其进行标记。重试将包含显式的风险约束。
内容生成:评估器检查完整性、偏见或敏感内容。如果答案遗漏了问题的关键部分或显示出潜在偏见,系统将使用强调透彻性和公平性的提示词重试。
总结
核心模式是一个简单的循环:对输出评分、生成反馈并使用更好的提示词重试。我们看到了如何通过将评估器连接到保存业务逻辑的外部奖励服务,以及通过检查多变的外部状态来确保模型输出在现实世界中合理,从而使这种模式更强大。
对于许多应用来说,这种实时辅导已经足够。但当模型执行改变系统状态的操作时,架构需要更进一步。我们讨论了赋予评估器触发回滚、使用补偿交易和构建断路器的权限。目标始终一致:在错误传播之前捕获并纠正它们。
通过结合这些模式,你可以构建不仅能报告失败而且能从失败中学习的系统。其结果是更可靠、可审计且值得信赖的 AI,能够不断改进并与你的业务目标保持一致。
准备开始构建了吗?
请查看 快速入门教程,或使用 Weaviate Cloud (WCD) 的免费试用版构建令人惊叹的应用程序。





