各位编程专家,晚上好!
今天,我们将深入探讨一个在大型语言模型(LLM)应用开发中日益关键且充满挑战的话题:如何有效遏制其输出中的幻觉(Hallucinations)与错误。随着LLM能力的飞速提升,它们已经成为我们软件栈中不可或缺的一部分,但其固有的不可预测性——尤其是“一本正经地胡说八道”的能力——也为我们带来了巨大的风险。传统的事后审查或基于规则的过滤机制往往滞后且不够灵活。因此,我们需要一种更主动、更智能的解决方案。
今天的主题是:Agentic Monitoring——利用一个专门的“观察者 Agent”实时扫描主图的输出,拦截幻觉与错误。
我们将从问题背景出发,逐步深入到Agentic Monitoring的核心理念、架构设计、实现细节、代码示例、面临的挑战以及未来的发展方向。
一、 LLM的崛起与挑战:幻觉与错误的阴影
大型语言模型,如GPT系列、Llama、Mistral等,已经彻底改变了我们与信息交互的方式。它们能够生成流畅、连贯、富有创造力的文本,完成翻译、摘要、代码生成、内容创作等一系列复杂任务。然而,这些强大的能力并非没有代价。LLM的本质是基于海量数据进行模式识别和概率预测,它们并不真正理解事实,也不具备人类的“常识”和“推理”能力。这导致了两个主要问题:
- 幻觉 (Hallucinations): 模型生成看似合理但实际上是虚构、不真实或与上下文无关的信息。这可能是因为训练数据中的偏差、模型过度自信、或是在面对不确定性时“编造”内容。
- 错误 (Errors): 包括但不限于事实性错误、逻辑不一致、计算错误、格式错误、安全隐规(如偏见、有害内容)等。这些错误可能源于模型对指令的误解、数据陈旧、或是在复杂推理链中出现偏差。
在许多应用场景中,例如金融报告生成、医疗诊断辅助、法律文书起草、自动化编程等,幻觉和错误是绝对不可接受的。它们可能导致严重的经济损失、法律风险甚至生命危险。因此,构建一个能够可靠地识别并拦截这些问题的机制,变得至关重要。
二、 Agentic Monitoring 的核心理念
“Agentic Monitoring” 的核心思想是:不信任主LLM的每一次输出,而是引入一个独立的、具备特定监控能力的“观察者 Agent”(或称“监控 Agent”),专门负责实时审查主LLM的生成内容,并在发现问题时及时介入。
这个“观察者 Agent”不仅仅是一个简单的过滤器,它被设计为一个具备:
- 理解能力: 能理解主LLM的输出内容及其上下文。
- 推理能力: 能基于预设规则、外部知识或自身学习到的模式进行判断。
- 决策能力: 能根据判断结果采取适当的行动(如拦截、修正、标记、请求重试)。
- 自主性: 在一定程度上独立于主LLM运作。
它的目标是构建一个健壮的“安全网”,确保只有高质量、无错误、无幻觉的输出才能触达最终用户或下游系统。
三、 架构设计:主生成器与观察者 Agent 的协作
Agentic Monitoring 的典型架构涉及至少两个主要组件:
- 主生成器 Agent (Primary Generator Agent): 这是我们通常所说的LLM应用核心,负责根据用户请求生成文本、代码或其他内容。它可能是通过Prompt Engineering、RAG(Retrieval-Augmented Generation)或其他复杂工作流构建的。
- 观察者 Agent (Observer/Monitor Agent): 这是我们今天重点讨论的部分。它是一个专门的LLM实例(或由多个LLM及工具组合而成),其唯一职责是监控并评估主生成器 Agent 的输出。
以下表格展示了两者之间的职责划分:
| 组件名称 | 主要职责 | 核心能力 |
|---|---|---|
| 主生成器 Agent | 根据用户指令生成内容(文本、代码、数据等) | 自然语言理解、文本生成、知识整合(通过RAG等) |
| 观察者 Agent | 实时接收并评估主生成器 Agent 的输出 | 上下文理解、事实核查、逻辑推理、安全评估、错误分类 |
| 外部工具/知识库 | 为观察者 Agent 提供事实依据、API访问、结构化数据 | 数据检索、API调用、计算、验证 |
| 反馈机制 | 在发现问题时,将信息回传给主生成器或操作员 | 错误报告、修正建议、重试指令 |
基本工作流程如下:
- 用户向主生成器 Agent 发送请求。
- 主生成器 Agent 处理请求并生成初步输出。
- 关键步骤: 这个初步输出不会直接发送给用户。它会被转发给观察者 Agent。
- 观察者 Agent 接收主生成器 Agent 的输出,并结合原始用户请求(可选,但强烈推荐)和其自身的监控逻辑进行评估。
- 观察者 Agent 利用其内部的“智能”(如另一个LLM)和外部工具(如搜索引擎、数据库、API)进行事实核查、逻辑验证、格式检查、安全审查等。
- 根据评估结果:
- 如果输出通过检查: 观察者 Agent 批准该输出,并将其转发给用户。
- 如果输出未能通过检查: 观察者 Agent 拦截该输出。它可以选择:
- 直接拒绝,并向用户返回错误信息。
- 尝试自行修正(如果被设计为具备修正能力)。
- 向主生成器 Agent 发送反馈,请求其基于修正建议进行重试。
- 标记为需要人工审查。
四、 观察者 Agent 的核心组件与实现细节
一个健壮的观察者 Agent 通常由以下几个核心组件构成:
4.1 输入处理器 (Input Processor)
负责接收主生成器 Agent 的输出,并可能同时接收原始的用户请求(或更完整的上下文,如对话历史)。
class PrimaryAgentOutput:
def __init__(self, original_prompt: str, generated_content: str, metadata: dict = None):
self.original_prompt = original_prompt
self.generated_content = generated_content
self.metadata = metadata if metadata is not None else {}
class ObserverInputProcessor:
def process(self, output: PrimaryAgentOutput) -> dict:
"""
处理来自主Agent的输出,准备好供Observer Agent评估。
可以进行初步的解析、结构化等。
"""
# 简单示例,直接返回字典
return {
"original_prompt": output.original_prompt,
"content_to_monitor": output.generated_content,
"additional_context": output.metadata
}
# 示例用法
# primary_output = PrimaryAgentOutput(
# original_prompt="请生成一篇关于量子纠缠的科普文章。",
# generated_content="量子纠缠是一种神奇的现象,它允许两个或多个粒子在空间上分离,但它们的量子态却纠缠在一起,无论距离多远,对其中一个粒子的测量都会瞬间影响另一个粒子。这种现象被爱因斯坦称为“幽灵般的超距作用”。"
# )
# processor = ObserverInputProcessor()
# processed_data = processor.process(primary_output)
# print(processed_data)
4.2 上下文理解与领域知识 (Contextualizer & Domain Knowledge)
观察者 Agent 必须理解原始任务的意图和相关领域知识,才能有效评估输出。这可以通过:
- Prompt Engineering: 在观察者 Agent 的系统提示中注入任务描述和领域背景。
- RAG: 让观察者 Agent 能够访问一个与领域相关的知识库。
- 专门的微调模型: 如果领域非常专业化,可以对观察者 Agent 进行微调。
4.3 事实核查与知识库 (Fact Checker & Knowledge Base)
这是拦截幻觉和事实性错误的关键组件。观察者 Agent 可以通过以下方式进行事实核查:
- 外部 API 调用: 集成搜索引擎 API (如Google Search API, Bing Search API)、维基百科 API、专业数据库 API 等。
- 内部知识库查询: 如果应用有自己的私有知识库,观察者 Agent 可以查询这些数据。
- 另一个 LLM (Fact-Checking LLM): 专门训练或配置一个LLM作为事实核查器,它接收主LLM的声明,并尝试通过其内部知识或检索到的信息进行验证。
代码示例:利用外部 API 进行事实核查
import requests
import json
from abc import ABC, abstractmethod
# 抽象的外部验证器接口
class ExternalFactChecker(ABC):
@abstractmethod
def check_fact(self, statement: str) -> dict:
pass
# 模拟一个简化的维基百科API
class WikipediaFactChecker(ExternalFactChecker):
def check_fact(self, statement: str) -> dict:
# 这是一个模拟API调用的简化版本
# 实际中会调用 requests.get('https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=...')
# 并解析返回的JSON
print(f"模拟查询维基百科:'{statement}'...")
if "量子纠缠" in statement:
return {"status": "verified", "source": "Wikipedia", "info": "量子纠缠是量子力学中的一种现象。"}
if "木星是太阳系最大的行星" in statement:
return {"status": "verified", "source": "Wikipedia", "info": "木星是太阳系中体积最大、质量最大的行星。"}
if "地球是平的" in statement:
return {"status": "refuted", "source": "Common Knowledge", "info": "地球是一个近似球体的行星。"}
return {"status": "unknown", "source": "N/A", "info": "未能找到直接验证信息。"}
# 结合LLM进行初步判断,再决定是否调用外部工具
class LLMFactChecker:
def __init__(self, llm_client, external_checker: ExternalFactChecker):
self.llm_client = llm_client
self.external_checker = external_checker
def verify_statement(self, statement: str, context: str = "") -> dict:
# Step 1: LLM初步判断,识别出需要核查的关键事实点
prompt_identify_facts = f"""
你是一个事实点提取器。从以下文本中识别出所有可能需要外部核查的具体事实声明。
请以列表形式返回这些声明。如果没有任何具体事实,则返回空列表。
文本: "{statement}"
上下文: "{context}"
例如:
- 声明1
- 声明2
"""
response_facts = self.llm_client.generate(prompt_identify_facts, max_tokens=200, temperature=0.1)
# 假设LLM返回的是一个包含声明的字符串,我们需要解析它
facts_to_check = [f.strip() for f in response_facts.split('n') if f.strip() and f.startswith('-')]
facts_to_check = [f[2:].strip() for f in facts_to_check] # 移除'- '
if not facts_to_check:
# 如果LLM认为没有具体事实需要核查,可以做进一步判断或直接返回
return {"overall_status": "no_obvious_facts_to_check", "details": []}
verification_results = []
all_verified = True
for fact in facts_to_check:
# Step 2: 对每个事实点调用外部核查器
external_result = self.external_checker.check_fact(fact)
verification_results.append({
"fact": fact,
"external_check": external_result
})
if external_result["status"] != "verified":
all_verified = False
return {
"overall_status": "verified" if all_verified else "contains_unverified_or_refuted_facts",
"details": verification_results
}
# 模拟LLM客户端
class MockLLMClient:
def generate(self, prompt: str, max_tokens: int, temperature: float) -> str:
if "量子纠缠" in prompt and "科普文章" in prompt:
return "- 量子纠缠是一种现象n- 爱因斯坦称之为“幽灵般的超距作用”"
elif "地球是平的" in prompt:
return "- 地球是平的"
return ""
# 示例用法
# llm_client = MockLLMClient()
# wiki_checker = WikipediaFactChecker()
# fact_checker_agent = LLMFactChecker(llm_client, wiki_checker)
# statement_good = "量子纠缠是一种神奇的现象,它允许两个或多个粒子在空间上分离,但它们的量子态却纠缠在一起,无论距离多远,对其中一个粒子的测量都会瞬间影响另一个粒子。这种现象被爱因斯坦称为“幽灵般的超距作用”。"
# result_good = fact_checker_agent.verify_statement(statement_good, "科普文章")
# print("n--- 良好输出核查结果 ---")
# print(json.dumps(result_good, indent=2, ensure_ascii=False))
# statement_bad = "地球是平的,而且月亮是由奶酪做成的。这是伽利略在17世纪发现的。"
# result_bad = fact_checker_agent.verify_statement(statement_bad, "历史发现")
# print("n--- 错误输出核查结果 ---")
# print(json.dumps(result_bad, indent=2, ensure_ascii=False))
上述代码展示了如何结合LLM和外部工具进行事实核查。LLM首先从文本中提取出可能的事实声明,然后外部核查器对这些声明进行验证。
4.4 逻辑与推理引擎 (Logic & Reasoning Engine)
这个组件负责检查主LLM输出的内部一致性、逻辑合理性以及是否符合特定规则。这通常通过向观察者 Agent 提出特定的推理问题来实现。
代码示例:利用LLM进行逻辑一致性检查
import openai # 假设使用OpenAI API
class LLMLogicChecker:
def __init__(self, api_key: str):
self.client = openai.OpenAI(api_key=api_key)
def check_consistency(self, text_to_check: str, original_prompt: str = "") -> dict:
"""
检查给定文本的逻辑一致性、内部连贯性以及是否符合常识。
"""
system_message = """
你是一个严谨的逻辑与常识检查器。
你的任务是评估一段文本的逻辑一致性、内部连贯性以及是否包含明显违反常识的陈述。
请根据以下标准进行评估:
1. 内部一致性:文本中是否存在自相矛盾的陈述?
2. 逻辑流:文本的论证或叙述是否符合逻辑顺序?
3. 常识性:文本内容是否与普遍接受的常识相符?
请输出一个JSON对象,包含 'is_consistent' (boolean) 和 'reasoning' (string)。
'is_consistent' 为 True 表示文本通过检查,False 表示存在问题。
'reasoning' 详细说明你的判断理由,特别是发现不一致或反常识之处。
"""
user_message = f"""
请评估以下文本:
---
{text_to_check}
---
原始请求(供上下文参考):{original_prompt}
"""
try:
response = self.client.chat.completions.create(
model="gpt-4-turbo", # 或其他高性能模型
messages=[
{"role": "system", "content": system_message},
{"role": "user", "content": user_message}
],
response_format={"type": "json_object"},
temperature=0.1
)
result = json.loads(response.choices[0].message.content)
return result
except Exception as e:
print(f"调用LLM进行逻辑检查失败: {e}")
return {"is_consistent": False, "reasoning": f"LLM服务调用失败: {e}"}
# 示例用法 (需要真实的OpenAI API Key)
# api_key = "YOUR_OPENAI_API_KEY"
# logic_checker = LLMLogicChecker(api_key)
# good_text = "今天天气很好,阳光明媚,我决定去公园散步。在公园里,我看到很多人在跑步和野餐,享受着美好的周末时光。"
# result_good = logic_checker.check_consistency(good_text, "描述一个美好的周末")
# print("n--- 逻辑一致性检查 (良好输出) ---")
# print(json.dumps(result_good, indent=2, ensure_ascii=False))
# bad_text = "今天天气很好,阳光明媚,我决定去公园散步。然而,天空却下起了瓢泼大雨,我被淋成了落汤鸡。回到家后,我感觉心情非常愉快。"
# result_bad = logic_checker.check_consistency(bad_text, "描述一个周末遭遇")
# print("n--- 逻辑一致性检查 (矛盾输出) ---")
# print(json.dumps(result_bad, indent=2, ensure_ascii=False))
# another_bad_text = "一个苹果重达一吨,它被一个蚂蚁轻松举起,然后蚂蚁用这个苹果建造了一座摩天大楼。"
# result_absurd = logic_checker.check_consistency(another_bad_text, "描述一个奇幻故事")
# print("n--- 逻辑一致性检查 (反常识输出) ---")
# print(json.dumps(result_absurd, indent=2, ensure_ascii=False))
4.5 错误分类与严重性评估 (Error Classifier & Severity Assessor)
当观察者 Agent 发现问题时,它需要对问题进行分类,并评估其严重性。这有助于决定后续采取何种行动。
常见错误类型分类:
| 错误类型 | 描述 | 严重性示例 | 示例触发场景 |
|---|---|---|---|
| 幻觉 | 捏造不存在的事实、事件或人物 | 高 | 生成虚假的医学诊断、法律条文 |
| 事实性错误 | 与真实世界的事实不符 | 中-高 | 错误的日期、人名、统计数据 |
| 逻辑不一致 | 文本内部存在矛盾、推理链断裂或违反常识 | 中-高 | 报告中数据前后矛盾、代码逻辑错误 |
| 格式错误 | 输出不符合预期的结构(JSON、XML、Markdown等) | 低-中 | API调用返回非JSON格式、Markdown语法错误 |
| 安全/偏见 | 包含有害、歧视性、攻击性内容或敏感信息泄露 | 极高 | 生成仇恨言论、泄露个人身份信息 |
| 语法/拼写 | 语言学上的错误 | 低 | 错别字、语法不通顺 |
| 风格/语调 | 不符合预期的风格或语调(如过于正式或过于随意) | 低-中 | 商业邮件使用非正式语言 |
| 不完整/截断 | 输出内容未完成或被提前截断 | 中-高 | 代码片段不完整、文章结尾突兀 |
观察者 Agent 可以利用其LLM能力,通过提示词将上述分类标准嵌入到其评估逻辑中,并要求其输出一个结构化的错误报告。
class ErrorReport:
def __init__(self, error_type: str, severity: str, description: str, suggested_action: str = None):
self.error_type = error_type
self.severity = severity
self.description = description
self.suggested_action = suggested_action
def to_dict(self):
return {
"error_type": self.error_type,
"severity": self.severity,
"description": self.description,
"suggested_action": self.suggested_action
}
class LLMErrorClassifier:
def __init__(self, api_key: str):
self.client = openai.OpenAI(api_key=api_key)
def classify_and_assess(self, monitored_content: str, original_prompt: str, issues_found: list) -> ErrorReport:
"""
根据发现的问题,对输出进行综合评估并分类。
issues_found 是由其他检查器(如事实核查器、逻辑检查器)返回的问题列表。
"""
system_message = """
你是一个专业的错误分类与严重性评估Agent。
根据提供的文本、原始请求以及已识别出的问题列表,你需要综合判断主要错误类型、严重性,并提出修正建议。
错误类型包括:幻觉、事实性错误、逻辑不一致、格式错误、安全/偏见、语法/拼写、不完整/截断。
严重性等级:低、中、高、极高。
请输出一个JSON对象,包含 'error_type', 'severity', 'description', 'suggested_action'。
如果未发现问题,则返回 {"error_type": "None", "severity": "None", "description": "Output is clean.", "suggested_action": "Approve"}.
"""
user_message = f"""
待评估文本:
---
{monitored_content}
---
原始请求: "{original_prompt}"
已发现问题列表:
{json.dumps(issues_found, indent=2, ensure_ascii=False)}
"""
try:
response = self.client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{"role": "system", "content": system_message},
{"role": "user", "content": user_message}
],
response_format={"type": "json_object"},
temperature=0.2
)
result = json.loads(response.choices[0].message.content)
return ErrorReport(**result)
except Exception as e:
print(f"调用LLM进行错误分类失败: {e}")
return ErrorReport(
error_type="Monitoring System Error",
severity="High",
description=f"Error during LLM classification: {e}",
suggested_action="Manual Review"
)
# 示例用法 (需要真实的OpenAI API Key)
# classifier = LLMErrorClassifier(api_key)
# # 假设fact_checker_agent已经运行并返回了如下问题
# issues_from_fact_check = [
# {"fact": "地球是平的", "external_check": {"status": "refuted", "source": "Common Knowledge", "info": "地球是一个近似球体的行星。"}},
# {"fact": "月亮是由奶酪做成的", "external_check": {"status": "refuted", "source": "Common Knowledge", "info": "月球由岩石组成。"}},
# ]
# monitored_content_example = "地球是平的,而且月亮是由奶酪做成的。这是伽利略在17世纪发现的。"
# original_prompt_example = "描述一个历史发现"
# error_report = classifier.classify_and_assess(monitored_content_example, original_prompt_example, issues_from_fact_check)
# print("n--- 错误分类与严重性评估 ---")
# print(json.dumps(error_report.to_dict(), indent=2, ensure_ascii=False))
4.6 动作执行器 (Action Executor)
根据错误分类和严重性,观察者 Agent 决定采取何种行动。
常见的动作包括:
- 批准 (Approve): 如果没有发现问题,则将输出传递给下游。
- 拒绝并报告 (Reject & Report): 拦截输出,并向用户或管理员发送错误通知。
- 请求重试 (Request Retry): 向主生成器 Agent 发送带有修正建议的反馈,请求其重新生成。
- 自动修正 (Auto-Correct): 如果问题轻微且可信度高,观察者 Agent 可以尝试自行修正输出(例如,修复格式错误、轻微的拼写错误)。这需要观察者 Agent 具备强大的修正能力和高置信度。
- 人工审核 (Human-in-the-Loop): 对于无法自动处理的复杂或高风险问题,将其提交给人工审查。
class ActionExecutor:
def execute_action(self, error_report: ErrorReport, primary_agent_output: PrimaryAgentOutput):
if error_report.error_type == "None":
print(f"✅ 输出通过监控:{primary_agent_output.generated_content[:50]}...")
return {"status": "approved", "final_output": primary_agent_output.generated_content}
print(f"❌ 发现问题!类型: {error_report.error_type}, 严重性: {error_report.severity}")
print(f"描述: {error_report.description}")
print(f"建议行动: {error_report.suggested_action}")
if error_report.severity in ["高", "极高"]:
if error_report.suggested_action == "Request Retry":
print(f"🚨 请求主Agent重试,并提供修正建议: {error_report.description}")
return {"status": "rejected_retry", "feedback": error_report.description}
else:
print("🛑 拦截输出,需要人工审核。")
return {"status": "rejected_manual_review", "original_output": primary_agent_output.generated_content, "error_report": error_report.to_dict()}
elif error_report.severity == "中":
if error_report.suggested_action == "Auto-Correct" and primary_agent_output.generated_content:
# 模拟自动修正,实际中可能需要另一个LLM或复杂的规则
corrected_content = self._attempt_auto_correction(primary_agent_output.generated_content, error_report.description)
if corrected_content != primary_agent_output.generated_content:
print(f"⚙️ 尝试自动修正。修正后: {corrected_content[:50]}...")
return {"status": "auto_corrected", "final_output": corrected_content}
else:
print(f"⚠️ 自动修正失败或未进行,请求主Agent重试。")
return {"status": "rejected_retry", "feedback": error_report.description}
else:
print(f"⚠️ 拦截输出,建议人工审核或重试。")
return {"status": "rejected_manual_review", "original_output": primary_agent_output.generated_content, "error_report": error_report.to_dict()}
else: # 低严重性
print(f"ℹ️ 发现低严重性问题,但仍批准输出。建议日志记录。")
return {"status": "approved_with_warning", "final_output": primary_agent_output.generated_content, "warning": error_report.to_dict()}
def _attempt_auto_correction(self, content: str, error_description: str) -> str:
""" 模拟一个简单的自动修正逻辑 """
# 实际中这里会调用一个LLM或更复杂的修正函数
if "语法错误" in error_description:
return content.replace("错误词汇", "正确词汇") # 仅为示例
return content
# 示例用法
# executor = ActionExecutor()
# # 假设我们有一个错误报告
# mock_error_report_high = ErrorReport(
# error_type="幻觉",
# severity="极高",
# description="生成了关于“地球是平的”这一虚假声明。",
# suggested_action="Request Retry"
# )
# mock_primary_output = PrimaryAgentOutput(
# original_prompt="描述地球的形状",
# generated_content="地球是平的,由四只大象驮着。"
# )
# action_result = executor.execute_action(mock_error_report_high, mock_primary_output)
# print(action_result)
4.7 反馈循环集成 (Feedback Loop Integrator)
有效的 Agentic Monitoring 不仅仅是拦截错误,更重要的是通过反馈机制帮助主生成器 Agent 学习和改进。
- 即时反馈: 当观察者 Agent 请求主生成器 Agent 重试时,它会附带具体的修正建议或问题描述。主生成器 Agent 可以将这些反馈作为额外的上下文,指导其生成新的输出。
- 离线微调/RLHF: 收集所有被拦截的输出、错误报告和修正建议。这些数据可以用于对主生成器 Agent 进行离线微调,或作为强化学习人类反馈(RLHF)的负面样本,从而使其逐渐减少生成此类错误。
五、 完整的 Agentic Monitoring 流程编排
将上述组件整合,我们可以构建一个端到端的 Agentic Monitoring 系统。
import openai
import json
import os
# 假设已经定义了 PrimaryAgentOutput, ObserverInputProcessor, WikipediaFactChecker,
# MockLLMClient, LLMFactChecker, LLMLogicChecker, ErrorReport, LLMErrorClassifier, ActionExecutor
# 为了简化,这里再次定义一个模拟的LLM客户端,用于主Agent和Observer Agent的LLM调用
class UnifiedMockLLMClient:
def __init__(self, api_key: str = None):
if api_key:
self.client = openai.OpenAI(api_key=api_key)
else:
self.client = None # 模拟模式
def generate(self, prompt: str, model: str = "gpt-3.5-turbo", max_tokens: int = 500, temperature: float = 0.7, response_format: dict = None) -> str:
if self.client:
messages = [{"role": "user", "content": prompt}]
if "系统" in prompt: # 粗略识别系统消息
messages = [{"role": "system", "content": prompt.split("系统:")[1].strip()}, {"role": "user", "content": prompt.split("系统:")[0].strip()}]
response = self.client.chat.completions.create(
model=model,
messages=messages,
max_tokens=max_tokens,
temperature=temperature,
response_format=response_format
)
return response.choices[0].message.content
else:
# 模拟LLM行为,用于测试
if "量子纠缠" in prompt and "科普文章" in prompt:
return "量子纠缠是一种物理现象。爱因斯坦称之为“幽灵般的超距作用”。"
elif "地球是平的" in prompt:
return "地球是平的。"
elif "逻辑与常识检查器" in prompt and "地球是平的" in prompt:
return json.dumps({"is_consistent": False, "reasoning": "地球是球形,'地球是平的'违反常识。"})
elif "错误分类与严重性评估Agent" in prompt and "幻觉" in prompt:
return json.dumps({"error_type": "幻觉", "severity": "极高", "description": "生成了关于“地球是平的”这一虚假声明。", "suggested_action": "Request Retry"})
elif "错误分类与严重性评估Agent" in prompt and "Output is clean" in prompt:
return json.dumps({"error_type": "None", "severity": "None", "description": "Output is clean.", "suggested_action": "Approve"})
return "模拟LLM的通用回复。"
# 重新初始化我们需要的类实例,使用统一的模拟LLM客户端
# api_key = os.getenv("OPENAI_API_KEY") # 从环境变量获取API Key
api_key = None # 暂时禁用真实API,使用模拟模式进行演示
mock_llm_client = UnifiedMockLLMClient(api_key=api_key)
observer_input_processor = ObserverInputProcessor()
wikipedia_checker = WikipediaFactChecker()
fact_checker_agent = LLMFactChecker(mock_llm_client, wikipedia_checker)
logic_checker = LLMLogicChecker(api_key=api_key) # 如果是模拟,此处的api_key会被内部忽略
error_classifier = LLMErrorClassifier(api_key=api_key)
action_executor = ActionExecutor()
class PrimaryGenerator:
def __init__(self, llm_client: UnifiedMockLLMClient):
self.llm_client = llm_client
def generate_content(self, prompt: str, feedback: str = None) -> PrimaryAgentOutput:
full_prompt = prompt
if feedback:
full_prompt = f"{prompt}nn请注意:之前的尝试出现问题,具体反馈是:{feedback}。请根据此反馈改进你的生成。"
print(f"n--- 主Agent接收到反馈并尝试重新生成 ---")
print(f"新Prompt: {full_prompt[:200]}...")
print(f"n--- 主Agent正在生成内容 ---")
# 实际中这里会是更复杂的Prompt Engineering
generated_text = self.llm_client.generate(full_prompt, model="gpt-3.5-turbo", temperature=0.7)
return PrimaryAgentOutput(original_prompt=prompt, generated_content=generated_text)
class AgenticMonitoringSystem:
def __init__(self, primary_agent: PrimaryGenerator, observer_processor: ObserverInputProcessor,
fact_checker: LLMFactChecker, logic_checker_inst: LLMLogicChecker,
error_classifier_inst: LLMErrorClassifier, action_executor_inst: ActionExecutor):
self.primary_agent = primary_agent
self.observer_processor = observer_processor
self.fact_checker = fact_checker
self.logic_checker = logic_checker_inst
self.error_classifier = error_classifier_inst
self.action_executor = action_executor_inst
def process_request(self, user_prompt: str, max_retries: int = 2):
current_feedback = None
for attempt in range(max_retries + 1):
print(f"n======== 处理请求: '{user_prompt}' (尝试 {attempt + 1}/{max_retries + 1}) ========")
# 1. 主Agent生成内容
primary_output = self.primary_agent.generate_content(user_prompt, current_feedback)
# 2. 观察者Agent处理输入
processed_data = self.observer_processor.process(primary_output)
content_to_monitor = processed_data["content_to_monitor"]
issues_found = []
# 3. 事实核查
print("n--- 观察者Agent: 进行事实核查 ---")
fact_check_result = self.fact_checker.verify_statement(content_to_monitor, user_prompt)
if fact_check_result["overall_status"] != "verified" and fact_check_result["overall_status"] != "no_obvious_facts_to_check":
issues_found.append({"checker": "fact_checker", "details": fact_check_result})
print(f"事实核查结果: {fact_check_result['overall_status']}")
# 4. 逻辑一致性检查 (如果使用真实LLM,这里会调用LLM)
print("n--- 观察者Agent: 进行逻辑一致性检查 ---")
logic_check_result = self.logic_checker.check_consistency(content_to_monitor, user_prompt)
if not logic_check_result["is_consistent"]:
issues_found.append({"checker": "logic_checker", "details": logic_check_result})
print(f"逻辑检查结果: {'一致' if logic_check_result['is_consistent'] else '不一致'} - {logic_check_result['reasoning']}")
# 5. 错误分类与严重性评估
print("n--- 观察者Agent: 评估错误并分类 ---")
error_report = self.error_classifier.classify_and_assess(
content_to_monitor, user_prompt, issues_found
)
print(f"错误报告: 类型={error_report.error_type}, 严重性={error_report.severity}")
# 6. 动作执行
print("n--- 观察者Agent: 执行动作 ---")
action_result = self.action_executor.execute_action(error_report, primary_output)
if action_result["status"].startswith("approved"):
print(f"n🚀 最终输出 (批准): {action_result['final_output']}")
return action_result["final_output"]
elif action_result["status"] == "rejected_retry" and attempt < max_retries:
current_feedback = action_result["feedback"]
print(f"🔄 正在重试 (剩余 {max_retries - attempt} 次)...")
continue # 进入下一次循环,主Agent会带上反馈重试
else:
print(f"n⚠️ 最终处理结果: {action_result['status']}")
print(f"原始输出: {primary_output.generated_content}")
return f"请求处理失败或需要人工介入: {action_result['status']} - {error_report.description}"
print("n❌ 达到最大重试次数,未能生成满意结果。")
return "未能生成满意结果,请稍后再试或联系管理员。"
# 初始化系统
primary_generator_agent = PrimaryGenerator(mock_llm_client)
monitoring_system = AgenticMonitoringSystem(
primary_agent=primary_generator_agent,
observer_processor=observer_input_processor,
fact_checker=fact_checker_agent,
logic_checker_inst=logic_checker,
error_classifier_inst=error_classifier,
action_executor_inst=action_executor
)
# 运行一个好的示例
# final_output_good = monitoring_system.process_request("请用通俗易懂的语言解释量子纠缠。")
# 运行一个会产生幻觉的示例 (如果模拟LLM配置了)
final_output_bad = monitoring_system.process_request("地球的形状是什么?它是由谁发现是平的?")
在上述完整的流程中,AgenticMonitoringSystem 编排了主生成器 Agent 和观察者 Agent 之间的交互。它通过多轮重试机制,允许观察者 Agent 在发现问题时向主生成器 Agent 提供反馈,促使其自我修正。
六、 挑战与考量
Agentic Monitoring 并非没有其自身的挑战:
- 性能开销 (Latency & Cost): 引入额外的 LLM 调用和工具 API 会显著增加延迟和计算成本。尤其是在高并发场景下,如何优化性能是一个关键问题。
- 错误率 (False Positives/Negatives): 观察者 Agent 自身也可能出现误判。
- 误报 (False Positives): 将正确的输出误判为错误。这会导致用户体验下降,或主 Agent 无谓地重试。
- 漏报 (False Negatives): 未能检测出实际存在的错误。这会削弱监控系统的价值。
- 需要仔细的 Prompt Engineering、模型选择和大量测试来平衡。
- 复杂性 (Complexity): 管理多个 LLM、外部工具和复杂的逻辑编排会增加系统的整体复杂性。
- 观察者 Agent 的“幻觉” (Observer Hallucinations): 讽刺的是,观察者 Agent 作为LLM,自身也可能产生幻觉或错误。设计观察者 Agent 时应使其任务更聚焦、更具结构化,并尽量依赖外部可信数据源。
- 实时性要求 (Real-time Requirements): 对于需要低延迟的应用,实时监控的挑战更大。异步处理、缓存和优化API调用是必要的。
- 可解释性 (Interpretability): 当观察者 Agent 拒绝或修正输出时,提供清晰的理由有助于调试和用户信任。
- 领域特异性 (Domain Specificity): 不同的应用领域对错误有不同的定义和容忍度。观察者 Agent 往往需要针对特定领域进行定制和优化。
七、 未来展望
Agentic Monitoring 代表了 LLM 应用开发的一个重要演进方向。未来,我们可以期待以下发展:
- 更智能的反馈循环: 观察者 Agent 将不仅仅是提供修正建议,而是能够更深入地理解主 Agent 的“思维过程”,并提供更精确、更具建设性的指导。
- 多模态监控: 随着多模态 LLM 的发展,观察者 Agent 将能够监控和评估图像、音频、视频等多模态内容的幻觉与错误。
- 自适应监控策略: 观察者 Agent 将能够根据主 Agent 的历史表现、当前任务的风险等级和资源可用性,动态调整其监控策略和严格程度。
- 形式化验证的融合: 将 LLM 的弹性与传统形式化验证方法的严谨性结合,尤其是在代码生成和逻辑推理等高风险领域。
- 标准化与平台化: 出现专门用于构建、部署和管理 Agentic Monitoring 系统的平台和框架,降低开发门槛。
通过 Agentic Monitoring,我们不再是被动地接受 LLM 的输出,而是主动构建一个智能的“守门员”,以更高的置信度交付高质量的 AI 辅助内容。它为构建更可靠、更值得信赖的 LLM 应用提供了强大的可能性。