欢迎使用 FlowZap,快速、清晰、掌控的绘图应用。

MiroFish:构建你自己的合成焦点小组

2026/4/12

Tags: MiroFish, 合成焦点小组, 多智能体系统, AI 智能体, 仿真, LLM 架构

Jules Kovac

Jules Kovac

Business Analyst, Founder

MiroFish:构建你自己的合成焦点小组

如果你可以在凌晨 2 点启动一场焦点小组讨论,让 50 个“很有主见”的 AI 智能体围绕你提供的任意文档展开辩论,并且在第二天早晨喝咖啡之前就得到一份按优先级排序的异议清单,会怎样?

这正是 MiroFish 的核心想法。它是一个开源多智能体仿真引擎,会生成具备不同 persona 的 LLM 智能体,给它们一份“种子文档”作为反应对象,然后让它们在一个模拟社交平台上进行多轮互动。最终得到的不是预测,而是一种合成公众意见仿真。把它理解为数字民族志,而不是预测工具。

在你兴奋之前,有几件事必须先说明白:

  • 许可证是 AGPL v3.0,不是 MIT。 如果你把它嵌入到封闭式商业 SaaS 中,你就必须开源你的修改版本。若是内部工具、研究用途或咨询工作流,通常没有问题。
  • 它是场景模拟器,不是神谕。 它不会告诉你下个季度的流失率,但它会告诉你哪些 persona 类型最反感你的定价页面。
  • Token 成本并不低。 50 个智能体 × 20 轮 = 大量 LLM 调用。建议先用 Ollama 本地跑,或者用像 DeepInfra 这样较便宜的接口(约 0.20 美元 / 100 万 tokens)。

安装方面,README 已经写得很完整:github.com/666ghj/MiroFish。你需要 Node.js 18+、Python 3.11–3.12、uv 和一个 LLM API Key。如果你不想手动折腾环境,也可以直接使用 Docker Compose。

 

 

它实际上是如何工作的(系统架构)

当你点击 Launch 时,底层会发生什么?这里有三个参与者:你的浏览器、MiroFish 技术栈(运行在 :3000 的 React 前端和运行在 :5001 的 Python/OASIS 后端),以及你接入的 LLM API。

browser { # 你的浏览器
n1: circle label="Start"
n2: rectangle label="粘贴种子文档\n并配置智能体"
n3: rectangle label="Launch"
n10: rectangle label="查看讨论日志\n与洞察"
n11: circle label="Done"
n1.handle(right) -> n2.handle(left)
n2.handle(right) -> n3.handle(left)
n3.handle(bottom) -> mirofish.n4.handle(top) [label="POST /simulation/start"]
n10.handle(right) -> n11.handle(left)
}

mirofish { # MiroFish 技术栈 (:3000 / :5001)
n4: rectangle label="生成 N 个带 persona\n的智能体"
n5: rectangle label="把种子文档\n分发给每个智能体"
n6: rectangle label="编排互动轮次"
n9: rectangle label="汇总日志并\n准备结果"
n4.handle(right) -> n5.handle(left)
n5.handle(right) -> n6.handle(left)
n6.handle(bottom) -> llm.n7.handle(top) [label="并行智能体\nprompts"]
n9.handle(top) -> browser.n10.handle(bottom) [label="结果 JSON"]
}

llm { # LLM API (OpenAI / Ollama / DeepInfra)
n7: rectangle label="为每个智能体\n执行推理"
n8: rectangle label="返回智能体响应"
n7.handle(right) -> n8.handle(left)
loop [每轮] n7 n8
n8.handle(top) -> mirofish.n9.handle(bottom) [label="智能体输出"]
}

注意 LLM 这一条 lane:它是按每个智能体、每一轮、并行调用的。若你设置 50 个智能体、10 轮互动,那一次仿真就是 500 次 LLM 调用。现在你就能明白,为什么 token 成本是真正需要被认真管理的问题。

 

 

场景 1:上线前文案验证

你的 landing page 写好了。你觉得它不错。MiroFish 让你可以先用 50 个合成版 ICP 去“折磨测试”这份文案,再决定是否花钱投广告。

这里同样有三个参与者:你自己、负责管理仿真的 MiroFish 引擎,以及真正去阅读、争论、更新观点的智能体群体。

