人的全部本领无非是耐心和时间的混合物。——巴尔扎克

MiroFish:一条“会做梦”的鱼,把未来放进数字沙盘里反复彩排

我第一次点开 @666ghj/MiroFish 的 README,感觉像推开了一扇有点科幻、但又非常务实的门。

它不先跟你讲大道理,而是开门见山地自我介绍:

简洁通用的群体智能引擎,预测万物
A Simple and Universal Swarm Intelligence Engine, Predicting Anything.

如果要我用拟人化的方式形容它:MiroFish 像一位“模拟导演”。你把现实里的一点点“种子信息”递给它——突发新闻、政策草案、金融信号,甚至是一份数据分析报告或一段小说——它就开始搭景、定人设、布置社会关系,最后把一整个“高保真平行世界”推到你面前,让你用上帝视角不断改变量、反复试演,直到你对“可能的未来走向”心里有数。


这条鱼到底在做什么?(项目概述,按 README 原意转述)

按中文 README 的描述,MiroFish 是基于多智能体技术的新一代 AI 预测引擎

  • 从现实世界提取“种子信息”(例如:突发新闻、政策草案、金融信号)
  • 自动构建一个高保真的平行数字世界
  • 在这个世界里,有成千上万个智能体:
    • 有独立人格
    • 有长期记忆
    • 有行为逻辑
    • 会自由交互与社会演化
  • 你可以以“上帝视角”动态注入变量,推演未来走向
    目标是:让未来在数字沙盘中预演,让决策在百战模拟后胜出

它还用一句很有“产品感”的话告诉你输入输出是什么:

  • 你只需:上传种子材料(数据分析报告或者有趣的小说故事),用自然语言描述预测需求
  • 它将返回:一份详尽的预测报告 + 一个可深度交互的高保真数字世界

这段描述让我特别在意两个关键词:“高保真”“可深度交互”。很多项目会停在“生成报告”,但 MiroFish 明确说它会给你一个“世界”,而不是一张“结论纸”。


它的愿景:既想服务宏观决策,也想照顾微观好奇心

README 里把愿景拆成了两层,很清晰:

  • 宏观层面:做决策者的预演实验室,让政策与公关可以零风险试错
  • 微观层面:做个人用户的创意沙盘——不管是推演小说结局还是探索脑洞,都要“有趣、好玩、触手可及”

我很喜欢它最后那句话的情绪:

从严肃预测到趣味仿真,我们让每一个如果都能看见结果,让预测万物成为可能。

这句话像是它给自己定的“性格底色”:认真,但不无聊。


你可以先不安装:它准备了在线 Demo、截图和视频

如果你想“先看再说”,README 给了一个在线体验入口:

  • 在线 Demo:https://666ghj.github.io/mirofish-demo/

另外还有系统截图(README 里直接用表格展示了多张运行截图),以及两组演示视频:

  1. 武汉大学舆情推演预测 + 项目讲解(B 站链接在 README)
  2. 《红楼梦》失传结局推演预测(B 站链接在 README)

它甚至还说:金融方向、时政要闻等示例会陆续更新中——这种“持续迭代”的语气很真实:不像 PPT,更像一个正在长大的系统。


工作流程:从“图谱”开始,到“模拟 + 报告 + 对话”结束

README 把整体流程列成了 5 步(我按原顺序复述):

  1. 图谱构建:现实种子提取 & 个体与群体记忆注入 & GraphRAG 构建
  2. 环境搭建:实体关系抽取 & 人设生成 & 环境配置 Agent 注入仿真参数
  3. 开始模拟:双平台并行模拟 & 自动解析预��需求 & 动态更新时序记忆
  4. 报告生成:ReportAgent 拥有丰富工具集,可与模拟后环境深度交互
  5. 深度互动:可与模拟世界中的任意一位对话,也可与 ReportAgent 对话

如果把它拟人化一点:
它先“认识这个世界的角色和关系”,再“让角色们自己活起来”,最后“找一个会写报告的记者把故��讲明白”,并且你还能“走进故事里跟人物聊天”。


快速开始:源码部署(推荐)与 Docker 部署

这部分 README 写得很“工程化”,我照着它的结构走一遍,让你可以直接按步骤开跑。

前置要求

工具 版本要求 说明
Node.js 18+ 前端运行环境(含 npm)
Python ≥3.11, ≤3.12 后端运行环境
uv 最新版 Python 包管理器

1)配置环境变量

1
2
cp .env.example .env
# 编辑 .env 文件,填入必要的 API 密钥

README 给出的必需环境变量(原文关键字段):

1
2
3
4
5
6
7
# LLM API配置(支持 OpenAI SDK 格式的任意 LLM API)
LLM_API_KEY=your_api_key
LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
LLM_MODEL_NAME=qwen-plus

# Zep Cloud 配置
ZEP_API_KEY=your_zep_api_key

这里的信息密度很高:它强调 LLM 接口是“OpenAI SDK 兼容格式”,也就是你可以接很多兼容 OpenAI API 形态的服务;并在示例里给了一个推荐方向(README 示例里写的是阿里百炼 qwen-plus 以及对应 base url)。

2)安装依赖

一键安装:

1
npm run setup:all

或者分步安装:

