Personal Chief(私厨) 是一个基于 LangChain/LangGraph 构建的 AI 智能私厨助手。用户通过上传食材照片或输入食材清单,系统可自动识别食材、检索匹配食谱,并从营养价值和制作难度两个维度进行多维度评分排序,最终输出结构化的烹饪建议报告。
- 项目名称:
lc-course(Personal Chief API) - 版本: 0.1.0
- Python 版本要求:
>=3.13, <3.14 - 包管理器: uv
| 层级 | 技术选型 | 说明 |
|---|---|---|
| Web 框架 | FastAPI 0.136+ | 高性能异步 Web 框架 |
| AI 框架 | LangChain 1.2+ / LangGraph | Agent 编排、工具调用、记忆管理 |
| LLM 模型 | Qwen3.5-Plus (百炼 DashScope) | 主要对话与推理模型 |
| 搜索引擎 | Tavily Search | Web 搜索工具,用于食谱检索 |
| 记忆存储 | SQLite + LangGraph SqliteSaver | 会话 checkpoint 持久化 |
| 对象存储 | 阿里云 OSS | 用户上传食材图片存储 |
| 前端 | Next.js 静态导出 | SPA 前端,嵌入 FastAPI 静态服务 |
| 服务器 | Uvicorn | ASGI 服务器 |
| 日志 | Python logging | 标准日志模块 |
lc-course/
├── app/ # 主应用目录
│ ├── __init__.py
│ ├── main.py # FastAPI 应用入口,路由注册,静态文件挂载
│ ├── agent/
│ │ └── project.py # AI Agent 核心:模型初始化、工具定义、记忆管理、流式对话
│ ├── api/
│ │ └── v1/
│ │ ├── __init__.py
│ │ ├── chat.py # 对话 API 路由(流式聊天、历史查询、清空会话)
│ │ └── oss.py # OSS 预签名上传 URL API
│ ├── common/
│ │ ├── __init__.py
│ │ └── logger.py # 全局日志配置
│ ├── models/
│ │ ├── __init__.py
│ │ └── schemas.py # Pydantic 数据模型(ChatRequest)
│ └── static/ # Next.js 前端静态资源
├── resources/ # 资源文件(SQLite 数据库等)
├── Agent/ # Agent 相关实验/扩展目录
├── RAG/ # RAG 相关实验
├── RAGProject/ # RAG 项目实验
├── pyproject.toml # 项目依赖与元数据
├── langgraph.json # LangGraph CLI 配置
├── .env # 环境变量(API Keys 等)
├── main.py # 实验入口脚本
├── tools.py # Agent 工具定义实验
├── SystemPrompt.py # 系统提示词实验
├── init_chat.py # 模型初始化与多模态对话实验
├── init_ollama.py # Ollama 本地模型 Agent 实验
├── ollama_model.py # Ollama 多模态 Agent 实验
├── getweather.py # 天气工具 Agent 实验
├── mesMult.py # 多模态消息 Agent 实验
├── mesMultLocal.ipynb # 多模态本地实验 Notebook
├── _memory.py # Agent 记忆管理实验(SummarizationMiddleware)
├── hello.py / hello.ipynb # 入门实验
└── resume_text.txt # 简历文本(RAG 测试数据)
┌──────────────────────────────────────────────────────┐
│ 浏览器 / 客户端 │
└──────────────────────┬───────────────────────────────┘
│ HTTP/SSE
▼
┌──────────────────────────────────────────────────────┐
│ FastAPI (Uvicorn) │
│ ┌─────────────────┐ ┌──────────────────────────┐ │
│ │ /api/v1/chat/* │ │ /api/v1/oss/presign │ │
│ │ (流式对话 API) │ │ (OSS 预签名上传) │ │
│ └────────┬────────┘ └────────────┬─────────────┘ │
│ │ │ │
│ ┌────────┴────────────────────────┴─────────────┐ │
│ │ 静态文件服务 (Next.js SPA) │ │
│ └───────────────────────────────────────────────┘ │
└──────────────────────┬───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────┐
│ LangChain Agent │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ Qwen3.5-Plus │ │ TavilySearch │ │ SQLite │ │
│ │ (LLM) │ │ (工具) │ │ (Checkpoint)│ │
│ └──────────────┘ └──────────────┘ └────────────┘ │
└──────────────────────────────────────────────────────┘
用户输入(文本/图片)
│
▼
┌──────────────────┐
│ 1. 食材识别评估 │ ← 多模态模型解析图片中的食材
│ 整理可用食材清单 │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 2. 智能食谱检索 │ ← 调用 TavilySearch Web 搜索
│ 以食材为核心关键词 │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 3. 多维度评估排序 │ ← 营养价值 + 制作难度双维度打分
│ 简单营养的排前面 │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ 4. 结构化方案输出 │ ← 食谱信息 / 得分 / 推荐理由 / 参考图片
│ 生成建议报告 │
└──────────────────┘
POST /api/v1/chat/stream
请求体 (JSON):
{
"message": "我有番茄、鸡蛋和青椒,能做什么菜?",
"image_url": "https://example.com/ingredients.jpg",
"thread_id": "user_session_001"
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
message |
string | 是 | 用户输入的文本消息 |
image_url |
string | 否 | 食材图片的 OSS 访问 URL |
thread_id |
string | 是 | 会话线程 ID,用于区分不同用户/会话 |
响应: text/event-stream (SSE 流式输出),逐 chunk 返回 AI 生成的文本内容。
GET /api/v1/chat/messages?thread_id={thread_id}
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
thread_id |
string | 是 | 会话线程 ID |
响应:
{
"messages": [
{ "role": "user", "content": "..." },
{ "role": "assistant", "content": "..." }
]
}DELETE /api/v1/chat/messages?thread_id={thread_id}
清空指定会话的全部历史消息,底层调用 SqliteSaver.delete_thread()。
响应:
{ "success": true }GET /api/v1/oss/presign?filename={filename}
获取阿里云 OSS 的预签名上传 URL(有效期 3600 秒),用于客户端直传图片。
响应:
{
"uploadUrl": "https://bucket.oss-cn-beijing.aliyuncs.com/xxx.jpg?...",
"contentType": "image/jpeg",
"accessUrl": "https://bucket.oss-cn-beijing.aliyuncs.com/xxx.jpg"
}支持的文件类型: jpg, jpeg, png, gif, webp
这是整个项目的核心模块,负责 AI Agent 的初始化和运行。
模型初始化:
model = init_chat_model(
model="qwen3.5-plus",
model_provider="openai",
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url=os.getenv("DASHSCOPE_BASE_URL")
)使用阿里云百炼 (DashScope) 的 Qwen3.5-Plus 模型,通过 OpenAI 兼容接口调用。
工具配置:
search_tool = TavilySearch(max_results=3, topic="general")使用 Tavily Search 作为 Web 搜索工具,每次搜索返回最多 3 条结果。
记忆管理:
connection = sqlite3.connect("resources/personal_chief.db", check_same_thread=False)
checkpointer = SqliteSaver(connection)基于 SQLite 的 LangGraph Checkpoint 机制,实现跨会话的对话记忆持久化。每个 thread_id 对应独立的对话线程。
系统提示词 (System Prompt):
Agent 遵循严格的四步工作流:
- 识别和评估食材(支持图片输入)
- 以食材清单为关键词进行 Web 搜索
- 从营养价值和制作难度双维度量化评分
- 输出结构化报告(含食谱信息、得分、推荐理由、参考图片)
核心函数:
| 函数 | 类型 | 说明 |
|---|---|---|
search_recipes(prompt, image, thread_id) |
异步生成器 | 流式调用 Agent,支持多模态输入,yield 文本 chunk |
clear_messages(thread_id) |
同步函数 | 删除指定会话的全部 checkpoint |
get_messages(thread_id) |
同步函数 | 查询指定会话的历史消息列表 |
class ChatRequest(BaseModel):
message: str # 用户消息文本
image_url: Optional[str] = None # 可选的食材图片 URL
thread_id: str # 会话线程标识LOG_FORMAT = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"- 全局 logger 名称:
personal_chief - 默认输出到 stdout,日志级别 INFO
- 可按需启用文件日志(
logging.FileHandler)
项目依赖 .env 文件进行配置,需要以下环境变量:
| 变量名 | 说明 |
|---|---|
DASHSCOPE_API_KEY |
阿里云百炼 API Key(Qwen 模型调用) |
DASHSCOPE_BASE_URL |
阿里云百炼 API 端点 URL |
DEEPSEEK_API_KEY |
DeepSeek API Key(实验/备选模型) |
DEEPSEEK_BASE_URL |
DeepSeek API 端点 URL |
OSS_ENDPOINT |
阿里云 OSS 域名(默认 oss-cn-beijing.aliyuncs.com) |
OSS_BUCKET |
阿里云 OSS Bucket 名称 |
TAVILY_API_KEY |
Tavily Search API Key(LangChain Tavily 集成自动读取) |
# 安装依赖
uv sync
# 启动服务
python -m app.main
# 或
uvicorn app.main:app --host 127.0.0.1 --port 8001 --reload服务启动后访问 http://127.0.0.1:8001,API 文档自动生成于 http://127.0.0.1:8001/docs。
项目配置了 langgraph.json,可通过 LangGraph CLI 启动:
langgraph devGraph 注册名称: chief_agent → ./app/agent/project.py:agent
- fastapi — Web 框架
- langchain / langchain-community — AI Agent 框架
- langgraph-checkpoint-sqlite — SQLite 记忆持久化
- langchain-tavily — Tavily 搜索工具集成
- openai — OpenAI 兼容接口(调用百炼/DeepSeek)
- dashscope — 阿里云百炼 SDK
- alibabacloud-oss-v2 — 阿里云 OSS SDK
- python-dotenv — 环境变量管理
- uvicorn — ASGI 服务器
- langchain-ollama — Ollama 本地模型集成
- langchain-deepseek — DeepSeek 模型集成
- langchain-chroma / chromadb — 向量数据库(RAG 实验)
- langchain-text-splitters — 文本分割(RAG 实验)
- langgraph-checkpoint-postgres — PostgreSQL checkpoint(备选)
- langgraph-cli[inmem] — LangGraph 开发 CLI
- streamlit — 可视化实验
- pypdf — PDF 解析(RAG 实验)
- ipywidgets / notebook — Jupyter Notebook 支持
Agent 接收的消息格式根据是否有图片动态切换:纯文本时发送 HumanMessage(content=prompt),有图片时发送包含 image 和 text 的多模态 HumanMessage。
对话接口采用 Server-Sent Events 协议,通过 StreamingResponse + 异步生成器实现,确保用户在 Agent 推理过程中即可看到逐步生成的结果。
每个用户/会话通过 thread_id 隔离,底层利用 LangGraph 的 checkpoint 机制实现对话历史的持久化和独立管理。
Next.js 静态导出文件放置在 app/static/ 目录,FastAPI 通过 StaticFiles 中间件挂载,并配置 SPA fallback 路由,使得前端路由刷新不会 404。
开发阶段配置了 allow_origins=["*"],允许浏览器扩展或其他来源的跨域请求。生产环境应限制为具体域名。
项目根目录下的若干 .py 文件为开发过程中的实验脚本,记录了技术演进路径:
| 文件 | 实验内容 |
|---|---|
hello.py / hello.ipynb |
LangChain 入门 |
init_chat.py |
DeepSeek 模型 + 多模态 Agent |
init_ollama.py |
Ollama 本地模型 Agent |
ollama_model.py |
Ollama 多模态能力测试 |
getweather.py |
自定义 Tool + Agent 调用 |
tools.py |
多工具组合(Tavily Search + 结构化输出) |
SystemPrompt.py |
系统提示词效果测试 |
mesMult.py / mesMultLocal.ipynb |
多模态消息格式实验 |
_memory.py |
Agent 记忆管理(InMemorySaver / SqliteSaver / SummarizationMiddleware) |
- 生产环境 CORS 策略收紧
- 用户认证与鉴权机制
- 食谱收藏与个性化推荐
- 营养数据量化(接入食物营养成分 API)
- 支持更多 LLM 模型热切换
- 图片预处理与食材识别专用模型
- 前端路由与 SSR 优化