J.B-Lin commited on
Commit
35f8467
·
1 Parent(s): 2ddf335

docs: 恢复完整版README(补充Cline协作规范强调+新增UI设计说明章节)

Browse files
Files changed (1) hide show
  1. README.md +580 -79
README.md CHANGED
@@ -1,94 +1,595 @@
1
- # 🌸 PregoPal - 孕期陪护AI助手
2
-
3
- 一个温馨的家庭式孕期AI伴侣,基于语音交互与智能分析,为孕妇提供全方位的饮食营养陪伴。
4
-
5
- ## ✨ 核心功能
6
-
7
- ### 1. 🏠 现代仪表盘首页
8
- - **全双工语音交互**:大圆形语音按钮,点击即可说话
9
- - **AI 实时思考**:显示AI当前的思维状态
10
- - **信息卡片**:
11
- - 📅 孕期阶段展示
12
- - 🥗 营养关注与推荐食物
13
- - 🍽️ 昨日饮食回顾
14
- - 🍳 家庭菜谱概览
15
- - ⚖️ 体重管理状态
16
- - **最近饮食记录**:以表格形式展示近3天饮食
17
-
18
- ### 2. 👨‍👩‍👧‍👦 家庭饮食习惯(纯展示)
19
- - **🍳 家庭菜谱**:自动收藏菜谱卡片网格
20
- - **🥗 饮食偏好**:每位家庭成员的偏好/忌
21
- - **📝 家庭记事**:AI记忆的时间线展示
22
- - 支持手动刷新
23
-
24
- ### 3. 📊 三天营养总结
25
- - 选择孕期阶段(早/中/晚期)
26
- - 分析近三天饮食数据
27
- - 智能菜单改进建议
28
-
29
- ### 4. 📈 营养报告(纯HTML仪表盘)
30
- - **综合营养评分**:渐变进度条 + 状态标签
31
- - **餐次完成率**:早餐/午餐/晚餐/加餐的柱状统计
32
- - **关键营养覆盖**:各营养素百分比进度条
33
- - **饮食多样性**:分数 + 食材种类统计
34
- - **AI 饮食建议**根据分析结果智能提示
35
-
36
- ### 5. 🌐 中英文切换
37
- 一键切换中/英文界面
38
-
39
- ## 🚀 快速启动
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
  ```bash
42
- # 1. 安装依赖
43
- pip install -r requirements.txt
44
 
45
- # 2. 运行
46
- python app.py
 
47
 
48
- # 3. 打开浏览器访问
49
- # http://127.0.0.1:7860
 
 
 
 
50
  ```
51
 
52
- ## 🏗️ 项目结构
53
 
54
  ```
55
- PregoPal/
56
- ├── app.py # 应用入口
57
- ├── config.py # 全局配置
58
- ├── loop.py # 核心循环引擎
59
- ├── utils.py # 工具函数CSS/翻译/HTML渲染
60
- ├── requirements.txt # 依赖清单
61
- ├── ui/
62
- │ └── app_builder.py # Gradio界面构建(4 Tab)
63
- ├── modules/
64
- │ ├── voiceprint.py # 声纹识别
65
- │ ├── diet_logger.py # 饮食日志
66
- │ ├── diet_extractor.py # 饮食信息提取
67
- │ ├── nutrition_analyzer.py # 营养分析
68
- │ ├── meal_recommender.py # 菜品推荐
69
- │ ├── family_manager.py # 家庭管理
70
- │ └── nutrition_standards.py # 营养标准
71
- ├── plugins/ # Loop插件
72
- ├── core/ # 核心基础设施
73
- └── data/ # 数据存储
74
  ```
75
 
76
- ## 🎨 UI 设计特色
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
- - **Glassmorphism 毛玻璃卡片**:现代、轻盈的视觉风格
79
- - **粉色主题**:温暖、舒适的孕期配色
80
- - **纯HTML渲染**:营养报告无需matplotlib,实时生成
81
- - **响应式布局**:桌面与移动端自适应
82
- - **Tab永不折叠**:所有Tab始终可见
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
- ## 🔧 技术栈
85
 
86
- - **前端**:Gradio + 自定义CSS/HTML
87
- - **后端**:Python
88
- - **语音**:声纹识别 + 全双工语音交互
89
- - **AI**:大语言模型驱动分析
90
- - **数据**:JSON本地存储
91
 
92
- ## 📝 许可
93
 
94
- MIT License
 
