Documentation Index
Fetch the complete documentation index at: https://docs.mirobody.ai/llms.txt
Use this file to discover all available pages before exploring further.
Mirobody 是一套分层、可插拔的引擎。每一层都可以独立替换或扩展 —— 没有单体,没有隐藏耦合。
AI 与 Agent 引擎
| 模块 | 路径 | 说明 |
|---|
| Chat 服务 | mirobody/chat/ | 会话管理、对话历史、HTTP + WebSocket 流式适配器、记忆集成、会话分享 |
| Agent 实现 | mirobody/pub/agents/ | DeepAgent(基于 LangChain)、MixAgent(两阶段融合)、BaselineAgent(直连 LLM) |
| LLM 客户端 | mirobody/utils/llm/ | 适配 OpenAI、Gemini、Anthropic、Azure OpenAI、火山引擎、阿里 Dashscope;含 HIPAA 合规路由 |
| MCP 服务器 | mirobody/mcp/ | JSON-RPC 2.0,本地 + HTTP 远程端点,自动发现工具与资源 |
| Tools | mirobody/pub/tools/、tools/ | 内置工具(文件操作、图表、execute)+ 你拖入的 Python 文件 |
| Skills | skills/ | Claude Agent Skills(SKILL.md + metadata.json),启动时自动发现 |
| Embeddings | mirobody/utils/embedding.py | 1024 维、提供商无关(Gemini / Qwen),pgvector 语义检索 |
| Prompt 模板 | prompts/ | Jinja2 系统 prompt,可动态注入上下文(用户时区、可用工具、健康 profile) |
三种 Agent,各司其职
| Agent | 阶段 | 适用场景 |
|---|
| DeepAgent | 单模型处理工具 + 回复 | 复杂多步研究、文件操作、规划 |
| MixAgent | 编排者模型(如 Claude Sonnet)→ 回复者模型(如 Gemini Flash) | 高吞吐场景,对推理要求高过文笔 |
| BaselineAgent | 直连 LLM,无工具 | 简单 Q&A、低延迟、测试 |
默认是 DeepAgent。切换方式与配置见 工具概览。
Tools 就是 tools/ 下的普通 Python 函数 —— 类型提示 + docstring 就是它唯一的”schema”。Mirobody 在启动时解析一次,然后通过 MCP 暴露出去。
# tools/my_tool.py
def get_my_metric(date: str, user_info: dict) -> dict:
"""
获取指定日期的自定义指标。
Args:
date: ISO 8601 日期字符串。
Returns:
包含指标值与单位的字典。
"""
user_id = user_info["user_id"] # 由 Mirobody 从 JWT 中自动注入
return {"value": 42, "unit": "steps"}
Skills 即 Claude Agent Skills —— 一个 SKILL.md(被激活时 Agent 读取的 playbook)加上一个 metadata.json(Mirobody 用于发现与 IDE 集成的元数据)。
skills/glucose-coach/
├── metadata.json # name、summary、when_to_use、when_not_to_use、tags
└── SKILL.md # YAML frontmatter(name、description、license)+ 正文
参见 添加工具 与 MCP 集成。
FHIR 与健康标准
| 模块 | 路径 | 说明 |
|---|
| FHIR 映射 | mirobody/pulse/core/fhir_mapping.py | 内存缓存 indicator → FHIR code,可选自动注册新代码 |
| 指标注册表 | mirobody/pulse/core/indicators_info.py | 400+ StandardIndicator 枚举,多源(Vital、Apple Health、Garmin、Whoop、Renpho ……) |
| 单位换算 | mirobody/pulse/core/units.py | 双向:kg ↔ lb、°C ↔ °F、mg·dL⁻¹ ↔ mmol·L⁻¹、mmHg ↔ kPa 等 |
| 指标搜索 | mirobody/indicator/ | 基于 Embedding 的自由文本 → 指标代码,跨 LOINC / SNOMED CT / RxNorm / CVX / DCM 的概念图扩展 |
| 概念图 | mirobody/indicator/concept_graph.py + fhir_concept_graph.bin | 跨术语桥与同体系兄弟节点;通过 Git LFS 拉取 |
两种检索模式
| 方法 | 范围 | 输入 | 返回 |
|---|
adapter.search(user_id, embeddings, top_k) | 单用户 | 预先算好的查询 Embedding | 这个用户 有什么与查询相符 |
adapter.resolve(term, top_k) | 全局 | 自由文本 | 这个术语映射到哪些规范代码 |
adapter.resolve_many(terms, top_k) | 全局批处理 | 自由文本列表 | 比循环 resolve() 快 ~20–30× |
search 会 join th_series_data 把范围限定到一个用户;resolve 对整个词表做余弦匹配,按每个代码体系(LOINC、SNOMED CT、RXNORM、CVX、DCM、THETA)各自取 top-k。
单位归一化
来自任何设备或图表、覆盖多语言(en、zh、ja、ko、ru、de、fr、es)的”数值 + 单位”自由文本,会被归一化到一个规范的 UCUM 单位 + 一个 LOINC PROPERTY 家族:
"90次每分钟" → ParsedQuantity(value=90.0, unit="/min", family="NRat")
"<5.6 mg/dL" → ParsedQuantity(value=5.6, unit="mg/dL", family="MCnc", comparator="<")
"Millimol pro Liter" → "mmol/L"
"600步" → ParsedQuantity(value=600.0, unit="{steps}", family="Num")
完全本地计算 —— 不依赖数据库,不调用 Embedding API。
健康数据管线 (Pulse)
| 模块 | 路径 | 说明 |
|---|
| Platform 管理器 | mirobody/pulse/ | Platform–Provider 插件架构,统一归一化到 StandardPulseData |
| Theta 平台 | mirobody/pulse/theta/ | 直接对接:Garmin、Whoop、Oura、Renpho、PostgreSQL 等 |
| Apple Health | mirobody/pulse/apple/ | Apple Health 导入、CDA(临床文档架构)处理 |
| 数据上行 | mirobody/pulse/data_upload/ | StandardPulseData → th_series_data 写入流水线 |
| 文件解析 | mirobody/pulse/file_parser/ | 多格式:PDF、CSV、Excel、音频、图像、基因;LLM 抽取指标 |
| 聚合 | mirobody/pulse/core/aggregate_indicator/ | 时间序列 → 日聚合;派生指标;睡眠窗口 18:00–18:00 |
| 健康 Insight | mirobody/pulse/core/insight/ | AI 趋势识别、异常分析、模式 recipe(多信号、恢复、血糖) |
Provider 生命周期
无论是内置 Provider(mirobody/pulse/theta/mirobody_garmin/)还是自定义 Provider(providers/mirobody_mydevice/),都实现同一份 BaseThetaProvider 契约 —— 参见 Provider 集成。
基础设施
| 模块 | 路径 | 说明 |
|---|
| 配置 | mirobody/utils/config/ | 分层 YAML + 环境变量;含 _KEY / _SECRET / _TOKEN 等字段的 Fernet 自动加密 |
| 存储后端 | mirobody/utils/config/storage/ | 可插拔:本地文件系统、AWS S3、阿里云 OSS |
| 认证与用户 | mirobody/user/ | JWT、OAuth 2.0(Google / Apple)、WebAuthn / FIDO2、邮箱验证 |
| 服务端 | mirobody/server/ | Starlette ASGI、JWT 中间件、限流 |
| 数据库 | mirobody/utils/db.py | 异步 PostgreSQL(psycopg)+ pgvector,Redis 缓存 / 会话存储 |
| 沙箱 | E2B(外部) | execute 工具在隔离的云沙箱内跑 shell + Python |
配置层级
config.yaml ← 基础配置,不要修改
└── config.{env}.yaml ← 你的覆盖;ENV=localdb → config.localdb.yaml
└── 环境变量 ← 优先级最高,通过 .env 或 shell 注入
敏感字段(键名包含 _KEY、_PASSWORD、_PASS、_PWD、_SECRET、_SK、_TOKEN)在首次加载时使用你的 CONFIG_ENCRYPTION_KEY 自动加密。详见 配置。
扩展点
把文件丢进去,下次启动自动生效:
| 目录 | 被识别为 | 命名约定 |
|---|
tools/ | MCP 工具 | .py 结尾;顶层函数或 *Service 类;_*.py 文件被忽略 |
skills/ | Claude Agent Skills | 每个 skill 一个子目录,含 SKILL.md + metadata.json |
agents/ | 对话 Agent | *Agent 类;需要 async generate_response |
providers/ | 数据 Provider | mirobody_<slug>/provider_<slug>.py,继承 BaseThetaProvider |
prompts/ | Prompt 模板 | Jinja2 .jinja 文件,被 PROMPTS_<AGENT> 引用 |
resources/ | MCP 资源 | HTML、JSON 或其他静态文件,通过 MCP 暴露 |
同名时,自定义目录优先于内置。
端到端请求流程
用户在 Web UI 里发 “Show me my knee pain trend” 之后会发生什么:
1. 浏览器 POST 到 /api/chat(SSE)。
2. JWT 中间件 → user_id。
3. Chat 服务建立或复用 session,把用户消息持久化到 th_messages。
4. DeepAgent(默认)按用户的 PROVIDERS_DEEP 配置加载。
5. Agent 调用 MCP tools/list 规划,然后顺序调用工具:
- get_user_profile → user_id、时区、可用 provider
- 指标搜索 → "knee pain" → SNOMED CT / LOINC 候选
- get_health_data → 按 user_id + 指标 join 时间序列
- chart_service → 渲染 PNG、上传 S3、返回 presigned URL
6. Agent 通过 SSE 流式输出 thinking / reply chunk;响应持久化。
7. 聚合 + Insight 在后台运行,为下一次会话准备好。
会话分享(无需登录的只读路径)见 会话分享。
下一步去哪
Tools 与 MCP
构建工具并跨 MCP 生态暴露