
当人工智能应用不断深入多智能体已经从偏研究的概念逐渐走进了工程落地阶段。本文围绕“开放世界多智能体环境中的自主数学发现”这个主题实现一个轻量级但足够完整的“正反博弈 裁判”多智能体系统用 Python 代码演示提出者、批评者、裁判三个角色如何协作从一串数字中自动发现数学规律。适合想了解多智能体协作模式、正在做智能体应用开发、或者对自动数学发现感兴趣的开发者阅读。读完你可以掌握一套可扩展的 Agent 最小框架并且知道如何在真实项目中把它改造成大模型驱动版本。1. 背景与核心概念1.1 什么是开放世界多智能体环境“开放世界”原本是游戏设计中的概念指的是玩家不会被强制线性推进可以在一个大而连续的空间里自由探索。放到人工智能领域开放世界环境强调的是环境状态不是预先穷举好的智能体面对的是一个动态扩展、信息不完全、目标模糊的空间。多智能体环境则意味着环境中存在多个独立决策的智能体它们之间可以合作、竞争、辩论、交易也可以互相验证。与单智能体相比多智能体系统最重要的特征是“分布式认知”没有哪一个智能体掌握全部信息也没有哪一个智能体拥有绝对正确的判断力。结合到自主数学发现场景我们可以把“开放世界”理解为数学对象空间是开放的例如整数、数列、几何图形、逻辑命题规则库也是开放的新的运算、新的定义可以不断加入。智能体无法一眼看到所有真相只能通过与环境的交互不断提出假设、验证假设、推翻假设。1.2 什么是自主数学发现自主数学发现不是让计算机执行已知公式而是让计算机自动完成以下这类过程观察一组数据发现其中隐藏的模式根据模式提出一个数学猜想构造更多数据来测试猜想在尝试反例失败后修正猜想最终形成一条可以被验证的数学结论。传统程序能做的是设定好规则后批量计算这种方式不具备“发现问题”的能力。自主数学发现要求系统具备假设生成机制、反例搜索机制、结论判定机制这三者恰好对应多智能体中的不同角色。需要说明的是本文不会把问题上升到“让 AI 证明黎曼猜想”这种层面而是先在一个可复现的小规模环境中把完整闭环跑通。这个闭环一旦成立后续可以接入更强的语言模型、符号计算工具、形式化验证器能力边界会逐步扩展。1.3 为什么“正反博弈 裁判”适合数学发现在数学研究过程中一条猜想从提出到被接受通常会经历几个阶段有人提出想法有人尝试证明也有人尝试找反例推翻它最后由同行评审判断是否成立。这种“提出—质疑—裁决”的机制天然适合用多智能体来模拟。正反博弈的核心价值在于提出者倾向于生成“看起来有道理”的假设而批评者倾向于寻找“推翻假设”的证据两者形成了对抗压力。如果只有提出者系统容易陷入自嗨式输出如果只有批评者系统无法生成新假设。裁判则负责最终裁决避免双方陷入无休止的争论。所以在本文示例中我们设计了三个 Agent提出者Proposer负责生成数学规律候选批评者Critic负责在已有数据中寻找反例裁判Judge负责在扩展数据上验证候选规律是否成立。三者循环运转构成一个最小可行的自主数学发现系统。2. 系统总体架构2.1 三类角色的职责先看一张角色职责表方便后续对照代码理解。角色职责输入输出Proposer提出者从规则空间中选择一个候选规律当前已观察到的序列数据一条数学规律假设Critic批评者用已有数据检验假设寻找反例序列数据 假设反例信息或“未发现反例”Judge裁判扩展生成更多数据对假设做最终验证环境对象 假设真/假判定 置信度三种角色中前两者形成对抗裁判负责收敛。放在实际工程中你可以把“角色”理解成不同的提示词模板、不同的服务、甚至不同的模型。2.2 主循环流程整个发现过程可以拆成如下循环系统先向环境查询一段初始观察数据Proposer 根据当前数据选择一个候选规律Critic 检查该规律是否与所有已知数据冲突如果 Critic 找到了反例记录结论并回到步骤 2如果 Critic 没有找到反例交给 Judge 扩展数据做深度验证Judge 验证通过则接受该规律发现流程结束Judge 验证失败则记录失败原因并回到步骤 2。这个流程并不复杂但已经具备正反博弈和裁判仲裁的核心特征。实际项目中可以增加记忆模块、知识库、多轮辩论等扩展能力。2.3 数据流与状态管理系统运行过程中最核心的数据对象是“假设”一个假设至少应该包含规律名称例如a[n] a[n-1] a[n-2]对应的预测函数输入索引和前缀序列输出预测值当前验证结果验证过程中发现的反例信息已经验证过的样本数量。有了统一的数据结构Proposer、Critic、Judge 之间才能解耦。这一点在后续扩展到大模型版本时尤其重要结构化数据比自然语言更能被稳定地计算和检查。3. 环境准备与项目结构3.1 运行环境本文示例以 Python 3.9 以上版本为例主要使用标准库不依赖第三方包这样在任何一台带有 Python 的机器上都能直接运行。如果本机还没有 Python建议先安装 Python 3.10 或 3.11 版本。示例中用到的标准库如下random控制随机种子用于保证实验可复现dataclasses定义轻量数据结构typing提供类型注解提高可读性logging可选用于记录运行日志。如果你后续要接入大模型 API再额外安装openai或requests等库即可。本文不依赖这些避免示例运行受阻。3.2 项目目录结构为了让代码层次清晰我建议按下面的目录结构组织文件math_multi_agent/ ├── environment.py ├── hypothesis.py ├── agents.py └── main.py各文件职责如下文件职责environment.py定义数学环境向外部隐藏真实规律只提供查询能力hypothesis.py定义假设数据结构统一 Proposer 输出格式agents.py实现 Proposer、Critic、Judge 三个 Agentmain.py组装系统并运行主循环这样的好处是每个模块都可以单独替换。比如你想把 Critic 换成大模型驱动只需要修改agents.py中对应的类即可。3.3 模块职责说明环境模块是整个实验的“裁判场所”。在真实世界中我们无法控制客观规律但在模拟环境中可以设置一个隐藏规则用于检验多智能体系统能否发现它。我这里选择“整数序列规律发现”作为场景原因有三点整数序列容易生成和检查读者可以直观看到规律候选规则可以预先定义成函数避免依赖复杂表达式解析数列规律是数学发现里最基础、也最容易理解的一类问题。如果希望扩展成真正的开放世界可以把环境替换成平面几何对象、图结构、逻辑表达式等核心逻辑保持不变。4. 核心代码与实现4.1 假设数据结构设计先定义Hypothesis数据结构。它承载了 Proposer 的输出结果也是 Critic 和 Judge 的输入对象。# hypothesis.py from dataclasses import dataclass from typing import Callable, List, Optional dataclass class Hypothesis: 一条数学规律假设。 name: str predict_fn: Callable[[int, List[int]], int] is_true: Optional[bool] None confidence: float 0.0 counterexample: Optional[List[int]] None test_size: int 0字段含义name规律的字符串描述例如a[n] a[n-1] a[n-2]predict_fn预测函数签名是fn(index, prefix_seq)其中index表示要预测的位置prefix_seq是不包含当前位置的前缀序列is_true是否通过验证初始为 Noneconfidence置信度简单场景下通过“通过样本数 / 总验证样本数”估算counterexample反例信息保存(位置, 期望值, 预测值)三元组test_size已经验证的样本数量。这个数据结构虽然简单但已经能支撑最小闭环。后续如果要接入更复杂的规则可以增加expression_tree或derivation_steps字段。4.2 环境模块未知规则的提供者环境模块的核心是能生成有限长度的序列数据但外部无法直接看到规则函数本身。# environment.py from typing import Callable, List class SequenceEnvironment: 整数序列环境对外只暴露查询能力隐藏真实规则。 def __init__( self, seed_values: List[int], rule_fn: Callable[[int, List[int]], int], name: str secret_rule, ): self.seed_values seed_values[:] self.rule_fn rule_fn self.name name def generate(self, length: int) - List[int]: 生成指定长度的序列。 seq self.seed_values[:] for i in range(len(seq), length): seq.append(self.rule_fn(i, seq)) return seq def query(self, length: int 10) - List[int]: 向 Agent 提供一次有限长度查询。 return self.generate(length)generate方法从种子值开始不断调用隐藏规则函数生成后续项。由于 Agent 拿到的只是最终列表它只能从数据本身反推规律。这里有一个值得注意的设计点环境只暴露有限长度的数据而不是一次性给全部数据。这是“开放世界”和“有限观察”之间的折中Agent 可以先基于一段观察提出假设再想办法验证而不是一开始就掌握全部信息。4.3 提出者 Agent 实现提出者的任务是生成候选规律。在模拟环境中我们使用一个“候选规则库”来模拟 Agent 的归纳偏置。真实情况下这个规则库可以替换为符号回归程序或大语言模型生成器。# agents.py import random from typing import Callable, Dict, List, Optional, Tuple from hypothesis import Hypothesis def rule_fib(i: int, seq: List[int]) - int: return seq[-1] seq[-2] def rule_double_plus(i: int, seq: List[int]) - int: return seq[-1] * 2 1 def rule_add_three(i: int, seq: List[int]) - int: return seq[-1] 3 def rule_square_diff(i: int, seq: List[int]) - int: return seq[-1] ** 2 - seq[-2] ** 2 CANDIDATE_RULES: Dict[str, Callable[[int, List[int]], int]] { a[n] a[n-1] a[n-2]: rule_fib, a[n] 2*a[n-1] 1: rule_double_plus, a[n] a[n-1] 3: rule_add_three, a[n] a[n-1]^2 - a[n-2]^2: rule_square_diff, } class RuleSpace: 候选规则空间用于模拟提出者的搜索空间。 def __init__(self, rules: Optional[Dict[str, Callable]] None): self.rules rules if rules is not None else CANDIDATE_RULES def sample(self) - Tuple[str, Callable[[int, List[int]], int]]: name random.choice(list(self.rules.keys())) return name, self.rules[name] class ProposerAgent: 提出者从规则空间中采样一个候选假设。 def __init__(self, rule_space: RuleSpace): self.rule_space rule_space def propose(self, observed_seq: List[int]) - Hypothesis: name, fn self.rule_space.sample() return Hypothesis(namename, predict_fnfn)在上述代码中ProposerAgent.propose当前实现是随机采样这看起来有点“笨”但没有关系。它代表了一个核心思想提出者负责广度探索哪怕经常出错只要最终能覆盖到正确规则即可。如果你希望提出者更聪明可以在这里加入基于差分表、序列拟合、频率分析等策略也可以接一个大模型接口让它根据当前序列生成更有针对性的候选公式。4.4 批评者 Agent 实现批评者的工作是“找茬”。它拿到一条假设后会用已经观察到的数据去测试假设。只要有一个位置预测错误就返回这个反例。class CriticAgent: 批评者在已知数据中寻找反例。 def find_counterexample( self, observed_seq: List[int], hypothesis: Hypothesis ) - Optional[Tuple[int, int, int]]: for idx in range(2, len(observed_seq)): predicted hypothesis.predict_fn(idx, observed_seq[:idx]) expected observed_seq[idx] if predicted ! expected: return (idx, expected, predicted) return None这里从索引 2 开始是为了保证有足够的“前项”供规则函数计算。很多递推规则至少需要前两项。Critic 的价值在于快速淘汰错误假设避免它们进入代价更高的深度验证阶段。如果 Critic 返回了反例系统就不需要再调用 Judge省下环境查询成本。需要注意的是Critic 只能使用“已知数据”来反驳。它并不能证明假设在未知数据上正确所以它的结论是“未发现反例”而不是“肯定正确”。4.5 裁判 Agent 实现裁判负责做最终裁决。它的验证方式比批评者更严格会向环境请求更多数据在扩展数据集上验证假设是否依然成立。class JudgeAgent: 裁判在扩展数据上验证假设是否成立。 def validate( self, env: SequenceEnvironment, hypothesis: Hypothesis, base_seq: List[int], extra_len: int 50, ) - Hypothesis: extended_seq env.generate(len(base_seq) extra_len) for idx in range(2, len(extended_seq)): predicted hypothesis.predict_fn(idx, extended_seq[:idx]) expected extended_seq[idx] if predicted ! expected: hypothesis.is_true False hypothesis.confidence max(0.0, (idx - 2) / extra_len) hypothesis.counterexample [idx, expected, predicted] hypothesis.test_size idx return hypothesis hypothesis.is_true True hypothesis.confidence 1.0 hypothesis.test_size len(extended_seq) return hypothesis裁判的判定逻辑并不复杂但在架构上非常重要。它使用了环境模块的generate方法相当于在真实世界中做更多实验来检验猜想。这种“实验验证”比单纯的知识推理更接近科学方法论。置信度的计算方式比较简单如果验证到第idx项失败则认为它通过了idx - 2项扩展验证用通过数量除以extra_len得到置信度。如果全部通过置信度为 1。4.6 主循环让三个 Agent 协同工作现在把环境、提出者、批评者、裁判组合到一起。# main.py import random from agents import CriticAgent, JudgeAgent, ProposerAgent, RuleSpace from environment import SequenceEnvironment def main(): random.seed(42) env SequenceEnvironment( seed_values[1, 1], rule_fnlambda i, seq: seq[-1] seq[-2], nameFibonacci-like, ) rule_space RuleSpace() proposer ProposerAgent(rule_space) critic CriticAgent() judge JudgeAgent() base_seq env.generate(10) print(观察到的前 10 项, base_seq) best None max_rounds 30 for round_id in range(1, max_rounds 1): hypothesis proposer.propose(base_seq) counter critic.find_counterexample(base_seq, hypothesis) if counter is not None: print( f[第 {round_id} 轮] {hypothesis.name} 被 Critic 反驳 f位置 {counter[0]} 期望 {counter[1]}规则预测 {counter[2]} ) hypothesis.is_true False else: hypothesis judge.validate(env, hypothesis, base_seq, extra_len50) if hypothesis.is_true: print( f[第 {round_id} 轮] {hypothesis.name} f通过全部验证采纳为发现结果。 ) best hypothesis break else: print( f[第 {round_id} 轮] {hypothesis.name} 通过已有数据但在扩展验证中失败。 ) if best is not None: print(\n最终发现, best.name) print(验证样本量, best.test_size) else: print(\n未在限定轮数内找到可用规则请扩展规则库或增加轮数。) if __name__ __main__: main()主循环逻辑很强地体现了“正反博弈 裁判”协作模式Proposer 每轮生成一个假设Critic 用已有数据快速反驳只有通过 Critic 反驳的假设才会进入 Judge 的扩展验证环节Judge 通过扩展数据给出最终结论。4.7 运行与结果分析运行上面的代码输出结果大致如下观察到的前 10 项 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] [第 1 轮] a[n] a[n-1] 3 被 Critic 反驳位置 2 期望 2规则预测 4 [第 2 轮] a[n] a[n-1]^2 - a[n-2]^2 被 Critic 反驳位置 2 期望 2规则预测 3 [第 3 轮] a[n] 2*a[n-1] 1 被 Critic 反驳位置 2 期望 2规则预测 3 [第 4 轮] a[n] a[n-1] a[n-2] 通过全部验证采纳为发现结果。 最终发现 a[n] a[n-1] a[n-2] 验证样本量 60可以看到系统在随机采样规则的情况下经过几轮博弈就找到了正确的递推规则。虽然这里候选规则库很小但整个验证链路是完整的。由于Proposer是随机选择规则实际运行时可能需要更多轮次才能命中正确规则这很正常。你可以通过设置随机种子、增大候选规则库、或者引入启发式规则来提升命中率。5. 常见问题与排查思路在实际运行和扩展过程中比较容易遇到下面这些问题。问题现象常见原因解决思路程序运行多轮仍找不到规则候选规则库中没有真实规则检查环境隐藏规则是否在候选集合中规则通过已有数据但扩展验证失败Critic 数据量太少过拟合增加初始观察长度或让 Judge 扩大验证范围输出结果不可复现缺少随机种子在main()开头设置random.seed()预测函数报越界错误规则函数依赖前项数量不足检查索引起点给足最少前缀长度置信度计算结果异常没有统一处理验证失败位置检查idx - 2是否出现负数想把规则换成复杂表达式简单的字符串描述无法计算改用表达式树或 Python 函数对象除了上表中的问题还有一个容易被忽视的点Proposer的候选规则应该是“有偏见的”。如果候选规则空间和真实规律相差太远无论跑多少轮都找不到。这其实对应了机器学习里的“归纳偏置”在真实数学发现中也是如此。数学家提出猜想时也不是凭空枚举而是基于已有知识筛选有希望的路径。如果你在适配自定义规则时发现某个规则函数接收的参数长度不足可以把find_counterexample里的起始索引调大。比如一个规则依赖前 3 项那起始索引就应该从 3 开始否则前几个位置无法计算。6. 最佳实践与工程建议6.1 保证可复现性多智能体系统一旦引入随机性运行结果会变得不稳定。调试阶段务必设置随机种子。更稳妥的做法是把每一轮的关键信息写到日志里包括假设名称、预测函数、反例位置、裁判判定结果。这样即使运行结果不理想也能回溯是哪一步出了问题。6.2 让每个 Agent 的输入输出结构化不要只传自然语言字符串结构化数据能让系统更稳定。比如Hypothesis里的predict_fn是一个 Python 函数对象而不是字符串描述。这样 Critic 和 Judge 可以直接调用它做数值验证而不需要解析字符串。如果你需要向大模型 Agent 传递信息可以在类内部增加prompt方法把结构化数据转成提示词拿到模型输出后再转回结构化数据。这样可以兼顾数值验证和语言推理。6.3 控制环境查询成本在实际项目中环境可能代表昂贵的模拟计算或真实实验。因此需要控制查询次数优先让 Critic 基于已有数据做快速反驳只有候选假设通过 Critic 后才调用 Judge 扩展验证可以为环境查询增加次数上限避免无限探索。这实际上是一种分层验证策略能够有效降低系统的整体计算成本。6.4 避免过拟合到已知数据如果批评者只使用固定一段历史数据模型很容易找到一条“只对这一小段正确”的规律。解决思路有几种让环境定期补充新数据在 Judge 验证时使用不同于观察数据的时间段在候选规则构造时限制复杂度比如避免使用过高阶的多项式函数。在数学发现中避免过拟合意味着不能因为一个规律符合前 100 个样本就断定它是对的必须继续寻找更广泛的证明或更强的证据。6.5 以合法合规方式接入大模型能力如果你想把这个框架扩展成大模型版本建议注意两点。第一接入任何大模型 API 之前确保你拥有合法的接口权限和调用额度并且遵守数据隐私要求。不要把内部敏感数据直接拼进提示词更不要在多智能体交互日志里记录不必要的隐私信息。第二大模型输出不可直接当作数学结论。最合理的做法是让大模型负责“提出假设”和“解释反例”而“数值验证”和“最终裁定”依然交给确定性代码完成。这样既利用了生成模型的灵活性也保留了验证环节的可靠性。6.6 为角色增加记忆与反思能力当前的ProposerAgent每次随机采样没有记忆。实际项目中你可以为它增加一个“失败规则黑名单”同一规则失败过就不再提出。也可以让 Critic 在返回反例时附带失败原因帮助 Proposer 调整生成方向。更进一步的方案是引入“反思”机制每次验证完成后把成功或失败经验写入共享知识库下一轮提出假设时参考这些经验。这会让系统从“随机搜索”逐步变成“有导向的搜索”。7. 总结与学习路线本文从开放世界多智能体环境的概念出发实现了一个“正反博弈 裁判”的 Python 多智能体框架并把它用在自主数学发现的数列规律场景中。你掌握的内容包括多智能体协作的基本角色划分、假设数据结构的定义、环境模块的隐藏规则设计、Critic 快速反驳与 Judge 深度验证的分层机制以及一套可复现的完整代码。下一步可以沿着三个方向继续深入第一扩充规则表达空间把候选规则从固定函数扩展到符号表达式第二接入大模型生成能力让 Proposer 根据当前序列生成更聪明的猜想第三引入形式化验证工具让裁判不再只是做数值检查而是对数学命题做构造性证明。如果你刚开始实践建议先把这个最小闭环跑通亲手改一改环境和候选规则库再逐步替换每个 Agent 的内部策略。这样即使以后面对更复杂的智能体任务也能快速搭建出属于自己的协作框架。