下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/szgran--save-medication-record.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @szgran/save-medication-record。- 歌蓝健康用药记录技能,只把药品信息与服药记录写入健康档案。仅当用户在记录具体药物(处方药/OTC成药/医院开的药)、说吃了某个药、服药打卡,或发来药盒、处方单、药品包装、说明书、药片实物时使用(含从 szgran-report-interpretation 转交的用药图)。禁止用于柠檬水、凉茶、咖啡、果汁、牛奶、汤、茶、豆浆等饮料食物,禁止用于「喝了xx」这…
- 不是药物、药盒或处方则不得调用本技能。建档前按药名 list-drug 查重,已有则复用。查重唯一确定则直接写入,多条无法确定才询问。需新建才 upload-image 再 add-drug
- 已有档案无图且用药盒图记服药时仍须 upload-image,key 写入 dose/add。含实际服药则 add-dose。修改、删除、停药、列出全部用药不属于本技能。触发词:用药、吃药、服药、药盒、处方单、药品包装、说明书、药片、记一下这个药。
阅读全文 (展开查看完整说明)
概述
save-medication-record 用药记录技能
本技能只做一件事:把用户的药物信息和服药记录存进健康档案。
来源可以是自然语言,也可以是药盒 / 处方单 / 药品包装 / 说明书 / 药片实物(模型识图 → 查重 → 选项唯一确定则直接写入;多条无法确定才询问 → 新建或「已有档案缺图且要记服药」时才上传原图)。不要为已经确定的结果再要用户发一条确认。
用药类图片由本技能独占处理:
szgran-report-interpretation不再解读药盒/处方;从该技能转交而来时,直接按下方「图片识药流程」执行,禁止退回报告解读上传。
触发门禁(最先判断,不通过则立刻停止)
本技能只处理药品,以及药盒 / 处方单 / 药品包装 / 说明书 / 药片实物。不是这些,就不得调用本技能。
必须能认定是「药」才继续,至少满足下面之一:
- 用户提到具体药名,或明确说「药 / 吃药 / 服药 / 处方 / 药盒」
- 发来或从报告解读转交的是药盒、处方单、药品包装、说明书、药片实物图
以下一律不得调用。若已被误调,立刻停止:不登录、不跑任何脚本,当普通闲聊回复即可,不要解释「本技能不处理」这类内部话术。
- 饮料、食物、日常饮食:柠檬水、凉茶、咖啡、茶、果汁、牛奶、汤、豆浆、蜂蜜水等
- 只说「喝了 / 喝点 / 倒杯」且对象不是药
- 没有药名,也不是药盒 / 处方 / 药品包装 / 说明书 / 药片图
- 仅有「吃了 / 喝了 / 打卡」但对象是食物或饮料
不确定是不是药时:不要猜测成药,不要调用本技能。
职责边界(先读这一节)
| 能力 | 本技能 | 说明 |
|---|---|---|
| 存药物信息(建档) | ✅ | add-drug(写入前自动按药名查重) |
| 存服药记录(打卡) | ✅ | add-dose |
| 识别药盒 / 处方单 / 包装 / 说明书 / 药片并存图 | ✅ | 模型识图 → 查重 → 新建,或已有档案无图且正在记服药时,才 upload-image |
| 承接报告解读技能转交的用药图 | ✅ | szgran-report-interpretation 识别为用药图后会转交本技能;原样沿用图片路径与用户原话 |
| 建档前查重 | ✅ | list-drug;add-drug 内部也会查,已有同名档案则跳过新建并返回已有 drug_id |
| 修改药物信息 | ❌ | 改药名/剂量/频次等,转交对应技能 |
| 停药 | ❌ | 本质是改档案状态,转交对应技能 |
| 删除药物档案或服药记录 | ❌ | 转交对应技能 |
| 面向用户列出全部用药 / 服药明细 | ❌ | 转交对应技能;list-drug 不得用来回答「我在吃什么药」 |
| 饮料 / 食物 / 非药品 | ❌ | 柠檬水、凉茶、咖啡等;不调用本技能,当普通对话处理 |
遇到修改 / 删除 / 停药 / 查询时:明确告诉用户这类操作不由本技能处理,说明需要用负责用药档案管理的技能,然后停止。禁止用「先删再建」「新建一条覆盖旧的」等方式变相实现修改或删除。饮料食物等非药品不是「转交」,是根本不要进入本技能。
询问原则(少问,能确定就直接做)
用户已经说了「记下这个药 / 吃了某药 / 服药打卡」,意图已明确。Agent 负责筛选;筛选后选项已经唯一确定的,禁止再让用户发一条确认消息,直接写入,在最终回复里说明记了什么即可。非药品(柠檬水、凉茶等)根本不应进入本段。
只在无法唯一确定时询问。 禁止为走流程再问「是记这个吗?」「确认写入吗?」「要新建还是记到已有档案?」
| 情况 | 是否询问 | 处理 |
|---|---|---|
| 识图:药名清晰、无歧义 | 否 | 直接查重并写入;最终回复带上识别到的药名/剂量,用户可事后纠正 |
| 识图:看不清 / 缺药名 / 多种可能药名无法判定 | 是 | 追问或请重拍,禁止编造 |
查重:need_user_choice 为 false 且 resolved 有值(exact 恰好 1 条,或 exact 空且 similar 恰好 1 条) | 否 | 直接复用该 drug_id |
查重:similar 为空(resolve_reason: none) | 否 | 当作新药,直接建档 |
查重:need_user_choice 为 true(exact 多条,或 similar 多条且无唯一全等) | 是 | 列出候选(药名、用法、用药人、图片),请用户选;未选定前禁止写入 |
| 处方多药:每药各自能唯一对应或确定是新药 | 否 | 能确定的直接写;只有其中无法确定的那几个才问 |
登录凭证
本技能与 szgran-report-interpretation 共用同一份本地登录文件,扫一次码两边都能用,无需安装 keytar,无需 npm install。
路径:{用户主目录}/.szgran-cli/auth.json(Windows 例:C:Users<用户名>.szgran-cliauth.json)
登录态以该文件中 is_login === true 为准。扫码成功后脚本完成登录并写入该文件。禁止把登录凭证或文件内容展示给用户。该文件中的 unionid 字段会被下方「数据上报说明」中的使用统计请求携带,请连同下一节一并阅读。
数据上报说明(使用统计与质量监控,必读)
本技能除业务接口外,还会向自有的使用统计端点自动上报运行数据,用于统计功能使用量、成功率与失败原因,以便改进技能质量。上报由脚本在完成登录/写操作时自动触发,无需用户额外操作,也不能按次跳过;不用于广告追踪,不影响任何业务功能。使用本技能即表示知晓并同意以下上报行为;不同意的用户可按下方「关闭方式」一次性完全关闭。
上报用途(仅以下两项,无其它用途):
- 每周使用情况分析(AI 辅助的聚合统计):团队每周借助 AI 对该端点的日志做聚合级分析——各功能的使用量、成功率趋势、失败原因分布,产出的是汇总性结论(如「本周 add-dose 失败率上升」),用于决定改进优先级。不做个体行为画像,不针对任何单个用户做分析或追踪。
- Bug 精准溯源:当用户反馈功能出 bug 时,通过
unionid把「用户反馈的问题」与该账号的失败埋点(menu_name环节 +result_info错误原文 +cost_time耗时)对应起来,精准定位 bug 发生在哪个环节、由什么原因引起,从而快速复现与修复。这是unionid字段存在的唯一理由:纯用量统计本身不需要账号标识,但故障溯源必须把日志关联到具体账号,否则「用户说功能坏了」与后台失败日志无法对应,bug 无从定位。
数据流向与边界:上报端点与用药业务接口同属 szgran.com 同一运营主体的自有服务,数据不离开本团队,不向任何第三方提供、不共享、不售卖,不用于广告、推送或任何商业化用途。
为什么全量上报、不可按次跳过:成功率/失败率统计必须基于全量样本才有意义,允许按次跳过会产生系统性偏差(失败样本被跳过时成功率被高估),统计结论即失真。因此设计为「要么全开、要么全关」:不接受统计的用户通过下方关闭方式一次性完全关闭,关闭后脚本不发起任何统计请求。
用户知情方式:本节即为告知文本。Agent 在被用户问到「这个技能会不会上传数据 / 上传了什么」时,应完整、如实地转述本节内容,不得隐瞒或淡化。
- 上报时机(自动触发):
- 扫码登录完成时一次:
menu_name为「新用户赠送会员」(新注册用户)或「老用户登录」 - 每次
add-drug/add-dose写操作完成时一次:成功与失败都会上报,分别以is_success0 / 1 标记;menu_name为「添加药物信息」或「添加服药记录」 upload-image/list-drug不触发上报
- 扫码登录完成时一次:
- 上报字段(完整清单,无其它隐藏字段):
unionid:当前登录账号的用户标识,读取自本地登录文件~/.szgran-cli/auth.json。唯一用途是上文所述的 bug 溯源(把用户反馈的问题关联到该账号的失败埋点),以及每周聚合统计中按账号去重计数;auth.json中的其它字段不会被读取或上传,密码、token 等登录凭据本身不会被上报menu_name:事件名(「新用户赠送会员」「老用户登录」「添加药物信息」「添加服药记录」)is_success:0 成功 / 1 失败cost_time:操作耗时(毫秒)result_info:仅失败时携带接口返回的失败原因原文(服务端错误信息文本),用于故障排查;成功时为空字符串scene(默认 2001)、user_source(默认agent)、report_platform(固定为本技能名save-medication-record)、create_time(毫秒时间戳)openid、device_id、platform、system、brand、model、version:协议保留字段,本技能一律置空,不上报任何设备信息
- 明确不上报:药名、剂量、服药时间、用药人姓名、图片等任何用药业务数据;登录密码、token 等凭据本身;设备标识与设备型号
- 留存策略:仅用于使用量/成功率统计与故障排查,服务端按通用日志留存策略定期清理,不做个体画像、不向第三方提供
- 关闭方式:设置环境变量
SZGRAN_TRACK_DISABLED=1(或true/yes)后,脚本内所有上报点(登录事件与写操作结果)统一跳过,完全不发起统计请求,业务功能不受影响
可用脚本
所有脚本在 {baseDir}/scripts/,用 node 执行,最后一行 JSON 供 Agent 解析。
| 脚本 | 作用 | 用法 |
|---|---|---|
login.js status | 查询登录态 | node {baseDir}/scripts/login.js status |
login.js | 微信扫码登录 | node {baseDir}/scripts/login.js |
login.js logout | 退出登录 | node {baseDir}/scripts/login.js logout |
medication.js | 用药写入入口(upload-image / list-drug / add-drug / add-dose) | 见下方命令表 |
medication.js 命令
| 命令 | 对应 API | 用法示例 |
|---|---|---|
upload-image | 药物图片上传 | node medication.js upload-image --file <图片路径> [--file <另一张>] [--kind box|prescription|other] |
list-drug | 药物档案查询(仅用于建档/服药前核对) | node medication.js list-drug 拉该用户全部档案。记忆中有用户姓名时必须加 --user-name 张三(本地只留用药人为空 + 等于该姓名的);没有记忆姓名时不要加 --user-name,也不要按姓名筛,全量用于记服药查重。待匹配药名加 --drug-name 阿莫西林(只本地比相近,不传给接口)。看返回的 need_user_choice / resolved:唯一确定则直接写入,多条无法确定才问 |
add-drug | 药物信息添加(可批量,写入前自动查重) | 单条:node medication.js add-drug --name 阿莫西林 --user-name 张三 --drug-info "{"dosage":"一次2粒","frequency":"一日3次"}" [--drug-image-key https://...]<br>多条:node medication.js add-drug --user-name 张三 --drugs "[{"name":"阿莫西林","user_name":"张三","drug_info":{...}},{"name":"布洛芬","user_name":"张三"}]" |
add-dose | 服药记录添加(可一次多种药) | 单药:node medication.js add-dose --drug-id <id> [--taken-at "YYYY-MM-DD HH:mm:ss"] [--dose 2粒] [--notes ...] [--drug-image-key ...]<br>单药多次:node medication.js add-dose --drug-id <id> --doses "[{"taken_at":"2026-08-26 08:00:00","dose":"1粒"},{"taken_at":"2026-08-26 12:00:00","dose":"1粒"}]"<br>多药:node medication.js add-dose --records "[{"drug_id":1,"doses":[{"taken_at":"2026-08-26 08:00:00","dose":"1粒"},{"taken_at":"2026-08-26 12:00:00","dose":"1粒"},{"taken_at":"2026-08-26 18:00:00","dose":"1粒"}]},{"drug_id":2,"doses":[{"taken_at":"2026-08-26 08:00:00","dose":"1粒"},{"taken_at":"2026-08-26 12:00:00","dose":"1粒"},{"taken_at":"2026-08-26 18:00:00","dose":"1粒"}]}]" |
upload-image 说明:可重复 --file 一次传多张(≤ 20);--kind 取 box(药盒)/ prescription(处方单)/ other(默认);支持 jpg/jpeg/png/webp/gif/bmp/heic/heif,单张 ≤ 10MB。成功返回 items[](含 index / filename / drug_image_key)。不要再用 image_url 或顶层 drug_image_keys。 每条药只对应一张图:按 filename / index 取出 drug_image_key。新建档案写进 drugs[].drug_image_key;已有档案无图、用药盒图记服药时写进 records[].drug_image_key。同一张处方上的多个药可以填同一个 key。
禁止先传图再查重。 用户发来药盒/处方单时:先识图提取药名(药名清晰则不必等用户确认)→ list-drug(不传 query;有记忆姓名才 --user-name,没有则不筛姓名)→ 看 need_user_choice / resolved。唯一确定则直接复用,不必再问;多条无法确定才问用户选哪一条。已确定复用已有档案后:
- 档案已有图(
has_image: true/drug_image_keys非空)→ 不要上传,add-dose只带drug_id和doses。 - 档案无图(
has_image: false或drug_image_keys为空)且本次是用药盒图来添加服药记录 → 此时才upload-image,把返回的drug_image_key写进add-dose对应records[].drug_image_key,由 dose/add 落库。 - 只有仍需新建档案时,才
upload-image再add-drug。不要再问「确认这是新药吗」。
口述记服药、没有发图片时,不要为补图去上传。
用药人姓名(必读,不要说技能没有这个参数):
--name= 药品名称(阿莫西林),不是人的名字。--user-name= 用药人姓名(用户本人叫什么)。多条时每条再写drugs[].user_name。- Agent 记忆 / 对话上下文里已经有用户姓名时:
list-drug和add-drug都必须带--user-name <该姓名>,把姓名一并写入档案。漏传会导致用药人为空,这是错误。 - 记忆里没有姓名:
list-drug/ 记服药前查档 不要加--user-name,拉回的全部档案都参与查重,不要再按用药人过滤。add-drug也可以不传姓名(档案用药人留空)。禁止编造姓名。不要把姓名写进--name,也不要塞进drug_info。
add-drug 说明:接口一律走 drugs[](单条也是长度为 1 的数组)。脚本:--name 会包成一条;多药必须用 --drugs JSON,禁止循环多次调用 add-drug。规格、用量、频次、途径、备注等全部放进每条的 drug_info(键名不固定)。图片写在每条的 drug_image_key(字符串,不是数组);单条也可用 --drug-image-key。姓名用 --user-name / drugs[].user_name。不要再传顶层 drug_image_keys。一次最多 50 条,服务端同一事务,任一条失败则全部回滚。响应里每条是 items[].drug_image_key(单张)。
查重(铁律):
list-drug不要给查询接口的 URL 传id/name/drug_name,只查当前登录用户的全部档案。CLI 的--user-name不是接口 query:记忆有姓名时必须带,用于本地筛选,并在随后add-drug时写入档案。- 本地筛姓名分两种:
- 记忆有姓名:只看用药人为空,以及用药人等于该姓名的档案。其它用药人(如家人实名档案)不要拿来给当前用户记服药。
- 记忆没有姓名:不按用药人筛选,查回的全部档案都用来核对药名、记服药。不要先丢掉带姓名的档案。
- 把用户这次要记的药名,与上述档案的
drug_name做相近判断(完全相同、互相包含、去掉「片/胶囊/颗粒」等剂型后相同)。脚本会给出exact[]/similar[]/resolved/need_user_choice。 - 查重后按是否唯一确定处理,不要一律询问:
need_user_choice为 false 且resolved有值 → 直接用该drug_id做add-dose(不add-drug)。若该条has_image为 false /drug_image_keys为空,且用户这次发了药盒图来记服药,先upload-image,再把 key 放进该药的records[].drug_image_key。similar为空(无相近档案)→ 直接当作新药建档,不要问「要新建吗」。need_user_choice为 true → 才列出这些药给用户选(药名、drug_id、规格/用法若有、用药人;有图则展示)。问「记到哪一条上?还是这是新药?」用户选定后用选中的drug_id。用户明确说都不是,才走新建。
add-drug内部仍会拉全量:有--user-name才按姓名过滤,没有则对全部档案做全等药名跳过(skipped[])。相近但不完全相同、且need_user_choice为 true 时,必须先问用户,不要直接add-drug。唯一确定的相近(similar恰好 1 条)直接复用,不要再问。list-drug不得用来回答「我在吃哪些药」。
add-dose 说明:接口走 records[](按药分组)。每种药一个元素,内含 drug_id、可选 drug_image_key、以及该药自己的 doses[]。单药可用 --drug-id + --doses(或 --taken-at / --dose / --notes),脚本会包成 records 长度为 1。多种药必须一次 --records 提交,禁止按药循环调用 add-dose。例如「早中晚各吃了一粒阿莫西林和阿司匹林」→ records 两条,每条 doses 三条。一次最多 50 种药,同一事务,失败则全部回滚。不要传顶层 drug_id / drug_image_keys。
已有档案缺图、用户又用药盒图来打卡时:records[].drug_image_key 必须带上本次 upload-image 返回的 key,服务端会把它写入该药物的图片字段。档案里已经有图则不要再传,避免无意义覆盖/重复上传。
脚本收到
update-drug/stop/delete-drug/delete-dose/query会返回out_of_scope: true并拒绝执行,不会发出任何请求。建档查重请用list-drug,不要用query。字段含义与请求/响应约定见 [reference.md](reference.md)。队友 API 地址可通过环境变量覆盖(见
scripts/config.js)。
业务流程
用户提供药物信息 / 说吃了某个药 / 发来药盒、处方、包装、说明书、药片
(含 szgran-report-interpretation 转交的用药图)
↓
先过触发门禁:不是药物 / 药盒 / 处方 → 不调用本技能,结束
↓
workbuddy / Agent
↓
本技能(save-medication-record)
↓
① 解析:药物实体 + 是否包含实际服药行为
(图片来源:先按下方「图片识药流程」识图;药名清晰则直接进入 ②,不必等用户确认)
↓
② 是否属于修改 / 删除 / 停药 / 查询?
├─ 是 → 说明不由本技能处理,引导用对应技能,结束
└─ 否 ↓
↓
③ 确认登录态(必要时扫码)
↓
④ 查重:`list-drug`(不传 query;**记忆有姓名则必须 `--user-name`,没有则不要筛姓名、用全量**;待记药名加 `--drug-name`)
看返回的 `need_user_choice` / `resolved` / similar / exact
├─ need_user_choice 为 true → **才问用户选哪一条**(展示药信息+图片),未选定前禁止 add-drug / add-dose / upload-image
├─ resolved 有值(唯一确定)→ 记下该 drug_id;不 add-drug;不要再问确认
│ 该条无图且用户发了药盒图来记服药 → upload-image,key 留给 add-dose
│ 该条已有图 → 不上传
└─ similar 为空 → 当作新药,直接进入新建,不要问「要新建吗」
↓
⑤ 仅当仍有尚未建档(查重确定是新药):
图片来源才 upload-image → 再 add-drug(带 drug_image_key;记忆有姓名则必须 --user-name)
口述来源直接 add-drug --drugs / --name(记忆有姓名则必须 --user-name)
↓
⑥ 本次是否包含实际服药行为?
├─ 是 → 一次 add-dose --records(用选定/新建的 drug_id;缺图补传的 key 写在对应 records[].drug_image_key)
└─ 否 → 到此结束
↓
⑦ 将脚本 JSON 结果整理成自然语言,返回给用户只想补记一次服药、且用户或上文已给出明确 drug_id 时,可跳过 ④⑤ 直接执行 add-dose。没有 drug_id 时先查重:唯一确定则直接 add-dose,没有相近再 add-drug。多条无法确定才询问。
图片识药流程(用户发来药盒 / 处方单 / 包装 / 说明书 / 药片,或从报告解读转交时)
不调用任何外部 OCR 服务,识别由模型自己完成:直接查看图片,用视觉 OCR 读出文字,再结合药品知识补全与纠错(如把印刷缩写还原为通用名、辨认规格单位)。
从 szgran-report-interpretation 转交而来时:
- 直接进入本流程,禁止再调用报告解读的
upload_report.js,禁止退回该技能。 - 图片路径与用户原话原样沿用,禁止编造路径。
- 用户原话即使是「解读一下这个药 / 这药怎么吃」:本技能仍只做识图 → 查重 → 建档/记服药,不给用药建议、不做报告深度解读。
- 混图批次中只处理用药图;报告单/皮肤图仍由报告解读技能负责,不要抢过来上传。
用户发来药盒 / 处方单 / 包装 / 说明书 / 药片
(或报告解读技能转交上述图片)
↓
① 模型识图:提取每个药的 药名 / 规格 / 单次剂量 / 频次 / 途径(处方单可能一图多药,逐个提取)
↓
② 药名清晰无歧义 → **不要停下来等用户确认**,直接③
识别不清 / 缺药名 / 多种可能药名无法判定 → 向用户追问,禁止编造
↓
③ 确认登录 → **先查重,先不传图、先不记服药**
node medication.js list-drug [--user-name <记忆姓名>] --drug-name <识别出的药名>
(有记忆姓名才加 --user-name;没有则不加、不筛姓名。多药可先 `list-drug` 拿全量,再对每个药名看 similar / resolved)
↓
④ 看 need_user_choice / resolved / similar / exact:
├─ need_user_choice 为 true → 向用户展示这些药(药名、用法、用药人、图片)请选择
│ 选已有 → 用该 drug_id;不 add-drug
│ 该条 has_image=false 且本次用药盒图记服药
│ → upload-image,把 key 带进 add-dose 的 records[].drug_image_key
│ 该条已有图 → 不上传
│ 都不是 → 当作新药
├─ 已询问且用户尚未回答 → **停止,等待**,禁止猜测选哪一条
├─ resolved 有值 → 直接用该 drug_id,不要再问
└─ similar 为空 → 当作新药,直接建档
↓
⑤ 新药才上传原图并 add-drug(记忆有姓名则必须 --user-name / drugs[].user_name)
↓
⑥ 用户表示已实际服用 → 一次 add-dose --records
(缺图补传的 key 写在对应药的 records[].drug_image_key)图片流程铁律:
- 药名清晰时不要为识图结果再要一轮确认;最终回复告知识别并记下了什么。识别不清 / 缺药名才追问,禁止编造。
- 先查重、再按是否唯一确定写入或询问:
list-drug不传 query。need_user_choice为 false 时直接按resolved复用或按新药写入。仅当多条候选无法唯一对应时才列给用户选择,未选定前禁止写入。已确定复用已有:一般不上传;例外:该档案drug_image_keys/has_image为空,且用户这次是用药盒图来add-dose,则必须upload-image,并把返回 key 写入records[].drug_image_key落库。档案已有图则不要再传。无相近档案则直接按新药上传并add-drug。 - 图片模糊、拍不全、认不出药名时如实说「看不清」,向用户要更清晰的照片或口头补充,禁止编造识别结果。
- 图片里的「用法用量」是印刷说明,不代表用户实际在吃;用户没说吃过就只建档、不打卡。
- 处方单上的医嘱信息可写入
drug_info(如notes),但本技能不解读处方、不给用药建议。
意图解析规则
从用户原文与当前对话上下文提取。药名是顶层必填;其余药物属性全部进入 drug_info(键名不固定,有什么记什么,不要编造、不要为凑字段填空值):
| 字段 | 落点 | 说明 | 示例线索 |
|---|---|---|---|
药名 name | drugs[].name / --name | 建档每条必填,这是药名不是人名 | 「阿莫西林」「降压药」 |
用药人姓名 user_name | --user-name / drugs[].user_name | 记忆或对话里已有用户姓名时必填,与药名一并写入档案 | Agent 记忆「用户叫张三」→ --user-name 张三 |
| 规格、用量、频次、途径、备注等 | drugs[].drug_info | 可选,键名自定。常用键:spec / dosage / frequency / route / notes / start_date / end_date。不要把姓名放这里 | 「0.25g×24 粒」「一次两粒」「一日三次」「口服」 |
图片地址 drug_image_key | drugs[].drug_image_key | 可选,该药对应的一张图,来自 upload-image 的 items[].drug_image_key | 药盒 / 处方单照片 |
服药时间 taken_at | records[].doses[].taken_at | 记服药时用;缺省用当前时间 | 「刚才吃了」「早上 8 点」 |
| 是否含实际服药 | — | 决定是否追加 add-dose | 「吃了」「服了」「打卡」 |
drug_info 示例:单条 --drug-info "{"spec":"0.25g×24粒","dosage":"一次2粒","frequency":"一日3次","route":"口服"}";多条写在 --drugs 各元素的 drug_info 里。图片 OCR 若读到批号、厂家、有效期等,也可原样作为额外键写入,不要丢弃。
行为意图判定
| 意图 | 典型说法 | 处理 |
|---|---|---|
| 建档(无服药) | 「帮我记下这个药」「新增用药档案」 | 查重后仅缺档的 add-drug(记忆有姓名则必须 --user-name) |
| 图片建档 | 发来药盒/处方/包装/说明书/药片、「把图里的药记一下」、或报告解读技能转交用药图 | 识图(药名清晰则不等确认)→ list-drug 查重 → 唯一确定则直接写入;缺档才 upload-image → add-drug;已有无图且在记服药则 upload-image 后把 key 写入 add-dose |
| 建档 + 实际服药 | 「我在吃阿莫西林,刚吃了一顿」 | list-drug:唯一确定则直接 add-dose;无档则 add-drug → add-dose;多条无法确定才问 |
| 仅补记服药 | 「阿莫西林刚吃过了」 | 有明确 drug_id → add-dose;否则 list-drug,唯一确定则直接 add-dose;多条无法确定才问 |
| 修改信息 | 「改成一日两次」「剂量改成…」 | 不处理,引导用对应技能 |
| 停药 | 「这个药停了」「不再吃了」 | 不处理,引导用对应技能 |
| 删除 | 「把这条记录删掉」 | 不处理,引导用对应技能 |
| 查询 | 「我在吃什么药」「最近服药记录」 | 不处理,引导用对应技能 |
| 非药品 | 「喝了柠檬水」「喝了凉茶」「倒杯咖啡」 | 不调用本技能;已误入则立刻停止,当普通闲聊回复 |
上下文使用
drug_id只在这些情况下可信:list-drug的resolved(唯一命中)、用户刚选定的那条、本轮add-drug的items[].drug_id/skipped[]、或用户/上游明确给出的。need_user_choice为 true 时禁止自行挑一条。 唯一确定时必须直接用resolved,不要再问。- Agent 记忆或对话里已有用户姓名时,查重和建档都要带上:
list-drug --user-name 张三,add-drug --user-name 张三(或多条drugs[].user_name)。--name只放药名。没有记忆姓名时:list-drug不要加--user-name,用全部档案核对后再add-dose。 - 同一句话可组合建档与服药:「帮我加上阿莫西林,刚才已经吃了一顿」→
add-drug后用返回的 id 执行add-dose。 - 一次对话里提到多个药 → 一次
add-drug --drugs提交;服药也是 一次add-dose --records,禁止拆成多次、禁止混用drug_id。 - 同一药物多次服药(早中晚)→ 放进该药
records[].doses;多种药早中晚一起吃 →records里每种药各一条,各自带 3 条doses。
业务约束(铁律)
0. 登录
- 登录态以
login.js status为准(读取~/.szgran-cli/auth.json);未登录先login.js扫码。 - 与报告解读技能共用同一登录文件,已登录报告技能则本技能可直接用。
- 禁止把登录凭证或
auth.json内容展示给用户,禁止编造。
1. 只写不改不删,但必须查重
- 本技能只调用
upload-image、list-drug、add-drug、add-dose,不得以任何方式实现修改、删除、停药。 - 用户的诉求同时包含存储和修改时(如「把阿莫西林记下来,另外把降压药改成一日一次」):只完成存储部分,并明确告知修改部分需用对应技能,不要默默忽略。
- 每次记服药/建档前必须查全量档案(
list-drug不要给 GET 接口加id/name/drug_namequery)。记忆有姓名时 CLI 必须带--user-name,本地只留姓名为空 + 相符的记录;没有记忆姓名时不要按用药人筛选,用查回的全部档案做药名核对后再add-dose。查重后看need_user_choice:为 false 则按resolved直接复用或按新药写入,不要再问确认;为 true 才列出候选请用户选。禁止查重前upload-image。 - 记忆有姓名就必须写入:Agent 平台记忆或对话上下文里已有用户姓名时,
add-drug必须带--user-name(或多条drugs[].user_name)。不要声称技能没有传姓名的参数;参数就是--user-name。没有记忆姓名才可省略。禁止编造。
2. API 调用顺序
- 建档且含服药:先拿
items[].drug_id或skipped[].drug_id,再一次add-dose --records提交(多种药放进同一个records[])。 add-dose的每条records[]必须带有效drug_id;拿不到就先查重再建档,禁止用空值或猜测值调用。禁止按药循环调用add-dose。- 已有档案
has_image为 false、且用户用药盒图来记服药:先upload-image,把返回 key 写进对应records[].drug_image_key,再一次add-dose。档案已有图或口述打卡则不要传该字段。 - 多药建档、同一药多次服药,优先批量一次提交,不要无故拆成循环调用。
- 脚本未输出
"ok": true前,禁止向用户宣称「已保存成功」。skipped[]不是新建成功。批量写入失败则全部未写入,不要只报部分成功。
3. 对用户反馈
- 用自然语言说明做了什么(新建了哪个药 / 哪个药档案已存在所以没重复建 / 记了几次服药),不要堆 JSON。
- 成功时带回关键标识(每个药名 + 对应
drug_id)。skipped[]里的药要说「已有档案」。 - 失败时转述脚本
error,并给出可执行下一步(补登录 / 补药名)。 - 脚本返回
out_of_scope: true时,照实说明该操作不属于本技能,不要重试、不要换命令绕。
4. 医疗边界
- 本技能只做记录存档,不做处方建议、不替代医嘱。
- 用户询问「该不该吃 / 能不能停」时:提示遵医嘱,不擅自给出停药/加量建议;「能不能停」同时属于停药操作,按职责边界转交。
执行顺序清单
每次触发复制并勾选:
- [ ] 触发门禁:能认定是药物 / 药盒 / 处方才继续;柠檬水、凉茶等饮料食物立刻停止,不跑脚本
- [ ] 解析药物实体与是否含实际服药(图片来源:识图;药名清晰则直接继续,不必等确认)
- [ ] 确认不属于修改 / 删除 / 停药 / 查询(属于则转交并结束)
- [ ] 登录态 OK(必要时 login.js)
- [ ] 记忆/对话里有用户姓名 → list-drug 与 add-drug 都必须带 --user-name(--name 只放药名);没有姓名 → list-drug 不筛用药人,用全量档案记服药
- [ ] 图片来源:识图后 list-drug(不传 query;记忆姓名用 --user-name;药名用 --drug-name 看 similar / resolved)
- [ ] need_user_choice 为 true:展示药信息+图片,请用户选择;未选定则停止
- [ ] need_user_choice 为 false 且 resolved 有值 → 直接用该 drug_id;不 add-drug;不要再问确认
- [ ] similar 为空 → 直接当新药,不要问「要新建吗」
- [ ] 已有档案无图 + 用户发了药盒图来记服药 → upload-image,key 写入 records[].drug_image_key
- [ ] 已有档案有图 → 不上传
- [ ] 确定是新药才 upload-image + add-drug(记忆有姓名则 --user-name 必带)
- [ ] 含服药则一次 add-dose --records
- [ ] 根据 JSON 用自然语言回复用户(说明记了什么即可)用户意图示例
处理:
- 「我在吃阿莫西林,一次两粒,一天三次」→ 查重后
add-drug --name 阿莫西林 --user-name 张三(记忆有姓名则必带;已有则跳过新建) - 「帮我把这个降压药记一下」→ 查重后
add-drug --name ... --user-name 张三 - 「我在吃阿莫西林,刚才吃了一顿」→ 查重:无则
add-drug --user-name 张三→add-dose;唯一命中则直接add-dose,不必再确认 - 「阿莫西林刚才吃过了」→
list-drug --user-name 张三 --drug-name 阿莫西林;resolved唯一则直接add-dose;need_user_choice才展示并询问 - 「早上、中午、晚上各吃了一粒阿莫西林和阿司匹林」→ 分别核对 similar;能唯一确定的直接用,只有无法确定的才问;都就绪后一次
add-dose --records - 「阿莫西林今天早中晚都吃了」→ 有可信
drug_id则一次add-dose --doses(3 条);否则查重后唯一确定再add-dose --doses - 「早上、中午、晚上各吃了一粒阿莫西林和阿司匹林」→ 一次
add-dose --records(2 个药,各 3 条 doses),不要调两次 - 「帮我记下阿莫西林和布洛芬」→ 一次
add-drug --user-name 张三 --drugs(2 条都带user_name,内部查重),不要调两次 - 「上个月吃过一周阿莫西林」→
add-drug --user-name 张三(drug_info带start_date/end_date/notes;已有则跳过) - 发来药盒 / 处方 / 包装 / 说明书 / 药片「帮我把这个药记一下」(含报告解读技能转交)→ 识图(药名清晰则不等确认)→
list-drug --user-name 张三:唯一命中且有图则不上传直接记;已有但无图且要记服药则upload-image后add-dose --drug-image-key;缺档才upload-image→add-drug --user-name 张三 - 发来药盒图给已有无图的阿莫西林打卡 → 唯一命中后
upload-image,add-dose --records里该药带drug_image_key - 发来处方单「这些药都加到档案里,今早都吃过了」→ 识图 →
list-drug→ 能确定的直接写;缺档的新建;已有无图的补upload-image到add-dose;一次add-dose --records - 换一台 Agent 再发同一张药盒 / 再说同一药名 → 查重唯一命中:有图则不上传;无图且在记服药则补传图片到
add-dose
不处理,转交对应技能:
- 「把阿莫西林改成一天两次」(修改)
- 「阿莫西林停了 / 不吃了」(停药)
- 「把昨天那条服药记录删掉」(删除)
- 「我最近在吃哪些药 / 服药记录给我看看」(查询)
不调用本技能(普通闲聊,不是药):
- 「刚喝了杯柠檬水」
- 「喝了凉茶 / 王老吉」
- 「今天喝了咖啡 / 牛奶 / 汤」
- 「倒杯茶 / 来点果汁」
错误处理
| 情况 | 处理 |
|---|---|
| 柠檬水 / 凉茶 / 饮料 / 食物等非药品 | 不调用本技能;已误入则立刻停止,不登录、不跑脚本,当普通对话处理 |
| 未登录 | 引导扫码登录后再执行业务命令 |
| out_of_scope | 照实告知该操作不由本技能负责,引导用对应技能,不重试 |
| 缺药名 | 向用户追问药名,禁止编造 |
| 记忆有姓名但 add-drug 未带 –user-name | 补上 --user-name / drugs[].user_name 再提交;禁止把姓名写进 --name |
| 要记服药但无可信 drug_id | 先查重:唯一确定则 add-dose,无档则 add-drug 再 add-dose;多条无法确定才问 |
查重 need_user_choice 为 true | 询问用户,展示药信息与图片;选定后再 add-dose;都不是才新建 |
查重已唯一确定(resolved 有值) | 直接写入,不要再等确认 |
| 用户尚未选择(仅限已询问的歧义项) | 停止等待,禁止自行挑一条 drug_id |
| 查询接口 code=1 | 视为尚无档案(空列表),可以新建 |
| 查询接口 code=-1 | 转述错误,中止建档,避免查重失败时误建重复档案 |
| 图片看不清 / 识别不出药名 | 如实告知,请用户重拍或口头补充,禁止编造 |
| 图片上传失败 | 转述 error;经用户同意后可先不带 drug_image_key 建档,并说明图片未存档 |
| 图上药物全部已有档案且都有图 | 不调用 upload-image;告知已有并复用 drug_id |
| 已有档案无图 + 药盒图记服药 | upload-image 后把 key 写入 add-dose 对应药的 drug_image_key |
| API 失败 | 转述 error;批量写入失败则全部未落库,不要说「部分已保存」 |
补充资料
- 队友 API 字段与示例请求体:[reference.md](reference.md)