# 电商售后 Agentic RAG 课程项目 技术栈:Python 3.11、FastAPI、LangGraph、Milvus、SQLite、Tavily、DeepSeek。 项目默认使用确定性的 `demo` 决策引擎和 Hash Embedding。无需模型 Key 即可完成数据准备、意图路由、Milvus 检索、SQL 查询、证据评分和多源执行。 ## 1. 环境要求 - Python 3.11 - uv - 使用现有 Ubuntu Milvus 时,Windows 必须能访问其 `19530` 端口 - 本地启动 Milvus 时,需要 Docker Desktop、WSL 2、至少 4 CPU 和 8 GB 内存 ## 2. 安装 ```powershell uv venv --python 3.11 uv sync --extra test ``` 项目直接读取根目录下的 `.env`。DeepSeek、Tavily、Milvus 和数据路径等运行配置统一在该文件中维护。 按需安装可选能力: ```powershell # DeepSeek 模型适配。 uv sync --extra test --extra deepseek # Tavily 网页搜索。 uv sync --extra test --extra web # 本地 Sentence Transformers。 uv sync --extra test --extra embeddings ``` ### 2.1 路径约定 仓库中使用相对路径,运行时根据 `app/config.py` 的位置解析为绝对路径,不依赖当前工作目录。 ```env SQLITE_PATH=./data/shop.db ORDERS_SOURCE_PATH=./data/source/orders.csv DOCUMENTS_PATH=./data/documents ``` 不要提交本机绝对路径和 `.env`。部署时如需使用仓库外的数据目录,可以在本地 `.env` 中配置绝对路径。 ## 3. 连接或启动 Milvus ### 3.1 使用现有 Ubuntu Milvus Ubuntu Milvus 的 `19530` 已映射到 Windows 时: ```env MILVUS_URI=http://localhost:19530 ``` ```powershell uv run python scripts/wait_for_milvus.py ``` Milvus 位于另一台主机时,将 `localhost` 替换为 Windows 可访问的 Ubuntu IP。 ### 3.2 使用项目内 Compose ```powershell docker compose -f infra/milvus/docker-compose.yml config --quiet docker compose -f infra/milvus/docker-compose.yml up -d uv run python scripts/wait_for_milvus.py ``` ## 4. 准备电商数据 本地数据分为两组: - `data/source/orders.csv`:脱敏订单,写入 SQLite `orders` 表。 - `data/documents/*.md`:退货、运费和价保政策,切分后写入 Milvus。 ```powershell uv run python scripts/prepare_data.py ``` 准备脚本会重建课程数据库和 Milvus Collection。切换 Embedding 模型后也必须重新执行,不能混用不同模型或维度的向量。 ## 5. 示例问题 | 类型 | 问题 | 预期工具 | |---|---|---| | 向量检索 | 耳机拆封后还能七日无理由退货吗? | Milvus | | SQL 查询 | U1001 最近 30 天有几笔有效订单,实付总额是多少? | SQLite | | 网页搜索 | 查询品牌官网关于 XPhone 15 Pro 的最新公告 | Tavily | | 双源组合 | 统计 U1001 最近 30 天订单,并结合内部运费规则说明是否包邮 | Milvus + SQLite | | 三源组合 | 统计 U1001 最近 30 天购买 XPhone 15 Pro 的订单金额,结合内部退货政策和品牌官网最新公告给出售后建议 | Milvus + SQLite + Tavily | 订单用户编号在课程数据中使用 `U1001`。生产系统必须从登录态或服务端认证上下文注入,不能信任模型从自然语言生成的用户编号。 ## 6. 查看实际工具 Query 使用 `--debug` 时,CLI 会先打印每个工具实际执行的 Query、参数和状态,再输出完整响应: ```powershell uv run python -m app.cli ` "统计 U1001 最近 30 天订单,并结合内部运费规则说明是否包邮" ` --debug ``` 输出结构: ```text === 实际执行的工具查询 === - milvus_search: query='...' arguments={'policy_type': 'shipping_policy', 'top_k': 4} - sql_query: query='...' arguments={'user_id': 'U1001', 'days': 30, ...} ``` API 请求设置 `debug=true` 时,响应中的 `executed_queries` 返回相同信息。普通请求不返回内部查询轨迹。 ## 7. 自动化测试 ```powershell uv run pytest uv run python scripts/smoke_test.py ``` 单元测试不访问真实模型或网页;Smoke Test 使用真实 Milvus 与 SQLite。 ## 8. 启动 API ```powershell uv run uvicorn app.main:app --reload ``` ```powershell $body = @{ query = "统计 U1001 最近 30 天订单,并结合内部运费规则说明是否包邮" session_id = "demo" debug = $true } | ConvertTo-Json Invoke-RestMethod ` -Method Post ` -Uri "http://127.0.0.1:8000/query" ` -ContentType "application/json" ` -Body $body ``` Swagger UI:`http://127.0.0.1:8000/docs` ## 9. 配置 Web Search 在 `.env` 中配置 Tavily: ```env TAVILY_API_KEY=your-tavily-api-key WEB_SEARCH_MAX_RESULTS=5 ``` 未配置 Key 时,Milvus 和 SQLite 路由不受影响;`web_search` 返回 `WEB_SEARCH_NOT_CONFIGURED`。 运行时代码只通过 `Settings` 读取 `TAVILY_API_KEY`,不会从代码常量、请求参数或 CLI 参数接收 Key。 ## 10. 切换到 DeepSeek ```env LLM_PROVIDER=deepseek DEEPSEEK_API_KEY=your-deepseek-api-key DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL_NAME=deepseek-v4-flash DEEPSEEK_ANSWER_THINKING=true ``` `DeepSeekDecisionEngine` 使用 Function Calling 输出 `RouteDecision` 和 `QualityGrade`。这两个结构化调用固定关闭 Thinking,避免 Thinking 模式与强制 `tool_choice` 冲突;最终答案是否使用 Thinking 由 `DEEPSEEK_ANSWER_THINKING` 控制。 `DEEPSEEK_API_KEY` 只通过 `Settings` 读取。所有 Key 使用 `SecretStr` 保存,打印配置对象时只显示掩码,不输出真实值。 ## 11. 停止本地 Compose 服务 ```powershell docker compose -f infra/milvus/docker-compose.yml down ``` 数据目录位于 `infra/milvus/volumes`,已在 `.gitignore` 中排除。