builder { # Builder
n1: circle label="Start"
n2: rectangle label="撰写文案草稿\n+ 定义 personas"
n3: rectangle label="提交到\nMiroFish"
n12: rectangle label="阅读异议\n报告"
n13: circle label="迭代优化"
n1.handle(right) -> n2.handle(left)
n2.handle(right) -> n3.handle(left)
n3.handle(bottom) -> engine.n4.handle(top) [label="POST /simulation/start"]
n12.handle(right) -> n13.handle(left)
}

engine { # MiroFish 引擎
n4: rectangle label="初始化仿真\n并生成智能体"
n5: rectangle label="分发种子文档\n+ persona 配置"
n10: rectangle label="收集并排序\n主要异议"
n11: rectangle label="生成报告"
n4.handle(right) -> n5.handle(left)
n5.handle(bottom) -> agents.n6.handle(top) [label="种子文档 + persona"]
n10.handle(right) -> n11.handle(left)
n11.handle(top) -> builder.n12.handle(bottom) [label="Top 3 异议"]
}

agents { # 智能体群体(50 个 LLM 智能体)
n6: rectangle label="阅读文案\n并形成观点"
n7: rectangle label="发布到模拟\n社交平台"
n8: rectangle label="阅读其他智能体\n的反应"
n9: rectangle label="更新记忆\n与立场"
n6.handle(right) -> n7.handle(left)
n7.handle(right) -> n8.handle(left)
n8.handle(right) -> n9.handle(left)
loop [10 轮] n6 n7 n8 n9
n9.handle(top) -> engine.n10.handle(bottom) [label="每轮输出"]
}

智能体循环是整个系统的核心:智能体发布意见、阅读彼此的反应,并在每一轮之后更新自己的立场。到了第 10 轮,主导性的观点簇会逐渐形成。引擎再对这些观点进行排序,并把最值得你关注的异议返回给你。

一个 B2B SaaS 产品的 persona 配置示例:

{
  "seed_document": "你的 landing page 文案...",
  "agent_count": 50,
  "personas": [
    { "type": "skeptical_cto", "weight": 0.2 },
    { "type": "budget_conscious_pm", "weight": 0.3 },
    { "type": "early_adopter", "weight": 0.2 },
    { "type": "enterprise_buyer", "weight": 0.3 }
  ],
  "max_rounds": 10
}

如何后处理输出: 原始输出通常是一份 JSON 讨论日志。你可以再交给另一个 LLM,用类似这样的提示词进行总结:请从这份讨论日志中提炼出最常见的 3 个定价异议、最受赞赏的功能,以及最常被要求补充的能力。

 

 

场景 2:仿真中途注入危机变量

这才是 MiroFish 真正有意思的地方。你可以在仿真运行到任意一轮时暂停它,注入一个新变量——新闻事件、竞争对手公告、政策变化——然后观察智能体如何基于新的背景重新评估它们此前相信的一切。

下面这个流程展示了完整的三方链路:你触发注入,引擎广播事件,智能体把新的上下文写入记忆后重新展开辩论。

builder { # Builder
n1: circle label="Start"
n2: rectangle label="定义基线场景\n+ 种子文档"
n3: rectangle label="启动基线仿真"
n9: rectangle label="注入危机事件"
n15: rectangle label="比较变化:\n前 vs 后"
n16: circle label="End"
n1.handle(right) -> n2.handle(left)
n2.handle(right) -> n3.handle(left)
n3.handle(bottom) -> engine.n4.handle(top) [label="POST /simulation/start"]
n9.handle(bottom) -> engine.n10.handle(top) [label="POST /simulation/{id}/inject"]
n15.handle(right) -> n16.handle(left)
}

engine { # MiroFish 引擎
n4: rectangle label="初始化基线仿真"
n5: rectangle label="调度智能体执行\n第 1–5 轮"
n8: rectangle label="基线已捕获\n— 通知 builder"
n10: rectangle label="接收危机变量"
n11: rectangle label="向智能体广播\n该事件"
n14: rectangle label="汇总危机后的\n日志"
n4.handle(right) -> n5.handle(left)
n5.handle(bottom) -> agents.n6.handle(top) [label="运行 5 轮"]
n8.handle(top) -> builder.n9.handle(bottom) [label="基线准备完成——现在注入"]
n10.handle(right) -> n11.handle(left)
n11.handle(bottom) -> agents.n12.handle(top) [label="注入:危机上下文"]
n14.handle(top) -> builder.n15.handle(bottom) [label="危机后讨论日志"]
}

