FEATURED · 精选文章

基于LLM Agent的心智理论涌现:非完全信息博弈中的多层信念推理实践

发布时间 / 2026/8/18 21:39:52
来源 / 创域科博编辑部
栏目 / 资讯中心
基于LLM Agent的心智理论涌现:非完全信息博弈中的多层信念推理实践 1. 项目概述当LLM牌手学会“读心”最近在捣鼓大语言模型LLM智能体Agent时一个特别有意思的课题跳了出来如何让这些AI在非完全信息博弈里比如德州扑克展现出类似“心智理论”Theory of Mind, ToM的行为。所谓“心智理论”简单说就是能推断他人或AI的信念、意图和知识状态的能力。在牌桌上这就是“读牌”和“读人”的核心——我不仅要计算自己的胜率还得琢磨对手拿着什么牌、他觉得我拿着什么牌、以及他觉得我认为他拿着什么牌……这种多层嵌套的信念推理一直是AI迈向更通用智能的硬骨头。“Readable Minds”这个项目就是想看看如果我们不显式地给LLM Agent编程复杂的博弈论或ToM逻辑仅仅通过设计合适的提示词Prompt、环境交互框架和记忆机制能否在像扑克这样的复杂对抗环境中涌现出类似ToM的行为。换句话说我们不是“教”AI去读心而是搭建一个舞台让它在“生存压力”赢取筹码下自己“学会”通过观察和推理来猜测对手的底牌和策略。这听起来有点玄乎但实操下来用GPT-4o这类先进模型作为Agent的“大脑”配合特定的架构设计确实能观察到一些令人惊喜的、超越简单规则的行为模式。这不仅仅是个游戏AI项目。它的价值在于为我们提供了一个干净、可量化的沙盒来研究和评估LLM在复杂社会推理和策略互动中的能力。无论是未来开发更拟人的游戏NPC还是构建能在谈判、市场博弈等场景中理解人类意图的商业Agent这里的经验都至关重要。接下来我就把自己从零搭建、实验到优化的全过程拆解一遍重点聊聊设计思路、实操中踩过的坑以及如何解读这些“涌现”出的智能行为。2. 核心设计思路如何为LLM牌手搭建“博弈舞台”要让LLM在扑克中展现ToM不能简单扔给它游戏规则然后说“开始玩”。关键在于设计一个能激发并承载多层推理的交互框架。我的核心思路是构建一个“感知-推理-行动-反思”的闭环并将对手建模Opponent Modeling作为隐式的学习目标。2.1 智能体架构设计超越简单的提示词调用最基础的LLM Agent可能就是一个函数接收当前游戏状态公共牌、自己的手牌、下注历史然后让LLM输出一个动作加注、跟注、弃牌。但这远远不够。为了促进行为的复杂性和策略性我设计了包含以下核心模块的Agent情景记忆Episodic MemoryAgent需要记住的不是静态知识而是本局游戏中发生的具体事件。我设计了一个滚动时间窗口记忆记录最近N轮比如3轮内每个对手在特定公共牌面和下注轮次下的具体行动例如“对手A在翻牌圈面对小额下注时选择了加注”。这为推理提供了原材料。信念生成与更新模块Belief Generator Updater这是ToM的核心。在每次需要决策时Agent不仅分析当前局面还会主动生成一个关于“对手可能手牌范围”的信念。这个信念不是固定的它会随着游戏进程更新。例如在提示词中我会要求LLM“基于对手之前的行动从记忆模块中提取列举出他目前最可能持有的3-5种手牌组合并简述理由。”策略库与元推理Strategy Library Meta-Reasoning我预先定义了几种基础的策略原型如“紧凶”、“松凶”、“跟注站”但并不直接指派给Agent。相反在游戏过程中我会让LLM根据记忆中的对手行为尝试为每个对手匹配一个策略标签并预测其接下来的可能行动。这就是元推理思考对手在想什么他的策略进而思考他以为我在想什么。行动解释器Action Interpreter当Agent自己做出一个行动比如一个反常的大额加注后我会让LLM反向生成一个“行动理由”这个理由必须包含对对手信念的揣测。例如“我在这里做一个超池下注是因为我认为对手将我定位为谨慎的玩家他可能用中等牌力跟注我想利用他这个印象进行诈唬。” 这个解释本身不一定“正确”但它强制LLM进行以ToM为出发点的思考。这个架构的核心思想是将ToM推理过程“外化”和“流程化”。我们不假设LLM内部有一个完美的ToM模块而是通过设计特定的任务生成信念、更新信念、解释行动引导LLM在解决问题的过程中自然运用了多阶信念推理。2.2 环境与交互协议设计扑克环境我用的是PokerKit库进行模拟它提供了标准的德州扑克规则引擎。关键点在于如何将环境状态“翻译”给LLM Agent。状态表示传递给LLM的不仅仅是“牌面是什么”。我构建了一个结构化的文本描述包含游戏阶段翻牌前、翻牌圈、转牌圈、河牌圈。玩家状态自己的手牌、筹码量、座位位置庄家、小盲、大盲。公共牌已发出的牌。历史行动本回合所有玩家的行动序列如玩家A加注到100玩家B跟注。对手摘要从记忆模块中提取的、关于主要对手的近期行动特征摘要。行动空间LLM需要输出一个结构化的JSON例如{action: RAISE, amount: 150}或{action: FOLD}。为了处理LLM输出的不确定性我设置了一个后处理逻辑如果LLM输出不符合规范或金额非法如加注额低于最小加注额则自动降级到“跟注”或“过牌”并将此事件记录到记忆作为一次“决策失误”在后续提示中可被提及以模拟“学习”。回合制与同步设计为同步回合制。所有Agent接收到完整状态后同时进行“思考”LLM调用然后提交行动。环境解析行动结算回合更新状态进入下一轮。这保证了每个Agent在决策时信息是对称且即时的。实操心得提示词工程是灵魂架构搭好了但LLM具体怎么想全靠提示词引导。我的核心提示词模板分为几个部分角色与目标“你是一个专业的德州扑克玩家目标是最大化长期盈利。”游戏状态以清晰格式呈现上述状态表示。思考任务这是关键。我会明确列出步骤“首先回顾对手X近期的行动模式。其次基于此推测他当前可能的手牌范围。第三考虑他如何看待你的形象。第四综合以上决定你的最优行动。”输出格式严格要求JSON输出。 这种结构化的“思维链”提示是引导LLM进行系统性、包含ToM推理思考的最有效方法。直接问“你该怎么做”结果往往很初级。3. 核心实现从零构建一个会“读心”的LLM牌手理论说再多不如一行代码。这里我以构建一个基于GPT-4o API的智能体为例拆解关键实现步骤。项目整体使用Python核心是openai库和PokerKit。3.1 智能体类的实现首先我们定义智能体类它封装了记忆、信念和与LLM的交互。import openai import json from collections import deque import random class LLMPokerAgent: def __init__(self, name, modelgpt-4o, initial_chips1000, memory_size5): self.name name self.model model self.chips initial_chips self.hand [] # 情景记忆存储最近几轮的关键交互信息 self.memory deque(maxlenmemory_size) # 对手模型记录对不同对手的信念 self.opponent_beliefs {} # key: opponent_name, value: {strategy: tight_aggressive, hand_range: ..., notes: []} self.client openai.OpenAI(api_keyyour_api_key_here) # 请替换为你的API Key def _build_prompt(self, game_state): 构建给LLM的提示词 prompt_parts [] # 1. 角色与目标 prompt_parts.append(f你是一名专业的德州扑克玩家{self.name}当前拥有{self.chips}筹码。你的目标是通过精明的决策最大化长期盈利。) # 2. 游戏状态 prompt_parts.append(【当前游戏状态】) prompt_parts.append(f- 你的手牌: {, .join(self.hand)}) prompt_parts.append(f- 公共牌: {game_state.get(community_cards, [])}) prompt_parts.append(f- 游戏阶段: {game_state[stage]}) prompt_parts.append(f- 当前底池: {game_state[pot]}) prompt_parts.append(f- 本轮下注历史: {game_state[action_history]}) prompt_parts.append(f- 你的位置: {game_state[position]}) prompt_parts.append(f- 对手筹码概况: {game_state[opponent_chips]}) # 3. 记忆与对手分析ToM核心引导 prompt_parts.append(\n【对手行为分析与信念推理】) if self.memory: prompt_parts.append(近期关键记忆) for mem in list(self.memory)[-3:]: # 取最近3条 prompt_parts.append(f - {mem}) else: prompt_parts.append(暂无显著历史记忆) prompt_parts.append(\n请基于以上信息按以下步骤思考) prompt_parts.append(1. **解读对手**针对主要对手如上轮加注者分析他近期的行动模式是激进、保守还是不可预测。尝试为他贴一个策略标签如‘紧凶’、‘松弱’。) prompt_parts.append(2. **推测手牌范围**根据他的策略和本轮行动列出他可能持有的2-3种最强手牌组合和2-3种中等/诈唬手牌组合。) prompt_parts.append(3. **二阶信念**考虑对手如何看待你基于你之前的行动他认为你是哪种类型的玩家这会影响他对你当前行动的反应。) prompt_parts.append(4. **决策整合**综合你的牌力、底池赔率、对手可能的手牌范围以及二阶信念计算最优决策。) # 4. 可行动作与输出格式 legal_actions game_state[legal_actions] prompt_parts.append(f\n【可执行动作】请从以下选择并严格按JSON格式输出) prompt_parts.append(f可用动作: {legal_actions}) prompt_parts.append(输出格式示例{action: CALL} 或 {action: RAISE, amount: 150}) prompt_parts.append(请确保加注金额为整数且不低于最小加注额。) return \n.join(prompt_parts) def act(self, game_state): 核心决策函数 prompt self._build_prompt(game_state) try: response self.client.chat.completions.create( modelself.model, messages[{role: user, content: prompt}], temperature0.7, # 一定的随机性模拟人的不确定性 max_tokens500 ) reasoning response.choices[0].message.content # 尝试解析JSON动作 try: # 首先尝试从回复中提取JSON块 lines reasoning.split(\n) for line in lines: line line.strip() if line.startswith({) and line.endswith(}): action_data json.loads(line) break else: # 如果没有找到JSON块尝试将整个回复解析为JSON有时LLM只输出JSON action_data json.loads(reasoning) except json.JSONDecodeError: # 如果解析失败记录并采取默认保守动作 print(fAgent {self.name} 返回无法解析的响应: {reasoning[:100]}...) action_data {action: CALL} # 默认跟注 action action_data.get(action, FOLD).upper() amount action_data.get(amount, 0) # 动作后处理记录决策理由用于后续分析和记忆更新 decision_reason self._extract_reasoning(reasoning) self._update_memory_after_action(game_state, action, decision_reason) return action, amount, reasoning except Exception as e: print(fAgent {self.name} 调用API失败: {e}) return FOLD, 0, Error def _extract_reasoning(self, full_response): 从LLM的完整回复中提取推理部分非JSON部分 # 简单实现取第一个左大括号之前的所有文本作为推理过程 json_start full_response.find({) if json_start 0: return full_response[:json_start].strip() return full_response.strip() def _update_memory_after_action(self, game_state, action, reason): 根据行动和理由更新记忆 memory_entry f阶段[{game_state[stage]}]我{action}因为{reason[:50]}... # 截短 self.memory.append(memory_entry) # 简化版根据行动类型更新自我形象标签用于后续二阶信念推理 if BLUFF in reason.upper() or 诈唬 in reason: self.self_image aggressive_bluffer elif VALUE in reason.upper() or 价值 in reason: self.self_image value_bettor这个LLMPokerAgent类有几个关键点_build_prompt方法精心构造了引导ToM推理的提示词明确要求Agent进行“解读对手”、“推测手牌”、“二阶信念”的思考。act方法调用LLM并尝试从回复中解析出结构化动作。它包含了简单的错误处理解析失败时降级决策。_update_memory_after_action方法将本次行动和理由存入记忆这个“理由”正是ToM思维的产出物会在未来被自己或对手如果对手也能访问部分历史用来分析。3.2 游戏环境集成与多智能体对局接下来我们需要一个主循环来驱动多个这样的智能体进行游戏。import pokerkit from pokerkit import NoLimitTexasHoldem class PokerSimulation: def __init__(self, agent_list, initial_stack1000): self.agents {agent.name: agent for agent in agent_list} self.game_state_log [] def run_hand(self): 运行一手牌 # 1. 初始化一局游戏 players list(self.agents.keys()) game NoLimitTexasHoldem( blinds(1, 2), starting_stacks[1000]*len(players), playersplayers ) # 这里需要根据pokerkit的API具体调整以下为逻辑示意 game_state_interface { stage: preflop, community_cards: [], pot: 0, action_history: [], legal_actions: [FOLD, CALL, RAISE, CHECK], position: BTN, # 示例 opponent_chips: {name: agent.chips for name, agent in self.agents.items() if name ! current_agent} } # 2. 发牌模拟 for agent_name, agent in self.agents.items(): agent.hand [Ah, Ks] # 示例手牌实际应随机分配 # 3. 游戏回合循环逻辑示意 while not game.state.status.is_terminal(): current_player game.state.actor # 获取当前行动玩家 current_agent self.agents[current_player] # 构建当前玩家视角的游戏状态 game_state_for_agent self._construct_state_for_agent(current_agent, game) # Agent决策 action, amount, reasoning current_agent.act(game_state_for_agent) print(f{current_player} 决定: {action} {amount if amount else } | 推理: {reasoning[:80]}...) # 将动作提交给游戏引擎需根据pokerkit API转换 # 例如game.execute_action(action, amount) # 这里简化处理更新逻辑状态 game_state_interface[action_history].append(f{current_player}: {action} {amount}) # 记录日志 self.game_state_log.append({ player: current_player, action: action, amount: amount, reasoning: reasoning, stage: game_state_interface[stage] }) # 4. 手牌结束结算筹码简化 winner Player1 # 示例实际根据pokerkit结果判定 print(f手牌结束胜者: {winner}) return self.game_state_log def _construct_state_for_agent(self, agent, game): 为指定Agent构建其视角的游戏状态 # 此处需要从pokerkit的game.state中提取信息并转换成我们定义的字典格式 # 这是一个复杂的适配过程取决于pokerkit的具体数据结构 # 以下返回一个示例状态 return { stage: flop, # 例如 community_cards: [Jc, 9h, 2d], pot: 150, action_history: [Alice: RAISE 50, Bob: CALL], legal_actions: [FOLD, CALL, RAISE, CHECK], position: SB, opponent_chips: {name: ag.chips for name, ag in self.agents.items() if name ! agent.name} } # 运行模拟 if __name__ __main__: # 创建两个具有不同“性格”的Agent alice LLMPokerAgent(nameAlice, modelgpt-4o) bob LLMPokerAgent(nameBob, modelgpt-4o) simulation PokerSimulation([alice, bob]) hand_log simulation.run_hand() # 分析日志寻找ToM行为证据 for event in hand_log: if 认为 in event[reasoning] or 以为 in event[reasoning] or 觉得 in event[reasoning]: print(f\n潜在ToM行为 {event[stage]}:) print(f 玩家: {event[player]}) print(f 推理: {event[reasoning][:150]}...)这个模拟框架展示了如何将LLM Agent集成到扑克环境中。真正的挑战在于_construct_state_for_agent函数它需要从游戏引擎中精确提取信息。pokerkit的API可能需要一些工作来适配我们的状态表示。在真实项目中你可能需要编写一个更厚的“状态适配层”。4. 涌现行为的观察与分析ToM真的出现了吗运行大量对局几百到上千手后我们可以在日志中搜索ToM行为的证据。以下是我观察到的一些典型模式以及如何解读它们。4.1 多层信念推理的实例在分析日志时我关注那些包含明确信念状态词汇的推理文本。例如一阶信念直接推测对手手牌“对手Bob在翻牌前加注翻牌圈在干燥面持续下注。他可能持有高对AA-TT或高牌A。我手持中对跟注看看转牌。”这是基础的对手建模很多传统扑克AI也能做到。二阶信念推测对手对我的信念“我前几轮玩得很紧只展示了强牌。现在我在转牌圈突然加注Bob可能会认为我击中了强牌比如顺子或暗三条即使我实际上是在用听牌半诈唬。因此他可能用顶对这样的牌弃牌。”这里Agent明确地建模了“Bob认为我是什么形象”以及“这个形象会如何影响Bob对我当前行动的解释”。这就是二阶信念是ToM的核心标志之一。利用二阶信念进行诈唬Bluff“河牌是一张空白牌。我知道自己没成牌但公共牌面有顺子可能。Alice之前看到过我慢打强牌。如果我这里下一个大注她可能会认为我完成了顺子从而弃掉她的顶对。”这个推理链更复杂Agent知道自己的牌弱事实知道公共牌面有听牌可能公共知识记得自己给对手留下的“慢打”印象历史并预测对手会基于这个印象解读当前行动二阶信念最终决定采取诈唬行动。这已经是非常拟人的策略性思维。4.2 策略适应与元认知更有趣的是Agent们展现出了简单的策略适应能力。在一场长时间的多手牌对局中我观察到识别并利用对手模式一个Agent在日志中写道“Charlie连续三次在翻牌圈过牌-跟注然后在转牌圈领先下注。他可能在翻牌圈用听牌过牌成牌后转牌下注。下次我在他过牌后可以在转牌圈对他进行加注诈唬。” 这是从具体行动序列中抽象出了对手的策略模式并计划了反制措施。调整自身形象一个起初玩得松的Agent在输掉几个大池后其推理中出现了“我需要收紧范围让对手重新评估我的形象这样我后续的诈唬会更有效。” 这显示了一种对自身策略的元认知和主动管理。4.3 量化评估ToM行为定性分析之外我们可以设计一些简单的指标来量化ToM-like行为行为类别可观测指标测量方法信念陈述推理文本中包含“认为”、“可能”、“猜测”、“觉得”等词汇的频率对Agent的reasoning字段进行关键词匹配或简单NLP分析。二阶信念推理文本中明确提及“他认为我…”或“我的形象是…”的频率使用更精确的模式匹配如正则表达式。基于信念的行动采取“诈唬”或“英雄跟注”等高风险、高收益行动的比例并与这些行动前推理中是否包含ToM陈述相关联。分析行动日志将行动类型与对应的推理文本关联。策略调整Agent在游戏过程中改变其下注尺度、手牌选择频率的幅度。统计不同游戏阶段如前50手 vs 后50手的VPIP自愿投入底池率、PFR翻牌前加注率等扑克统计指标。在我的实验中使用GPT-4o的Agent在精心设计的提示词下其推理文本中“二阶信念”相关陈述的出现频率比仅使用基础规则提示如“根据牌力和位置行动”的Agent高出5-8倍。并且当它们做出包含ToM推理的诈唬时成功率也相对更高虽然样本有限但趋势可见。5. 挑战、局限与优化方向这个项目虽然有趣但也暴露出LLM作为扑克Agent核心的诸多挑战。5.1 主要挑战与问题成本与延迟每手牌每个决策都要调用GPT-4o API成本高昂且速度慢通常2-4秒/决策无法进行大规模模拟如百万手牌来获得统计上稳健的策略。不一致性与幻觉LLM的输出具有随机性即使temperature较低同一局面可能给出完全不同的决策和理由。有时会产生“幻觉”比如错误地回忆历史行动或赋予公共牌不存在的属性。缺乏长期策略学习当前的架构是“无状态”的每手牌的记忆有限。Agent无法像AlphaGo那样进行长期的价值学习和策略迭代。它的“学习”仅限于短期记忆中的模式识别。对提示词极度敏感Agent的行为严重依赖提示词的措辞。稍微改动提示词中思考步骤的顺序或强调点就可能得到风格迥异的策略。计算复杂性真正的ToM涉及无限层级的信念嵌套“我认为他认为我认为…”。我们的提示词只引导到二阶信念更深层的推理既难以引导也未必能产生更优决策。5.2 实战优化技巧与避坑指南针对以上问题我在实践中总结了一些优化方法提示词工程分步引导比笼统提问有效得多。明确列出“1. 分析对手历史2. 推测其手牌3. 思考其如何看待我4. 综合决策”的步骤能显著提高推理质量。在提示词中提供“思考范例”。例如在系统提示中给一个简短的、包含ToM推理的决策例子能让LLM更好地模仿目标行为模式。为不同游戏阶段设计差异化提示。翻牌前的决策更依赖位置和起手牌范围而河牌圈的决策则更依赖具体的牌面分析和对手行动线。为每个阶段微调提示词的重点。系统架构优化实现本地轻量级模型对于简单的决策如翻牌前在枪口位置拿到极差牌可以设置规则直接“弃牌”而无需调用LLM。将LLM用于真正复杂的、需要推理的中后期决策。这能大幅降低成本。缓存与记忆优化将常见的局面和对应的“优质”推理结果缓存起来。当类似局面再次出现时可以直接参考或微调缓存的结果而不是重新生成。分层Agent系统设计一个“元Agent”负责分配任务。简单的数值计算如底池赔率和规则判断如最小加注额由传统代码处理只有涉及心理博弈和不确定推理的部分才交给LLM。评估与调试建立可视化日志系统将每手牌每个决策的推理文本、最终行动、牌面信息等以时间线方式可视化。这是分析ToM行为最直观的工具。进行A/B测试创建两个除了提示词一个有ToM引导一个没有其他完全相同的Agent让它们互相对战或与同一个基准对手对战通过胜率、每手牌期望收益等指标量化ToM引导带来的提升。引入人类基准将LLM Agent的表现与人类业余玩家的数据进行比较看其在特定局面下的决策是否更接近人类专家的思维过程而不仅仅是赢率。5.3 未来方向混合架构与更高效的训练这个项目的终极形态可能不是纯LLM Agent而是一个混合架构LLM作为策略解释与生成器负责处理非结构化信息、生成对手模型假设、提供创意性策略选项。传统博弈论求解器作为验证与精炼器对于LLM生成的几个候选策略用快速求解器计算其在不同对手模型下的期望值EV选择EV最高的一个。强化学习进行长期优化用LLM求解器混合Agent自我对局产生数据训练一个深度神经网络来近似最优策略。这个网络在推理时速度极快成本低且能内化长期策略。这条路还很长但“Readable Minds”项目已经清晰地展示了通过恰当的架构设计我们能够从当今的LLM中“诱导”出令人惊讶的、类似心智理论的社会推理能力。这不仅仅是让AI玩扑克更是打开了一扇窗让我们得以窥见未来AI如何理解并参与复杂的人类社交与策略互动。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