1
+ ---
2
+ title: PregoPal
3
+ emoji: 📈
4
+ colorFrom: pink
5
+ colorTo: green
6
+ sdk: gradio
7
+ sdk_version: 6.16.0
8
+ python_version: '3.13'
9
+ app_file: app.py
10
+ pinned: false
11
+ license: mit
12
+ short_description: Voice-based Pregnant Meal & Nutrition Tracker
13
+ ---
14
+
15
+ # PregoPal — 孕期陪护 AI 助手
16
+
17
+ > 🔴 **【Cline 并行协作核心文档】**
18
+ >
19
+ > README 是所有并行 Cline 同步接口规范、数据结构、协作约定唯一全局文档。
20
+ > **任何 Cline 不得随意简化、删除或修改本 README 的结构性内容**(包括但不限于模块接口签名、数据 Schema、协作流程、冲突策略)。
21
+ >
22
+ > 修改原则:
23
+ > 1. 改接口签名 → 必须同步更新对应章节
24
+ > 2. 新增模块 → 必须在架构图/模块表中添加条目
25
+ > 3. 新增配置 → 必须在 config 章节追加说明
26
+ > 4. 数据格式变更 → 更新 Schema 表
27
+ >
28
+ > 每次 commit 前请检查:本 README 是否仍反映项目最新状态。
29
+
30
+ ---
31
+
32
+ ## 1. 项目概述
33
+
34
+ PregoPal 是一款面向孕期家庭的 AI 陪护工具,支持
35
+
36
+ | 功能 | 状态 | 负责模块 |
37
+ |------|------|----------|
38
+ | 🎤 声纹识别与家庭成员区分 | 基线可用 | `modules/voiceprint.py` |
39
+ | 🍽️ 今日菜品推荐(营养+家庭能力) | 基线可用 | `modules/meal_recommender.py` |
40
+ | 📝 饮食记录储存(JSON + Markdown) | 已实现 | `modules/diet_logger.py` + `modules/diet_extractor.py` |
41
+ | 📊 营养分析与可视化报告 | 基线可用 | `modules/nutrition_analyzer.py` + `modules/nutrition_standards.py` |
42
+
43
+ **技术栈**: Python 3.13 · Gradio 6.16 · MiniCPM-o 4.5 · Matplotlib · Pandas
44
+
45
+ ---
46
+
47
+ ## 2. 架构总览
48
+
49
+ ```
50
+ app.py ← Gradio 薄入口
51
+ ├── ui/app_builder.py ← 前端 Tab 布局(4 Tab: 首页/家庭/总结/报告)
52
+ ├── loop.py ← 每日自动分析循环(状态机)
53
+ │ ├── plugins/base.py ← 插件基类(LoopPlugin, PluginRegistry, LoopContext)
54
+ │ ├── plugins/family_quiz.py ← 家庭问卷插件(菜谱/体重检查)
55
+ │ ├── plugins/diet_summary.py ← 昨日饮食总结
56
+ │ ├── plugins/weight_check.py ← 体重检查插件
57
+ │ ├── plugins/family_memory.py← 家庭记忆处理
58
+ │ ├── plugins/dri_analysis.py ← DRIs 营养对比分析
59
+ │ ├── plugins/briefing_generator.py ← 今日简报生成
60
+ │ ├── plugins/three_day_summary.py ← 每三天综合总结
61
+ │ └── plugins/preset_writer.py ← 预设/缓存写入
62
+ ├── modules/ ← 核心业务逻辑(纯函数/无状态)
63
+ │ ├── voiceprint.py ← 声纹识别
64
+ │ ├── meal_recommender.py ← 菜品推荐
65
+ │ ├── diet_extractor.py ← AI 回复数据提取
66
+ │ ├── diet_logger.py ← 饮食记录存储
67
+ │ ├── family_manager.py ← 家庭信息管理
68
+ │ ├── nutrition_standards.py ← 中国官方营养标准
69
+ │ ├── nutrition_analyzer.py ← 营养分析与可视化
70
+ │ └── core/ ← 核心能力层
71
+ │ ├── model_loader.py ← MiniCPM-o 模型加载
72
+ │ ├── voice_processor.py ← 语音处理
73
+ │ ├── vision_processor.py ← 视觉处理
74
+ │ └── conversation_manager.py ← 对话管理
75
+ ├── config.py ← 全局配置(路径/常量/数据模板)
76
+ ├── utils.py ← 工具函数(CSS/翻译/HTML渲染/中文字体设置)
77
+ └── data/ ← 持久化存储
78
+ ├── diet_logs.json ← 结构化饮食记录 JSON
79
+ ├── nutrition_db.json ← 营养数据库 JSON
80
+ ├── family.json ← 家庭成员声纹 JSON
81
+ ├── family/ ← 家庭信息 Markdown(recipes/preferences/memory)
82
+ ├── logs/ ← 每日饮食日志 Markdown
83
+ ├── presets/ ← 预设/缓存 + .daily_status.json
84
+ ├── reports/ ← 营养报告 Markdown
85
+ ├── voices/ ← 声纹音频文件
86
+ └── nutrition/ ← 营养标准原始文档
87
+ ```
88
+
89
+ ---
90
+
91
+ ## 3. 核心模块接口说明
92
+
93
+ > **约定**:模块间通过函数调用传递数据。所有返回 dict 的接口,其 key 约定在下方列出。
94
+ > **修改清单**:改任何模块的输入/输出签名时,必须同步更新本 README 对应条目。
95
+
96
+ ### 3.1 声纹识别 — `modules/voiceprint.py`
97
+
98
+ 类:`VoiceprintManager`
99
+
100
+ | 方法 | 输入 | 输出 | 说明 |
101
+ |------|------|------|------|
102
+ | `register_member(name, relation, audio_path)` | `name: str`, `relation: str`, `audio_path: str` (Path) | `(member_info: dict\|None, msg: str)` | 注册新成员声纹,返回 `{"id","name","relation","registered_at","audio_path","features"}` |
103
+ | `identify_speaker(audio_path)` | `audio_path: str` (Path) | `(member_info: dict\|None, msg: str)` | 识别说话人,需声纹库非空 |
104
+ | `get_members_list()` | — | `str` (格式化文本) | 获取已注册成员列表 |
105
+ | `delete_member(member_id)` | `member_id: str` | `str` (结果消息) | 删除指定成员 |
106
+
107
+ **依赖**:
108
+ - `VOICE_DIR`(`data/voices/`)从 `config.py` 导入
109
+ - `FAMILY_FILE`(`data/family.json`)— JSON 格式 `{"members": [...], "voiceprints": {...}}`
110
+ - `config.VOICEPRINT_SIMILARITY_THRESHOLD`(默认 0.7)
111
+
112
+ **内部数据结构**(`data/family.json`):
113
+ ```json
114
+ {
115
+ "members": [
116
+ {
117
+ "id": "abc12345",
118
+ "name": "小红",
119
+ "relation": "孕妇",
120
+ "registered_at": "2026-06-09T07:00:00",
121
+ "audio_path": "data/voices/abc12345.wav",
122
+ "features": {"mean": 0.01, "std": 0.05, "max": 0.5, "min": -0.5, "zero_crossing_rate": 0.3, "energy": 0.001, "duration": 3.5}
123
+ }
124
+ ],
125
+ "voiceprints": {
126
+ "abc12345": {"mean": 0.01, ...}
127
+ }
128
+ }
129
+ ```
130
+
131
+ > ⚠️ **风险等级:中** — 当前使用频谱统计特征(baseline),后续升级 Whisper encoder 需保持 `register_member`/`identify_speaker` 签名不变。
132
+
133
+ ---
134
+
135
+ ### 3.2 菜品推荐 — `modules/meal_recommender.py`
136
+
137
+ 类:`MealRecommender`
138
+
139
+ | 方法 | 输入 | 输出 | 说明 |
140
+ |------|------|------|------|
141
+ | `get_recommendation(preference, trimester, restrictions)` | `preference: str=""`, `trimester: str="孕中期"`, `restrictions: str=""` | `dict` | 返回今日推荐食谱 |
142
+ | `format_meal_plan(recommendation)` | `recommendation: dict`(上一个方法的返回值) | `str` | 格式化为可读文本 |
143
+
144
+ **输出 dict schema**(`get_recommendation` 返回):
145
+ ```json
146
+ {
147
+ "date": "2026-06-09",
148
+ "trimester": "孕中期",
149
+ "preference": "想吃清淡的",
150
+ "focus": "补充蛋白质、钙、铁",
151
+ "meals": {
152
+ "早餐": "小米粥+包子+煮鸡蛋",
153
+ "午餐": "番茄牛腩+杂粮饭+凉拌黄瓜",
154
+ "晚餐": "蒸蛋羹+小米粥+炒青菜",
155
+ "加餐": "酸奶+坚果"
156
+ },
157
+ "tips": ["🌿 孕中期建议:...", "💡 建议每天饮水..."]
158
+ }
159
+ ```
160
+
161
+ **依赖**:
162
+ - `config.MEAL_TEMPLATES`(4 餐次 × 4 选项的食谱模板 dict)
163
+ - `config.TRIMESTER_ADJUSTMENTS`(各孕期阶段的 focus/avoid 建议)
164
+ - `config.TRIMESTER_TIPS`(各孕期阶段的饮食提示字符串)
165
+
166
+ > ⚠️ **风险等级:中** — 当前为随机模板推荐。后续对接 AI 对话推荐时需保持 `get_recommendation` 签名,内部逻辑可任意替换。
167
+
168
+ ---
169
+
170
+ ### 3.3 AI 对话数据提取 — `modules/diet_extractor.py`
171
+
172
+ 类:`DietExtractor`(全静态方法)
173
+
174
+ | 方法 | 输入 | 输出 | 说明 |
175
+ |------|------|------|------|
176
+ | `extract_all(text)` | `text: str` (AI 回复全文) | `dict` | 正则提取所有结构化数据 |
177
+ | `fallback_extract_diet(text)` | `text: str` | `dict\|None` | 关键词 fallback 提取饮食 |
178
+ | `fallback_extract_thinking(text)` | `text: str` | `dict\|None` | 关键词 fallback 提取思考 |
179
+ | `robust_extract(text)` | `text: str` | `dict` | 正则优先 → fallback 兜底 |
180
+
181
+ **`extract_all` 返回 dict schema**:
182
+ ```json
183
+ {
184
+ "diets": [
185
+ {
186
+ "meals": {"早餐": "全麦面包+鸡蛋+牛奶", "午餐": "清蒸鱼", "晚餐": "", "加餐": ""},
187
+ "日期": "2026-06-09",
188
+ "记录人": "孕妇",
189
+ "备注": "孕妇吃了"
190
+ }
191
+ ],
192
+ "recipes": [{"菜名": "清蒸鱼", "制作人": "丈夫", "难度": "简单", "食材": "鱼、姜", "备注": ""}],
193
+ "preferences": [{"人员": "孕妇", "类型": "偏好", "内容": "爱吃酸"}],
194
+ "weights": [{"日期": "2026-06-09", "体重": "65", "记录人": "孕妇自己"}],
195
+ "memories": [{"类型": "事件", "内容": "婆婆今天来家里"}],
196
+ "thinking": {"当前步骤": "记录饮食", "下一步": "分析营养"} // or None
197
+ }
198
+ ```
199
+
200
+ **Markdown 提取标记格式**(AI 回复中需含):
201
+ ```
202
+ [EXTRACT_DIET]...[/EXTRACT_DIET]
203
+ [EXTRACT_RECIPE]...[/EXTRACT_RECIPE]
204
+ [EXTRACT_PREFERENCE]...[/EXTRACT_PREFERENCE]
205
+ [EXTRACT_WEIGHT]...[/EXTRACT_WEIGHT]
206
+ [EXTRACT_MEMORY]...[/EXTRACT_MEMORY]
207
+ [THINKING]...[/THINKING]
208
+ ```
209
+
210
+ **辅助函数**:
211
+ - `get_extract_prompt(date_str=None) -> str` — 返回含日期占位符的 System Prompt 模板
212
+
213
+ > ✅ **风险等级:低** — 接口稳定,已存在完整测试(`tests/test_diet_extractor.py`)。
214
+
215
+ ---
216
+
217
+ ### 3.4 饮食记录存储 — `modules/diet_logger.py`
218
+
219
+ 类:`DietLogger`
220
+
221
+ | 方法 | 输入 | 输出 | 说明 |
222
+ |------|------|------|------|
223
+ | `add_record(member_name, member_relation, date, meals, mood, notes)` | `member_name: str`, `member_relation: str`, `date: str (ISO)`, `meals: dict`, `mood: str=""`, `notes: str=""` | `(record: dict, md_path: Path)` | 添加记录 → JSON + MD 双写 |
224
+ | `get_recent_records(days=7)` | `days: int` | `list[dict]` | 获取近 N 天记录 |
225
+ | `get_all_markdown_files()` | — | `list[Path]` | 所有 MD 日志文件 |
226
+ | `parse_diet_record(text) — static` | `text: str` | `dict\|None` | [DIET_RECORD] 标记解析(后续 AI 版本用) |
227
+
228
+ **`add_record` 返回的 record dict**:
229
+ ```json
230
+ {
231
+ "id": "a1b2c3d4",
232
+ "member_name": "小红",
233
+ "member_relation": "孕妇",
234
+ "date": "2026-06-09",
235
+ "meals": {"早餐": "燕麦粥+坚果", "午餐": "清蒸鱼+米饭"},
236
+ "mood": "挺好",
237
+ "notes": "今天胃口不错",
238
+ "extensions": {},
239
+ "created_at": "2026-06-09T12:00:00"
240
+ }
241
+ ```
242
+
243
+ **依赖**:
244
+ - `config.DIET_LOG_FILE`(`data/diet_logs.json`)— JSON 格式
245
+ - `config.LOGS_DIR`(`data/logs/`)— Markdown 日志目录
246
+ - `config.DIET_LOG_SCHEMA_VERSION`(当前 "1.0")
247
+
248
+ **Markdown 日志文件格式**(`data/logs/饮食日志_YYYY-MM-DD.md`):
249
+ ```markdown
250
+ # 🥗 孕期饮食日志
251
+
252
+ ## 📋 基本信息
253
+ - **日期**: 2026-06-09
254
+ - **记录人**: 孕妇 - 小红
255
+ - **记录时间**: 2026-06-09T12:00:00
256
+
257
+ ## 🍽️ 今日饮食记录
258
+
259
+ ### 早餐
260
+ - 燕麦粥+坚果
261
+ ... (output truncated) ...
262
+ ```
263
+
264
+ ---
265
+
266
+ ### 3.5 家庭信息管理 — `modules/family_manager.py`
267
+
268
+ 类:`RecipeManager`, `PreferenceManager`, `MemoryManager`
269
+
270
+ | 方法 | 输入 | 输出 | 说明 |
271
+ |------|------|------|------|
272
+ | `RecipeManager.add_recipe(name, maker, difficulty, ingredients, notes)` | 字段见函数签名 | `str` (结果消息) | 添加菜谱 |
273
+ | `RecipeManager.load_all()` | — | `list[dict]` | 加载所有菜谱 |
274
+ | `PreferenceManager.add_preference(member, ptype, content)` | `member/type/content: str` | `str` | 添加偏好/忌口 |
275
+ | `PreferenceManager.load_all()` | — | `list[dict]` | 加载所有偏好 |
276
+ | `MemoryManager.add_memory(mtype, content)` | `mtype/content: str` | `str` | 添加家庭记事 |
277
+ | `MemoryManager.load_all()` | — | `list[dict]` | 加载所有记忆 |
278
+
279
+ **依赖**:
280
+ - `config.FAMILY_DIR`(`data/family/`)— 目录包含 `recipes.md` / `preferences.md` / `memory.md`
281
+
282
+ ---
283
+
284
+ ### 3.6 营养标准 — `modules/nutrition_standards.py`
285
+
286
+ 类:`DRIsParser`(全静态方法)
287
+
288
+ | 方法 | 输入 | 输出 | 说明 |
289
+ |------|------|------|------|
290
+ | `get_dri_for_trimester(trimester)` | `trimester: str`(孕早期/中期/晚期) | `dict` | 获取对应孕期 DRIs 推荐值 |
291
+ | `calculate_bmi(weight, height)` | `weight: float (kg)`, `height: float (cm)` | `float` | BMI 计算 |
292
+ | `get_weight_gain_goal(pre_bmi, trimester)` | `pre_bmi: float`, `trimester: str` | `dict` | 体重增长建议 |
293
+ | `get_dietary_guidelines(trimester)` | `trimester: str` | `dict` | 膳食指南建议 |
294
+ | `assess_nutrient_intake(actual, dri)` | `actual: dict (mg)`, `dri: dict (mg)` | `dict` | 实际 vs 推荐对比 |
295
+
296
+ **输出示例**:
297
+ ```python
298
+ DRIsParser.get_dri_for_trimester("孕中期")
299
+ # 返回:
300
+ {
301
+ "能量": {"推荐摄入量_kcal": 2100, ...},
302
+ "蛋白质": {"推荐摄入量_g": 70, ...},
303
+ "钙": {"推荐摄入量_mg": 1000, ...},
304
+ "铁": {"推荐摄入量_mg": 24, ...},
305
+ "叶酸": {"推荐摄入量_ug": 600, ...},
306
+ "维生素D": {"推荐摄入量_ug": 10, ...},
307
+ "DHA": {"适宜摄入量_mg": 200, ...}
308
+ }
309
+ ```
310
+
311
+ > ✅ **风险等级:低** — 接口清晰。如需调整推荐值数值,修改 `DRIsParser` 内部常量即可。
312
+
313
+ ---
314
+
315
+ ### 3.7 营养分析与可视化 — `modules/nutrition_analyzer.py`
316
+
317
+ 类:`NutritionAnalyzer`
318
+
319
+ | 方法 | 输入 | 输出 | 说明 |
320
+ |------|------|------|------|
321
+ | `analyze_diet(records)` | `records: list[dict]` (diet_logger 格式) | `dict` | 营养覆盖分析 |
322
+ | `generate_report_chart(analysis)` | `analysis: dict`(上一个方法返回) | `matplotlib.figure.Figure` | 4 面板可视化图表 |
323
+ | `generate_report_text(analysis)` | `analysis: dict` | `str` | 文本格式报告 |
324
+ | `export_report_markdown(analysis, filename)` | `analysis: dict`, `filename: str\|None` | `Path` | 导出 Markdown 报告 |
325
+
326
+ **`analyze_diet` 返回 dict schema**(最新版,含 `score` 综合评分):
327
+ ```json
328
+ {
329
+ "score": 72,
330
+ "total_days": 7,
331
+ "total_records": 21,
332
+ "meal_counts": {"早餐": 5, "午餐": 6, "晚餐": 6, "加餐": 4},
333
+ "food_items": ["全麦面包", "鸡蛋", "牛奶", "清蒸鱼", ...],
334
+ "nutrition_coverage": {
335
+ "叶酸": {
336
+ "matched_foods": ["菠菜"],
337
+ "covered": true,
338
+ "recommended_foods": ["菠菜", "西兰花", "芦笋"],
339
+ "benefit": "预防胎儿神经管畸形",
340
+ "daily_recommend": "0.4",
341
+ "unit": "mg"
342
+ },
343
+ ...
344
+ },
345
+ "diversity_score": 75,
346
+ "diversity_details": ["[OK] 早餐: 6/7天 (86%)", ...],
347
+ "suggestions": ["⚠️ 以下营养素摄入不足: 铁, 钙", ...]
348
+ }
349
+ ```
350
+
351
+ **图表输出**(`generate_report_chart` — 保留 matplotlib 版本):
352
+ 1. 左上:营养覆盖雷达图(最多 8 种营养素)
353
+ 2. 右上:各餐次频率柱状图
354
+ 3. 左下:饮食多样性评分环形图
355
+ 4. 右下:营养建议文本框
356
+
357
+ **依赖**:
358
+ - `config.NUTRITION_DB_FILE`(`data/nutrition_db.json`)— 可自定义
359
+ - `config.DEFAULT_NUTRITION_DB`(10 种营养素的内置推荐)
360
+ - `config.REPORTS_DIR`(`data/reports/`)
361
+ - `utils.setup_chinese_font()` — matplotlib 中文字体
362
+
363
+ > 🔴 **风险等级:高(待改造)** — 当前使用通用 `DEFAULT_NUTRITION_DB` 做营养覆盖分析,**尚未对接 `modules/nutrition_standards.py` 的 DRIs 数据**。改造时需:
364
+ > 1. 将 `_calculate_nutrition_coverage` 中的 `self.nutrition_db` 替换为 `DRIsParser.get_dri_for_trimester()`
365
+ > 2. 保持 `analyze_diet(records) -> dict` 签名不变
366
+ > 3. 保持 `nutrition_coverage` 的 dict key 不变(nutrient name 为 key)
367
+
368
+ ---
369
+
370
+ ### 3.8 插件基类 — `plugins/base.py`
371
+
372
+ 核心类型(供所有插件和 loop 使用):
373
+
374
+ ```python
375
+ # 阶段枚举
376
+ class LoopStage(Enum):
377
+ FAMILY_QUIZ = "family_quiz"
378
+ SUMMARIZE = "summarize"
379
+ ANALYZE = "analyze"
380
+ BRIEF = "brief"
381
+ THREE_DAY = "three_day"
382
+ CONSOLIDATE = "consolidate"
383
+
384
+ # 上下文容器(插件间共享)
385
+ @dataclass
386
+ class LoopContext:
387
+ briefing: dict = {} # 累积的简报数据
388
+ weight_data: dict = {}
389
+ diet_records: list = []
390
+ family_recipes: list = [] # family_manager.RecipeManager.load_all() 格式
391
+ family_memory: dict = {} # family_manager.MemoryManager.load_all() 格式
392
+ analysis_results: dict = {}
393
+ errors: list = []
394
+
395
+ # 插件结果
396
+ @dataclass
397
+ class PluginResult:
398
+ success: bool = True
399
+ data: dict = {}
400
+ message: str = ""
401
+
402
+ # 插件基类
403
+ class LoopPlugin(ABC):
404
+ @abstractmethod
405
+ def stage(self) -> LoopStage: ...
406
+ @abstractmethod
407
+ def name(self) -> str: ...
408
+ @abstractmethod
409
+ async def run(self, ctx: LoopContext) -> PluginResult: ...
410
+ ```
411
+
412
+ > ✅ **风险等级:低** — 核心架构稳定。新增插件:实现 `LoopPlugin`,在 `loop.py` 的 `_register_default_plugins` 中注册即可。
413
+
414
+ ---
415
+
416
+ ## 4. 插件管线一览
417
+
418
+ | 插件名 | 阶段 | 文件 | 职责 |
419
+ |--------|------|------|------|
420
+ | `FamilyRecipeQuizPlugin` | `FAMILY_QUIZ` | `plugins/family_quiz.py` | 检查是否需要询问家庭菜谱 |
421
+ | `WeightQuizPlugin` | `FAMILY_QUIZ` | `plugins/family_quiz.py` | 检查是否需要询问体重 |
422
+ | `DietSummaryPlugin` | `SUMMARIZE` | `plugins/diet_summary.py` | 读取昨日饮食日志 |
423
+ | `WeightCheckPlugin` | `SUMMARIZE` | `plugins/weight_check.py` | 体重变化分析 |
424
+ | `FamilyMemoryPlugin` | `SUMMARIZE` | `plugins/family_memory.py` | 提取家庭记忆 |
425
+ | `DRIAnalysisPlugin` | `ANALYZE` | `plugins/dri_analysis.py` | DRIs 营养对比 |
426
+ | `BriefingGeneratorPlugin` | `BRIEF` | `plugins/briefing_generator.py` | 汇总生成今日简报 |
427
+ | `ThreeDaySummaryPlugin` | `THREE_DAY` | `plugins/three_day_summary.py` | 三天综合总结 |
428
+ | `PresetWriterPlugin` | `CONSOLIDATE` | `plugins/preset_writer.py` | 写入预设/缓存 |
429
+
430
+ **插件向 `ctx.briefing` 写入的 key**(`BriefingGeneratorPlugin` 最终消费):
431
+ ```
432
+ ctx.briefing["trimester"] # str
433
+ ctx.briefing["need_ask_weight"] # bool
434
+ ctx.briefing["weight_quiz_message"] # str
435
+ ctx.briefing["weight_evaluation"] # dict
436
+ ctx.briefing["need_ask_recipe"] # bool
437
+ ctx.briefing["recipe_quiz_message"] # str
438
+ ctx.briefing["yesterday_diet"] # dict {"status","summary","meal_count"}
439
+ ctx.briefing["dri_analysis"] # dict {"focus_nutrients","summary"}
440
+ ctx.briefing["recommended_foods"] # list[str]
441
+ ctx.briefing["family_memory"] # dict
442
+ ctx.briefing["thinking_keywords"] # str
443
+ ```
444
+
445
+ ---
446
+
447
+ ## 5. 配置模块 — `config.py`
448
+
449
+ 每个 Cline 如需新增全局常量,**追加到同类型区域末尾**,并在 commit message 中注明。
450
+
451
+ | 配置区 | 主要内容 | 修改风险 |
452
+ |--------|---------|----------|
453
+ | 目录路径 | `DATA_DIR`, `VOICE_DIR`, `LOGS_DIR`, `REPORTS_DIR`, `FAMILY_FILE`, `DIET_LOG_FILE`, `NUTRITION_DB_FILE` | ⚠️ 中 |
454
+ | 常量枚举 | `FAMILY_ROLES`, `TRIMESTERS` | ✅ 低 |
455
+ | 数据模板 | `DEFAULT_NUTRITION_DB` (10种营养素), `MEAL_TEMPLATES` (4×4), `TRIMESTER_ADJUSTMENTS`, `TRIMESTER_TIPS` | ⚠️ 中 |
456
+ | Schema 版本 | `DIET_LOG_SCHEMA_VERSION = "1.0"` | ⚠️(改版本号前需评估向后兼容) |
457
+ | 声纹阈值 | `VOICEPRINT_SIMILARITY_THRESHOLD = 0.7` | ✅ 低 |
458
+
459
+ ---
460
+
461
+ ## 6. 数据文件格式规范
462
+
463
+ | 文件 | 格式 | Schema | 读模块 | 写模块 |
464
+ |------|------|--------|--------|--------|
465
+ | `data/diet_logs.json` | JSON | `{"schema_version": "1.0", "records": [...]}` | `diet_logger`, `nutrition_analyzer` | `diet_logger` |
466
+ | `data/nutrition_db.json` | JSON | `{"营养素名": {"category", "daily_recommend_mg/g/mcg", "foods": [...], "benefit"}}` | `nutrition_analyzer` | `nutrition_analyzer` (首次初始化) |
467
+ | `data/family.json` | JSON | `{"members": [...], "voiceprints": {...}}` | `voiceprint` | `voiceprint` |
468
+ | `data/family/recipes.md` | Markdown | `### 菜名\n- **制作人**: ...` | `family_manager.RecipeManager` | `family_manager.RecipeManager` |
469
+ | `data/family/preferences.md` | Markdown | `### 成员:姓名\n- **偏好**: ...` | `family_manager.PreferenceManager` | `family_manager.PreferenceManager` |
470
+ | `data/family/memory.md` | Markdown | `## 重要事件\n- **日期**: ...` | `family_manager.MemoryManager` | `family_manager.MemoryManager` |
471
+ | `data/logs/饮食日志_*.md` | Markdown | 见 3.4 节 | `plugins/diet_summary` | `diet_logger` |
472
+ | `data/reports/营养报告_*.md` | Markdown | 见 3.7 节 | 用户 | `nutrition_analyzer` |
473
+ | `data/presets/.daily_status.json` | JSON | `{"YYYY-MM-DD": {"summary_done": bool, "day_ended": bool}}` | `loop.DailyStatus` | `loop.DailyStatus` |
474
+
475
+ ---
476
+
477
+ ## 7. 并行 Cline 协作规范
478
+
479
+ ### 7.1 分工建议
480
+
481
+ ```
482
+ Cline A: Modules 强化(营养分析对接 DRIs、菜谱推荐 AI 化)
483
+ Cline B: UI 界面优化(Gradio 前端增强、报告模板美化) ← 当前 Cline
484
+ Cline C: 声纹升级(Whisper encoder 替换频谱特征)
485
+ Cline D: 数据处理与插件增强(diet_extractor fallback、新插件)
486
+ ```
487
+
488
+ ### 7.2 关键约定
489
+
490
+ 1. **改接口前先 grep**:用 `search_files` 搜索方法名找到所有调用方
491
+ 2. **config.py 修改需沟通**:新增常量追加到同类型区域,不删改已有常量名
492
+ 3. **数据文件向后兼容**:新增字段优先用 `extensions: {}` 或新增可选 key,不删除已有 key
493
+ 4. **测试保持通过**:`python tests/run_tests.py` 零失败
494
+ 5. **README 同步更新**:接口签名变更 → 更新本 README 对应章节
495
+
496
+ ### 7.3 Git 工作流(强制执行)
497
 
