如果你玩过《足球经理》,又关注大模型 Agent 的进展,看到这个标题大概率会好奇:让 Frontier AI 模型去管理一家足球俱乐部,到底是“套壳聊天机器人”的多轮对话,还是真的能把阵容、战术、转会、训练这些复杂决策串起来变成一个可运行的系统?
我的判断是,这个项目最有价值的不是“足球”,而是它的系统形态:一个多智能体、有状态、有反馈、有可观测胜负结果的决策沙盒。它把大模型从“你说什么我答什么”的问答场景,拉到了“在持续变化的世界里连续决策并承担后果”的 Agent 化场景。这个转变,恰好是目前大模型工程落地最难也最值得探讨的部分。
对于正在研究 Agent 架构、评测大模型决策能力,或者想给模型找一个不为零的复杂场景的开发者来说,这个项目比普通的聊天机器人 demo 值得拆解得多。本文会从项目标题展开,梳理一个机器人足球联赛系统从模拟引擎到 AI 决策闭环的技术设计,给出可复制的 Python 代码骨架、常见问题和工程实践建议。
需要先说明一点:本文并不代表该项目官方文档或源码说明。当前可获取的公开细节有限,所以下面内容更多是“这类项目要想稳定跑起来,技术上是如何设计”的通用架构拆解。你完全可以把它当作一个可以直接落地的 Agent 系统模板来理解和使用。
1. 这篇文章真正要解决的问题
只看“机器人足球联赛”这个短语,容易联想到 RoboCup 那样真机对抗的机器人竞赛。但这个项目加上了“frontier AI models manage the clubs”,含义完全不同:它更像是把“足球俱乐部经营决策”交给多个大模型智能体,让它们在同一个联赛世界里有策略地博弈。
这类项目真正要解决的问题,可以拆成四层。
第一层是大模型与模拟环境的连接。模型不能直接操作世界,它只能通过文本或结构化数据读取状态,再通过预定义动作改变状态。这是所有 LLM Agent 落地场景的共性难点,只是足球经理场景把“状态空间”和“动作空间”包装得更清晰了。
第二层是决策的连续性和一致性。一支球队不是踢完一场就结束,经理需要基于历史战绩、球员状态、对手风格连续做决策。如何让大模型“记得”已经发生的事,如何保持自己的执教风格,是系统设计问题,不是简单的提示词能解决的。
第三层是多智能体博弈。联赛里有多个俱乐部经理,每个经理的行为会相互影响。一个经理买走了明星前锋,另一个经理的补强计划就被破坏。如何管理回合顺序、状态同步和信息不对称,是传统单 Agent 项目没有的压力。
第四层是可评估性。大模型生成的内容很难客观打分,但比赛胜负、联赛积分、球队财务是硬指标。这意味着这个项目天然构成了一个可以自动评估的 Agent benchmark:模型好不好,不看它说了什么,而看它把球队带到了第几名。
所以这篇文章表面讲“AI 管理足球队”,实际讲的是“大模型在状态化模拟环境里做连续决策”的完整技术路径。后面每一章都会落到可以操作的设计和代码上。
2. 机器人足球联赛的核心概念与适用场景
2.1 什么是机器人足球联赛
项目里的“机器人足球”,最合理的理解是一套高度抽象化的模拟联赛。与 RoboCup 真实机器人平台不同,它不要求机器人做物理运动,而是把球队看作由球员属性和战术构成的“数据体”,比赛结果由模拟引擎结合双方策略计算出来。
这种抽象有一个明显好处:模型不需要理解机器人动力学,可以只关注战略决策。它模拟的是“经理视角”,而不是“机器人视角”。也就是说,这里的重点不是怎么踢球,而是怎么决策。
2.2 Frontier AI 模型在项目中扮演什么角色
Frontier AI 模型通常指当前综合能力处于第一梯队的大语言模型,特点是推理能力强、能处理长文本、具备较好的工具调用能力。它们在这个项目中扮演的是“俱乐部经理”,需要承担的决策至少包括:
- 赛前布置:根据对手风格和己方阵容选择阵型、排首发。
- 临场指挥:根据比分和场上数据决定换人、变阵。
- 转会管理:评估球员性价比,决定买入或卖出。
- 训练安排:分配训练重点,提升球员属性。
- 风险决策:应对伤病潮、经济压力、更衣室矛盾等突发情况。
这些任务本质上可以统一抽象成“状态输入 -> 决策输出”的模式。系统把球队和世界状态压缩成模型能理解的简报,模型产出动作,系统校验动作后写回世界。
2.3 它和传统足球经理游戏、普通 Agent 框架的本质区别
传统足球经理游戏里的“AI 经理”,通常是规则算法或有限状态机:基于固定脚本决定买谁、排谁、换谁。优点是稳定、快、不消耗 API 费用,缺点是风格固定,遇到规则外的情况就变得非常机械。
普通 Agent 框架则强调“自主完成目标”,但往往缺少一个强约束的世界模型。状态可以很随意,目标边界模糊,最后很难评价系统到底好不好。
这个项目恰好介于两者之间:
- 世界状态由模拟引擎统一仲裁,所有模型共用同一套状态。
- 模型决策只能通过接口进入世界,不能直接修改积分或资金。
- 胜负是硬性指标,评价天然可量化,不需要人工打分。
这也是它对 Agent 工程很有参考价值的原因:它给出了一条既保留模型自由度,又不至于让系统失控的中间路线。
2.4 哪些场景适合借鉴这套架构
- LLM Agent 稳定性测试平台:观察模型在多轮决策中是否保持一致性。
- 多智能体博弈研究:让不同模型在同一个封闭世界中竞争,对比决策风格。
- 游戏 AI 与 NPC 系统:给经营策略类游戏接入更灵活的 AI 经理。
- 对抗性评测:用联赛积分和财务指标评估前沿模型在长周期任务中的表现。
3. 系统架构:把 AI 经理接进模拟世界
从工程角度看,这套系统至少需要六个模块协作。
- 模拟引擎:负责世界状态推进,处理比赛结果、球员属性变化、经济变化。
- 状态序列化层:把复杂的世界状态转换成模型可理解的文本或结构化数据。
- 模型决策接口:调用 Frontier AI 模型,并要求它返回结构化的动作。
- 动作校验器:模型返回的内容未必合法,必须经过校验和纠错才能进入引擎。
- 日志与评估层:记录每个经理的决策、比赛结果、积分变化,用于横向对比。
- 调度控制层:串起所有步骤,控制回合、超时、重试和成本。
一个核心设计问题是:什么时候调用模型?
推荐做法不是每时每刻调用,而是事件驱动。比如:
- 比赛开始前:触发“赛前决策”事件。
- 比赛进行中:按进球、红牌、伤病等关键事件触发“临场决策”。
- 每个转会窗口:触发“转会决策”事件。
- 每个训练周期:触发“训练计划”事件。
这样做的好处很明显:既能降低 API 调用成本,也更符合现实里足球经理的工作节奏。没有任何一家俱乐部经理会每秒都在做重大决策,大多数时间只是观察和等待。
4. 环境准备与前置条件
实现一个最小可运行版本,需要的环境并不复杂:
- Python 3.10 或更高版本。
- 一个可以访问 Frontier AI 模型 API 的 key。
- 安装必要的 Python 依赖。
下面是一个参考依赖文件,版本号以你实际安装时官方文档为准,因为各家 SDK 更新速度很快:
openai>=1.30.0 httpx>=0.27.0 pydantic>=2.0.0 rich>=13.0.0 python-dotenv>=1.0.0安装命令:
pip install -r requirements.txt真实项目中,还需要想清楚“联赛世界”是单机演示还是持续服务。如果只是验证 AI 经理能否做出合理决策,单机脚本就够了;如果要长期运行,就需要引入数据库、任务队列、定时调度和监控告警。本文先以单机脚本为例,把核心闭环跑通。
5. 核心实现:最小可运行的 AI 足球经理联赛
下面我构建一个极简版本。它不追求真实足球模拟的精度,而是把“LLM 决策闭环”完完整整跑通。你可以在这个基础上替换成更专业的模拟引擎,也可以把模型调用换成任意 Frontier AI 模型的 API。
5.1 定义比赛世界状态
先设计球队、球员和比赛结果的数据结构。为了保持代码可读,这里用 Python 的 dataclass 实现。
# 文件路径:league_state.py from dataclasses import dataclass, field from typing import List @dataclass class Player: name: str position: str # GK / DF / MF / FW ability: int # 0-100,越高越强 energy: int = 100 # 体力,比赛后下降 @dataclass class Club: club_id: str manager: str squad: List[Player] tactics: str = "4-4-2" finance: int = 100 points: int = 0 @dataclass class LeagueMatchResult: home_club_id: str away_club_id: str home_score: int away_score: int detail: str = ""这段代码定义的是世界的“元素”。实际项目中,球员还可以扩展年龄、潜力、状态、合同年限、伤病状态等属性。核心原则是:状态信息要足够丰富,让模型有决策依据;又要保持精简,避免超出模型上下文窗口。
5.2 比赛模拟引擎
比赛结果需要从双方战术和球员能力中计算出来。这里用一个很朴素的方法:计算双方整体战力的加权平均值,再叠加随机因子。
这里写得简单,是有意为之。模拟引擎的专业程度决定项目天花板,但不会影响架构验证。如果你想先跑通闭环,就不要在模拟引擎上过度设计。
# 文件路径:match_simulator.py import random from league_state import Club, LeagueMatchResult def _team_strength(club: Club) -> float: ability_sum = sum(p.ability for p in club.squad) morale_bonus = random.uniform(0.95, 1.05) return ability_sum * morale_bonus def simulate_match(home: Club, away: Club) -> LeagueMatchResult: home_strength = _team_strength(home) away_strength = _team_strength(away) # 简单近似:强弱差距决定期望进球数 home_exp = max(0.2, (home_strength / away_strength) * 1.2) away_exp = max(0.2, (away_strength / home_strength) * 1.0) home_goals = max(0, int(random.gauss(home_exp, 1.0))) away_goals = max(0, int(random.gauss(away_exp, 1.0))) return LeagueMatchResult( home_club_id=home.club_id, away_club_id=away.club_id, home_score=home_goals, away_score=away_goals, detail=f"{home.club_id} {home_goals} - {away_goals} {away.club_id}" )这段代码的作用是给整个系统一个“客观结果”。AI 经理无论说什么,最终都要通过比赛验证。下一轮提示词里会包含上一轮结果,模型因此能感知自己的决策是否有效。
5.3 定义 AI 经理的决策接口
这是整套系统最关键的部分:让模型输出结构化动作。推荐使用 function calling 或者 JSON Schema 约束输出。
下面是一个 JSON Schema 风格的接口设计,不依赖特定 SDK,方便你移植到不同模型平台。
{ "name": "manager_decide", "description": "AI manager makes weekly decision for the club", "parameters": { "type": "object", "properties": { "reasoning": { "type": "string", "description": "Brief reasoning for the decision" }, "starting_formation": { "type": "string", "enum": ["4-4-2", "4-3-3", "3-5-2", "5-3-2"] }, "training_focus": { "type": "string", "enum": ["defense", "attack", "energy", "morale"] }, "market_action": { "type": "string", "enum": ["buy_striker", "buy_defender", "sell_player", "do_nothing"] } }, "required": ["reasoning", "starting_formation", "training_focus", "market_action"] } }为什么一定要用结构化输出?
因为模型返回自由文本时,表面看起来各种决策都能表达,但程序很难判断“Buy a strong striker”和“花钱补强锋线”是不是同一件事。结构化输出可以把开放决策收敛到有限动作集合,程序能直接应用,也能方便地统计每个动作被选中的频率。
5.4 让多个 AI 俱乐部经理在模拟循环中博弈
下面这个是主循环。它会创建两个俱乐部,用同一个模型 API 但不同 system prompt 来扮演不同风格的经理,每一轮进行“训练调整 + 市场操作 + 比赛 + 积分更新”。
# 文件路径:main_loop.py import os import json import time import openai from dotenv import load_dotenv from league_state import Club, Player from match_simulator import simulate_match load_dotenv() client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY")) CLUB_A_SYSTEM = ( "You are a cautious football club manager. " "Prioritize defense and financial stability." ) CLUB_B_SYSTEM = ( "You are an aggressive football club manager. " "Prioritize attack and bold signings." ) MANAGER_SCHEMA = { "name": "manager_decide", "description": "AI manager makes weekly decision for the club", "parameters": { "type": "object", "properties": { "reasoning": {"type": "string"}, "starting_formation": {"type": "string", "enum": ["4-4-2", "4-3-3", "3-5-2", "5-3-2"]}, "training_focus": {"type": "string", "enum": ["defense", "attack", "energy", "morale"]}, "market_action": {"type": "string", "enum": ["buy_striker", "buy_defender", "sell_player", "do_nothing"]} }, "required": ["reasoning", "starting_formation", "training_focus", "market_action"] } } def build_prompt(club: Club, standings: str, last_result: str) -> str: squad_desc = "\n".join( f"- {p.name} ({p.position}, ability={p.ability}, energy={p.energy})" for p in club.squad ) return f"""You manage club {club.club_id}. Current finance: {club.finance} Points: {club.points} Current squad: {squad_desc} League standings: {standings} Last match: {last_result} Please use manager_decide to give your decision for this week.""" def call_ai_manager(system_prompt: str, user_prompt: str): resp = client.chat.completions.create( model="gpt-4o-mini", # 换成你手上可用的模型 temperature=0.7, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], tools=[ { "type": "function", "function": MANAGER_SCHEMA, } ], tool_choice={"type": "function", "function": {"name": "manager_decide"}}, ) tool_call = resp.choices[0].message.tool_calls[0] return json.loads(tool_call.function.arguments) def apply_decision(club: Club, decision: dict): if decision["training_focus"] == "attack": for p in club.squad: if p.position == "FW": p.ability = min(100, p.ability + 1) elif decision["training_focus"] == "defense": for p in club.squad: if p.position in ("DF", "GK"): p.ability = min(100, p.ability + 1) elif decision["training_focus"] == "energy": for p in club.squad: p.energy = min(100, p.energy + 5) if decision["market_action"] == "buy_striker": club.finance -= 20 club.squad.append(Player(name="New Striker", position="FW", ability=75)) elif decision["market_action"] == "buy_defender": club.finance -= 15 club.squad.append(Player(name="New Defender", position="DF", ability=78)) elif decision["market_action"] == "sell_player": if len(club.squad) > 5: club.squad.pop() club.finance += 10 def main(): club_a = Club(club_id="AI United", manager="CLUB_A", squad=[ Player("A01", "GK", 70), Player("A02", "DF", 72), Player("A03", "DF", 71), Player("A04", "MF", 74), Player("A05", "FW", 76), ]) club_b = Club(club_id="Bold City", manager="CLUB_B", squad=[ Player("B01", "GK", 68), Player("B02", "DF", 70), Player("B03", "DF", 73), Player("B04", "MF", 75), Player("B05", "FW", 80), ]) standings = f"1. {club_a.club_id}: {club_a.points}\n2. {club_b.club_id}: {club_b.points}" last_result = "Season start" for week in range(1, 4): print(f"\n===== Round {week} =====") decision_a = call_ai_manager(CLUB_A_SYSTEM, build_prompt(club_a, standings, last_result)) decision_b = call_ai_manager(CLUB_B_SYSTEM, build_prompt(club_b, standings, last_result)) print("AI United decision:", decision_a) print("Bold City decision:", decision_b) apply_decision(club_a, decision_a) apply_decision(club_b, decision_b) result = simulate_match(club_a, club_b) print("Match result:", result.detail) if result.home_score > result.away_score: club_a.points += 3 elif result.home_score < result.away_score: club_b.points += 3 else: club_a.points += 1 club_b.points += 1 last_result = result.detail standings = ( f"1. {club_a.club_id}: {club_a.points}\n" f"2. {club_b.club_id}: {club_b.points}" ) time.sleep(1) if __name__ == "__main__": main()这个主循环已经把核心思路演示完整了:
- 每轮先让两个模型经理读取当前世界状态。
- 模型返回结构化决策。
- 通过 apply_decision 将决策写回世界。
- 模拟引擎计算比赛结果。
- 更新积分榜,进入下一轮。
现实中,你会加入伤病、体力消耗、球员士气、杯赛抽签、转会窗口等更多细节,但闭环骨架已经成立。后续所有扩展,都是在为这个“感知 -> 决策 -> 行动 -> 反馈”的循环增加更丰富的世界信息。
5.5 提示词的构造细节
在这个系统里,提示词不是“请帮我写一段话”,而是“请根据当前状态做出决策”。因此提示词的结构要固定,建议包含以下部分:
- 身份设定:这部分放在 system prompt,决定经理的风格。
- 当前状态:包括积分、球员列表、资金、上一轮结果。
- 世界约束:说明有哪些动作可选,可选动作的含义。
- 决策要求:明确必须调用工具返回 JSON,不能自由发挥。
有一个容易被忽略的细节:不要把上一次的完整决策历史全部塞进去。模型上下文有限,早期决策信息对当前帮助不大。更合适的做法是只保留最近三轮的比赛结果和关键事件摘要。如果你希望模型能长期总结规律,可以让它每周输出一段“教练笔记”,然后在下一轮的提示词中传入这段笔记。
6. 运行结果与效果验证
运行上面的脚本后,预期会看到类似这样的输出:
===== Round 1 ===== AI United decision: {'reasoning': 'We need a solid defense first...', 'starting_formation': '5-3-2', 'training_focus': 'defense', 'market_action': 'do_nothing'} Bold City decision: {'reasoning': 'All in on attack...', 'starting_formation': '4-3-3', 'training_focus': 'attack', 'market_action': 'buy_striker'} Match result: AI United 0 - 2 Bold City ===== Round 2 ===== ...需要特别说明的是,大模型输出带随机性,每次运行结果不会完全一致。这是正常现象,因为这类系统不是求一个固定答案,而是观察“不同策略背后模型推理的差异”。
怎么判断运行是否成功?
- 模型能够按 schema 返回合法 JSON。
- 每条决策都实际改变了俱乐部状态。
- 比赛结果会随阵容和训练方向变化,而不是恒定不变。
- 多轮联赛后,积分榜有区分度,保守型经理和激进型经理的积分走势不一样。
如果第一轮就卡住,先不要怀疑模型能力,优先检查三个方面:
- API Key 能否访问所选模型。
- 提示词是否把“当前状态”讲清楚。
- 返回内容能否被正确解析成 JSON。
建议加一个调试模式,把每次调用模型的完整请求和响应都打印出来。这样定位问题会快很多。
7. 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 模型返回的不是合法 JSON | 提示词约束不够,或 SDK 版本内置 schema 格式不一致 | 打印原始返回,检查 tool_calls 结构 | 使用 function calling 强制工具返回;增加 JSON Schema 校验与重试 |
| 决策一直不稳定,同一局结果差异巨大 | temperature 过高,或状态描述缺失关键信息 | 查看 reasoning 输出,确认模型是否注意到积分、伤病等信息 | 调低 temperature;把关键指标放到提示词最前面 |
| 比赛越踢越像随机数,决策不起作用 | 模拟引擎的“强弱”计算与战术决策没有真正挂钩 | 人工验证强队是否更容易获胜 | 调整模拟引擎公式,让阵型、训练方向产生可感知影响 |
| API 调用超时或限流 | 推理模型响应慢,或并发数过小 | 查看服务端日志,统计 P95 延迟 | 增加重试、超时时间;把多个俱乐部调用改为并发;低风险决策使用更快的辅助模型 |
| 上下文过长,模型忽略早期信息 | 世界状态、历史比赛、球员档案全部塞进提示词 | 计算 token 占用,检查模型是否只按最后几段做决策 | 精简状态;只给最近三轮结果;引入结构化摘要或检索 |
| 成本过高,联赛跑几十轮就超预算 | 每个事件都调用大模型 | 查看调用日志中每轮消耗 token | 事件驱动调用 + 分层模型:低风险决策用便宜模型,重要决策用强模型 |
| 多个模型同时改世界状态,导致数据错乱 | 共享状态没有加锁或没有事务控制 | 检查是否有并发写操作 | 采用单线程事件循环;或用数据库事务保护状态更新 |
这里最容易踩的坑是最后一个。很多人一开始写多智能体时,会开多个线程让不同俱乐部经理并行决策,以为这样更高效。但如果没有处理好共享状态,两个经理会同时读取到旧积分,然后分别更新自己的副本,最后谁后写谁覆盖,积分榜就会错乱。稳妥做法是:让每个客户端持有独立的“世界状态快照”,决策完成后由一个中央调度器统一合并状态变更。
8. 最佳实践与工程建议
8.1 用结构化输出代替自由文本
大模型返回自由文本看起来更自然,但放到系统里是灾难。任何要进入模拟引擎的决策,都应当走 function calling 或 JSON Schema,并且校验字段范围。宁可让一个决策失败并触发重试,也不要接收“买一个强力前锋”这种无法直接执行的文本。
8.2 把状态压缩成“决策简报”
不要直接把整个联赛数据库丢给模型。要像真实经理获取球探报告一样,准备一份“决策简报”:当前积分、对手风格、最近战绩、球员关键属性、转会预算。内容越精炼,模型决策越聚焦,token 成本也越低。
这里有一个实际经验:一份好的决策简报,信息密度要高于聊天式提示词。别问“请分析一下现在的局势”,而是给“你目前积 6 分排第二,落后榜首 2 分,下一场对手擅长反击,你的主力中卫体能只有 70”。信息越具体,模型给出的判断越有价值。
8.3 用确定性回退兜底
前沿模型也可能失误:超时、返回不合法 JSON、甚至给出明显愚蠢的决策。生产级实现必须有回退策略:
- 超时重试两次。
- JSON 解析失败后,让模型重新只输出 JSON。
- 连续失败时使用上一轮决策或规则策略顶替,保证联赛继续。
确定性问题不是小事。一个模型在一个时间窗口内的失误可能被掩盖,但在整个赛季几十轮比赛里,任何一个未处理的异常都可能让积分榜数据错乱。
8.4 做好日志、版本和可复现性
AI 决策有随机性,因此系统必须把每次调用使用的提示词版本、模型版本、temperature、随机种子、原始返回完整记录下来。否则你无法判断“这周积分上涨”是因为模型决策变强了,还是因为随机种子换了。
推荐做法是把每一次决策存成 JSON 日志文件,文件名包含赛季、轮次、俱乐部 ID。日志目录结构可以是:
logs/ season_2025/ round_01/ ai_united_decision.json bold_city_decision.json match_result.json这样既方便复盘,也方便回溯为什么某场比赛结果异常。
8.5 隔离模型与模拟世界的权限
无论模型输出什么,都不能直接修改数据库或文件。所有动作必须经过校验器,再通过固定接口写回世界对象。即使模型被恶意提示词诱导,也无法越权操作。要记住,LLM 是无权限的概念,权限边界在代码里,不在模型规则里。
8.6 用分层模型控制成本
不是每轮决策都需要最强推理模型。可以在关键节点使用强模型,比如转会窗口、决赛前、赛季末冲刺;在常规训练、普通比赛日使用小模型。项目标题里写的是 Frontier AI,但工程上必须有成本意识,长期跑联赛的成本可能超出预期。
8.7 评估指标不要只看胜率
胜率能反映结果,但不能完全反映决策质量。建议同时记录这些指标:
- 决策合法性:模型返回是否符合 schema,非法返回占比多少。
- 决策多样性:模型是否一直在复读同一套战术。
- 决策一致性:相同状态下重复调用,决策差异有多大。
- 战术有效性:比如选择高位逼抢后,对手失误率是否上升。
只有把这些指标统一记录,才能横向比较不同模型、不同提示词策略的表现。
9. 总结与后续学习方向
这个项目标题背后藏着一条很完整的 Agent 工程链路:外部世界状态建模、结构化决策接口、多智能体调度、模拟引擎仲裁、可量化评估。它不只是一个“让 AI 踢球”的趣味 demo,更是把大模型放进复杂动态博弈环境中做压力测试的好载体。
如果你接下来想深入,可以从这几个方向入手:
- 把比赛模拟换成 MuJoCo、PyBullet 或 Isaac Lab 等物理仿真环境,让“机器人足球”从决策层延伸到动作层。
- 把联赛从回合制改成时间驱动,引入并行决策和状态同步,这会触及更真实的多智能体工程问题。
- 引入“模型 vs 模型”评测矩阵,用同一个数据集对比不同模型在长周期任务中的决策能力。
- 给每个俱乐部经理加上记忆机制,让它能总结历史比赛并沉淀自己的“执教手册”。
最后提醒一点:这类项目很依赖 API 成本、延迟和模型能力。建议先用两到三个俱乐部、三到五轮的迷你赛季跑通闭环,再慢慢扩大规模。跑通以后,剩下的无非是给世界加细节、给模型加记忆、给系统加并发。