跳转到主要内容

概览

Mirobody 能摄取健康文档 —— 检验报告、电子表格、扫描记录 —— 并把它们转成一次聊天回合可以携带的内容。这项工作由 src/transcode/ 中的文档转码器document.hpp / document.cpp)完成,它是图像转码器在文档侧的对应物。其策略是文本优先,图像(及 OCR)兜底
转码器把文档拆解为文本与图像片段;具备视觉能力的 LLM 在对话轮次中读取它们。

支持的格式

容器格式由起始的 magic bytes 嗅探得出,再路由到对应的处理器:
格式构建开关输出
PDFPDFiumMIROBODY_ENABLE_PDF(默认关闭逐页文本;扫描页 → 图像(+ OCR)
.xlsxxlnt找到 xlnt 时开启(Windows 上经 vcpkg 始终开启)每个工作表一张 Markdown 表格
.xls(旧版 BIFF)内置的 libxlsMIROBODY_ENABLE_XLS(默认关闭每个工作表一张 Markdown 表格
.csv内建(RFC 4180)始终可用单张 Markdown 表格
当某开关关闭时,输入仍会被嗅探,但 process() 会抛出 DocumentError("... not built") —— 不会有任何内容被悄悄错误处理。
单独上传的图像由姊妹图像转码器src/transcode/image.hpp)处理,它会把图像适配到目标视觉模型的输入上限。旧文档中的音频与基因文件处理不属于这个 C++ 转码器。(verify)

流水线

1

嗅探格式

detect_format() 读取 magic bytes:%PDF- → PDF,PK\x03\x04 → xlsx(任意 OOXML zip),OLE2 签名 → 旧版 .xls,其余非空内容 → CSV。
2

PDF —— 文本层优先

对每一页,先把内嵌的文本层提取为一个文本片段。若某页可提取的文本低于一个很小的阈值(即扫描页),则改按图像处理。
3

扫描页 —— 栅格化 → 符合视觉模型要求的图像

扫描页会被栅格化(默认 150 dpi),重新打包为 PNG,并经 image::Transcoder 处理,使其满足目标视觉模型的上限(默认 Qwen-VL;也提供 Gemini / GPT 的上限)。它会作为一个图像片段发出,由聊天回合内联给视觉模型。
4

OCR(可选)

MIROBODY_ENABLE_OCR 构建中(还额外要求 MIROBODY_ENABLE_PDF),同一张栅格图还会经过 Tesseract,并把识别出的文本追加为一个文本片段 —— 于是一张扫描页会同时产出图像及其 OCR 文本。OCR 语言默认为 eng(混排文档可用 eng+chi_sim)。
5

电子表格 —— 始终为文本

每个工作表(xlsx / xls)或整个 CSV 都会渲染为一张 GitHub 风格的 Markdown 表格;电子表格处理绝不产生图像片段。
结果是一个 Document:一个有序的 Part 列表,每个片段要么是 Text(UTF-8 / Markdown),要么是 Image(一张已符合视觉模型要求的图像),并标注其从 1 起算的来源页 / 工作表。max_pages 上限可为超大文档设界;触发时会追加一条尾注,从而不会有内容被悄悄丢弃。Transcoder::to_markdown() 会把整份文档渲染为单个 Markdown 块,供想要单一字符串的调用方(以及 CLI)使用。

单位归一化到 UCUM

从文档与图表中提取的数值,由 src/fhir/units/ 中的术语引擎归一化:一段自由文本的”数值 + 单位”字符串会变成一个规范的 UCUM 单位,外加用于消歧的 LOINC PROPERTY 族。这是纯本地计算 —— 无数据库、无 embedding API。
"MG/DL"              → "mg/dL"
"毫摩尔每升"          → "mmol/L"
"mmHg"               → "mm[Hg]"
"<5.6 mg/dL"         → value 5.6, unit "mg/dL", comparator "<"
支持多语言输入(en、zh、ja、ko、ru、de、fr、es)。

数据的去向

转码后的片段在聊天回合中由 agent 读取:上传的文件按用户存储,agent 通过 list_filesread_file 这两个 MCP 工具列出 / 读取它们,并把文本片段和符合视觉模型要求的图像片段喂给 LLM。
要理解文档,至少需要一个 LLM key(或设备本地的 Gemma) —— 上传并存储文件无需 key 即可完成,但从 PDF / 图像中提取含义需要一个模型。纯文本格式(CSV / xlsx)渲染为 Markdown 无需模型。
把提取出的检验值作为带编码的 Observation 写回 FHIR 存储(文档 → 指标 → FHIR 流水线)尚在进行中:UCUM 单位归一化与 RESTful FHIR 存储已上线;术语解析(SNOMED CT / LOINC / RxNorm)与自动写回尚在计划中。(verify against src/fhir/README.md.)

测试

转码器由 Catch2 测试覆盖:tests/transcode/document_test.cpptests/transcode/image_test.cpp;单位引擎由 tests/fhir/units_test.cpp 覆盖。参见测试

下一步

数据流

上传如何与 vendor 及设备本地数据并存

文件处理实现

深入了解转码器 API 与构建开关

Vendor 系统

服务端到服务端的健康数据源

API 参考

兼容 OpenAI 的 /v1 接口