1
2
npm run setup        # 根目录 + 前端 Node 依赖
npm run setup:backend # 后端 Python 依赖(uv sync,会自动创建虚拟环境)

(这些脚本来自项目根目录的 package.json。)

3)启动服务

同时启动前后端:

1
npm run dev

服务地址(README 明确给出):

  • 前端:http://localhost:3000
  • 后端 API:http://localhost:5001

也可以单独启动:

1
2
npm run backend
npm run frontend

Docker 部署

1
2
cp .env.example .env
docker compose up -d

README 说明默认会读取根目录 .env,并映射端口 3000(前端)/5001(后端)


来点“贴着代码长出来的”案例:MiroFish 如何读取 .env、如何用 OpenAI SDK 兼容接口

你说希望“如果可以的话,上点代码案例”,我这里选两段仓库里真实存在的 Python 代码来讲(不编 API,不写不存在��类名),让文章更落地。

1)配置是怎么统一从根目录 .env 加载的?

后端配置类在 backend/app/config.py。它会优先加载项目根目录的 .env,找不到再尝试加载环境变量(用于生产环境)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"""
配置管理
统一从项目根目录的 .env 文件加载配置
"""

import os
from dotenv import load_dotenv

# 加载项目根目录的 .env 文件
# 路径: MiroFish/.env (相对于 backend/app/config.py)
project_root_env = os.path.join(os.path.dirname(__file__), '../../.env')

if os.path.exists(project_root_env):
load_dotenv(project_root_env, override=True)
else:
# 如果根目录没有 .env,尝试加载环境变量(用于生产环境)
load_dotenv(override=True)


class Config:
"""Flask配置类"""

# LLM配置(统一使用OpenAI格式)
LLM_API_KEY = os.environ.get('LLM_API_KEY')
LLM_BASE_URL = os.environ.get('LLM_BASE_URL', 'https://api.openai.com/v1')
LLM_MODEL_NAME = os.environ.get('LLM_MODEL_NAME', 'gpt-4o-mini')

# Zep配置
ZEP_API_KEY = os.environ.get('ZEP_API_KEY')

@classmethod
def validate(cls):
"""验证必要配置"""
errors = []
if not cls.LLM_API_KEY:
errors.append("LLM_API_KEY 未配置")
if not cls.ZEP_API_KEY:
errors.append("ZEP_API_KEY 未配置")
return errors

这段代码传递出来的“工程直觉”是:
MiroFish 把运行时依赖(LLM、Zep)的开关,尽量收敛到一处(.env),并且强制校验。
它像是在对你说:“别怕复杂,先把钥匙配齐,我再带你进场。”


2)LLM 客户端是怎么封装的?(OpenAI SDK 兼容调用)

backend/app/utils/llm_client.py,它用 openai 包里的 OpenAI 客户端,并允许传入 base_url,这正好对应 README 里“OpenAI SDK 格式兼容任意 LLM API”的说法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""
LLM客户端封装
统一使用OpenAI格式调用
"""

import json
import re
from typing import Optional, Dict, Any, List
from openai import OpenAI

from ..config import Config


class LLMClient:
"""LLM客户端"""

def __init__(
self,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
model: Optional[str] = None
):
self.api_key = api_key or Config.LLM_API_KEY
self.base_url = base_url or Config.LLM_BASE_URL
self.model = model or Config.LLM_MODEL_NAME

if not self.api_key:
raise ValueError("LLM_API_KEY 未配置")

self.client = OpenAI(
api_key=self.api_key,
base_url=self.base_url
)

def chat(
self,
messages: List[Dict[str, str]],
temperature: float = 0.7,
max_tokens: int = 4096,
response_format: Optional[Dict] = None
) -> str:
...
response = self.client.chat.completions.create(**kwargs)
content = response.choices[0].message.content
# 部分模型会在content中包含<think>思考内容,需要移除
content = re.sub(r'<think>[\s\S]*?</think>', '', content).strip()
return content

我特别注意到它还做了一个小处理:如果某些模型会输出 <think>...</think> 这种思考内容,它会用正则清理掉。
这像是它在悄悄替你挡坑:“你要的是结果,我把碎碎念收起来。”


一句话讲清楚:MiroFish 适合谁?

根据它的 README、topics 和代码结构,我会把它描述为:

  • 你想做舆情推演/社会模拟/多智能体社会演化一类的“未来排练”
  • 你希望输入可以是现实材料(新闻、政策、金融信号、报告、文本故事)
  • 你希望输出不止是“预测结论”,而是一个能互动的模拟世界 + 报告

那么 MiroFish 会很对味。它不是一把“只会生成文本”的刀,更像一个“能搭舞台、能排戏、还能写复盘”的系统。


项目信息(来自仓库 metadata)

  • 仓库:666ghj/MiroFish
  • 描述:A Simple and Universal Swarm Intelligence Engine, Predicting Anything. 简洁通用的群体智能引擎,预测万物
  • 主要语言:Python
  • License:GNU AGPL v3.0
  • Homepage / Demo:https://666ghj.github.io/mirofish-demo/

继续阅读(你可以顺着这些入口走)

  • README(中文):仓库根目录 README.md
  • README(英文):仓库根目录 README-EN.md
  • 后端配置与 LLM 封装:
    • backend/app/config.py
    • backend/app/utils/llm_client.py