说实话,第一次看到“LLM实时解析饮食日记,糖尿病管理更精准”这个项目标题时,我的第一反应不是技术兴奋,而是长出一口气——终于有人开始认真解决“饮食记录”这个糖尿病管理里最让人头疼的环节了。
我做慢病健康管理相关系统已经有些年头,接触过大量糖尿病患者和内分泌科医生。大家其实心里都清楚一件事:糖尿病管理,七分靠吃,三分靠药。但“吃”这件事,恰恰是最难量化的。传统方式下,患者靠手写日记或者用普通健康App记录,要么记不全,要么记不准,更别提把每餐的碳水、升糖指数、营养结构算明白。医生拿到记录也是一头雾水,只能凭经验给个大概的建议。
我实际落地过一个饮食解析项目,就是用LLM去实时处理患者的饮食日记,把一句话、一张照片、甚至一段语音,转成结构化营养数据,再结合血糖动态数据做精准干预。这篇文章就围绕这个项目,把从方案选型、系统设计、提示词工程、实测踩坑,到和血糖监测系统打通的完整链路,原原本本讲清楚。适合正在做慢病数字化产品、健康管理类App、或者对LLM落地医疗场景感兴趣的开发者来参考。
1. 方案整体设计:为什么选择LLM来做这件事
项目启动之前其实调研过一条“传统路径”——规则引擎加公开食物成分数据库。听起来很成熟,但真往细了做发现完全不够用。
1.1 传统规则词表的痛点:中餐的“歧义地狱”
最开始我尝试维护一份高频食物词表,收录“米饭”“面条”“馒头”这种常见项,再用关键词匹配去解析日记。理论上可行,但很快暴露出几个硬伤。
第一是口语化输入几乎无解。患者不会按营养学的口径记录,他写“今天中午吃了碗兰州拉面,加了个蛋,还来了几口小菜”。这里面“几口”是多少?“小菜”是什么菜?你让规则引擎去猜,猜出来的结果完全不可信。
第二是中餐的命名歧义大。同一个“饼”,可以是“葱油饼”“煎饼”“月饼”“发面饼”,升糖指数和碳水含量天差地别。同一样菜品,不同家庭做法不一样,油盐糖用量根本不是一个量级。硬编码的规则词表覆盖面再广,也永远追不上真实饮食输入的无序和碎片化。
第三涉及存量数据利用。项目中有一部分试点患者之前用传统App记过一段时间日记,那些日记如果不能被解析利用,等于几千条宝贵的行为数据全部作废。规则引擎面对这些“脏数据”,基本是束手无策。
1.2 LLM介入后解决的核心问题
换成LLM路径后,上面几个痛点有了比较干净的解法。
LLM的语义理解和上下文建模能力,能理解“几口”“来点”“加个蛋”这类模糊表达,还能结合整段语境推断份量区间。它本身具备大量的营养学先验知识,可以反推出“兰州拉面+蛋”的碳水估计值。更重要的是,LLM支持自由对话追问——“你说的这碗面,大概是多少?大碗还是小碗?”——这正好契合了实时交互的产品预期。
实际项目里我们把LLM定位成一个“营养信息抽取器”,而不是“营养计算器”。计算的部分仍然交给结构化数据和经过验证的计算公式来保证精度,LLM负责把非结构化的自由文本,稳定地映射到结构化的营养变量上。分工清楚之后,整个系统的可靠性就有了保障。
2. 整体系统架构与LLM选型
架构设计上,项目走的是“端—云—服务”三层分工。移动端负责采集日记图文信息,云端负责大模型推理与营养计算,服务端再把解析结果推给医生工作站和患者的血糖管理模块。
2.1 端侧采集层的特殊设计
端侧采集是整个流程的第一步,直接影响后续解析质量。围绕实时性,我把采集分成两个通道。
第一是文本输入通道。患者直接输入一句话,比如“早餐吃了两个香菇青菜包,还有一杯无糖豆浆”,后端拿到的是一条短文本。为了提升后续解析准确率,我在端侧做了一层轻量化预处理,包括纠正常见错别字、识别食物量词、标记模糊词汇(“一些”“一点点”“几块”)。
第二是拍照识别通道。这个更有挑战性,也更有实际价值。患者拍一张饭菜照片,端侧先做基础的食物区域检测,再用多模态模型把照片内容描述成结构化文本,例如“图片中有一个白色餐盘,包含一个拳头大小的米饭、约三块红烧肉、少量炒青菜”。这层描述再喂给后续的编排层做Nutrition Data Extraction。
之所以这么设计,是因为我们碰过试错:如果不做前置描述,直接把图片丢给主调度模型等场景识别,会出现幻觉问题和细节丢失,比如漏掉饮料、忽略蘸料这些对血糖有影响的“隐形碳水”。
2.2 模型选型与回退机制
很多团队关心模型选型,我的建议是“别神化模型,也别轻视工程”。
项目初期做过一轮主模型对比,覆盖了通用语义理解能力、结构化输出稳定性、上下文记忆能力、延迟表现几个维度。最终主调度选择了一个综合性价比合适的模型,但没有把鸡蛋全放在一个篮子里。系统设计了双模型回退机制:当主模型解析结果置信度低于阈值时,自动切换到备选模型重试,两边结构差异比较大时再转人工审核。实测下来,双模型回退能把单模型偶发抽风导致解析失败的比例控制在千分之三以下。
提示:在医疗相关场景里,必须设计兜底方案。模型输出的解析结果,要能落到明确兜底规则上(例如解析置信度低时拒绝返回营养数据,并提示患者重新描述),绝对不能“带病输出”。
2.3 从自由文本到结构化营养变量的数据流
系统的核心数据流是一条四段式流水线:
文本/图片描述进入输入通道后,第一站是“分句分段规整”,把一天多餐的记录切分成多个单独的食物事件。比如一段日记写了“早上一杯酸奶,两个鸡蛋,中午吃了黄焖鸡米饭”,就切出两个事件。
第二站进入LLM抽取模块,针对每个食物事件提取“食材名称、份量描述(大小、数量、容器)、烹饪方式、添加糖或油情况、进餐时间”五个字段,并输出JSON结构。提示词层面固定要求输出Schema,同时要求每个字段附带置信度和理由。
第三站是营养计算器。系统基于解析出的食材和份量,在食物成分表里查值计算碳水、蛋白质、脂肪、总热量、膳食纤维和估算升糖负荷。这一站的计算逻辑完全程序化,不依赖模型。为什么这么设计?因为营养计算必须精确且可复现,模型搞计算的确定性和准确性都不够用,让模型负责抽取,让代码负责算术,是我们项目中最重要的架构决策。
第四站根据血糖数据做关联标注。拿到当次进食时间点后,调取动态血糖仪(CGM)的对应时间窗口数据,标注出餐前血糖、进餐后0.5小时、1小时、2小时的血糖变化曲线。这样每天生成的不再是零散的“患者吃了什么”,而是一张“饮食事件 × 血糖响应”的完整关联表。
3. 核心环节实现与实操细节:提示词、校准与结构化输出
这一部分聊聊最关键的工程实现细节,也是整个项目最花费精力的地方。
3.1 完整提示词框架:从“问什么”到“怎么答”
很多同行提示词写得随意,导致解析结果飘忽不定。我这边把饮食日记解析的提示词拆成三个固定段落:角色定义、任务步骤、输出约束。
角色定义用于把模型设定成一个专业的糖尿病营养师兼数据标注员。任务步骤明确要求模型先阅读整段日记再拆分食物事件,再对每个事件做五字段抽取,最后自检。输出约束直接绑死JSON格式,并用枚举值限定识别类型,从根源上杜绝“自由发挥”。
这里补充一个典型提示词示例(简化版):
你是一名营养科数据标注助手。你的任务是从用户随意记录的饮食日记中, 抽取结构化餐饮数据。 ### 必须抽取的字段 - food_items: 该餐包含的食物列表 - name: 食物名称(使用常见通俗名称) - portion: 份量描述(如1碗、2个、半份) - portion_grams: 参考估算的克数数值(不精确可给范围) - cooking_score: 烹饪方式健康评分(0-100,煎炸类低分、蒸煮类高分) - added_sugar_level: 添加糖等级(0-2,0无糖1含糖2明显含糖) - confidence: 对该条抽取结果的置信度(0-1) ### 格式要求 输出JSON数组,不要输出额外解释。 示例输出:[{"food_items": [...]}]提示词里的示例输出非常关键。我在实践过程中反复验证,对于结构化抽取任务,示例比长篇大论的规则描述效果更直接。第一次迭代时只在提示词里写了格式说明,没有给示例,结果模型的输出JSON嵌套层级五花八门,后续被迫加了Schema校验和修正逻辑。后来把示例输出补进去,结构稳定性提升了将近一半。
3.2 份量估算:不要求患者精确称重的工程策略
这是整个解析链路里最难的一环,也是和医生讨论最久的一环。临床营养师希望拿到精确的碳水克数,但患者不可能每顿饭都上称。折中的方案是采用“描述映射参照系”。
我们内置了一套参照物体模型,比如“一个拳头大小的米饭约150克”“一拇指大小的油脂约5克”“一个鸡蛋约50克”。LLM在抽取份量时,需要优先判断患者描述对应哪个参照物,再换算到克数范围。
实测下来这个策略效果不错。患者写“晚上吃了小半碗米饭”,模型输出“小半碗≈100-130克米饭,碳水约26-34克”,这个区间已经足够给医生做决策参考了。对比实验里,同一批30条测试日记,用精确估计策略,碳水估算结果和营养师人工评分的误差控制在正负15克以内,在饮食管理场景下算可接受。
3.3 实时解析的调度策略与延迟控制
项目名里的“实时”二字,工程上对应着两条要求:一是单条日记的解析延迟要低,二是患者新增日记后,系统能主动触发解析并更新反馈。
延迟控制上,用了三层手段。第一层是模板快速路由,约三成输入命中高频模板句式,直接走轻量规则,返回耗时低于300毫秒。第二层是普通LLM调用,单条日记解析控制在1.5秒内,区域网络环境下实测平均1.2秒。第三层是批处理兜底,如果某时段请求量大,进入队列后由异步Worker处理,保证不阻塞用户的后续操作。
这个设计比较现实。因为患者记录行为本来就是碎片化的,他们需要的是“刚发完一条消息很快有回应”的感受,而不是等一个分析报告。所以系统对每条日记解析完成后,会立刻返回一个粗粒度结果——“这顿主食偏多,建议下一餐减少约20克碳水”,而完整的营养分析报告则延后几秒自动生成。
3.4 质量评估体系:怎么证明LLM解析得准
做医疗相关产品,没有量化评估就上线,等于拿患者健康开玩笑。项目里建立了一套五维评估框架,每一维度都设定通过标准:食物名称准确率、份量估计误差、营养计算偏差、结构化输出完整率、不良输入拒绝率(也就是面对跟饮食无关或者玩笑性质的内容,系统要正确拒答)。
落地方式是双人独立评审加抽检。项目初期收集了500条真实患者日记脱敏样本,两条同源数据分别给模型解析和营养师人工标注,然后逐条比对。第一次联调时,食物名称准确率只有八成,主要问题出在别称和口语称呼上。后来在提示词里加了一条强制要求——当食物名称不确定时,必须标注“需人工复核”并给出候选列表,准确率才稳定到九成以上。
注意:医疗场景下的AI应用,评估体系不只是用来证明做得好不好,它决定了你是否有资格进入真实临床流程。前期花在评测集上的每一分钟,后期都在省麻烦。
4. 与血糖管理系统的深度联动:从“解析”到“干预”
如果止步于“把日记变成营养成分”,这个项目其实只完成了一半。它真正有决策价值的地方,在于把解析结果和血糖数据打通。
4.1 饮食事件与CGM血糖曲线的自动关联
项目对接的血糖数据源是动态血糖仪(CGM)的数据流,五分钟一个血糖点。系统拿到饮食事件的进餐时间后,自动截取进餐前15分钟到进餐后120分钟的血糖曲线,计算三个衍生指标:血糖峰值、峰值时间和波动幅度。
这三个指标加上营养解析结果,就构成了一次完整“进食—血糖响应”样本。连续积累一段时间后,系统可以按食物类别做数据切片。举个例子,某患者记录“早餐吃燕麦片”后血糖曲线相对平缓,而“早餐吃白粥配咸菜”后血糖峰值明显抬高。系统就会自动生成一条提醒,建议患者注意精制碳水的比例。
这个逻辑并不需要多么复杂的算法,但前提是吃和血糖的对应关系要构建得足够准。纯靠患者自己回忆去关联,几乎不可能积累出稳定的个性化数据。LLM把饮食记录结构化了,等于把个性化的根基打牢了。
4.2 个性化饮食建议的生成策略
生成建议时,我是把LLM当“翻译官”来用的,决策逻辑还是放在规则代码里。
系统根据解析出的碳水总量和血糖波动幅度,自动判断需要给什么级别的干预指令:餐后血糖增幅小于2.0mmol/L时,仅提示“控制良好”;增幅在2.0到3.8之间时,建议“适当减少主食量”;增幅超过3.8时,则提示“限制升糖负荷高的食物,并考虑增加饭后步行活动”。然后,把这条分级建议作为指令,让LLM生成一段口语化、有依据的回复推送给患者。
为什么要这样分开?因为过去踩过坑:让LLM直接根据血糖数据生成建议,它有时会给出过于激进或者前后矛盾的结论,这在我们实际测试里真的发生过,差点导致一次误报。规则层保证决策的底线,LLM只负责语言表达,这样兼顾了个性化语气和安全性。
4.3 医生工作台的汇总视图与复诊辅助
患者侧体验到的是每天“吃—血糖—建议”的闭环,而医生侧需要一个更高维的视图。
在复诊前,系统自动生成一份“两周饮食与血糖趋势报告”,包括:高频食物分布、各餐平均碳水摄入、餐后血糖达标率、可疑的高升糖食物清单、依从性评分(连续记录天数和有效记录条数)。
医生拿到这份报告后,在门诊对话里可以非常聚焦地讨论具体行为,而不是空泛地让患者“注意饮食”。在一次回访中,某医生对这个设计评价很直接:“以前问患者吃什么怎么吃,患者自己都记不全。现在有了报告,我直接指着上面的数据说‘你这周吃面条和饼比较多,精制碳水偏多’,患者也心服口服。这比空谈原理有效得多。”
这个反馈让我意识到,饮食解析的价值不仅体现在患者端,也极大缩短了门诊沟通的时间成本。
5. 常见问题与避坑实录
最后这部分,把项目调试过程中遇到的高频问题整理成一份排查清单,有相似场景的可以直接抄作业。
5.1 食物名称歧义冲突
典型案例是“土豆炒肉”和“红烧肉”。普通解析模型很容易把“土豆”和“肉”分开处理,但在营养素计算时,这种拆分直接导致碳水翻倍。解决方案是在提示词里强调“一道菜是一个整体食物事件,不要拆分同一道菜中的主料配料”,同时在算营养时设定组合菜规则,优先按整道菜的做法去查参考值。
类似的问题也出现在“凉拌黄瓜花生米”这种混合菜色上。单看“黄瓜”是低升糖,但一加花生米,脂肪含量上去了。如果系统分开算出两条独立记录,餐后血糖分析就会出现不必要的偏差。
5.2 多轮追问与信息补全机制
单条日记信息不全的情况很多,比如患者只写了“午餐:黄焖鸡米饭,微辣”。这个“微辣”对碳水没有影响,但酱料里的糖分可能不少。如果系统直接计算,很可能漏掉酱汁的隐性碳水。
项目里的处理方式是引入追问机制。当某些关键信息缺失时,系统会主动反问一条改进式提问:“问一下,这餐的酱汁是不是基本都拌到饭里了?大概吃了多少勺?”当患者回复补充信息后,系统会以多轮对话中的增量信息重新修正解析结果。
5.3 轻率拒答与幻觉内容
这个问题初期碰到过两次。一次是患者拍了一张风景照,端侧误判为食物图片送进了解析链路,模型一本正经地输出了“该餐包含一碗米饭和一杯饮料”这样的幻觉结果。另一次是患者把情绪不好的记录说成“今天心情不好没吃饭”,模型解析成了“该餐无进食”并没有触发告警,而这实际上正是需要医生关注的信号。
对应的修正是给输入通道加上了意图分类器。食物图片、非饮食记录、情绪表达,先做一个轻量分类,只有判定为“饮食相关且包含可解析食物信息”时,才进入营养抽取链路。既减少无效调用,也防止幻觉数据污染血糖关联分析。
5.4 解析结果冲突时的可信度降级
键控流程也有异常。曾经遇到同一个患者连发两条相互矛盾的日记:“午餐吃了一碗米饭”和“午餐没吃主食”,系统两条都进行了正常解析,导致当天碳水数据自相矛盾。
后来加入了时间窗口内重复记录的冲突检测。同一进食窗口内出现多个解析结果时,系统将较高置信度的结果保留,并给另一条打上“可能重复/请确认”标记,同时整体置信度降一级,在医生报告里单独标注异常。
结束语:一个比较务实的路线图
如果让我给准备做类似项目的人一个建议,核心是:把LLM放在“信息抽取器”的位置上,把安全决策放在规则代码里,两边的边界一定要清楚。这个定位决定了系统的稳定性上限。
很多人问我,这个项目最大的难点是什么。我的答案是:不是把LLM调通,而是想清楚“哪些事必须让模型干,哪些事不能让模型干”。模型擅长从杂乱语义里抽关键信息,模型非常不擅长做精确计算和稳定复现。顺着这个边界设计,项目每一步都会顺很多。
另外提醒一句,医疗场景的项目一定要从第一天就把数据闭环跑起来——每一格糖尿病患者的日记,经过解析、关联、反馈后再沉淀下来,就是一套别人追不上的个性化医疗数据资产。这个长期价值,比任何单独的技术亮点都重要。