# ShopAgent 基于 **LangGraph** 与 **ReAct 模式** 的自主多模态时尚购物智能体,支持文本与图片输入、商品搜索、风格分析与多轮对话。 ## Demo http://120.76.41.98:6008/ ## 概述 ShopAgent 根据用户意图自主决定是否调用工具、调用哪些工具,维护对话状态,并在适当时机给出回复。核心能力包括: - **自主工具选择与执行**:按需调用 `search_products`、`analyze_image_style`、`web_search` - **商品搜索**:通过外部 Search API 检索,结果经 LLM 质量评估后写入会话级结果库,回复中通过 `[SEARCH_RESULTS_REF:ref_id]` 引用,前端自动渲染为商品卡片 - **多轮对话与上下文**:LangGraph + MemorySaver 按 `thread_id` 持久化消息 - **图片理解**:上传图片时可调用 `analyze_image_style` 做风格/属性分析,再结合搜索 - **流式输出**:思考过程、工具调用与结果、正式回复以前端可感知的事件流实时展示,调试面板默认展开 ## 技术栈 | 组件 | 技术 | |------------|------| | Agent 框架 | LangGraph(StateGraph + ReAct) | | LLM | LangChain OpenAI 兼容(默认 gpt-4o-mini,可配 base_url 如 DashScope) | | 推理/思考 | 可选:OpenAI Responses API reasoning / DashScope enable_thinking | | 搜索 | 外部 Search API(HTTP),会话内结果登记到 SearchResultRegistry | | 前端 | Streamlit | ## 架构要点 ### Agent 流程(LangGraph) ``` START → Agent → [有 tool_calls?] → Tools → Agent → … → END ``` - **Agent 节点**:注入 system prompt,调用 `llm_with_tools.invoke(messages)`,产出 AIMessage(含 content 和/或 tool_calls)。 - **条件边**:若最后一条消息含 `tool_calls` 则进入 **Tools** 节点,否则结束。 - **Tools 节点**:执行本轮工具调用,将 ToolMessage 追加到 state,再次回到 Agent。 - **状态**:`AgentState = { messages, current_image_path }`,`messages` 使用 `add_messages` 累加。 ### 搜索结果与引用 - **SearchResultRegistry**:按会话存储每次 `search_products` 的结构化结果(query、质量统计、商品列表),并为每次搜索分配会话内唯一 `ref_id`(如 `sr_1`, `sr_2`)。 - **search_products 工具**:请求 Search API → 用 LLM 对每条结果打标(Relevant / Partially Relevant / Irrelevant)→ 将结果写入 registry,返回包含 `[SEARCH_RESULTS_REF:ref_id]` 的文本及质量摘要。 - **最终回复**:Agent 在正文中写入 `[SEARCH_RESULTS_REF:ref_id]`,前端用正则解析并在对应位置渲染商品卡片(见 `app.py` 中 `SEARCH_RESULTS_REF_PATTERN` 与 `render_message_with_refs`)。 ### 工具列表 | 工具 | 说明 | |------|------| | `search_products(query)` | 文本商品搜索,会话绑定,结果写入 Registry 并返回 ref 引用 | | `analyze_image_style(image_path)` | VLM 分析图片风格/属性,供后续搜索或回复使用 | | `web_search(query)` | 联网检索(如时效、天气、事件等) | ### 流式与调试 - **chat_stream**:`ShoppingAgent.chat_stream(query, image_path)` 迭代产出事件:`debug_update`(思考步骤、工具调用/结果)、`response_delta` / `response_replace`(正式回复增量)、`done`(最终结果)。 - **前端**:发送消息后消费 `chat_stream`,在占位区实时更新工具链、调试步骤和回复;调试面板「思考 & 工具调用详细过程」默认展开,可展示 thinking 与工具结果。 - **chat**:仍保留 `chat()`,内部改为消费 `chat_stream` 直至 `done`,保证兼容。 ## 示例 **文本搜索:** ``` 用户:「有没有适合通勤的女式大衣」 Agent:search_products("通勤 女式 大衣") → 返回 [SEARCH_RESULTS_REF:sr_1],页面展示商品卡片 ``` **图片 + 搜索:** ``` 用户:[上传一张外套图] 「这件是什么风格?找类似款」 Agent:analyze_image_style(path) → 得到风格描述 → search_products("…") → 引用 sr_1 等 ``` **多轮与引用:** ``` 第1轮:「红色连衣裙」→ search_products → 展示结果 第2轮:「要正式一点的」→ 结合上下文 search_products("红色 正式 连衣裙") ``` **时效类(web_search):** ``` 用户:「最近有什么流行元素」 Agent:web_search("时尚 流行 2025") → 结合结果回复 ``` ## 安装与运行 ### 环境要求 - Python 3.10+(LangChain/LangGraph 推荐 3.12+) - 配置 `.env`:至少 `OPENAI_API_KEY`;若用自建或第三方 LLM,可设 `OPENAI_API_BASE_URL`(如 DashScope 兼容地址) ### 步骤 ```bash git clone cd shop_agent python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install -r requirements.txt # 配置 cp .env.example .env # 编辑 .env:OPENAI_API_KEY、可选 OPENAI_API_BASE_URL、SEARCH_API_BASE_URL、SEARCH_API_TENANT_ID 等 ``` ### 可选:本地图片数据 若需本地商品图(如侧边栏「Similar」用本地图),可准备 `data/images/` 下的图片资源;图像风格分析不依赖该目录。 ### 启动 ```bash # 推荐 ./scripts/start.sh # 或 streamlit run app.py ``` 默认访问 `http://localhost:8501`。商品搜索依赖外部 Search API,请在 `.env` 中配置 `SEARCH_API_BASE_URL` 与 `SEARCH_API_TENANT_ID`。 ### 部署 CentOS 8 等部署说明见 **[docs/DEPLOY_CENTOS8.md](docs/DEPLOY_CENTOS8.md)**(若存在)。 ## 配置说明(.env 摘要) | 变量 | 说明 | 默认 | |------|------|------| | `OPENAI_API_KEY` | 必填,LLM/视觉调用 | - | | `OPENAI_API_BASE_URL` | 可选,兼容接口 base URL(如 DashScope) | - | | `OPENAI_MODEL` | 对话模型 | gpt-4o-mini | | `OPENAI_USE_REASONING` | 是否开启思考(OpenAI/DashScope 等) | true | | `OPENAI_REASONING_EFFORT` | reasoning 力度(如 medium) | medium | | `SEARCH_API_BASE_URL` | 搜索服务地址 | 见 config.py | | `SEARCH_API_TENANT_ID` | 租户 ID | 见 config.py | | `SEARCH_PRODUCTS_LIMIT` | 单次搜索返回条数上限 | 20 | 更多见 `app/config.py`。 ## 项目结构(概览) ``` shop_agent/ ├── app/ │ ├── agents/ │ │ └── shopping_agent.py # LangGraph 图、chat/chat_stream、thinking 支持 │ ├── config.py # 配置与环境变量 │ ├── search_registry.py # SearchResultRegistry、ProductItem、SearchResult │ ├── tools/ │ │ ├── search_tools.py # search_products、analyze_image_style、web_search │ │ └── __init__.py │ └── ... ├── app.py # Streamlit UI、流式渲染、引用解析与商品卡片 ├── docs/ │ └── 技术实现报告.md # 详细设计与实现说明 ├── scripts/ │ └── start.sh ├── .env.example ├── requirements.txt └── README.md ``` ---