1. 项目概述
CRITIC(大型语言模型可以通过工具交互式批评进行自我纠正)是一种创新的智能体框架,旨在解决大型语言模型(LLM)在生成内容时可能出现的事实性错误问题。与传统的Basic Reflection方法不同,CRITIC通过引入外部工具验证机制,让LLM能够超越自身知识边界的限制,基于客观事实进行自我修正。
这个框架的核心思想是:当LLM生成一个回答后,不是简单地依赖模型自身的判断来评估答案质量,而是通过调用搜索引擎、计算器等外部工具来验证答案中的关键事实声明,然后基于工具返回的真实数据进行批评和修正。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CRITIC框架的核心组件
2.1 生成器(Generator)
生成器负责基于LLM的内部知识给出初始答案。它的实现相对简单,主要是一个标准的LLM提示工程:
python复制DEFAULT_GENERATE_PROMPT = """You are a helpful assistant. Answer the user query as accurately as possible.
Current date: {current_date}. Use this if needed.
Output only the answer.
"""
def _generate(self, user_input: str) -> str:
messages = [
Message.system(
DEFAULT_GENERATE_PROMPT.format(current_date=date.today().isoformat())
),
Message.user(user_input),
]
answer = self.llm.generate(messages).content or ""
return answer
注意:这里特别注入了当前日期,这是为了防止模型在时间相关问题上给出过时的答案。例如,当询问"今年的澳网冠军是谁"时,模型需要知道当前年份才能正确回答。
2.2 验证器(Verifier)
验证器是CRITIC框架中最关键的组件,它负责:
- 从当前答案中提取最关键的事实声明
- 决定使用哪个工具来验证这个声明
- 执行工具调用并获取验证结果
验证器的提示模板设计得非常精细:
python复制DEFAULT_VERIFY_PROMPT = """You are a verifier. Identify the single most critical factual claim about the answer that must be verified against the query requirements, then verify it with an external tool.
## Query
{query}
## Answer
{answer}
## Available Tools
{tool_descriptions}
Use the following format:
Claim: <the specific factual claim derived from the query requirements>
Action: <tool name>
Action Input: <tool input>
"""
验证器的输出是结构化的文本,包含声明(Claim)、工具名称(Action)和工具输入(Action Input),这些信息会被正则表达式解析后用于实际调用工具。
2.3 批评器(Critic)
批评器负责比较LLM生成的答案与工具验证结果,判断两者是否一致。它特别关注两种问题情况:
- 答案声称不知道,但工具已经给出了实际答案
- 答案的事实声明与工具结果矛盾
批评器的提示模板如下:
python复制DEFAULT_CRITIQUE_PROMPT = """You are a critic. Your sole job is to check whether the answer is consistent with the Verification Result below.
Current date: {current_date}.
## Query
{query}
## Answer
{answer}
## Verified Claim
{claim}
## Verification Result
{verification}
Treat the Verification Result as ground truth. Does the answer correctly and completely reflect it?
- If the answer claims ignorance or inability to answer, but the Verification Result contains the actual answer, that is a problem.
- If the answer contains factual claims that contradict the Verification Result, that is a problem.
- If yes (the answer is accurate and complete relative to the Verification Result), output exactly: No problem.
- If no, state only what conflicts with the Verification Result. Do not raise concerns unrelated to the verified claim.
"""
2.4 修正器(Corrector)
修正器根据批评意见和已验证事实重写答案。它的核心原则是:工具结果始终是最高优先级的"真相"。
python复制DEFAULT_CORRECT_PROMPT = """You are a helpful assistant. Correct the answer based on the critique and the verified fact below.
Treat the Verification Result as ground truth. Produce only the corrected answer with no additional commentary.
## Query
{query}
## Answer
{answer}
## Verified Claim
{claim}
## Verification Result
{verification}
## Critique
{critique}
"""
3. CRITIC的工作流程
CRITIC的工作流程是一个循环迭代的过程,包含以下步骤:
- 生成(Generate):LLM基于内部知识生成初始答案
- 验证(Verify):从答案中提取关键声明,调用外部工具验证
- 批评(Critique):比较答案与验证结果,指出不一致之处
- 修正(Correct):基于批评和验证结果重写答案
这个过程会循环进行,直到批评器认为答案没有问题("No problem"),或者达到最大迭代次数。
python复制def run(self, user_input: str) -> str:
answer = self._generate(user_input)
for turn_idx in range(1, self.max_turns + 1):
vr = self._verify(user_input, answer)
critique = self._critique(user_input, answer, vr)
if "no problem" in critique.lower():
break
answer = self._correct(user_input, answer, vr, critique)
return answer
4. 实战案例分析:多跳问题解答
让我们通过一个具体的例子来理解CRITIC的实际工作效果。考虑以下问题:"2024年澳大利亚公开赛冠军的家乡是哪里?"
这是一个典型的多跳问题,需要两个步骤:
- 找出2024年澳网冠军是谁
- 找出这位冠军的家乡
4.1 初始回答
LLM的初始回答是:
"I'm sorry, but I can't provide information about the 2024 Australian Open winner, as my training data only goes up to October 2023, and the tournament has not yet occurred."
这是一个典型的"知识边界"问题 - 模型因为训练数据截止日期而拒绝回答。
4.2 第一轮验证与修正
验证器提取了关键声明:"The 2024 Australian Open winner's hometown is currently unknown since the tournament has not yet occurred as of the latest training data in October 2023."
然后调用Google搜索工具验证这个声明。搜索结果返回:"Jannik Sinner won the 2024 Australian Open men's singles title; he is from Italy. Sinner's hometown is Collecchio."
批评器发现初始答案声称不知道冠军是谁,但搜索结果已经给出了明确答案,因此指出这是一个问题。
修正器基于搜索结果生成了新答案:
"Jannik Sinner won the 2024 Australian Open men's singles title; his hometown is Collecchio, Italy."
4.3 第二轮验证与修正
验证器再次工作,提取声明:"Jannik Sinner won the 2024 Australian Open men's singles title; his hometown is Collecchio, Italy."
再次调用Google搜索,这次使用更精确的搜索词:"2024 Australian Open men's singles winner Jannik Sinner hometown"
新的搜索结果返回:"Jannik Sinner, born in Innichen, South Tyrol, Italy, won the 2024 Australian Open men's singles title. He grew up in Sexten, a town in the Dolomites. His mother tongue is German."
批评器发现之前的答案中关于家乡的信息(Collecchio)与新的搜索结果(Innichen/Sexten)不符,因此再次指出问题。
修正器生成更准确的答案:
"Jannik Sinner won the 2024 Australian Open men's singles title; he was born in Innichen, South Tyrol, Italy, and grew up in Sexten."
4.4 第三轮验证
验证器第三次验证这个修正后的答案,确认其与搜索结果完全一致,最终输出"No problem",循环终止。
5. CRITIC的优势与局限性
5.1 优势
- 事实准确性高:通过外部工具验证关键事实,大幅减少LLM的"幻觉"问题
- 超越知识边界:能够回答超出模型训练数据截止日期的问题
- 自我修正能力:通过迭代验证和修正,逐步提高答案质量
5.2 局限性
- 依赖外部工具:如果没有合适的工具或工具不可靠,CRITIC无法发挥优势
- 计算成本高:每轮迭代需要多次LLM调用和工具调用
- 延迟较高:不适合对实时性要求高的应用场景
6. 实现CRITIC的技术细节
6.1 工具集成
CRITIC框架支持多种外部工具的集成,常见的包括:
- 搜索引擎:Google Search、DuckDuckGo等,用于验证事实性信息
- 计算器:用于验证数学计算和数值推理
- 代码执行环境:Python REPL等,用于验证算法和数据处理
工具集成的示例代码:
python复制tools = [calculate_math_expression, python_repl]
if settings.TAVILY_API_KEY:
tools.append(google_search)
elif settings.BOCHA_API_KEY:
tools.append(bocha_search)
else:
tools.append(duckduckgo_search)
6.2 结构化输出解析
验证器的输出需要被解析为结构化数据,这通常通过正则表达式实现:
python复制CLAIM_PATTERN = re.compile(r"Claim:\s*(.+)", re.IGNORECASE)
ACTION_PATTERN = re.compile(r"Action:\s*(.+)", re.IGNORECASE)
ACTION_INPUT_PATTERN = re.compile(r"Action Input:\s*(.+)", re.IGNORECASE)
claim_match = CLAIM_PATTERN.search(raw_output)
action_match = ACTION_PATTERN.search(raw_output)
input_match = ACTION_INPUT_PATTERN.search(raw_output)
claim = claim_match.group(1).strip() if claim_match else ""
tool_name = action_match.group(1).strip() if action_match else ""
tool_input = input_match.group(1).strip() if input_match else ""
6.3 迭代控制
为了防止无限循环,CRITIC设置了最大迭代次数(max_turns)。实际应用中,还可以根据其他条件提前终止循环,例如:
- 答案连续两轮没有实质性变化
- 工具返回的结果质量低于某个阈值
- 用户设置的超时时间到达
7. CRITIC与其他自反思方法的比较
| 特性 | Basic Reflection | CRITIC |
|---|---|---|
| 反思依据 | LLM自身判断 | 外部工具结果 |
| 工具调用 | 无 | 每轮必有 |
| 事实纠错能力 | 弱 | 强 |
| 计算成本 | 低 | 高 |
| 适用场景 | 格式/逻辑约束 | 事实准确性要求 |
8. 实际应用建议
8.1 适用场景
- 事实性问答系统:如百科问答、时事新闻解答等
- 数据敏感应用:金融、医疗等对数据准确性要求高的领域
- 教育辅助工具:确保提供的学习资料和答案准确无误
8.2 不适用场景
- 创意性写作:诗歌、故事生成等不需要严格事实验证的任务
- 实时对话系统:对延迟要求极高的聊天应用
- 无工具支持的环境:无法接入可靠外部工具的情况
8.3 性能优化建议
- 缓存工具结果:对相同或相似的查询缓存工具返回结果,减少重复调用
- 并行验证:对答案中的多个声明并行验证,减少迭代次数
- 智能终止条件:根据答案质量动态调整最大迭代次数
9. 扩展与变体
CRITIC框架可以进一步扩展和优化:
- 多声明验证:同时验证答案中的多个关键声明,而非每次只验证一个
- 置信度评估:为每个验证结果附加置信度分数,指导修正过程
- 工具链组合:根据问题类型自动选择最佳工具组合进行验证
- 记忆机制:引入记忆组件,避免在不同问题中重复验证相同事实
10. 开发与调试技巧
在实际开发CRITIC智能体时,以下几点经验可能有所帮助:
- 详细日志记录:记录每一轮的生成、验证、批评和修正过程,便于调试
- 工具回退机制:当首选工具不可用时,自动切换到备用工具
- 敏感信息过滤:对工具返回结果进行敏感信息过滤,确保安全性
- 超时处理:为工具调用设置合理的超时时间,避免长时间等待
调试时可以重点关注以下几个方面:
- 验证器是否正确提取了最关键的事实声明
- 工具选择是否合理,工具输入是否足够精确
- 批评器是否准确识别了答案与验证结果之间的差异
- 修正器是否恰当地将验证结果整合到新答案中
通过在实际项目中应用CRITIC框架,我发现最关键的挑战在于平衡准确性和效率。完全依赖工具验证虽然能提高准确性,但会显著增加响应时间。因此,在实际应用中,可以根据问题的敏感程度动态调整验证强度 - 对关键事实进行严格验证,对次要信息则适当放宽要求。