498
  ```bash
499
+ # 工作前
500
+ git pull --rebase origin main
501
 
502
+ # 开发中:每完成一个独立功能点就提交
503
+ git add -A
504
+ git commit -m "feat: 描述做了什么"
505
 
506
+ # 推送前再次 pull
507
+ git pull --rebase origin main
508
+
509
+ # 测试通过后推送
510
+ python tests/run_tests.py
511
+ git push origin main
512
  ```
513
 
514
+ ### 7.4 Commit Message 规范
515
 
516
  ```
517
+ feat: 新功能/新模块/新接口
518
+ fix: 修复 bug
519
+ test: 添加或修改测试
520
+ refactor: 重构(不改功能)
521
+ docs: 文档更新含本 README
522
+ chore: 配置/依赖/路径调整
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  ```
524
 
525
+ ### 7.5 冲突处理策略
526
+
527
+ | 冲突类型 | 处理方式 |
528
+ |---------|---------|
529
+ | `config.py` 常量冲突 | 取并集,双方新增常量都保留 |
530
+ | 同函数不同实现 | 保留逻辑更完整的一方,另一方改动如果无冲突则合并到合适位置 |
531
+ | 数据文件(JSON/MD)冲突 | 保留两个版本共有的条目 + 各自独有条目(去重) |
532
+ | 测试文件冲突 | **取并集**:保留所有测试用例 |
533
+ | **本 README 冲突** | **取行数更长的一方**,手动整合 |
534
+ | `.gitignore` 冲突 | 取并集 |
535
+
536
+ ---
537
+
538
+ ## 8. UI 设计说明(当前 Cline B 负责)
539
+
540
+ ### 8.1 页面结构
541
+
542
+ 4 Tab 布局,使用 **唯一一个 `@gr.render`** 包裹全部 Tab(避免 Gradio 内部字典迭代崩溃):
543
 
