diff --git a/OCR_USAGE_GUIDE.md b/OCR_USAGE_GUIDE.md deleted file mode 100644 index 38a2258..0000000 --- a/OCR_USAGE_GUIDE.md +++ /dev/null @@ -1,237 +0,0 @@ -# OCR热量识别功能使用指南 - -## 功能概述 - -OCR热量识别功能允许用户通过拍摄或上传包含食物信息的图片,自动识别其中的热量信息,大大简化了餐食记录的过程。 - -## 主要特性 - -### 1. 多OCR引擎支持 -- **Tesseract OCR**: 开源OCR引擎,支持中英文识别 -- **PaddleOCR**: 百度开源OCR,对中文识别效果优秀 -- **EasyOCR**: 简单易用的OCR库,支持多语言 - -### 2. 智能验证机制 -- **多级验证**: 结合OCR结果、食物数据库和用户学习数据 -- **置信度评估**: 为每个识别结果提供置信度评分 -- **用户修正**: 支持用户手动修正识别结果 - -### 3. 学习优化系统 -- **用户反馈学习**: 记录用户修正,提高后续识别准确性 -- **数据库匹配**: 与内置食物数据库进行智能匹配 -- **模式识别**: 识别多种热量表示格式 - -## 使用方法 - -### 1. 启动OCR功能 - -#### 在移动端界面: -1. 打开应用,进入"记录"页面 -2. 在食物输入框右侧找到"📷"按钮 -3. 点击按钮打开OCR识别界面 - -#### 在桌面端界面: -1. 在主界面选择"OCR热量识别"功能 -2. 或通过菜单栏访问OCR功能 - -### 2. 上传图片 - -1. 点击"选择图片"按钮 -2. 选择包含食物信息的图片文件 -3. 支持的格式:JPG、JPEG、PNG、BMP、GIF -4. 图片将显示在预览区域 - -### 3. 开始识别 - -1. 确认图片选择正确后,点击"开始识别"按钮 -2. 系统将使用多个OCR引擎进行识别 -3. 识别过程中会显示进度条和状态信息 -4. 识别完成后显示结果 - -### 4. 查看和编辑结果 - -#### 识别结果表格: -- **食物名称**: 识别到的食物名称 -- **热量**: 识别到的热量数值(卡路里) -- **置信度**: 识别结果的置信度(0-1) -- **来源**: 数据来源(OCR、数据库、用户确认) - -#### 详细信息: -- OCR识别过程详情 -- 各引擎的识别结果 -- 处理时间和整体置信度 - -#### 建议: -- 系统提供的改进建议 -- 识别准确性提示 -- 手动输入建议 - -### 5. 编辑和确认结果 - -#### 编辑结果: -1. 双击表格中的任意行或选择后点击"编辑结果" -2. 在弹出的对话框中修改食物名称、热量和置信度 -3. 点击"保存"确认修改 - -#### 确认结果: -1. 检查所有识别结果是否正确 -2. 点击"确认结果"按钮 -3. 系统将保存到餐食记录中 - -## 识别准确性优化 - -### 1. 图片质量要求 - -#### 推荐条件: -- **清晰度**: 图片清晰,文字可读 -- **对比度**: 文字与背景对比明显 -- **角度**: 文字水平,避免倾斜 -- **光照**: 光线充足,避免阴影 - -#### 避免的情况: -- 模糊不清的图片 -- 文字过小或过大的图片 -- 严重倾斜的图片 -- 光线过暗或过亮的图片 - -### 2. 文字格式支持 - -#### 支持的热量表示格式: -- `130卡路里` -- `155 kcal` -- `52千卡` -- `42大卡` -- `110 KJ` (千焦) -- `76卡` - -#### 支持的食物名称: -- 中文食物名称:米饭、鸡蛋、苹果等 -- 英文食物名称:rice、egg、apple等 -- 混合格式:米饭 130卡路里 - -### 3. 提高识别准确性的技巧 - -#### 图片预处理: -- 确保图片中的文字清晰可见 -- 避免复杂的背景干扰 -- 保持文字区域的完整性 - -#### 结果验证: -- 仔细检查识别结果 -- 及时修正错误信息 -- 利用数据库匹配功能 - -#### 学习优化: -- 经常使用修正功能 -- 系统会学习您的修正习惯 -- 提高后续识别的准确性 - -## 故障排除 - -### 1. 常见问题 - -#### 识别失败: -- **原因**: 图片质量差、OCR引擎不可用 -- **解决**: 检查图片质量,确保OCR依赖已安装 - -#### 识别结果不准确: -- **原因**: 图片模糊、文字格式特殊 -- **解决**: 重新拍摄清晰图片,手动修正结果 - -#### 无法打开OCR界面: -- **原因**: 依赖包未安装、模块初始化失败 -- **解决**: 检查requirements.txt中的依赖是否已安装 - -### 2. 依赖安装 - -确保已安装以下依赖包: - -```bash -pip install pytesseract>=0.3.10 -pip install opencv-python>=4.8.0 -pip install paddleocr>=2.7.0 -pip install easyocr>=1.7.0 -``` - -#### Tesseract安装: -- **Windows**: 下载Tesseract安装包并添加到PATH -- **macOS**: `brew install tesseract` -- **Linux**: `sudo apt-get install tesseract-ocr` - -### 3. 性能优化 - -#### 提高识别速度: -- 使用较小的图片文件 -- 选择清晰的图片 -- 避免过于复杂的图片 - -#### 提高识别准确性: -- 使用标准格式的食物标签 -- 保持文字清晰可读 -- 及时修正错误结果 - -## 技术架构 - -### 1. 模块结构 - -``` -modules/ocr_calorie_recognition.py # OCR识别模块 -gui/ocr_calorie_gui.py # OCR GUI界面 -test_ocr_system.py # 测试脚本 -``` - -### 2. 核心组件 - -#### OCRCalorieRecognitionModule: -- 多OCR引擎集成 -- 图片预处理 -- 热量信息提取 -- 数据库匹配 -- 用户学习系统 - -#### OCRCalorieGUI: -- 图片上传界面 -- 识别结果展示 -- 结果编辑功能 -- 用户交互处理 - -### 3. 数据流程 - -1. **图片上传** → 图片预处理 -2. **OCR识别** → 多引擎并行识别 -3. **文本提取** → 热量信息解析 -4. **数据库匹配** → 食物信息验证 -5. **用户确认** → 结果保存和学习 - -## 未来改进计划 - -### 1. 功能增强 -- 支持更多图片格式 -- 增加批量识别功能 -- 支持手写文字识别 -- 集成营养信息识别 - -### 2. 性能优化 -- 优化识别算法 -- 提高处理速度 -- 减少内存占用 -- 支持GPU加速 - -### 3. 用户体验 -- 改进界面设计 -- 增加语音输入 -- 支持离线识别 -- 提供更多个性化选项 - -## 联系支持 - -如果您在使用OCR功能时遇到问题,请: - -1. 查看本文档的故障排除部分 -2. 运行测试脚本检查系统状态 -3. 检查依赖包是否正确安装 -4. 提供详细的错误信息和截图 - ---- - -*最后更新: 2024年12月* diff --git a/PROJECT_SUMMARY.md b/PROJECT_SUMMARY.md deleted file mode 100644 index 485f0b5..0000000 --- a/PROJECT_SUMMARY.md +++ /dev/null @@ -1,193 +0,0 @@ -# 个性化饮食推荐助手 - 项目完成总结 - -## 🎯 项目概述 - -基于您的需求,我已经完成了一个完整的个性化饮食推荐系统,具有以下核心特性: - -### ✨ 核心功能 -1. **5天数据采集** - 详细记录用户三餐数据 -2. **智能问卷系统** - 收集用户偏好、生理信息、个性化因素 -3. **大模型集成** - 深度理解用户需求,提供智能分析 -4. **混合推荐系统** - 结合机器学习和AI的个性化推荐 -5. **持续学习机制** - 根据用户反馈不断优化模型 -6. **女性专属优化** - 考虑生理周期、排卵期等特殊因素 -7. **现代化GUI** - 基于CustomTkinter的美观界面 - -## 🏗️ 基座架构设计 - -### 核心基座 (`core/base.py`) -- **BaseModule**: 所有功能模块的抽象基类 -- **DataManager**: 统一的数据管理基座 -- **EventBus**: 事件总线,支持模块间通信 -- **ModuleManager**: 模块管理器,统一管理所有功能模块 -- **AppCore**: 应用核心,协调所有模块 - -### 功能模块 -1. **数据采集模块** (`modules/data_collection.py`) - - 问卷数据收集 - - 餐食记录管理 - - 用户反馈处理 - -2. **AI分析模块** (`modules/ai_analysis.py`) - - 用户意图分析 - - 营养状况分析 - - 生理状态分析 - - 餐食建议生成 - -3. **推荐引擎模块** (`modules/recommendation_engine.py`) - - 基于历史数据的推荐 - - 基于相似用户的推荐 - - 基于内容相似性的推荐 - - 基于生理状态的推荐 - - 多维度融合推荐 - -4. **GUI界面模块** (`gui/main_window.py`) - - 现代化界面设计 - - 数据采集界面 - - AI分析界面 - - 推荐系统界面 - - 个人中心界面 - -## 🔧 技术特点 - -### 1. 基座架构优势 -- **代码复用**: 所有模块基于统一基座,减少重复代码 -- **模块化设计**: 每个功能独立,易于维护和扩展 -- **统一接口**: 所有模块使用相同的接口规范 -- **事件驱动**: 支持模块间松耦合通信 - -### 2. 大模型深度集成 -- **用户意图理解**: 不仅理解表面需求,还分析深层意图 -- **情绪状态分析**: 考虑用户当前情绪对饮食需求的影响 -- **生理周期智能**: 专门针对女性的生理周期分析 -- **个性化建议**: 结合星座、性格等多维度因素 - -### 3. 智能推荐系统 -- **多维度融合**: 历史偏好 + 相似用户 + 内容相似性 + 生理状态 -- **持续学习**: 根据用户反馈不断优化推荐算法 -- **个性化过滤**: 考虑过敏、不喜欢等个人限制 -- **置信度评估**: 为每个推荐提供置信度评分 - -### 4. 女性专属功能 -- **生理周期跟踪**: 自动计算月经周期状态 -- **营养需求调整**: 根据生理周期推荐不同营养素 -- **情绪变化考虑**: 分析生理周期对情绪和食欲的影响 -- **个性化建议**: 提供针对性的饮食建议 - -## 📁 项目结构 - -``` -diet_recommendation_app/ -├── core/ # 核心基座 -│ └── base.py # 基础架构 -├── modules/ # 功能模块 -│ ├── data_collection.py # 数据采集 -│ ├── ai_analysis.py # AI分析 -│ └── recommendation_engine.py # 推荐引擎 -├── gui/ # GUI界面 -│ └── main_window.py # 主窗口 -├── data/ # 数据存储 -│ ├── users/ # 用户数据 -│ └── training/ # 训练数据 -├── models/ # 模型存储 -├── logs/ # 日志文件 -├── main.py # 主应用入口 -├── start.py # 启动脚本 -├── requirements.txt # 依赖包 -├── .env.example # 配置示例 -└── README.md # 项目说明 -``` - -## 🚀 快速开始 - -### 1. 安装依赖 -```bash -pip install -r requirements.txt -``` - -### 2. 配置环境 -```bash -cp .env.example .env -# 编辑 .env 文件,配置API密钥(可选) -``` - -### 3. 启动应用 -```bash -python start.py -``` - -## 💡 使用流程 - -### 1. 用户注册/登录 -- 输入用户ID和姓名 -- 系统自动创建用户档案 - -### 2. 数据采集(5天) -- **基础信息问卷**: 年龄、性别、身高体重等 -- **口味偏好问卷**: 甜、咸、辣、酸等偏好评分 -- **生理信息问卷**: 月经周期、排卵期症状等 -- **餐食记录**: 详细记录三餐内容和满意度 - -### 3. AI分析 -- **用户意图分析**: 理解用户真实需求 -- **营养分析**: 分析餐食营养状况 -- **生理状态分析**: 分析当前生理周期状态 - -### 4. 个性化推荐 -- **智能推荐**: 基于多维度因素生成推荐 -- **用户反馈**: 收集用户对推荐的反馈 -- **持续优化**: 根据反馈不断改进推荐算法 - -## 🔮 核心创新点 - -### 1. 基座架构设计 -- 避免了"一个代码一个功能"的问题 -- 统一的数据管理和事件处理 -- 模块化设计,易于扩展和维护 - -### 2. 大模型深度集成 -- 不仅用于营养分析,还用于用户需求理解 -- 结合传统机器学习和大模型的优势 -- 提供更智能、更个性化的服务 - -### 3. 女性专属优化 -- 深度考虑生理周期对饮食需求的影响 -- 结合星座、性格等个性化因素 -- 提供更贴心的个性化服务 - -### 4. 持续学习机制 -- 避免完全随机推荐的问题 -- 根据用户反馈不断优化模型 -- 提供越来越精准的推荐 - -## 🎉 项目完成度 - -✅ **核心基座架构** - 完成 -✅ **数据采集系统** - 完成 -✅ **AI分析模块** - 完成 -✅ **推荐引擎** - 完成 -✅ **GUI界面** - 完成 -✅ **女性专属功能** - 完成 -✅ **持续学习机制** - 完成 -✅ **大模型集成** - 完成 - -## 🔧 后续扩展建议 - -1. **移动端适配**: 开发手机APP版本 -2. **云端部署**: 支持多用户在线使用 -3. **更多大模型**: 集成更多AI模型 -4. **营养数据库**: 扩展更丰富的食物营养数据 -5. **社交功能**: 添加用户交流和分享功能 - ---- - -**项目已完成,可以立即运行使用!** 🎊 - -所有功能都基于您提出的需求设计,特别是: -- ✅ 5天数据采集系统 -- ✅ 大模型深度集成用于需求分析 -- ✅ 女性生理周期智能优化 -- ✅ 星座等个性化因素考虑 -- ✅ 持续学习和模型矫正机制 -- ✅ 基座架构避免代码重复 -- ✅ 现代化桌面GUI界面 diff --git a/README_DOCKER.md b/README_DOCKER.md deleted file mode 100644 index 5499a0c..0000000 --- a/README_DOCKER.md +++ /dev/null @@ -1,273 +0,0 @@ -# Docker 部署指南 - -本文档说明如何使用Docker部署个性化饮食推荐助手Web应用。 - -## 📋 前置要求 - -- Docker Engine 20.10+ -- Docker Compose 2.0+ - -## 🚀 快速开始 - -### 方式一:使用 Docker Compose(推荐) - -#### 生产环境 - -```bash -# 构建并启动容器 -docker-compose up -d - -# 查看日志 -docker-compose logs -f - -# 停止容器 -docker-compose down -``` - -#### 开发环境(支持代码热重载) - -```bash -# 使用开发配置启动 -docker-compose -f docker-compose.dev.yml up -d - -# 查看日志 -docker-compose -f docker-compose.dev.yml logs -f - -# 停止容器 -docker-compose -f docker-compose.dev.yml down -``` - -### 方式二:使用 Docker 命令 - -```bash -# 构建镜像 -docker build -t diet-recommendation-app . - -# 运行容器 -docker run -d \ - --name diet_recommendation_app \ - -p 7400:7400 \ - -v $(pwd)/data:/app/data \ - -v $(pwd)/logs:/app/logs \ - -v $(pwd)/models:/app/models \ - diet-recommendation-app - -# 查看日志 -docker logs -f diet_recommendation_app - -# 停止容器 -docker stop diet_recommendation_app -docker rm diet_recommendation_app -``` - -## 🌐 访问应用 - -容器启动后,访问: -- **主页**: http://localhost:7400 -- **背诵排序**: http://localhost:7400/recitation -- **数据采集**: http://localhost:7400/data-collection -- **智能推荐**: http://localhost:7400/recommendation -- **营养分析**: http://localhost:7400/analysis -- **健康检查**: http://localhost:7400/health - -## 📁 数据持久化 - -以下目录会自动挂载到容器中,确保数据不丢失: - -- `./data` - 用户数据和数据库 -- `./logs` - 日志文件 -- `./models` - 训练好的模型文件 - -## 🔧 配置说明 - -### 环境变量 - -可以通过 `docker-compose.yml` 中的 `environment` 部分或 `.env` 文件配置: - -```yaml -environment: - - FLASK_ENV=production - - QWEN_API_KEY=your_api_key_here -``` - -### 端口配置 - -默认端口为 `7400`,如需修改: - -```yaml -ports: - - "8080:7400" # 将主机的8080端口映射到容器的7400端口 -``` - -## 🐛 故障排除 - -### 查看容器日志 - -```bash -# Docker Compose -docker-compose logs -f web - -# Docker -docker logs -f diet_recommendation_app -``` - -### 进入容器调试 - -```bash -# Docker Compose -docker-compose exec web bash - -# Docker -docker exec -it diet_recommendation_app bash -``` - -### 重启容器 - -```bash -# Docker Compose -docker-compose restart - -# Docker -docker restart diet_recommendation_app -``` - -### 重新构建镜像 - -```bash -# Docker Compose -docker-compose build --no-cache - -# Docker -docker build --no-cache -t diet-recommendation-app . -``` - -## 📊 健康检查 - -容器包含健康检查功能,可以通过以下方式查看状态: - -```bash -# Docker Compose -docker-compose ps - -# Docker -docker ps -``` - -健康检查端点:`http://localhost:7400/health` - -## 🔒 安全建议 - -1. **生产环境**: - - 使用反向代理(Nginx/Traefik) - - 配置HTTPS - - 限制端口访问 - - 使用环境变量管理敏感信息 - -2. **数据备份**: - - 定期备份 `data` 目录 - - 备份 `models` 目录中的模型文件 - -## 🚢 生产部署示例 - -### 使用 Nginx 作为反向代理 - -```nginx -server { - listen 80; - server_name your-domain.com; - - location / { - proxy_pass http://localhost:7400; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } -} -``` - -## 💾 小内存机器配置(512MB-1GB) - -如果你的 Linux 机器内存较小,可以使用专门优化的小内存版本: - -```bash -# 使用小内存优化的 Dockerfile 和配置 -docker-compose -f docker-compose.low-mem.yml up -d - -# 查看日志 -docker-compose -f docker-compose.low-mem.yml logs -f - -# 停止容器 -docker-compose -f docker-compose.low-mem.yml down -``` - -### 小内存优化措施 - -1. **单 Worker 配置**:Gunicorn 使用 1 个 worker + 2 个线程,减少内存占用 -2. **最小化依赖**:移除 GUI 相关依赖(CustomTkinter、Kivy等) -3. **OpenCV Headless**:使用 `opencv-python-headless`,不包含 GUI 组件 -4. **内存限制**:容器内存限制为 512MB(最大),保留 256MB -5. **环境变量优化**:设置 `MALLOC_ARENA_MAX=2` 和 `PYTHONHASHSEED=0` 减少内存碎片 - -### 内存需求对比 - -| 配置 | 内存需求 | 适用场景 | -|------|---------|---------| -| 标准版(Dockerfile) | 1GB+ | 服务器、开发环境 | -| 小内存版(Dockerfile.low-mem) | 512MB-1GB | 树莓派、小型 VPS、低配服务器 | - -### 手动调整内存限制 - -如果使用标准版,可以通过修改 `docker-compose.yml` 来限制内存: - -```yaml -services: - web: - deploy: - resources: - limits: - memory: 512M # 限制最大内存 - reservations: - memory: 256M # 保留内存 -``` - -## 📝 注意事项 - -1. **OCR功能**: - - Docker镜像已包含 Tesseract OCR 支持(轻量级) - - **未包含** PaddleOCR 和 EasyOCR(内存占用大,需要手动安装) - - 默认只使用 Tesseract OCR,内存占用很小 - -2. **内存限制**: - - 标准版:建议至少分配 **1GB 内存**给容器 - - 小内存版:可以在 **512MB 内存**的机器上运行 - -3. **Worker 数量调整**: - - 标准版默认 2 个 worker(适合 1GB+ 内存) - - 小内存机器可以在 `Dockerfile` 中修改为 1 个 worker: - ```dockerfile - CMD ["python", "-m", "gunicorn", "--bind", "0.0.0.0:7400", "--workers", "1", ...] - ``` - -4. **文件权限**:确保挂载的目录有适当的读写权限 - -5. **时区设置**:如需修改时区,在Dockerfile中添加: - ```dockerfile - ENV TZ=Asia/Shanghai - RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - ``` - -## 🔄 更新应用 - -```bash -# 停止容器 -docker-compose down - -# 拉取最新代码 -git pull - -# 重新构建并启动 -docker-compose build --no-cache -docker-compose up -d -``` - diff --git a/README_GIT_PUSH.md b/README_GIT_PUSH.md deleted file mode 100644 index b8fd907..0000000 --- a/README_GIT_PUSH.md +++ /dev/null @@ -1,182 +0,0 @@ -# Git 自动上传脚本使用指南 - -本目录提供了三个版本的 Git 自动上传脚本,适用于不同操作系统。 - -## 📋 脚本说明 - -### 1. `git_push.sh` - Linux/Mac Bash 脚本 -适用于 Linux 和 MacOS 系统。 - -**使用方法:** -```bash -# 给脚本添加执行权限(首次使用) -chmod +x git_push.sh - -# 基本使用(交互式输入提交信息) -./git_push.sh - -# 直接指定提交信息 -./git_push.sh "feat: 添加新功能" -``` - -### 2. `git_push.bat` - Windows 批处理脚本 -适用于 Windows 系统。 - -**使用方法:** -```cmd -# 基本使用(交互式输入提交信息) -git_push.bat - -# 直接指定提交信息 -git_push.bat "feat: 添加新功能" -``` - -### 3. `git_push.py` - Python 跨平台脚本(推荐) -适用于所有操作系统(Windows、Linux、Mac),需要 Python 3.6+。 - -**使用方法:** -```bash -# 基本使用(交互式输入提交信息) -python git_push.py - -# 直接指定提交信息 -python git_push.py "feat: 添加新功能" - -# 多个单词的提交信息 -python git_push.py "feat: 添加新功能和修复bug" -``` - -## 🚀 功能特性 - -所有脚本都包含以下功能: - -1. **自动检测 Git 仓库**:检查当前目录是否为 Git 仓库 -2. **显示更改状态**:显示将要提交的文件 -3. **交互式确认**:在提交前确认操作 -4. **智能提交信息**: - - 可以直接通过命令行参数指定 - - 也可以交互式输入 - - 默认提供带时间戳的提交信息 -5. **自动添加文件**:自动添加所有更改的文件 -6. **错误处理**:友好的错误提示和处理 -7. **颜色输出**:支持彩色输出(Python 版本) - -## 📝 使用示例 - -### 示例 1:基本使用 -```bash -# Linux/Mac -./git_push.sh - -# Windows -git_push.bat - -# Python(跨平台) -python git_push.py -``` -脚本会: -1. 显示当前更改的文件 -2. 询问是否继续 -3. 请求输入提交信息(或使用默认) -4. 自动添加、提交并推送 - -### 示例 2:指定提交信息 -```bash -# Linux/Mac -./git_push.sh "fix: 修复用户注册bug" - -# Windows -git_push.bat "fix: 修复用户注册bug" - -# Python -python git_push.py "fix: 修复用户注册bug" -``` - -### 示例 3:提交多个文件的更改 -```bash -# 脚本会自动检测所有更改的文件 -./git_push.sh "feat: 添加Docker支持和优化内存配置" -``` - -## ⚙️ 配置说明 - -### 默认分支 -脚本会自动检测当前分支并使用该分支进行推送。 - -### 远程仓库 -确保已配置远程仓库: -```bash -# 查看远程仓库 -git remote -v - -# 如果未配置,添加远程仓库 -git remote add origin -``` - -### 身份验证 -如果推送时遇到身份验证问题: - -1. **HTTPS 方式**: - - 需要输入用户名和密码(或访问令牌) - - 可以配置凭证助手避免每次输入: - ```bash - git config --global credential.helper store - ``` - -2. **SSH 方式**: - - 配置 SSH 密钥更安全 - - 将远程 URL 改为 SSH 格式: - ```bash - git remote set-url origin git@github.com:username/repo.git - ``` - -## 🔧 故障排除 - -### 问题 1:权限不足(Linux/Mac) -```bash -# 解决方案:添加执行权限 -chmod +x git_push.sh -``` - -### 问题 2:Python 脚本无法运行 -```bash -# 检查 Python 版本 -python --version # 需要 Python 3.6+ - -# 如果系统中有多个 Python 版本 -python3 git_push.py -``` - -### 问题 3:推送失败(认证问题) -- 检查远程仓库地址是否正确 -- 确认已配置 SSH 密钥或访问令牌 -- 可以手动执行 `git push origin ` 测试 - -### 问题 4:没有需要提交的更改 -- 脚本会检测是否有未提交的更改 -- 如果没有更改,可以选择拉取远程更新 - -## 💡 建议 - -1. **推荐使用 Python 版本**(`git_push.py`): - - 跨平台兼容性最好 - - 错误处理更完善 - - 支持彩色输出 - -2. **提交信息规范**: - - 使用规范的提交信息格式,例如: - - `feat: 添加新功能` - - `fix: 修复bug` - - `docs: 更新文档` - - `chore: 更新配置` - - `refactor: 代码重构` - -3. **定期提交**: - - 建议频繁提交小的更改 - - 避免一次性提交大量更改 - -## 📚 相关文档 - -- [Git 官方文档](https://git-scm.com/doc) -- [提交信息规范](https://www.conventionalcommits.org/) - diff --git a/core/base.py b/core/base.py index 5b523a2..62f0d67 100644 --- a/core/base.py +++ b/core/base.py @@ -207,15 +207,24 @@ class DataManager: conn.close() def save_user_data(self, user_data: UserData) -> bool: - """保存用户数据""" + """保存用户数据(只保存profile,其他数据用独立表)""" try: conn = sqlite3.connect(self.db_path) cursor = conn.cursor() + # 只保存profile和preferences到users表 + user_basic_data = { + 'user_id': user_data.user_id, + 'profile': user_data.profile, + 'preferences': user_data.preferences, + 'created_at': user_data.created_at, + 'updated_at': user_data.updated_at + } + cursor.execute(''' INSERT OR REPLACE INTO users (user_id, data, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP) - ''', (user_data.user_id, json.dumps(user_data.__dict__))) + ''', (user_data.user_id, json.dumps(user_basic_data))) conn.commit() conn.close() @@ -412,6 +421,110 @@ class DataManager: except Exception as e: logger.error(f"获取分析历史失败: {e}") return [] + + def save_meal_record(self, user_id: str, meal_data: Dict[str, Any]) -> bool: + """保存餐食记录(包括非推荐食物,用于学习)""" + try: + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + + # 提取food_items,如果没有则从foods生成 + food_items = meal_data.get('food_items', []) + if not food_items and meal_data.get('foods'): + food_items = [{'name': food, 'quantity': qty} + for food, qty in zip(meal_data.get('foods', []), + meal_data.get('quantities', []))] + + cursor.execute(''' + INSERT INTO meal_records + (user_id, date, meal_type, foods, quantities, calories, satisfaction_score, food_items) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ''', ( + user_id, + meal_data.get('date'), + meal_data.get('meal_type'), + json.dumps(meal_data.get('foods', [])), + json.dumps(meal_data.get('quantities', [])), + meal_data.get('calories'), + meal_data.get('satisfaction_score'), + json.dumps(food_items) + )) + + conn.commit() + conn.close() + return True + except Exception as e: + logger.error(f"保存餐食记录失败: {e}") + return False + + def save_recommendation_result(self, user_id: str, recommendation_data: Dict[str, Any]) -> int: + """保存推荐结果到recommendations表,返回recommendation_id""" + try: + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + + # 添加recommendations表(如果不存在) + cursor.execute(''' + CREATE TABLE IF NOT EXISTS recommendations ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id TEXT, + date TEXT, + meal_type TEXT, + recommended_foods TEXT, + reasoning TEXT, + confidence_score REAL, + special_considerations TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users (user_id) + ) + ''') + + cursor.execute(''' + INSERT INTO recommendations + (user_id, date, meal_type, recommended_foods, reasoning, confidence_score, special_considerations) + VALUES (?, ?, ?, ?, ?, ?, ?) + ''', ( + user_id, + recommendation_data.get('date', datetime.now().strftime('%Y-%m-%d')), + recommendation_data.get('meal_type'), + json.dumps(recommendation_data.get('recommended_foods', [])), + recommendation_data.get('reasoning', ''), + recommendation_data.get('confidence', 0.5), + json.dumps(recommendation_data.get('special_considerations', [])) + )) + + recommendation_id = cursor.lastrowid + conn.commit() + conn.close() + return recommendation_id + except Exception as e: + logger.error(f"保存推荐结果失败: {e}") + return -1 + + def save_feedback_record(self, user_id: str, feedback_data: Dict[str, Any]) -> bool: + """保存用户反馈(用户实际吃的食物,可能不是推荐的)""" + try: + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + + cursor.execute(''' + INSERT INTO feedback_records + (user_id, date, recommended_foods, user_choice, feedback_type) + VALUES (?, ?, ?, ?, ?) + ''', ( + user_id, + feedback_data.get('date', datetime.now().strftime('%Y-%m-%d')), + json.dumps(feedback_data.get('recommended_foods', [])), + feedback_data.get('user_choice', ''), + feedback_data.get('feedback_type', 'custom') # custom表示用户自定义选择 + )) + + conn.commit() + conn.close() + return True + except Exception as e: + logger.error(f"保存反馈记录失败: {e}") + return False class EventBus: diff --git a/modules/recommendation_engine.py b/modules/recommendation_engine.py index 0a93151..2a78b24 100644 --- a/modules/recommendation_engine.py +++ b/modules/recommendation_engine.py @@ -93,6 +93,9 @@ class RecommendationEngine(BaseModule): context = input_data.get('context', {}) try: + # 检查数据充足性 + data_check = self._check_data_sufficiency(user_data) + # 生成完整餐食搭配推荐 meal_combinations = self._generate_meal_combinations(user_data, meal_type, preferences, context) @@ -101,6 +104,7 @@ class RecommendationEngine(BaseModule): 'recommendations': meal_combinations, 'reasoning': self._generate_meal_reasoning(meal_combinations, user_data, meal_type), 'confidence': self._calculate_recommendation_confidence(user_data), + 'data_sufficiency': data_check, 'metadata': { 'meal_type': meal_type, 'combination_count': len(meal_combinations) @@ -117,27 +121,34 @@ class RecommendationEngine(BaseModule): combinations = [] try: - # 1. 基于用户历史数据生成搭配 - historical_combinations = self._generate_historical_combinations(user_data, meal_type) - combinations.extend(historical_combinations) + # 检查数据充足性 + data_check = self._check_data_sufficiency(user_data) - # 2. 基于用户偏好生成个性化搭配 - personalized_combinations = self._generate_personalized_combinations(user_data, meal_type, preferences) - combinations.extend(personalized_combinations) + # 数据充足:使用个性化推荐 + if data_check['sufficient']: + # 1. 基于用户历史数据生成搭配 + historical_combinations = self._generate_historical_combinations(user_data, meal_type) + combinations.extend(historical_combinations) + + # 2. 基于用户偏好生成个性化搭配 + personalized_combinations = self._generate_personalized_combinations(user_data, meal_type, preferences) + combinations.extend(personalized_combinations) + + # 3. 如果个性化推荐不足,补充模板 + if len(combinations) < 3: + template_combinations = self._generate_template_combinations(user_data, meal_type) + combinations.extend(template_combinations) - # 3. 基于相似用户生成搭配 - similar_user_combinations = self._generate_similar_user_combinations(user_data, meal_type) - combinations.extend(similar_user_combinations) - - # 4. 如果没有足够数据,使用模板生成 - if len(combinations) < 3: + # 数据不足:使用通用模板推荐 + else: + self.logger.info(f"用户数据不足({data_check['days']}天),使用通用推荐") template_combinations = self._generate_template_combinations(user_data, meal_type) combinations.extend(template_combinations) - # 5. 去重和排序 + # 去重和排序 combinations = self._deduplicate_and_rank_combinations(combinations, user_data) - # 6. 确保至少有一些推荐 + # 确保至少有推荐 if not combinations: combinations = self._generate_fallback_combinations(meal_type) @@ -145,7 +156,6 @@ class RecommendationEngine(BaseModule): except Exception as e: self.logger.error(f"生成餐食搭配失败: {e}") - # 返回基础推荐 return self._generate_fallback_combinations(meal_type) def _generate_historical_combinations(self, user_data: UserData, meal_type: str) -> List[Dict[str, Any]]: @@ -666,18 +676,44 @@ class RecommendationEngine(BaseModule): else: return f"推荐{top_rec['food']},基于您的个人偏好" + def _check_data_sufficiency(self, user_data: UserData) -> Dict[str, Any]: + """检查数据充足性(按日期去重计算天数)""" + if not user_data.meals: + return { + 'sufficient': False, + 'days': 0, + 'meals': 0, + 'message': '暂无餐食记录,将提供通用推荐' + } + + # 按日期去重计算天数 + unique_dates = set(meal.get('date') for meal in user_data.meals if meal.get('date')) + meal_count = len(user_data.meals) + day_count = len(unique_dates) + + return { + 'sufficient': day_count >= 3, + 'days': day_count, + 'meals': meal_count, + 'message': f'已收集{day_count}天{meal_count}餐数据' + (',数据充足' if day_count >= 3 else ',建议继续记录') + } + def _calculate_recommendation_confidence(self, user_data: UserData) -> float: """计算推荐置信度""" - meal_count = len(user_data.meals) + data_check = self._check_data_sufficiency(user_data) + meal_count = data_check['meals'] + day_count = data_check['days'] feedback_count = len(user_data.feedback) # 基于数据量计算置信度 - if meal_count >= 15 and feedback_count >= 5: + if day_count >= 5 and feedback_count >= 5: return 0.9 - elif meal_count >= 10 and feedback_count >= 3: + elif day_count >= 3 and meal_count >= 7: return 0.7 - elif meal_count >= 5: - return 0.5 + elif day_count >= 3: + return 0.6 + elif meal_count >= 3: + return 0.4 else: return 0.3 @@ -991,7 +1027,7 @@ if __name__ == "__main__": # 初始化应用 config = BaseConfig() if initialize_app(config): - print("✅ 应用初始化成功") + print(" 应用初始化成功") # 测试餐食推荐 test_user_id = "test_user_001" @@ -999,7 +1035,7 @@ if __name__ == "__main__": result = generate_meal_recommendations(test_user_id, "lunch", {"taste": "sweet"}) if result and result.get('success'): recommendations = result.get('recommendations', []) - print(f"✅ 餐食推荐成功,推荐了{len(recommendations)}种食物") + print(f" 餐食推荐成功,推荐了{len(recommendations)}种食物") for rec in recommendations[:3]: print(f" - {rec['food']}: {rec.get('score', 0):.2f}") @@ -1007,10 +1043,10 @@ if __name__ == "__main__": result = find_similar_foods(test_user_id, "米饭") if result and result.get('success'): similar_foods = result.get('similar_foods', []) - print(f"✅ 相似食物查找成功,找到{len(similar_foods)}种相似食物") + print(f" 相似食物查找成功,找到{len(similar_foods)}种相似食物") # 清理应用 cleanup_app() - print("✅ 应用清理完成") + print(" 应用清理完成") else: - print("❌ 应用初始化失败") + print(" 应用初始化失败")