agents { # 智能体群体
n6: rectangle label="运行基线\n第 1–5 轮"
n7: rectangle label="基线完成"
n12: rectangle label="吸收危机上下文"
n13: rectangle label="带着新信息\n重新辩论"
n6.handle(right) -> n7.handle(left)
n7.handle(top) -> engine.n8.handle(bottom) [label="基线输出"]
n12.handle(right) -> n13.handle(left)
n13.handle(top) -> engine.n14.handle(bottom) [label="危机后输出"]
}

危机注入 payload 示例:

{
  "event_type": "market_event",
  "content": "突发:一家主要竞争对手刚刚推出了一个完全免费的替代方案,并且功能覆盖率达到 80%。",
  "inject_at_round": 5
}

通过比较注入前后的情绪变化,你可以看出哪些 persona 类型最脆弱,以及脆弱到什么程度。这就是你的竞争风险地图。

 

 

场景 3:A/B 提案测试

两个会员机制。两次仿真。一个赢家。无需等待 4 周真实 A/B 测试结果。

pm { # Product Manager
n1: circle label="Start"
n2: rectangle label="定义变体 A\n和变体 B"
n3: rectangle label="提交变体 A\n进行仿真"
n7: rectangle label="提交变体 B\n进行仿真"
n11: rectangle label="比较结果:\n选出赢家"
n12: circle label="Ship it"
n1.handle(right) -> n2.handle(left)
n2.handle(right) -> n3.handle(left)
n3.handle(bottom) -> mirofish.n4.handle(top) [label="POST /simulation/start (A)"]
n7.handle(bottom) -> mirofish.n8.handle(top) [label="POST /simulation/start (B)"]
n11.handle(right) -> n12.handle(left)
}

mirofish { # MiroFish 引擎
n4: rectangle label="仿真变体 A:\n50 个智能体响应"
n5: rectangle label="智能体评估\n感知价值"
n6: rectangle label="汇总:\n变体 A 得分"
n8: rectangle label="仿真变体 B:\n50 个智能体响应"
n9: rectangle label="智能体评估\n感知价值"
n10: rectangle label="汇总:\n变体 B 得分"
n4.handle(right) -> n5.handle(left)
n5.handle(right) -> n6.handle(left)
n6.handle(top) -> pm.n7.handle(bottom) [label="变体 A:情绪 + 意图"]
n8.handle(right) -> n9.handle(left)
n9.handle(right) -> n10.handle(left)
n10.handle(top) -> pm.n11.handle(bottom) [label="变体 B:情绪 + 意图"]
}

在这两次运行中,你主要对比的是:激活意图分数、感知价值评分,以及流失风险信号。如果变体 A 在激活意图上更高,而变体 B 在感知价值上更强,那么你面对的是一个细分决策问题,而不是掷硬币。

 

 

在真正投入使用之前

检查项 为什么重要
Seed 质量 越密集、越具体的输入文案,智能体输出越有价值。模糊的 seed 只会得到模糊的结果。
Persona 权重 尽量贴近真实用户分布,否则模拟结果会偏离现实。
从小规模开始 先跑 5–10 轮,确认输出逻辑通顺之后再扩大规模。
模型选择 开发阶段可以用本地 7B 或 GPT-4o-mini。最终验证再切换到更强模型。
后处理 一定要把日志交给另一个 LLM 做聚合总结。原始 JSON 本身不是洞察。
先跑中性基线 先用中性 seed 建立情绪基准线,再做对比更有意义。
AGPL 内部工具通常没问题;如果你把它包装成 SaaS,就需要开源相关代码。

 

 

如何把这些流程图可视化

把上面的任意一个 FlowZap Code 代码块,或把它保存成 .fz 文件,然后导入到 你的 FlowZap 项目 中,就可以把它渲染成可分享给团队的可视化图表。

别再手动拖拽箭头了。用 FlowZap 设计系统。

 

 

参考链接

返回所有博客文章