各位听众,下午好。
今天,我们将深入探讨一个引人入胜且至关重要的主题:Agent 中的元认知,特别是如何让 Agent 具备“自我审查”的能力,从而检查并纠正其过去的决策。在人工智能领域,我们已经见证了 Agent 在特定任务中展现出卓越的性能。然而,真正的智能不仅仅是执行任务,更重要的是理解、反思和改进自身。这正是元认知能力的核心价值。
什么是元认知?以及它在 Agent 中的重要性
元认知(Meta-Cognition)一词源自心理学,指的是“关于认知的认知”,即个体对自己认知过程的理解、监控和调节。简单来说,就是“思考你的思考”。当一个人学习、解决问题或做出决策时,如果他能同时反思这个过程本身,例如“我是否理解了这个问题?”、“我目前的解决策略有效吗?”、“我犯了什么错误?”,那么他就具备了元认知能力。
在 Agent 的语境中,元认知意味着一个 Agent 不仅仅是感知环境、规划行动、执行任务,它还能:
- 监控自身的内部状态和外部行为。
- 评估其决策的质量和结果。
- 诊断失败的原因或次优行为。
- 调整其内部知识、策略或学习过程,以提高未来的表现。
为什么元认知在 Agent 中如此重要?
- 适应性与鲁棒性: 真实世界是动态、不确定且充满变化的。Agent 需要能够适应新的情况,从错误中学习,而不是简单地重复失败。元认知提供了这种适应性的基础。
- 自主学习与成长: 具备元认知能力的 Agent 可以更自主地进行学习和改进,减少对外部反馈或人工干预的依赖。
- 错误纠正与安全性: 识别和纠正错误对于部署在关键应用中的 Agent 至关重要,能够避免潜在的风险和损失。
- 可解释性与信任: 当 Agent 能够解释其决策过程以及为何进行修正时,这有助于提高人类对其行为的理解和信任。
今天,我们将聚焦于元认知的一个关键实践:让 Agent 定期运行一个“自我审查”节点,检查之前的决策是否有误。这如同人类在项目结束后进行复盘,或在考试后分析错题,旨在通过反思来优化未来的表现。
传统 Agent 决策流程的局限性
在深入探讨元认知 Agent 之前,让我们回顾一下一个典型的、不具备元认知能力的 Agent 是如何运作的。一个基础的 Agent 通常遵循一个感知-规划-行动(Sense-Plan-Act)循环:
- 感知 (Sense): Agent 通过传感器(或API)获取当前环境的状态信息。
- 规划 (Plan): 基于感知到的信息、其内部目标和现有的知识模型,Agent 制定一个行动计划或选择一个最佳行动。
- 行动 (Act): Agent 执行选定的行动,改变环境状态。
这个循环不断重复。
示例:一个简单的机器人 Agent
考虑一个在仓库中搬运物品的机器人 Agent。
- 感知: 摄像头识别周围环境(障碍物、目标物品、目的地),内部传感器提供电池电量、当前位置。
- 规划: 根据目标(将物品X从A搬到B),规划一条路径,决定抓取动作、移动速度。
- 行动: 移动到物品X旁,抓取物品,移动到目的地B,放下物品。
这种模式在环境稳定、规则明确、目标单一的情况下运作良好。然而,一旦环境变得复杂、动态或不确定,其局限性便会显现:
- 无法从错误中学习: 如果机器人选择了一条低效的路径,或者在某个地方卡住了,传统的 Agent 仅仅会尝试再次执行其当前的规划,或者在规划失败时简单地重新规划,而不会深入分析“为什么”会失败。它缺乏一种机制来识别其决策过程中的缺陷,并将其转化为经验教训。
- 重复犯错: 如果导致错误的根本原因(例如,对某个区域的地图信息不准确,或对抓取力度的估计有偏差)没有被识别和纠正,Agent 会在类似的情况下重复犯同样的错误。
- 缺乏适应性: 当环境规则发生变化(例如,仓库中新增了移动障碍物),Agent 可能无法有效地调整其策略,除非通过外部的人工重新编程或大量重新训练。
- 次优决策: 即使决策没有导致完全的失败,也可能不是最优的。传统 Agent 缺乏自我评估的能力来识别这些次优的路径或行动,从而错失提升效率的机会。
这些局限性促使我们思考:Agent 如何才能像人类一样,不仅能做,还能思考自己是如何做的,以及如何做得更好?这正是引入元认知“自我审查”节点的意义所在。
元认知:引入“自我审查”节点
元认知 Agent 的核心思想是,它不仅是一个“执行者”,更是一个“反思者”和“学习者”。它不再满足于仅仅完成任务,而是会周期性地停下来,回顾其过去的决策、行动和结果,进行深刻的自我分析。这个过程我们称之为“自我审查”或“反思”。
“自我审查”节点的功能主要包括:
- 回顾历史决策: 访问 Agent 的记忆模块,检索过去一段时间内的决策记录、环境观测、Agent 内部状态以及采取的行动。
- 评估结果: 比较实际发生的行动结果与 Agent 在决策时所预期的结果。判断目标是否达成,以及达成质量如何(例如,是否高效、是否符合约束条件)。
- 识别错误与次优: 基于评估结果,诊断导致失败或次优表现的根本原因。这可能涉及:
- 决策错误: Agent 在特定情境下选择了错误的行动。
- 知识缺陷: Agent 内部世界模型不准确或不完整。
- 推理偏差: Agent 的规划逻辑存在缺陷。
- 执行失败: 行动本身由于外部因素或自身能力限制未能成功执行。
- 生成改进建议: 根据识别出的问题,提出具体的改进措施,例如更新内部规则、调整模型参数、修改规划策略,甚至建议获取新的信息。
这就像一个工程师在项目完成后,不仅要提交代码,还要撰写事后分析报告(post-mortem),详细记录遇到的问题、解决方案,以及未来的改进方向。通过这种方式,Agent 能够将过去的经验转化为宝贵的知识,用于指导未来的决策,从而实现真正的“从错误中学习,不断进步”。
设计一个元认知 Agent 架构
为了实现上述的元认知能力,我们需要对传统的 Agent 架构进行扩展。一个新的架构将包含以下关键组件:
-
感知器 (Perceiver):
- 功能: 从环境中收集原始数据和信息。
- 输出: 格式化的环境观测数据,例如传感器读数、API响应、用户输入等。
-
决策器 (Planner/Decision Maker):
- 功能: 基于感知到的环境状态、Agent 目标、内部知识和当前策略,生成一个或一系列行动计划。
- 输入: 环境观测、Agent 目标、内部知识。
- 输出: 待执行的行动。
-
执行器 (Actuator):
- 功能: 将决策器生成的抽象行动转化为具体的物理或数字操作,并作用于环境。
- 输入: Agent 决策的行动。
- 输出: 环境状态的改变。
-
记忆模块 (Memory Module): (新增)
- 功能: 存储 Agent 的所有相关信息,包括环境观测、Agent 内部状态、采取的行动、决策过程(为什么选择该行动)、行动结果以及其他关键事件。这是自我审查的基础。
- 存储内容: 决策记录(
DecisionRecord)、环境历史、任务目标等。
-
自我审查模块 (Self-Critique Module): (新增)
- 功能: 定期或在特定条件下被触发,从记忆模块中检索历史决策,评估其有效性,诊断潜在的错误或次优之处,并生成改进建议。
- 输入: 历史决策记录和相关环境信息。
- 输出: 错误诊断报告、改进建议。
-
知识更新模块 (Knowledge Update Module): (新增)
- 功能: 接收来自自我审查模块的改进建议,并据此更新 Agent 的内部知识、决策规则、策略模型或系统提示(对于基于 LLM 的 Agent)。
- 输入: 改进建议。
- 输出: 更新后的 Agent 内部知识和行为策略。
Agent 核心循环(扩展后):
- 感知: Perceiver 收集环境信息。
- 记录: 将当前环境观测和 Agent 内部状态发送给 Memory Module。
- 决策: Decision Maker 基于当前信息和内部知识制定行动。
- 记录: 将决策过程和预期结果发送给 Memory Module。
- 执行: Actuator 执行行动。
- 记录: 将实际行动结果发送给 Memory Module。
- 循环检查(自我审查触发): 在特定时机(例如,每N个决策后,或当任务失败时),Self-Critique Module 被触发。
- 审查: Self-Critique Module 从 Memory Module 获取历史记录,进行分析,生成改进建议。
- 更新: Knowledge Update Module 根据建议修改 Decision Maker 的内部知识或策略。
- 继续循环。
通过这种扩展架构,Agent 形成了一个完整的学习闭环,使其能够持续地从经验中学习和成长。
记忆模块的实现:构建决策历史与环境状态存储
记忆模块是元认知 Agent 的基石。没有详细且结构化的记忆,自我审查就无从谈起。我们需要存储足够的信息,以便 Agent 在未来能够重现决策时的上下文,并评估其结果。
需要存储的内容:
- 时间戳 (Timestamp): 记录事件发生的时间,有助于排序和追溯。
- 环境观测 (Environmental Observation): Agent 在做出决策时所感知到的环境状态的详细快照。
- Agent 目标 (Agent Goal): Agent 在该时间点试图达成的具体目标。
- Agent 内部状态 (Agent Internal State): Agent 自身的内部变量、信念、效用函数参数等。
- 采取的行动 (Action Taken): Agent 实际执行的行动。
- 预期结果 (Expected Outcome): Agent 在选择该行动时所预期的结果。
- 实际结果 (Actual Outcome): 行动执行后环境的实际变化或Agent自身状态的变化。
- 决策理由 (Decision Rationale): Agent 做出该决策的思考过程、依据的规则或推理链。这对于基于 LLM 的 Agent 尤为重要。
数据结构选择:
- 列表 (List of Objects): 最简单的方式,将每个决策记录作为一个对象存储在列表中。适用于小规模、短期的记忆。
- 关系型数据库 (Relational Database): 适用于需要复杂查询、持久化存储和结构化数据的场景。可以为不同类型的记录创建表。
- 知识图谱 (Knowledge Graph): 对于需要存储复杂关系和语义信息的场景,知识图谱能提供更丰富的上下文。
- 向量数据库 (Vector Database): 结合 LLM,可以将决策记录编码为向量,方便进行语义相似性搜索和检索。
在这里,我们为了简洁和演示,将使用一个 Python 类来模拟一个简单的记忆模块,存储一系列 DecisionRecord 对象。
import datetime
import uuid
from typing import Any, Dict, List, Optional
# 定义一个决策记录的结构
class DecisionRecord:
"""
存储Agent每一次决策的详细信息,用于后续的自我审查。
"""
def __init__(self,
timestamp: datetime.datetime,
decision_id: str,
agent_goal: str,
environment_observation: Dict[str, Any],
agent_internal_state: Dict[str, Any],
action_taken: Dict[str, Any],
expected_outcome: Dict[str, Any],
actual_outcome: Optional[Dict[str, Any]] = None,
decision_rationale: Optional[str] = None,
critique_report: Optional[Dict[str, Any]] = None):
self.timestamp = timestamp
self.decision_id = decision_id # 唯一标识符
self.agent_goal = agent_goal
self.environment_observation = environment_observation
self.agent_internal_state = agent_internal_state
self.action_taken = action_taken
self.expected_outcome = expected_outcome
self.actual_outcome = actual_outcome
self.decision_rationale = decision_rationale
self.critique_report = critique_report # 存储审查结果,方便追溯
def __repr__(self):
return (f"DecisionRecord(ID={self.decision_id[:8]}, Goal='{self.agent_goal}', "
f"Action={self.action_taken}, Outcome={self.actual_outcome})")
def to_dict(self):
"""将记录转换为字典,便于存储或发送给LLM。"""
return {
"timestamp": self.timestamp.isoformat(),
"decision_id": self.decision_id,
"agent_goal": self.agent_goal,
"environment_observation": self.environment_observation,
"agent_internal_state": self.agent_internal_state,
"action_taken": self.action_taken,
"expected_outcome": self.expected_outcome,
"actual_outcome": self.actual_outcome,
"decision_rationale": self.decision_rationale,
"critique_report": self.critique_report
}
# 记忆模块类
class MemoryModule:
"""
负责存储和检索Agent的决策历史。
"""
def __init__(self):
self.decision_history: List[DecisionRecord] = []
def add_record(self, record: DecisionRecord):
"""
添加一个新的决策记录。
"""
self.decision_history.append(record)
print(f"Memory: Added new decision record {record.decision_id[:8]}.")
def get_records(self, count: Optional[int] = None, since: Optional[datetime.datetime] = None) -> List[DecisionRecord]:
"""
检索决策记录。
Args:
count: 要检索的最近记录的数量。
since: 从某个时间点开始检索记录。
Returns:
符合条件的DecisionRecord列表。
"""
records = self.decision_history
if since:
records = [r for r in records if r.timestamp >= since]
if count:
records = records[-count:] # 获取最新的N条记录
return records
def update_record_critique(self, decision_id: str, critique_report: Dict[str, Any]):
"""
更新特定决策记录的审查报告。
"""
for record in self.decision_history:
if record.decision_id == decision_id:
record.critique_report = critique_report
print(f"Memory: Updated critique for decision {decision_id[:8]}.")
return
print(f"Memory: Decision {decision_id[:8]} not found for critique update.")
# 示例用法
if __name__ == "__main__":
memory = MemoryModule()
# 模拟Agent做出一个决策并记录
current_time = datetime.datetime.now()
decision1 = DecisionRecord(
timestamp=current_time,
decision_id=str(uuid.uuid4()),
agent_goal="Find optimal path",
environment_observation={"location": "A", "traffic": "low", "weather": "sunny"},
agent_internal_state={"energy": 80, "knowledge_version": "1.0"},
action_taken={"action_type": "move", "destination": "B", "path_id": "path_1"},
expected_outcome={"arrival_time": "T+10min", "energy_cost": 5},
decision_rationale="Path_1 is shortest and traffic is low."
)
memory.add_record(decision1)
# 模拟一段时间后,Agent完成了行动并记录实际结果
import time
time.sleep(0.1)
decision1.actual_outcome = {"arrival_time": "T+15min", "energy_cost": 7, "obstacle_encountered": True}
print(f"Memory: Updated actual outcome for {decision1.decision_id[:8]}.")
# 模拟Agent做出第二个决策
time.sleep(0.1)
current_time = datetime.datetime.now()
decision2 = DecisionRecord(
timestamp=current_time,
decision_id=str(uuid.uuid4()),
agent_goal="Deliver package",
environment_observation={"location": "B", "package_status": "ready"},
agent_internal_state={"energy": 73, "knowledge_version": "1.0"},
action_taken={"action_type": "deliver", "package_id": "PKG123", "recipient": "C"},
expected_outcome={"delivery_status": "completed", "energy_cost": 2},
decision_rationale="Recipient C is nearby."
)
memory.add_record(decision2)
time.sleep(0.1)
decision2.actual_outcome = {"delivery_status": "completed", "energy_cost": 2}
print(f"Memory: Updated actual outcome for {decision2.decision_id[:8]}.")
# 检索最近的记录
print("nRetrieving last 2 records:")
recent_records = memory.get_records(count=2)
for r in recent_records:
print(r)
# 假设自我审查模块对 decision1 进行了审查并生成了报告
critique_report_for_d1 = {
"status": "failed",
"reason": "Path_1 had an unexpected obstacle, leading to longer travel time and higher energy cost.",
"suggestion": "Update map with obstacle information, consider alternative paths even if slightly longer initially."
}
memory.update_record_critique(decision1.decision_id, critique_report_for_d1)
print("nDecision 1 after critique update:")
print(decision1.to_dict())
这段代码展示了一个基础的记忆模块如何存储决策记录,并允许我们追溯和更新这些记录。这些记录将是自我审查模块进行分析的原始数据。
自我审查模块的核心逻辑与挑战
自我审查模块是元认知 Agent 的“大脑”,负责对过去的决策进行分析和反思。
审查触发机制 (Trigger Mechanism):
- 定期触发 (Periodic): 每隔一段时间(例如,每小时、每天)或每 N 个决策后运行一次。这确保了 Agent 能够持续地进行反思。
- 事件驱动触发 (Event-driven): 当特定事件发生时触发,例如:
- 任务失败: Agent 未能达成其目标。
- 异常行为: Agent 表现出与预期不符或效率低下的行为。
- 性能下降: 任务完成时间变长,资源消耗增加等。
- 外部反馈: 收到人类用户或环境的负面反馈。
- 需求驱动触发 (Demand-driven): Agent 内部检测到知识空白或决策不确定性高时主动触发。
审查对象 (Scope of Critique):
- 单一决策 (Single Decision): 分析某个特定的、最近的或失败的决策。
- 决策序列 (Sequence of Decisions): 分析一系列相关的决策,以理解其间的因果关系和整体策略的有效性。
- 特定类型决策 (Specific Decision Types): 针对某一类重复出现的决策模式进行审查。
审查方法 (Critique Methods):
这里我们将介绍几种主要的方法,并特别强调基于 LLM 的方法。
-
规则匹配 (Rule-based Critique):
- 原理: 预定义一系列的错误模式和触发条件。当决策记录符合这些模式时,就标记为错误。
- 优点: 简单、高效,对于已知且明确的错误非常有效。
- 缺点: 无法发现未知错误或复杂、隐含的模式。需要人工维护规则。
- 示例: "如果实际能耗超过预期能耗20%且任务完成时间延长,则标记为次优。"
-
模拟与反事实推理 (Simulation & Counterfactual Reasoning):
- 原理: Agent 内部维护一个环境模型。当审查一个决策时,Agent 可以在其内部模型中“回放”该决策,甚至尝试其他可能的行动(反事实),然后比较这些行动的预期结果与实际结果。
- 优点: 能够发现潜在的更好选择,评估不同策略的优劣。
- 缺点: 依赖于准确的环境模型,模拟成本高。
- 示例: "如果当时选择了路径A而不是路径B,结果会更好吗?" Agent 在模拟器中运行两种情况并比较。
-
基于模型的评估 (Model-based Evaluation):
- 原理: Agent 拥有一个评估模型(例如,一个预测任务成功率、资源消耗或奖励值的模型)。审查时,将决策输入评估模型,得到一个分数,与预期分数或最佳分数进行比较。
- 优点: 可以量化决策质量,发现次优决策。
- 缺点: 评估模型本身需要训练和维护。
- 示例: 使用一个预训练的Q-network来评估某个状态-动作对的Q值,看是否与期望值有较大偏差。
-
外部反馈融合 (External Feedback Integration):
- 原理: 将人类用户或外部系统提供的反馈信息整合到审查过程中。
- 优点: 引入了外部视角,可以纠正 Agent 自身无法识别的错误。
- 缺点: 外部反馈可能不及时、不完整或存在偏差。
- 示例: 用户手动标记某个Agent行动为“错误”或“低效”。
-
启发式评估 (Heuristic Evaluation):
- 原理: 使用一些简单的经验法则或启发式规则来快速判断决策的质量。
- 优点: 快速、低开销。
- 缺点: 粗略,可能漏掉细微的错误或次优情况。
- 示例: "如果目标未能在预设时间内完成,则视为失败决策。"
-
基于大型语言模型 (LLM) 的反思 (LLM-based Reflection):
- 原理: 利用 LLM 强大的文本理解、推理和生成能力,将决策记录和相关上下文作为 Prompt 输入,让 LLM 分析决策的合理性、识别错误并提出改进建议。
- 优点:
- 上下文理解: 能够理解复杂的决策理由和环境描述。
- 抽象推理: 能够识别高层次的策略缺陷,而不仅仅是表面错误。
- 自然语言解释: 以人类可读的方式输出错误诊断和改进建议。
- 泛化能力: 能够处理未曾明确编码的错误模式。
- 缺点:
- 计算成本: 调用 LLM 成本较高,延迟较大。
- 幻觉与偏差: LLM 可能生成不准确或不相关的建议。
- Prompt 工程: 需要精心设计 Prompt 才能获得高质量的输出。
- 缺乏真实世界交互: LLM 本身不具备感知和行动能力,其分析基于提供的文本信息。
识别错误的类型:
- 错误决策 (Incorrect Decision): Agent 选择了导致任务失败或严重负面后果的行动。
- 次优决策 (Suboptimal Decision): Agent 选择了能完成任务但效率低下、资源消耗过多的行动,存在更好的替代方案。
- 遗漏机会 (Missed Opportunity): Agent 在特定情境下没有识别或利用到一个可以带来显著收益的机会。
- 知识模型不准确 (Inaccurate Knowledge Model): Agent 对环境、自身能力或任务规则的理解存在偏差。
- 推理链缺陷 (Reasoning Flaw): Agent 在从观察到行动的推理过程中存在逻辑错误。
我们将主要关注基于 LLM 的自我审查方法,因为它在处理复杂、非结构化信息和生成可解释建议方面具有显著优势。
import datetime
import json
from typing import List, Dict, Any, Optional
# 假设我们有一个LLM客户端接口
class MockLLMClient:
def generate_response(self, prompt: str, temperature: float = 0.7) -> str:
"""
模拟LLM的响应。
在实际应用中,这里会调用OpenAI, Anthropic或其他LLM提供商的API。
"""
print(f"n--- MockLLM Input Prompt ---n{prompt}n--- End MockLLM Input ---")
# 这是一个非常简化的模拟,实际LLM会根据prompt内容进行复杂推理
if "任务失败" in prompt or "次优" in prompt:
return json.dumps({
"status": "critiqued",
"diagnosis": "The agent chose a suboptimal path due to outdated traffic data. The expected arrival time was missed, and energy consumption was higher.",
"root_cause": "Outdated traffic data in the agent's internal knowledge base.",
"suggestion": "Prioritize real-time traffic data integration. Consider dynamic path re-planning if conditions change significantly during travel.",
"confidence": "high"
})
else:
return json.dumps({
"status": "successful",
"diagnosis": "The agent successfully delivered the package as planned, on time and within energy budget.",
"root_cause": "Accurate route planning and efficient execution.",
"suggestion": "Continue to monitor for efficiency improvements, no immediate changes needed.",
"confidence": "high"
})
class SelfCritiqueModule:
"""
负责Agent的自我审查,诊断过去决策中的错误或次优之处。
"""
def __init__(self, memory: MemoryModule, llm_client: MockLLMClient, critique_interval: int = 5):
self.memory = memory
self.llm_client = llm_client
self.critique_interval = critique_interval # 每多少个决策触发一次审查
self._decision_count_since_last_critique = 0
def should_critique(self) -> bool:
"""
判断是否应该触发自我审查。
"""
self._decision_count_since_last_critique += 1
if self._decision_count_since_last_critique >= self.critique_interval:
self._decision_count_since_last_critique = 0 # 重置计数器
return True
return False
def _generate_critique_prompt(self, record: DecisionRecord) -> str:
"""
根据决策记录生成用于LLM的Prompt。
"""
prompt = f"""
你是一名高度智能的AI Agent审查专家。你的任务是分析一个AI Agent的决策记录,并提供一份详细的审查报告。
请仔细评估Agent的决策是否有效、是否达到预期目标,以及是否存在任何错误、次优之处或改进空间。
请根据以下JSON格式的决策记录进行分析:
{json.dumps(record.to_dict(), indent=2, ensure_ascii=False)}
请特别关注以下几点:
1. **目标达成情况:** Agent是否成功实现了 'agent_goal'?
2. **预期与实际结果对比:** 'expected_outcome' 和 'actual_outcome' 之间是否存在显著差异?如果有,请分析原因。
3. **决策合理性:** 基于 'environment_observation' 和 'agent_internal_state',Agent 的 'action_taken' 和 'decision_rationale' 是否合理?
4. **错误/次优识别:** 是否存在任何明显的错误、低效行为或可以改进的地方?
5. **根本原因分析:** 如果有错误或次优,请尝试分析其根本原因(例如,知识不准确、推理缺陷、环境变化等)。
6. **改进建议:** 提出具体的、可操作的建议,以帮助Agent在未来做得更好。
请以以下JSON格式返回你的审查报告。确保所有字段都存在,并且内容清晰、具体。
{{
"status": "string (e.g., 'successful', 'failed', 'suboptimal')",
"diagnosis": "string (详细描述Agent决策的表现和问题)",
"root_cause": "string (导致问题发生的根本原因)",
"suggestion": "string (具体的改进措施)",
"confidence": "string (e.g., 'high', 'medium', 'low')"
}}
"""
return prompt
def perform_critique(self) -> Optional[Dict[str, Any]]:
"""
执行自我审查过程,获取最近的决策记录并进行分析。
返回一个包含所有审查结果和建议的列表,或None如果无记录可审查。
"""
records_to_critique = self.memory.get_records(count=self.critique_interval)
if not records_to_critique:
print("SelfCritique: No new records to critique.")
return None
print(f"nSelfCritique: Starting critique for {len(records_to_critique)} records.")
all_critique_results = {}
for record in records_to_critique:
prompt = self._generate_critique_prompt(record)
try:
llm_response_str = self.llm_client.generate_response(prompt)
critique_report = json.loads(llm_response_str)
# 将审查报告存储回记忆模块,与原始决策关联
self.memory.update_record_critique(record.decision_id, critique_report)
all_critique_results[record.decision_id] = critique_report
print(f"SelfCritique: Critiqued decision {record.decision_id[:8]} -> Status: {critique_report.get('status')}")
except json.JSONDecodeError as e:
print(f"SelfCritique Error: Failed to parse LLM response for {record.decision_id[:8]}: {e}")
except Exception as e:
print(f"SelfCritique Error: An unexpected error occurred during LLM call for {record.decision_id[:8]}: {e}")
return all_critique_results
# 示例用法 (结合MemoryModule)
if __name__ == "__main__":
memory = MemoryModule()
llm_client = MockLLMClient()
critique_module = SelfCritiqueModule(memory, llm_client, critique_interval=2) # 每2个决策审查一次
# 模拟Agent的第一次决策
decision1 = DecisionRecord(
timestamp=datetime.datetime.now(),
decision_id=str(uuid.uuid4()),
agent_goal="Navigate to destination X",
environment_observation={"current_pos": "A", "route_options": ["path1", "path2"], "traffic_data": {"path1": "low", "path2": "medium"}},
agent_internal_state={"energy": 90, "map_version": "2.0"},
action_taken={"action_type": "move", "selected_route": "path1"},
expected_outcome={"arrival_time": "T+10min", "energy_cost": 5},
decision_rationale="Path1 is faster according to current traffic."
)
memory.add_record(decision1)
decision1.actual_outcome = {"arrival_time": "T+15min", "energy_cost": 8, "unexpected_congestion": True} # 模拟实际结果与预期不符
# 模拟Agent的第二次决策
import time
time.sleep(0.1)
decision2 = DecisionRecord(
timestamp=datetime.datetime.now(),
decision_id=str(uuid.uuid4()),
agent_goal="Pick up item Y",
environment_observation={"item_pos": "B", "robot_pos": "A", "item_status": "available"},
agent_internal_state={"energy": 82, "gripper_strength_setting": "medium"},
action_taken={"action_type": "grab", "item_id": "itemY"},
expected_outcome={"item_grabbed": True, "energy_cost": 2},
decision_rationale="Item Y is within reach, medium strength is sufficient."
)
memory.add_record(decision2)
decision2.actual_outcome = {"item_grabbed": True, "energy_cost": 2} # 模拟成功
# 此时,应该触发审查
if critique_module.should_critique():
print("n--- Triggering Self-Critique ---")
critique_results = critique_module.perform_critique()
if critique_results:
print("nAggregated Critique Results:")
for dec_id, report in critique_results.items():
print(f" Decision {dec_id[:8]}: {report.get('status')} - {report.get('diagnosis')}")
# 模拟Agent的第三次决策 (不会立即触发审查)
time.sleep(0.1)
decision3 = DecisionRecord(
timestamp=datetime.datetime.now(),
decision_id=str(uuid.uuid4()),
agent_goal="Report status",
environment_observation={"system_health": "good"},
agent_internal_state={"report_interval": "1hr"},
action_taken={"action_type": "send_report"},
expected_outcome={"report_sent": True},
decision_rationale="Standard operational procedure."
)
memory.add_record(decision3)
decision3.actual_outcome = {"report_sent": True}
if critique_module.should_critique():
print("n--- Triggering Self-Critique (after 3rd decision, now total 3) ---")
critique_results = critique_module.perform_critique()
if critique_results:
print("nAggregated Critique Results:")
for dec_id, report in critique_results.items():
print(f" Decision {dec_id[:8]}: {report.get('status')} - {report.get('diagnosis')}")
else:
print("nSelf-Critique not triggered yet for 3rd decision.")
在上述代码中,SelfCritiqueModule 定义了审查的触发机制 (should_critique) 和如何生成 LLM Prompt (_generate_critique_prompt)。perform_critique 方法将从记忆中获取最新的决策记录,并调用模拟的 LLM 客户端进行分析。LLM 的响应(这里是模拟的 JSON 字符串)会被解析并存储回原始的 DecisionRecord 中,以便于追溯。
挑战:
- Prompt 工程的艺术: 编写高质量的 Prompt 至关重要。Prompt 必须清晰、具体,引导 LLM 给出结构化的、有用的回答。模糊的 Prompt 会导致模糊的分析。
- LLM 的局限性: LLM 可能“幻觉”出不存在的问题或提出不切实际的建议。需要通过后续的验证或人类监督来筛选。
- 成本与延迟: 频繁调用大型 LLM 会带来显著的计算成本和延迟。需要权衡审查的频率和深度。
- 可验证性: LLM 给出的建议有时难以直接验证其有效性。
- 上下文窗口限制: LLM 的上下文窗口有限,一次性分析大量历史决策可能需要复杂的摘要或分批处理策略。
深入探讨基于 LLM 的自我审查
鉴于 LLM 在理解复杂文本和生成有意义解释方面的独特优势,我们进一步详细讨论如何利用它进行自我审查。
LLM 的优势在于:
- 理解非结构化数据: 能够处理自然语言描述的环境观测、决策理由和行动结果,而无需预先进行严格的结构化。
- 高层次推理: 能够识别出不仅仅是简单的规则匹配错误,而是更深层次的策略缺陷、逻辑漏洞或知识偏差。
- 生成解释和建议: 以自然语言形式输出详细的诊断报告,包括根本原因分析和具体的改进建议,这对于人类理解和后续的知识更新非常有价值。
- 泛化能力: 即使面对从未见过的特定错误模式,LLM 也能基于其广泛的知识进行合理的推断。
Prompt Engineering 的关键:
高质量的 Prompt 是从 LLM 获得高质量审查结果的关键。一个有效的 Prompt 应该包含以下要素:
- 明确的角色设定 (Role Assignment): 让 LLM 扮演一个专业的、公正的审查员角色。
- 示例: "你是一名经验丰富的AI Agent行为分析师和优化专家。"
- 清晰的任务定义 (Clear Task Definition): 明确告知 LLM 需要做什么。
- 示例: "你的任务是审查以下Agent的决策记录,识别问题,分析原因,并提供改进建议。"
- 提供详尽的上下文 (Provide Context): 将 Agent 的决策记录(包括环境、目标、行动、预期和实际结果、决策理由)完整地提供给 LLM。
- 示例: 以 JSON 格式嵌入
DecisionRecord的所有字段。
- 示例: 以 JSON 格式嵌入
- 指定分析维度 (Specify Analysis Dimensions): 引导 LLM 从哪些方面进行分析。
- 示例: 目标达成、预期与实际差异、决策合理性、错误类型、根本原因等。
- 明确的输出格式 (Explicit Output Format): 要求 LLM 以结构化的格式(如 JSON)返回结果,这便于后续的程序处理。
- 示例: 提供一个 JSON 模板,并要求严格遵守。
- 强调具体性和可操作性 (Emphasize Specificity & Actionability): 鼓励 LLM 提出具体的、可执行的建议,而不是泛泛而谈。
- 示例: "请确保改进建议是具体的,并且可以指导Agent的后续行为调整。"
示例 Prompt 优化:
在之前的 _generate_critique_prompt 基础上,我们可以进一步优化,使其更具指导性。
# ... (MemoryModule, DecisionRecord, MockLLMClient classes remain the same) ...
class SelfCritiqueModule:
# ... (init and should_critique methods remain the same) ...
def _generate_critique_prompt(self, record: DecisionRecord) -> str:
"""
根据决策记录生成用于LLM的Prompt。
优化后的Prompt,更强调结构化分析和具体建议。
"""
prompt = f"""
你是一名经验丰富的AI Agent行为分析师和优化专家。
你的任务是深入审查一份AI Agent的单一决策记录,并生成一份结构化的专业审查报告。
请你扮演一个严格而公正的审查员,旨在帮助Agent识别其决策过程中的潜在缺陷并提供具体改进方案。
以下是Agent的决策细节,请以JSON格式呈现:
```json
{json.dumps(record.to_dict(), indent=2, ensure_ascii=False)}
请按照以下步骤进行详细分析:
**步骤1:总结决策关键信息**
简要概述Agent的目标、采取的行动及其主要背景。
**步骤2:评估决策结果**
比较“expected_outcome”(预期结果)与“actual_outcome”(实际结果)。
- 目标是否完全达成?
- 实际结果是否与预期存在显著差异?请量化差异(如果可能)。
- 是否存在意外的积极或消极后果?
**步骤3:分析决策合理性**
基于“environment_observation”(环境观测)、“agent_internal_state”(Agent内部状态)和“decision_rationale”(决策理由),
- Agent选择的“action_taken”(采取的行动)在当时是否是最优的?是否存在更好的替代方案?
- “decision_rationale”是否充分且逻辑严谨?是否存在信息缺失、误解或推理偏差?
**步骤4:诊断问题类型与根本原因**
如果发现问题(如任务失败、次优决策、资源浪费、效率低下等),请明确指出问题类型,并深入分析其根本原因。
根本原因可能包括但不限于:
- **知识缺陷:** Agent对环境模型、规则或自身能力的认知不准确或不完整。
- **感知错误:** Agent对环境信息的感知有偏差或遗漏。
- **规划/推理缺陷:** Agent的决策逻辑或规划算法存在漏洞。
- **执行偏差:** 实际执行与计划有出入。
- **环境突变:** 外部环境发生了Agent未预料到的重大变化。
**步骤5:提出具体的改进建议**
根据根本原因分析,提出至少一条具体的、可操作的改进建议。这些建议应能直接指导Agent在未来类似情况下如何调整其知识、策略或行为。
建议可以是:
- 更新Agent的知识库(例如,添加新规则、修正世界模型)。
- 调整Agent的决策策略或参数。
- 建议Agent寻求更多信息或进行额外的环境探索。
- 优化Agent的Prompt(如果Agent本身基于LLM)。
请严格以以下JSON格式返回你的完整审查报告。请确保所有字段都存在,并且内容具体、详细、避免模糊表述。
{{
"decision_id": "{record.decision_id}",
"summary": "string (对决策的简要总结)",
"evaluation_outcome": {{
"goal_achieved": "boolean",
"outcome_comparison": "string (预期与实际结果的详细对比)",
"unexpected_impact": "string (意外的正面或负面影响)"
}},
"rationality_analysis": {{
"is_optimal": "boolean",
"alternative_actions": "string (是否存在更好的替代行动)",
"rationale_critique": "string (对决策理由的详细审查)"
}},
"problem_diagnosis": {{
"problem_type": "string (e.g., 'Failure', 'Suboptimal', 'Inefficiency', 'KnowledgeGap')",
"root_cause": "string (根本原因的详细描述)"
}},
"improvement_suggestions": [
{{
"type": "string (e.g., 'KnowledgeUpdate', 'StrategyAdjustment', 'ParameterTuning', 'DataCollection')",
"description": "string (具体可操作的建议)",
"priority": "string (e.g., 'high', 'medium', 'low')"
}}
],
"confidence_score": "float (0.0-1.0,表示审查报告的置信度)"
}}
"""
return prompt
# ... (perform_critique method remains the same) ...
示例用法 (进一步验证优化后的Prompt)
if name == "main":
… (MemoryModule, MockLLMClient, SelfCritiqueModule initialization as before) …
memory = MemoryModule()
llm_client = MockLLMClient()
critique_module = SelfCritiqueModule(memory, llm_client, critique_interval=1) # 简化为每1个决策审查一次
decision_example = DecisionRecord(
timestamp=datetime.datetime.now(),
decision_id=str(uuid.uuid4()),
agent_goal="Optimize energy consumption for data processing",
environment_observation={
"data_volume_gb": 1000,
"current_server_load_percent": 70,
"available_servers": ["server_A", "server_B", "server_C"],
"server_specs": {
"server_A": {"power_kw": 0.5, "max_load": 80, "cost_per_hour": 1.0},
"server_B": {"power_kw": 0.3, "max_load": 60, "cost_per_hour": 0.7},
"server_C": {"power_kw": 0.8, "max_load": 100, "cost_per_hour": 1.5}
}
},
agent_internal_state={
"energy_optimization_strategy": "cost_priority",
"current_energy_budget_usd": 50
},
action_taken={
"action_type": "allocate_processing",
"server_to_use": "server_A",
"estimated_processing_time_min": 60
},
expected_outcome={
"total_cost_usd": 1.0,
"processing_completed": True,
"final_server_load_A": 75
},
decision_rationale="Server A balances power efficiency and cost, suitable for current load and budget."
)
memory.add_record(decision_example)
# 模拟实际结果,假设服务器A超载,处理时间延长,导致成本增加
decision_example.actual_outcome = {
"total_cost_usd": 1.5,
"processing_completed": True,
"final_server_load_A": 95, # 实际超载
"actual_processing_time_min": 90, # 处理时间延长
"warning_message": "Server A overloaded during processing"
}
if critique_module.should_critique():
print("n--- Triggering Self-Critique with optimized prompt ---")
critique_results = critique_module.perform_critique()
if critique_results:
print("nOptimized Critique Results (for decision_example):")
for dec_id, report in critique_results.items():
print(f" Decision {dec_id[:8]}: {report.get('problem_diagnosis', {}).get('problem_type')} - {report.get('problem_diagnosis', {}).get('root_cause')}")
for suggestion in report.get('improvement_suggestions', []):
print(f" Suggestion ({suggestion.get('type')}): {suggestion.get('description')}")
通过优化 Prompt,我们可以更有效地引导 LLM 进行深度分析,并以期望的结构化格式返回结果,这对于后续的知识更新模块至关重要。
### 知识更新与 Agent 改进
自我审查模块生成了诊断报告和改进建议,但这些信息本身并不能改变 Agent 的行为。知识更新模块的职责就是将这些抽象的建议转化为 Agent 实际可执行的改变。
**审查结果的输出形式:**
* **错误报告 (Error Report):** 详细描述问题、根本原因和影响。
* **改进建议 (Improvement Suggestions):** 具体、可操作的建议。
**如何将建议融入 Agent 的未来行为:**
1. **规则库更新 (Rule-base Update):**
* **适用场景:** 基于规则的决策系统,或当建议是添加、修改、删除某个判断条件或行动规则时。
* **示例:** 如果审查发现“Agent 在交通拥堵时选择了最短路径导致延误”,建议可能是“添加规则:当交通拥堵超过阈值时,优先考虑避开拥堵区域的长路径,而非最短路径”。
* **实现:** 直接修改 Agent 内部存储的规则集(例如,一个 Python 字典、配置文件或一个简单的专家系统)。
2. **内部模型调整 (Internal Model Adjustment):**
* **适用场景:** Agent 依赖于内部世界模型、预测模型或效用函数来做出决策。
* **示例:** 如果审查发现“Agent 低估了某个操作的能量消耗”,建议可能是“调整能量消耗预测模型中的相关参数”。
* **实现:** 修改模型参数、重新训练部分模型,或更新模型所依赖的数据。
3. **策略学习 (Policy Learning):**
* **适用场景:** 强化学习 Agent,其行为由一个策略(Policy)决定。
* **示例:** 如果审查发现“Agent 在某个状态下选择了次优动作”,建议可能是“在那个状态下,降低该动作的Q值,或提高其他动作的Q值”。
* **实现:** 可以在 Agent 的学习循环中引入一个“元学习”步骤,根据审查结果微调策略,或者生成新的训练数据来引导策略学习过程。
4. **Prompt 优化 (Prompt Optimization):**
* **适用场景:** 基于 LLM 的 Agent。
* **示例:** 如果审查发现“Agent 经常忘记在规划时考虑用户偏好”,建议可能是“修改 Agent 的系统 Prompt,在规划指引中明确强调‘务必将用户偏好作为首要考虑因素’”。
* **实现:** 修改 Agent 的主要 Prompt 或为其提供更多的 Few-shot 示例。
5. **数据收集/探索策略调整 (Data Collection/Exploration Strategy Adjustment):**
* **适用场景:** Agent 缺乏必要信息导致决策失误。
* **示例:** 如果审查发现“Agent 对某个区域的实时交通信息不足”,建议可能是“调整感知模块,增加对该区域交通数据的查询频率和来源”。
* **实现:** 修改感知模块的配置或规划模块的探索策略。
**实现示例:**
我们来创建一个 `KnowledgeUpdateModule`,它将根据审查报告中的建议,尝试更新 Agent 的内部规则。
```python
import json
from typing import Dict, Any, List, Optional
# 假设Agent的决策器有一个简单的规则库
class AgentDecisionMaker:
def __init__(self):
self.rules: Dict[str, Any] = {
"path_selection_strategy": "shortest_path", # 默认策略
"energy_threshold_for_recharge": 20,
"traffic_avoidance_threshold": {"level": "medium", "max_delay_minutes": 5}
}
self.knowledge_base: Dict[str, Any] = {
"known_obstacles": ["obstacle_A_at_path1"],
"traffic_data_source_priority": ["realtime", "historical"]
}
print(f"DecisionMaker: Initialized with rules: {self.rules}")
def make_decision(self, observation: Dict[str, Any], goal: str) -> Dict[str, Any]:
"""
模拟Agent的决策逻辑,基于其内部规则。
"""
# 简化决策逻辑
if goal == "Navigate to destination X":
traffic_level = observation.get("traffic_data", {}).get("path1", "low")
if self.rules["path_selection_strategy"] == "shortest_path" and traffic_level == "low":
return {"action_type": "move", "selected_route": "path1", "rationale": "Shortest path, low traffic."}
elif self.rules["path_selection_strategy"] == "avoid_traffic" and traffic_level == "medium":
return {"action_type": "move", "selected_route": "path2", "rationale": "Avoiding medium traffic on path1."}
else:
return {"action_type": "move", "selected_route": "path1", "rationale": "Default path."}
elif goal == "Optimize energy consumption for data processing":
if self.rules["energy_optimization_strategy"] == "cost_priority": # 假设这条规则可以被更新
return {"action_type": "allocate_processing", "server_to_use": "server_B", "rationale": "Server B has lower cost."}
else:
return {"action_type": "allocate_processing", "server_to_use": "server_A", "rationale": "Default server A."}
return {"action_type": "no_action", "rationale": "No specific goal match."}
def update_rule(self, rule_name: str, new_value: Any):
"""
更新Agent的决策规则。
"""
if rule_name in self.rules:
self.rules[rule_name] = new_value
print(f"DecisionMaker: Rule '{rule_name}' updated to '{new_value}'.")
return True
else:
print(f"DecisionMaker: Rule '{rule_name}' not found.")
return False
def update_knowledge(self, knowledge_key: str, new_value: Any):
"""
更新Agent的知识库。
"""
self.knowledge_base[knowledge_key] = new_value
print(f"DecisionMaker: Knowledge '{knowledge_key}' updated to '{new_value}'.")
return True
class KnowledgeUpdateModule:
"""
负责根据自我审查模块的建议更新Agent的知识和决策策略。
"""
def __init__(self, decision_maker: AgentDecisionMaker):
self.decision_maker = decision_maker
def apply_suggestions(self, critique_report: Dict[str, Any]):
"""
解析审查报告,并尝试应用其中的改进建议。
"""
suggestions: List[Dict[str, Any]] = critique_report.get("improvement_suggestions", [])
if not suggestions:
print("KnowledgeUpdate: No suggestions to apply.")
return
print(f"nKnowledgeUpdate: Applying {len(suggestions)} suggestions...")
for suggestion in suggestions:
s_type = suggestion.get("type")
description = suggestion.get("description")
if s_type == "KnowledgeUpdate":
# 示例:假设建议描述中包含要更新的知识和值
if "map with obstacle information" in description:
self.decision_maker.update_knowledge("known_obstacles", ["obstacle_A_at_path1", "new_obstacle_X_on_path1"])
elif "real-time traffic data integration" in description:
self.decision_maker.update_knowledge("traffic_data_source_priority", ["realtime", "sensor_fusion", "historical"])
else:
print(f"KnowledgeUpdate: Unhandled KnowledgeUpdate suggestion: {description}")
elif s_type == "StrategyAdjustment":
if "dynamic path re-planning" in description:
self.decision_maker.update_rule("path_selection_strategy", "avoid_traffic") # 简化为切换策略
elif "prioritize real-time traffic data integration" in description:
self.decision_maker.update_rule("traffic_data_source_priority", ["realtime", "historical"])
elif "consider server B for lower cost" in description: # 对应LLM的建议
self.decision_maker.rules["energy_optimization_strategy"] = "cost_priority" # 直接修改规则
print(f"DecisionMaker: Rule 'energy_optimization_strategy' updated to 'cost_priority'.")
else:
print(f"KnowledgeUpdate: Unhandled StrategyAdjustment suggestion: {description}")
elif s_type == "ParameterTuning":
# 更复杂的实现会解析描述来调整具体数值
print(f"KnowledgeUpdate: ParameterTuning suggestion: {description} (requires specific parsing).")
else:
print(f"KnowledgeUpdate: Unrecognized suggestion type: {s_type}")
# 示例用法
if __name__ == "__main__":
# 初始化模块
memory = MemoryModule()
llm_client = MockLLMClient() # 使用MockLLMClient
decision_maker = AgentDecisionMaker()
critique_module = SelfCritiqueModule(memory, llm_client, critique_interval=1)
knowledge_update_module = KnowledgeUpdateModule(decision_maker)
print("n--- Initial Agent State ---")
print(f"Decision Maker Rules: {decision_maker.rules}")
print(f"Decision Maker Knowledge: {decision_maker.knowledge_base}")
# 模拟一个导致问题的决策
decision_bad = DecisionRecord(
timestamp=datetime.datetime.now(),
decision_id=str(uuid.uuid4()),
agent_goal="Optimize energy consumption for data processing",
environment_observation={
"data_volume_gb": 1000,
"current_server_load_percent": 70,
"available_servers": ["server_A", "server_B", "server_C"],
"server_specs": {
"server_A": {"power_kw": 0.5, "max_load": 80, "cost_per_hour": 1.0},
"server_B": {"power_kw": 0.3, "max_load": 60, "cost_per_hour": 0.7},
"server_C": {"power_kw": 0.8, "max_load": 100, "cost_per_hour": 1.5}
}
},
agent_internal_state={
"energy_optimization_strategy": "default_strategy", # 初始策略
"current_energy_budget_usd": 50
},
action_taken={
"action_type": "allocate_processing",
"server_to_use": "server_A",
"estimated_processing_time_min": 60
},
expected_outcome={
"total_cost_usd": 1.0,
"processing_completed": True,
"final_server_load_A": 75
},
decision_rationale="Server A is the default."
)
memory.add_record(decision_bad)
# 模拟实际结果,假设服务器A超载,处理时间延长,导致成本增加
decision_bad.actual_outcome = {
"total_cost_usd": 1.5,
"processing_completed": True,
"final_server_load_A": 95,
"actual_processing_time_min": 90,
"warning_message": "Server A overloaded during processing"
}
# 触发自我审查
if critique_module.should_critique():
print("n--- Triggering Self-Critique ---")
critique_results_map = critique_module.perform_critique() # 返回字典
if critique_results_map:
for dec_id, report in critique_results_map.items():
# 将审查报告应用到知识更新模块
knowledge_update_module.apply_suggestions(report)
print("n--- Agent State After Update ---")
print(f"Decision Maker Rules: {decision_maker.rules}")
print(f"Decision Maker Knowledge: {decision_maker.knowledge_base}")
# 再次模拟决策,看是否有所改进
print("n--- Agent making decision again ---")
new_observation = {
"data_volume_gb": 1000,
"current_server_load_percent": 70,
"available_servers": ["server_A", "server_B", "server_C"],
"server_specs": {
"server_A": {"power_kw": 0.5, "max_load": 80, "cost_per_hour": 1.0},
"server_B": {"power_kw": 0.3, "max_load": 60, "cost_per_hour": 0.7},
"server_C": {"power_kw": 0.8, "max_load": 100, "cost_per_hour": 1.5}
}
}
new_decision = decision_maker.make_decision(new_observation, "Optimize energy consumption for data processing")
print(f"New decision made: {new_decision}")
# 预期现在会选择 server_B 因为策略已更新为 cost_priority
assert new_decision["server_to_use"] == "server_B"
这个 KnowledgeUpdateModule 相对简单,它通过字符串匹配来解析 LLM 提供的建议,并调用 AgentDecisionMaker 的方法来更新规则或知识。在实际应用中,这部分会更加复杂,可能需要更精细的语义解析,甚至一个专门的“知识表示”层来管理 Agent 的信念和规则。
一个完整的元认知 Agent 示例流程
现在,让我们将所有组件整合起来,构建一个端到端的元认知 Agent。我们将模拟一个简单的场景:一个资源调度 Agent,负责将计算任务分配给不同的服务器,目标是最小化成本。
场景设定:
Agent 需要将一个计算任务分配给 server_A 或 server_B。
server_A: 成本较高,但处理能力较强(假设)。server_B: 成本较低,但处理能力较弱(假设)。
初始策略是默认使用server_A。
期望的元认知流程:
- Agent 首次运行,将任务分配给
server_A。 - 由于某些原因(例如,
server_A实际负载过高,导致成本意外增加),该决策被标记为次优。 - 自我审查模块被触发,分析该决策,并建议“优先考虑成本更低的
server_B”。 - 知识更新模块根据建议,修改 Agent 的策略。
- Agent 再次遇到类似任务时,会基于新的策略选择
server_B。
import datetime
import uuid
import json
import time
from typing import Any, Dict, List, Optional
# --- 1. DecisionRecord and MemoryModule (from previous sections) ---
class DecisionRecord:
def __init__(self,
timestamp: datetime.datetime,
decision_id: str,
agent_goal: str,
environment_observation: Dict[str, Any],
agent_internal_state: Dict[str, Any],
action_taken: Dict[str, Any],
expected_outcome: Dict[str, Any],
actual_outcome: Optional[Dict[str, Any]] = None,
decision_rationale: Optional[str] = None,
critique_report: Optional[Dict[str, Any]] = None):
self.timestamp = timestamp
self.decision_id = decision_id
self.agent_goal = agent_goal
self.environment_observation = environment_observation
self.agent_internal_state = agent_internal_state
self.action_taken = action_taken
self.expected_outcome = expected_outcome
self.actual_outcome = actual_outcome
self.decision_rationale = decision_rationale
self.critique_report = critique_report
def __repr__(self):
return (f"DecisionRecord(ID={self.decision_id[:8]}, Goal='{self.agent_goal}', "
f"Action={self.action_taken}, Outcome={self.actual_outcome})")
def to_dict(self):
return {
"timestamp": self.timestamp.isoformat(),
"decision_id": self.decision_id,
"agent_goal": self.agent_goal,
"environment_observation": self.environment_observation,
"agent_internal_state": self.agent_internal_state,
"action_taken": self.action_taken,
"expected_outcome": self.expected_outcome,
"actual_outcome": self.actual_outcome,
"decision_rationale": self.decision_rationale,
"critique_report": self.critique_report
}
class MemoryModule:
def __init__(self):
self.decision_history: List[DecisionRecord] = []
def add_record(self, record: DecisionRecord):
self.decision_history.append(record)
print(f"Memory: Added new decision record {record.decision_id[:8]}.")
def get_records(self, count: Optional[int] = None, since: Optional[datetime.datetime] = None) -> List[DecisionRecord]:
records = self.decision_history
if since:
records = [r for r in records if r.timestamp >= since]
if count:
records = records[-count:]
return records
def update_record_critique(self, decision_id: str, critique_report: Dict[str, Any]):
for record in self.decision_history:
if record.decision_id == decision_id:
record.critique_report = critique_report
print(f"Memory: Updated critique for decision {decision_id[:8]}.")
return
print(f"Memory: Decision {decision_id[:8]} not found for critique update.")
# --- 2. MockLLMClient (from previous sections) ---
class MockLLMClient:
def generate_response(self, prompt: str, temperature: float = 0.7) -> str:
# print(f"n--- MockLLM Input Prompt ---n{prompt}n--- End MockLLM Input ---")
# 针对资源调度Agent的模拟响应
if "server_A overloaded" in prompt or "total_cost_usd" in prompt and "1.5" in prompt:
return json.dumps({
"decision_id": "mock_id", # This will be replaced by actual ID later
"summary": "Agent allocated task to Server A, but it overloaded, leading to higher cost and processing time.",
"evaluation_outcome": {
"goal_achieved": True,
"outcome_comparison": "Actual cost ($1.5) was higher than expected ($1.0), and actual processing time (90min) was longer than expected (60min). Server A reached 95% load, indicating overload.",
"unexpected_impact": "Unexpected cost increase and time delay due to server overload."
},
"rationality_analysis": {
"is_optimal": False,
"alternative_actions": "Agent could have chosen Server B, which has lower cost and might have handled the load better if Server A was near capacity.",
"rationale_critique": "The rationale 'Server A is the default' is insufficient. Agent should consider real-time server load and cost-efficiency more rigorously."
},
"problem_diagnosis": {
"problem_type": "Suboptimal",
"root_cause": "Lack of dynamic server load consideration and insufficient cost-optimization strategy in default decision-making."
},
"improvement_suggestions": [
{
"type": "StrategyAdjustment",
"description": "Adjust resource allocation strategy to prioritize lower-cost servers (e.g., Server B) if their capacity is sufficient, especially when Server A is already under moderate to high load.",
"priority": "high"
},
{
"type": "KnowledgeUpdate",
"description": "Integrate real-time server load metrics more prominently into decision parameters.",
"priority": "medium"
}
],
"confidence_score": 0.95
})
else:
return json.dumps({
"decision_id": "mock_id",
"summary": "Agent successfully allocated task and processed it within expected parameters.",
"evaluation_outcome": {
"goal_achieved": True,
"outcome_comparison": "Actual outcome matched expected outcome.",
"unexpected_impact": "None"
},
"rationality_analysis": {
"is_optimal": True,
"alternative_actions": "No significantly better alternatives identified for this specific instance.",
"rationale_critique": "Rationale was sound based on available information."
},
"problem_diagnosis": {
"problem_type": "None",
"root_cause": "N/A"
},
"improvement_suggestions": [
{
"type": "NoChange",
"description": "Continue current strategy. Monitor for future optimizations.",
"priority": "low"
}
],
"confidence_score": 0.99
})
# --- 3. SelfCritiqueModule (from previous sections) ---
class SelfCritiqueModule:
def __init__(self, memory: MemoryModule, llm_client: MockLLMClient, critique_interval: int = 1):
self.memory = memory
self.llm_client = llm_client
self.critique_interval = critique_interval
self._decision_count_since_last_critique = 0
def should_critique(self) -> bool:
self._decision_count_since_last_critique += 1
if self._decision_count_since_last_critique >= self.critique_interval:
self._decision_count_since_last_critique = 0
return True
return False
def _generate_critique_prompt(self, record: DecisionRecord) -> str:
prompt = f"""
你是一名经验丰富的AI Agent行为分析师和优化专家。
你的任务是深入审查一份AI Agent的单一决策记录,并生成一份结构化的专业审查报告。
请你扮演一个严格而公正的审查员,旨在帮助Agent识别其决策过程中的潜在缺陷并提供具体改进方案。
以下是Agent的决策细节,请以JSON格式呈现:
```json
{json.dumps(record.to_dict(), indent=2, ensure_ascii=False)}
请按照以下步骤进行详细分析:
**步骤1:总结决策关键信息**
简要概述Agent的目标、采取的行动及其主要背景。
**步骤2:评估决策结果**
比较“expected_outcome”(预期结果)与“actual_outcome”(实际结果)。
- 目标是否完全达成?
- 实际结果是否与预期存在显著差异?请量化差异(如果可能)。
- 是否存在意外的积极或消极后果?
**步骤3:分析决策合理性**
基于“environment_observation”(环境观测)、“agent_internal_state”(Agent内部状态)和“decision_rationale”(决策理由),
- Agent选择的“action_taken”(采取的行动)在当时是否是最优的?是否存在更好的替代方案?
- “decision_rationale”是否充分且逻辑严谨?是否存在信息缺失、误解或推理偏差?
**步骤4:诊断问题类型与根本原因**
如果发现问题(如任务失败、次优决策、资源浪费、效率低下等),请明确指出问题类型,并深入分析其根本原因。
根本原因可能包括但不限于:
- **知识缺陷:** Agent对环境模型、规则或自身能力的认知不准确或不完整。
- **感知错误:** Agent对环境信息的感知有偏差或遗漏。
- **规划/推理缺陷:** Agent的决策逻辑或规划算法存在漏洞。
- **执行偏差:** 实际执行与计划有出入。
- **环境突变:** 外部环境发生了Agent未预料到的重大变化。
**步骤5:提出具体的改进建议**
根据根本原因分析,提出至少一条具体的、可操作的改进建议。这些建议应能直接指导Agent在未来类似情况下如何调整其知识、策略或行为。
建议可以是:
- 更新Agent的知识库(例如,添加新规则、修正世界模型)。
- 调整Agent的决策策略或参数。
- 建议Agent寻求更多信息或进行额外的环境探索。
- 优化Agent的Prompt(如果Agent本身基于LLM)。
请严格以以下JSON格式返回你的完整审查报告。请确保所有字段都存在,并且内容具体、详细、避免模糊表述。
{{
"decision_id": "{record.decision_id}",
"summary": "string",
"evaluation_outcome": {{
"goal_achieved": "boolean",
"outcome_comparison": "string",
"unexpected_impact": "string"
}},
"rationality_analysis": {{
"is_optimal": "boolean",
"alternative_actions": "string",
"rationale_critique": "string"
}},
"problem_diagnosis": {{
"problem_type": "string",
"root_cause": "string"
}},
"improvement_suggestions": [
{{
"type": "string",
"description": "string",
"priority": "string"
}}
],
"confidence_score": "float"
}}
"""
return prompt
def perform_critique(self) -> Dict[str, Any]:
records_to_critique = self.memory.get_records(count=self.critique_interval)
if not records_to_critique:
print("SelfCritique: No new records to critique.")
return {}
print(f"nSelfCritique: Starting critique for {len(records_to_critique)} records.")
all_critique_results = {}
for record in records_to_critique:
prompt = self._generate_critique_prompt(record)
try:
llm_response_str = self.llm_client.generate_response(prompt)
critique_report = json.loads(llm_response_str)
critique_report["decision_id"] = record.decision_id # 确保ID正确
self.memory.update_record_critique(record.decision_id, critique_report)
all_critique_results[record.decision_id] = critique_report
print(f"SelfCritique: Critiqued decision {record.decision_id[:8]} -> Status: {critique_report.get('problem_diagnosis',{}).get('problem_type', 'N/A')}")
except json.JSONDecodeError as e:
print(f"SelfCritique Error: Failed to parse LLM response for {record.decision_id[:8]}: {e}")
print(f"Raw LLM response: {llm_response_str}")
except Exception as e:
print(f"SelfCritique Error: An unexpected error occurred during LLM call for {record.decision_id[:8]}: {e}")
return all_critique_results
— 4. AgentDecisionMaker and KnowledgeUpdateModule (from previous sections, slightly adapted) —
class AgentDecisionMaker:
def init(self):
self.rules: Dict[str, Any] = {
"resource_allocation_strategy": "default_server_A", # 初始策略
"server_A_load_threshold_for_reconsideration": 85 # 阈值
}
self.knowledge_base: Dict[str, Any] = {
"server_A_cost_per_task": 1.0,
"server_B_cost_per_task": 0.7,
"server_A_capacity_max_load": 90,
"server_B_capacity_max_load": 70
}
print(f"DecisionMaker: Initialized with rules: {self.rules}")
def make_decision(self, observation: Dict[str, Any], goal: str) -> Dict[str, Any]:
task_type = observation.get("task_type")
current_load_A = observation.get("server_A_current_load", 0)
current_load_B = observation.get("server_B_current_load", 0)
if goal == "Allocate task to minimize cost":
if self.rules["resource_allocation_strategy"] == "default_server_A":
if current_load_A < self.rules["server_A_load_threshold_for_reconsideration"]:
return {"action_type": "allocate_task", "server_to_use": "server_A", "expected_cost": self.knowledge_base["server_A_cost_per_task"], "rationale": "Default strategy, Server A available."}
else: # Fallback if default server is too loaded
return {"action_type": "allocate_task", "server_to_use": "server_B", "expected_cost": self.knowledge_base["server_B_cost_per_task"], "rationale": "Server A overloaded, fallback to Server B."}
elif self.rules["resource_allocation_strategy"] == "cost_priority_B_first":
if current_load_B < self.knowledge_base["server_B_capacity_max_load"]: # 优先考虑B
return {"action_type": "allocate_task", "server_to_use": "server_B", "expected_cost": self.knowledge_base["server_B_cost_per_task"], "rationale": "Cost priority strategy, Server B available and cheaper."}
elif current_load_A < self.knowledge_base["server_A_capacity_max_load"]: # B不可用时考虑A
return {"action_type": "allocate_task", "server_to_use": "server_A", "expected_cost": self.knowledge_base["server_A_cost_per_task"], "rationale": "Cost priority strategy, Server B