Commit 702ba3aa74f87be1d98dd0b5b0cc3812ea7bbbaa
1 parent
8dcb1dc0
readme
Showing
1 changed file
with
126 additions
and
89 deletions
Show diff stats
README.md
| 1 | 1 | # ShopAgent |
| 2 | 2 | |
| 3 | -An autonomous multi-modal fashion shopping agent powered by **LangGraph** and **ReAct pattern**. | |
| 3 | +基于 **LangGraph** 与 **ReAct 模式** 的自主多模态时尚购物智能体,支持文本与图片输入、商品搜索、风格分析与多轮对话。 | |
| 4 | 4 | |
| 5 | 5 | ## Demo |
| 6 | 6 | |
| 7 | -📄 **[demo.pdf](./demo.pdf)** | |
| 8 | - | |
| 9 | -## Overview | |
| 10 | - | |
| 11 | -ShopAgent autonomously decides which tools to call, maintains conversation state, and determines when to respond. Built with **LangGraph**, it uses agentic patterns for intelligent product discovery. | |
| 12 | - | |
| 13 | -**Key Features:** | |
| 14 | -- Autonomous tool selection and execution | |
| 15 | -- Text search via Search API | |
| 16 | -- Conversational context awareness | |
| 17 | -- Real-time visual analysis (style extraction from images) | |
| 18 | - | |
| 19 | -## Tech Stack | |
| 20 | - | |
| 21 | -| Component | Technology | | |
| 22 | -|-----------|-----------| | |
| 23 | -| **Agent Framework** | LangGraph | | |
| 24 | -| **LLM** | any LLM supported by LangChain | | |
| 25 | -| **Search** | Search API (HTTP) | | |
| 26 | -| **Frontend** | Streamlit | | |
| 27 | -| **Dataset** | Kaggle Fashion Products | | |
| 28 | - | |
| 29 | -## Architecture | |
| 30 | - | |
| 31 | -**Agent Flow:** | |
| 32 | - | |
| 33 | -```mermaid | |
| 34 | -graph LR | |
| 35 | - START --> Agent | |
| 36 | - Agent -->|Has tool_calls| Tools | |
| 37 | - Agent -->|No tool_calls| END | |
| 38 | - Tools --> Agent | |
| 39 | - | |
| 40 | - subgraph "Agent Node" | |
| 41 | - A[Receive Messages] --> B[LLM Reasoning] | |
| 42 | - B --> C{Need Tools?} | |
| 43 | - C -->|Yes| D[Generate tool_calls] | |
| 44 | - C -->|No| E[Generate Response] | |
| 45 | - end | |
| 46 | - | |
| 47 | - subgraph "Tool Node" | |
| 48 | - F[Execute Tools] --> G[Return ToolMessage] | |
| 49 | - end | |
| 50 | -``` | |
| 7 | +http://120.76.41.98:6008/ | |
| 8 | + | |
| 9 | + | |
| 10 | +## 概述 | |
| 11 | + | |
| 12 | +ShopAgent 根据用户意图自主决定是否调用工具、调用哪些工具,维护对话状态,并在适当时机给出回复。核心能力包括: | |
| 51 | 13 | |
| 52 | -**Available Tools:** | |
| 53 | -- `search_products(query)` - Text-based product search via Search API | |
| 54 | -- `analyze_image_style(image_path)` - VLM style analysis | |
| 14 | +- **自主工具选择与执行**:按需调用 `search_products`、`analyze_image_style`、`web_search` | |
| 15 | +- **商品搜索**:通过外部 Search API 检索,结果经 LLM 质量评估后写入会话级结果库,回复中通过 `[SEARCH_RESULTS_REF:ref_id]` 引用,前端自动渲染为商品卡片 | |
| 16 | +- **多轮对话与上下文**:LangGraph + MemorySaver 按 `thread_id` 持久化消息 | |
| 17 | +- **图片理解**:上传图片时可调用 `analyze_image_style` 做风格/属性分析,再结合搜索 | |
| 18 | +- **流式输出**:思考过程、工具调用与结果、正式回复以前端可感知的事件流实时展示,调试面板默认展开 | |
| 55 | 19 | |
| 20 | +## 技术栈 | |
| 56 | 21 | |
| 22 | +| 组件 | 技术 | | |
| 23 | +|------------|------| | |
| 24 | +| Agent 框架 | LangGraph(StateGraph + ReAct) | | |
| 25 | +| LLM | LangChain OpenAI 兼容(默认 gpt-4o-mini,可配 base_url 如 DashScope) | | |
| 26 | +| 推理/思考 | 可选:OpenAI Responses API reasoning / DashScope enable_thinking | | |
| 27 | +| 搜索 | 外部 Search API(HTTP),会话内结果登记到 SearchResultRegistry | | |
| 28 | +| 前端 | Streamlit | | |
| 57 | 29 | |
| 58 | -## Examples | |
| 30 | +## 架构要点 | |
| 31 | + | |
| 32 | +### Agent 流程(LangGraph) | |
| 59 | 33 | |
| 60 | -**Text Search:** | |
| 61 | 34 | ``` |
| 62 | -User: "winter coats for women" | |
| 63 | -Agent: search_products("winter coats women") → Returns 5 products | |
| 35 | +START → Agent → [有 tool_calls?] → Tools → Agent → … → END | |
| 64 | 36 | ``` |
| 65 | 37 | |
| 66 | -**Style Analysis + Search:** | |
| 38 | +- **Agent 节点**:注入 system prompt,调用 `llm_with_tools.invoke(messages)`,产出 AIMessage(含 content 和/或 tool_calls)。 | |
| 39 | +- **条件边**:若最后一条消息含 `tool_calls` 则进入 **Tools** 节点,否则结束。 | |
| 40 | +- **Tools 节点**:执行本轮工具调用,将 ToolMessage 追加到 state,再次回到 Agent。 | |
| 41 | +- **状态**:`AgentState = { messages, current_image_path }`,`messages` 使用 `add_messages` 累加。 | |
| 42 | + | |
| 43 | +### 搜索结果与引用 | |
| 44 | + | |
| 45 | +- **SearchResultRegistry**:按会话存储每次 `search_products` 的结构化结果(query、质量统计、商品列表),并为每次搜索分配会话内唯一 `ref_id`(如 `sr_1`, `sr_2`)。 | |
| 46 | +- **search_products 工具**:请求 Search API → 用 LLM 对每条结果打标(Relevant / Partially Relevant / Irrelevant)→ 将结果写入 registry,返回包含 `[SEARCH_RESULTS_REF:ref_id]` 的文本及质量摘要。 | |
| 47 | +- **最终回复**:Agent 在正文中写入 `[SEARCH_RESULTS_REF:ref_id]`,前端用正则解析并在对应位置渲染商品卡片(见 `app.py` 中 `SEARCH_RESULTS_REF_PATTERN` 与 `render_message_with_refs`)。 | |
| 48 | + | |
| 49 | +### 工具列表 | |
| 50 | + | |
| 51 | +| 工具 | 说明 | | |
| 52 | +|------|------| | |
| 53 | +| `search_products(query)` | 文本商品搜索,会话绑定,结果写入 Registry 并返回 ref 引用 | | |
| 54 | +| `analyze_image_style(image_path)` | VLM 分析图片风格/属性,供后续搜索或回复使用 | | |
| 55 | +| `web_search(query)` | 联网检索(如时效、天气、事件等) | | |
| 56 | + | |
| 57 | +### 流式与调试 | |
| 58 | + | |
| 59 | +- **chat_stream**:`ShoppingAgent.chat_stream(query, image_path)` 迭代产出事件:`debug_update`(思考步骤、工具调用/结果)、`response_delta` / `response_replace`(正式回复增量)、`done`(最终结果)。 | |
| 60 | +- **前端**:发送消息后消费 `chat_stream`,在占位区实时更新工具链、调试步骤和回复;调试面板「思考 & 工具调用详细过程」默认展开,可展示 thinking 与工具结果。 | |
| 61 | +- **chat**:仍保留 `chat()`,内部改为消费 `chat_stream` 直至 `done`,保证兼容。 | |
| 62 | + | |
| 63 | +## 示例 | |
| 64 | + | |
| 65 | +**文本搜索:** | |
| 67 | 66 | ``` |
| 68 | -User: [uploads vintage jacket] "what style is this? find matching pants" | |
| 69 | -Agent: analyze_image_style(path) → "Vintage denim bomber..." | |
| 70 | - search_products("vintage pants casual") → Returns matching items | |
| 67 | +用户:「有没有适合通勤的女式大衣」 | |
| 68 | +Agent:search_products("通勤 女式 大衣") → 返回 [SEARCH_RESULTS_REF:sr_1],页面展示商品卡片 | |
| 71 | 69 | ``` |
| 72 | 70 | |
| 73 | -**Multi-turn Context:** | |
| 71 | +**图片 + 搜索:** | |
| 74 | 72 | ``` |
| 75 | -Turn 1: "show me red dresses" | |
| 76 | -Agent: search_products("red dresses") → Results | |
| 77 | - | |
| 78 | -Turn 2: "make them formal" | |
| 79 | -Agent: [remembers context] → search_products("red formal dresses") → Results | |
| 73 | +用户:[上传一张外套图] 「这件是什么风格?找类似款」 | |
| 74 | +Agent:analyze_image_style(path) → 得到风格描述 → search_products("…") → 引用 sr_1 等 | |
| 80 | 75 | ``` |
| 81 | 76 | |
| 82 | -**Complex Reasoning:** | |
| 77 | +**多轮与引用:** | |
| 78 | +``` | |
| 79 | +第1轮:「红色连衣裙」→ search_products → 展示结果 | |
| 80 | +第2轮:「要正式一点的」→ 结合上下文 search_products("红色 正式 连衣裙") | |
| 83 | 81 | ``` |
| 84 | -User: [uploads office outfit] "I like the shirt but need something more casual" | |
| 85 | -Agent: analyze_image_style(path) → Extracts shirt details | |
| 86 | - search_products("casual shirt [color] [style]") → Returns casual alternatives | |
| 87 | 82 | |
| 88 | -**Note:** For image uploads "find similar", use analyze_image_style first to extract attributes, then search_products with the description. | |
| 83 | +**时效类(web_search):** | |
| 89 | 84 | ``` |
| 85 | +用户:「最近有什么流行元素」 | |
| 86 | +Agent:web_search("时尚 流行 2025") → 结合结果回复 | |
| 87 | +``` | |
| 88 | + | |
| 89 | +## 安装与运行 | |
| 90 | 90 | |
| 91 | -## Installation | |
| 91 | +### 环境要求 | |
| 92 | 92 | |
| 93 | -**Prerequisites:** | |
| 94 | -- Python 3.12+ (LangChain 1.x 要求 Python 3.10+) | |
| 95 | -- OpenAI API Key | |
| 93 | +- Python 3.10+(LangChain/LangGraph 推荐 3.12+) | |
| 94 | +- 配置 `.env`:至少 `OPENAI_API_KEY`;若用自建或第三方 LLM,可设 `OPENAI_API_BASE_URL`(如 DashScope 兼容地址) | |
| 95 | + | |
| 96 | +### 步骤 | |
| 96 | 97 | |
| 97 | -### 1. Setup Environment | |
| 98 | 98 | ```bash |
| 99 | -# Clone and install dependencies | |
| 100 | 99 | git clone <repository-url> |
| 101 | -cd ShopAgent | |
| 100 | +cd shop_agent | |
| 102 | 101 | python -m venv venv |
| 103 | -source venv/bin/activate # Windows: venv\Scripts\activate | |
| 102 | +source venv/bin/activate # Windows: venv\Scripts\activate | |
| 104 | 103 | pip install -r requirements.txt |
| 105 | 104 | |
| 106 | -# Configure environment variables | |
| 105 | +# 配置 | |
| 107 | 106 | cp .env.example .env |
| 108 | -# Edit .env and add your OPENAI_API_KEY | |
| 107 | +# 编辑 .env:OPENAI_API_KEY、可选 OPENAI_API_BASE_URL、SEARCH_API_BASE_URL、SEARCH_API_TENANT_ID 等 | |
| 109 | 108 | ``` |
| 110 | 109 | |
| 111 | -### 2. (Optional) Download Dataset | |
| 112 | -For image style analysis, you may download the [Fashion Product Images Dataset](https://www.kaggle.com/datasets/paramaggarwal/fashion-product-images-dataset) from Kaggle: | |
| 110 | +### 可选:本地图片数据 | |
| 113 | 111 | |
| 114 | -```bash | |
| 115 | -python scripts/download_dataset.py | |
| 116 | -``` | |
| 112 | +若需本地商品图(如侧边栏「Similar」用本地图),可准备 `data/images/` 下的图片资源;图像风格分析不依赖该目录。 | |
| 113 | + | |
| 114 | +### 启动 | |
| 117 | 115 | |
| 118 | -### 3. Launch Application | |
| 119 | 116 | ```bash |
| 120 | -# 使用启动脚本(推荐) | |
| 117 | +# 推荐 | |
| 121 | 118 | ./scripts/start.sh |
| 122 | 119 | |
| 123 | -# 或直接运行 | |
| 120 | +# 或 | |
| 124 | 121 | streamlit run app.py |
| 125 | 122 | ``` |
| 126 | 123 | |
| 127 | -Product search uses the external Search API. Configure `SEARCH_API_BASE_URL` and `SEARCH_API_TENANT_ID` in `.env` if needed. | |
| 124 | +默认访问 `http://localhost:8501`。商品搜索依赖外部 Search API,请在 `.env` 中配置 `SEARCH_API_BASE_URL` 与 `SEARCH_API_TENANT_ID`。 | |
| 125 | + | |
| 126 | +### 部署 | |
| 127 | + | |
| 128 | +CentOS 8 等部署说明见 **[docs/DEPLOY_CENTOS8.md](docs/DEPLOY_CENTOS8.md)**(若存在)。 | |
| 129 | + | |
| 130 | +## 配置说明(.env 摘要) | |
| 131 | + | |
| 132 | +| 变量 | 说明 | 默认 | | |
| 133 | +|------|------|------| | |
| 134 | +| `OPENAI_API_KEY` | 必填,LLM/视觉调用 | - | | |
| 135 | +| `OPENAI_API_BASE_URL` | 可选,兼容接口 base URL(如 DashScope) | - | | |
| 136 | +| `OPENAI_MODEL` | 对话模型 | gpt-4o-mini | | |
| 137 | +| `OPENAI_USE_REASONING` | 是否开启思考(OpenAI/DashScope 等) | true | | |
| 138 | +| `OPENAI_REASONING_EFFORT` | reasoning 力度(如 medium) | medium | | |
| 139 | +| `SEARCH_API_BASE_URL` | 搜索服务地址 | 见 config.py | | |
| 140 | +| `SEARCH_API_TENANT_ID` | 租户 ID | 见 config.py | | |
| 141 | +| `SEARCH_PRODUCTS_LIMIT` | 单次搜索返回条数上限 | 20 | | |
| 142 | + | |
| 143 | +更多见 `app/config.py`。 | |
| 144 | + | |
| 145 | +## 项目结构(概览) | |
| 146 | + | |
| 147 | +``` | |
| 148 | +shop_agent/ | |
| 149 | +├── app/ | |
| 150 | +│ ├── agents/ | |
| 151 | +│ │ └── shopping_agent.py # LangGraph 图、chat/chat_stream、thinking 支持 | |
| 152 | +│ ├── config.py # 配置与环境变量 | |
| 153 | +│ ├── search_registry.py # SearchResultRegistry、ProductItem、SearchResult | |
| 154 | +│ ├── tools/ | |
| 155 | +│ │ ├── search_tools.py # search_products、analyze_image_style、web_search | |
| 156 | +│ │ └── __init__.py | |
| 157 | +│ └── ... | |
| 158 | +├── app.py # Streamlit UI、流式渲染、引用解析与商品卡片 | |
| 159 | +├── docs/ | |
| 160 | +│ └── 技术实现报告.md # 详细设计与实现说明 | |
| 161 | +├── scripts/ | |
| 162 | +│ └── start.sh | |
| 163 | +├── .env.example | |
| 164 | +├── requirements.txt | |
| 165 | +└── README.md | |
| 166 | +``` | |
| 128 | 167 | |
| 129 | -Opens at `http://localhost:8501` | |
| 168 | +--- | |
| 130 | 169 | |
| 131 | -### CentOS 8 部署 | |
| 132 | -详见 [docs/DEPLOY_CENTOS8.md](docs/DEPLOY_CENTOS8.md) | ... | ... |