544
+ | Tab | ID | 功能 |
545
+ |-----|----|------|
546
+ | 🏠 首页 | `tab_home` | 语音按钮 + AI 思考 + 信息卡片 + 最近记录 |
547
+ | 👨‍👩‍👧‍👦 家庭 | `tab_family` | 家庭菜谱/偏好/记事 HTML 卡片展示 |
548
+ | 📊 总结 | `tab_summary` | 三天营养分析 + 菜单建议 |
549
+ | 📈 报告 | `tab_report` | 纯 HTML 营养仪表盘(无需 matplotlib) |
550
+
551
+ ### 8.2 设计风格
552
+
553
+ - **Glassmorphism 毛玻璃**:`backdrop-filter: blur(20px)` 半透明卡片
554
+ - **粉色暖调主题**:主色 `#E91E63`、渐变 `#FF6B9D → #FFD6E0`
555
+ - **纯 HTML 渲染**:家庭信息卡、营养报告均使用 HTML + CSS,无需生成图片
556
+ - **中英文切换**:`lang_state` 驱动唯一 `@gr.render`
557
+
558
+ ### 8.3 关键文件
559
+
560
+ | 文件 | 职责 |
561
+ |------|------|
562
+ | `ui/app_builder.py` | Gradio 界面构建(4 Tab + 语言切换) |
563
+ | `utils.py` | CSS 定义 + 翻译字典 + HTML 渲染函数(家庭卡片 + 营养仪表盘) |
564
+
565
+ ---
566
+
567
+ ## 9. 测试
568
+
569
+ ```bash
570
+ # 运行全部测试
571
+ python tests/run_tests.py
572
+ ```
573
+
574
+ 当前测试覆盖:
575
+ - `test_diet_extractor.py` — ✅ 通过(正则解析 + fallback 提取)
576
+ - `test_family_manager.py` — ✅ 通过(菜谱/偏好/记忆 CRUD)
577
+ - `test_nutrition_standards.py` — ✅ 通过(BMI/膳食指南/DRIs 数据)
578
+ - `test_loop.py` — 循环执行测试
579
+ - `test_plugins.py` — 插件集成测试
580
+
581
+ ---
582
+
583
+ ## 10. Model: MiniCPM-o 4.5
584
+
585
+ ```
586
+ Model to be Used: MiniCPM-o 4.5
587
+ ```
588
 
589
+ 核心能力层(`core/` 目录)提供模型加载、语音处理、视觉处理、对话管理的底层能力封装。详见各文件 docstring。
590
 
591
+ ---
 
 
 
 
592
 
593
+ *最后更新: 2026-06-09 | 由 PregoPal Cline 团队维护*
594
 
595
+ > **⚠️ 重要提醒**:本 README 是所有并行 Cline 的协作基础,任何 Cline 在修改代码后,若涉及接口、数据格式、配置的变更,必须同步更新本文件。不得随意简化、删除结构性内容。