结论
- 现在的默认(1.5.4)是小号:MiniCPM5-2B(Q4_K_M,1.6 GB)回答问题,GLM-OCR-0.9B(1.4 GB)读文档,
合计 3.0 GB,跑在 llama.cpp 上,16 GB 内存、没有显卡就行。在现已发布的
benchmarks/local_models/评测上,它 24 道题过了 19 道(Claude Code 评分 248 分得 215),12 份文档的 140 个印刷行全部存对,31 条日记条目写出 22 条; 在 1.5.4 改 harness(见下)之前,24 道题过了 16 道,140 个印刷行存对 45 个,31 条日记条目一条也没写出来。 - 大号是 Qwen3.8-27B(GSQ-RCO IQ3_S,13 GB),实测见下:在我们的题目上答得和云端模型一样对,也能看照片, 但要约 20 GB 内存:32 GB 内存的 Mac,或 24 GB 显存的显卡。
- 1.6.0 交付目标:把这两个小模型针对 Mirobody 做后训练,作为 Mirobody 自己的模型发布(再训练), 合计约 3 GB,和今天的小号一样,16 GB 内存、没有显卡就能跑。是两个模型,不合并成一个。只有通过了和被替换的模型同样的评测,才替换默认。
- 看图:GLM-OCR 只读印刷的文字和表格,别的一概不会。看懂一张照片拍的是什么,比如一盘菜的热量、一块皮疹, 需要能看图的模型:大号,或云端模型。这对小模型做不到,Mirobody 会直说,而不是去猜。
- 和云端模型比:model-choice.zh-CN.md 把小号和五个云端模型(DeepSeek V4.1 Flash、Claude Sonnet 5.5、 Claude Opus 5.5、Gemini 3.8 Flash、GPT-6 Luna)放在同一套题目上比,也写了各自的费用和谁会读到数据。
实测了什么
Apple M4 Pro 48 GB,llama.cpp b11269,demo 数据。八道题各问两遍:三个月趋势图、最新值、 变化统计、用药、化验单、基因、别人共享给我的记录、常识题。一次运行算通过:调对工具、用对视图、 要图就画图、用提问的语言作答、并且答完。然后逐个核对回答里的每个数是否在库里有来处, 每个「偏高 / 正常」是否按报告上印的范围判断。
耗时只在同一台机器、同一时段内可比。产出这些数字的评测工具没有发布;取代它的评测是
benchmarks/local_models/:通过产品自己的 API 问 24 道题、读 12 份文档和 15 句日记,
云端参照和本地两种大小一起跑。
MiniCPM5-2B 细看
它快(大多 2–70 秒一答),结构也对,毛病很集中:- 2026-09-30 问「过去三个月」,它没传日期,拿到一整年真实的每日读数,回答的却是 2026 年 10 月到 12 月:92 个点和三个月均值,全都不存在。
- 有一道题(共享记录里的胆固醇)两次都没答出来(594 秒、375 秒)。
- 要它按 JSON 输出一个读数,它把数值写进了名字。
看图
GLM-OCR 官方只有四种提示:Text Recognition:、Table Recognition:、Formula Recognition:,
以及按 JSON 模板做信息抽取。四张图(显示 128/91、心率 76 的监护仪,中文营养成分表,FDA 样例标签,
一盘菜):
所以 Mirobody 只给 GLM-OCR 发它的文字和表格两种提示(
config.llm.yaml 里 local-ocr 条目),
从不发 JSON 模板,也从不问开放问题;128 和 91 是血压,由读这段文字的推理模型来判断。
从餐食照片估热量,即使模型能看图,也只能给个区间。
从 1.5.4 起,agent 会问模型服务它的模型能不能看图(llama.cpp 的 /props、Ollama 的 /api/show;
mirobody/utils/config/served.py)。不能看图的模型收到的是照片的 OCR 文字而不是图片,并被告知
这只是印刷文字;问题问的是图里的东西时,它要说自己看不到这张图。
计划
先改 harness
这些对所有模型都有用,云端的也一样,而且让小模型少出错的地方。1.5.4 做到了哪一步:- 算数交给工具。 均值、月均值、差值、趋势由工具算好返回,模型只负责转述。已具备:
view="stats"返回条数、 最小、最大、均值、第一条和最后一条读数及其日期、两者之差,view="month"返回月均值;1.5.4 让 stats 的日期 成为读数自己的本地日期,日、周、月视图也说明一天怎么计。还差的是模型去用它们:2026-10-06 的评测里,小号有两道题 (p002-rhr-monthly、p003-weight-change)是自己拿原始行算的平均。 - 日期交给工具。 「过去三个月」变成一个由服务端解析的参数,模型从不自己算日期。还没做。
- 图表引用工具的行。 图表的点直接取自工具结果,不再由模型一个个手写;那 92 个假点就是手写出来的。 还没做:点仍由模型写。1.5.4 只是让网页端把多了一个括号的图画出来,画不了就明说。
- 每个数显示前都要核对。 回答里的数如果在任何工具结果和文档里都找不到,就标出来并重新生成。
还没做:评测的
score.py事后数这样的数,产品本身不核对。 - 给小模型一个更短的提示词,按
benchmarks/local_agent/里那份提示词的量法来量。agent 的提示词还没做。 日记请求现在先给两个示范回答;两次评测之间,MiniCPM5-2B 的日记从 31 条写出 0 条变成最终版代码上的 22 条(第一轮改动之后是 24 条)。
- 表格按表头读、不用模型,不管配置的是什么模型;原生 PDF 的文字层、印刷页和 OCR 模型给出的表格都行;文本模型只拿到规则读剩的部分,并被告知那是一份医学报告的其余内容;
- 长报告逐页读,记录和日志带上每行自己的日期给出读数;印在两页上的同一个读数只存一次,页面的打印日期不再当作读数的日期;
- 循环输出的提取以文本长度为上限,并保留已完整的部分;
- 没指定指标就要某种视图时返回指标目录;分钟到月的视图只保留最新的 92 个点,不再撑爆上下文;
- 关键词不管单位和拼写都能找到读数(
FER、haemoglobin、复数); - 所有 JSON schema 都是封闭的,OpenAI 的模型也能读上传的文件和日记;
- 一个模型的两个槽共用一个 KV 池,一道题可以用满整个上下文。
再训练
这就是 1.6.0 要交付的,作为 Mirobody 自己的模型发布(model-choice.zh-CN.md)。 1.5.4 把 P0 做到了这里:上面的 harness 改动;评测发布在benchmarks/local_models/ 和
benchmarks/local_ocr/,MiniCPM5-2B 的基线已记下(2026-10-06),云端参照也一起跑了。
还没做的:200–500 道题,并分成训练、验证、测试三份。
已经具备的:
- 许可:MiniCPM5-2B 是 Apache-2.0,GLM-OCR 权重是 MIT,两家都给了官方微调路径 (MiniCPM:TRL + PEFT、LLaMA-Factory、ms-swift、unsloth;GLM-OCR:LLaMA-Factory 教程)。
- 老师模型:大号 27B 每次都通过,并按报告印的范围判断。
- 能算出来的奖励:回答里每个数在不在记录里,可以机械地核对,也能用来筛老师的运行。
- 零标注成本的数据:demo 生成器能造任意多的人和时间序列;从已知数值渲染出的报告,天生带标注。
暂不纳入
- 看懂照片。 MiniCPM5-2B 是纯文本模型,GLM-OCR 只读字。用这对小模型时,餐食照片得到的回答是 「请描述一下吃了什么」;看懂照片仍交给能看图的模型(大号 27B,或云端 key)。小的视觉模型另立项。
- 合并成一个模型。 两个任务要的数据和测试都不同,合并后出了回归也难定位。Mirobody 本来就把 agent 和文档分给不同的条目,两个模型直接插上即可。等两个都各自达标,再量一量一个小视觉模型同时做两件事值不值。
- 保持更新。 工具的格式一改就要再训练一次,所以评测每晚对训练出的模型跑一遍。