概览
Mirobody 能摄取健康文档 —— 检验报告、电子表格、扫描记录 —— 并把它们转成一次聊天回合可以携带的内容。这项工作由src/transcode/ 中的文档转码器(document.hpp / document.cpp)完成,它是图像转码器在文档侧的对应物。其策略是文本优先,图像(及 OCR)兜底。
转码器把文档拆解为文本与图像片段;具备视觉能力的 LLM 在对话轮次中读取它们。
支持的格式
容器格式由起始的 magic bytes 嗅探得出,再路由到对应的处理器:| 格式 | 库 | 构建开关 | 输出 |
|---|---|---|---|
| PDFium | MIROBODY_ENABLE_PDF(默认关闭) | 逐页文本;扫描页 → 图像(+ OCR) | |
| .xlsx | xlnt | 找到 xlnt 时开启(Windows 上经 vcpkg 始终开启) | 每个工作表一张 Markdown 表格 |
| .xls(旧版 BIFF) | 内置的 libxls | MIROBODY_ENABLE_XLS(默认关闭) | 每个工作表一张 Markdown 表格 |
| .csv | 内建(RFC 4180) | 始终可用 | 单张 Markdown 表格 |
process() 会抛出 DocumentError("... not built") —— 不会有任何内容被悄悄错误处理。
单独上传的图像由姊妹图像转码器(
src/transcode/image.hpp)处理,它会把图像适配到目标视觉模型的输入上限。旧文档中的音频与基因文件处理不属于这个 C++ 转码器。(verify)流水线
嗅探格式
detect_format() 读取 magic bytes:%PDF- → PDF,PK\x03\x04 → xlsx(任意 OOXML zip),OLE2 签名 → 旧版 .xls,其余非空内容 → CSV。扫描页 —— 栅格化 → 符合视觉模型要求的图像
扫描页会被栅格化(默认 150 dpi),重新打包为 PNG,并经
image::Transcoder 处理,使其满足目标视觉模型的上限(默认 Qwen-VL;也提供 Gemini / GPT 的上限)。它会作为一个图像片段发出,由聊天回合内联给视觉模型。OCR(可选)
在
MIROBODY_ENABLE_OCR 构建中(还额外要求 MIROBODY_ENABLE_PDF),同一张栅格图还会经过 Tesseract,并把识别出的文本追加为一个文本片段 —— 于是一张扫描页会同时产出图像及其 OCR 文本。OCR 语言默认为 eng(混排文档可用 eng+chi_sim)。Document:一个有序的 Part 列表,每个片段要么是 Text(UTF-8 / Markdown),要么是 Image(一张已符合视觉模型要求的图像),并标注其从 1 起算的来源页 / 工作表。max_pages 上限可为超大文档设界;触发时会追加一条尾注,从而不会有内容被悄悄丢弃。Transcoder::to_markdown() 会把整份文档渲染为单个 Markdown 块,供想要单一字符串的调用方(以及 CLI)使用。
单位归一化到 UCUM
从文档与图表中提取的数值,由src/fhir/units/ 中的术语引擎归一化:一段自由文本的”数值 + 单位”字符串会变成一个规范的 UCUM 单位,外加用于消歧的 LOINC PROPERTY 族。这是纯本地计算 —— 无数据库、无 embedding API。
数据的去向
转码后的片段在聊天回合中由 agent 读取:上传的文件按用户存储,agent 通过list_files 与 read_file 这两个 MCP 工具列出 / 读取它们,并把文本片段和符合视觉模型要求的图像片段喂给 LLM。
把提取出的检验值作为带编码的
Observation 写回 FHIR 存储(文档 → 指标 → FHIR 流水线)尚在进行中:UCUM 单位归一化与 RESTful FHIR 存储已上线;术语解析(SNOMED CT / LOINC / RxNorm)与自动写回尚在计划中。(verify against src/fhir/README.md.)测试
转码器由 Catch2 测试覆盖:tests/transcode/document_test.cpp 与 tests/transcode/image_test.cpp;单位引擎由 tests/fhir/units_test.cpp 覆盖。参见测试。
下一步
数据流
上传如何与 vendor 及设备本地数据并存
文件处理实现
深入了解转码器 API 与构建开关
Vendor 系统
服务端到服务端的健康数据源
API 参考
兼容 OpenAI 的
/v1 接口