# Homelegance Chatbot — 开发与部署日志 > 记录从初始部署到 ERP 集成、知识库等完整开发过程 --- ## 目录 1. [项目概述](#1-项目概述) 2. [部署架构](#2-部署架构) 3. [Phase 1 — 基础部署(MySQL → PostgreSQL)](#3-phase-1--基础部署) 4. [Phase 2 — 修复部署问题](#4-phase-2--修复部署问题) 5. [Phase 3 — ERP 集成(FastAPI Bridge)](#5-phase-3--erp-集成) 6. [Phase A — 知识库(Knowledge-First)](#6-phase-a--知识库) 7. [Phase B — 产品体验(快速回复按钮)](#7-phase-b--产品体验) 8. [Phase C — Workflow 流程引擎](#8-phase-c--workflow-流程引擎) 9. [服务器操作速查](#9-服务器操作速查) 10. [待完成事项](#10-待完成事项) --- ## 1. 项目概述 **产品名称**:Homelegance AI Chatbot(Ellie) **部署地址**:`www.homelegance.com/chat/` **服务器**:AlmaLinux 8.10,Apache httpd,同一台 Web 服务器 **技术栈**: | 层 | 技术 | |---|---| | 前端 | React 19 + Vite + TypeScript + Tailwind CSS + shadcn/ui | | 后端 | Node.js + Express + tRPC | | ORM | Drizzle ORM(drizzle-orm/pg-core) | | 数据库 | PostgreSQL(独立 DB 服务器,`chatbot` Schema) | | AI | Anthropic Claude API(`claude-sonnet-4-6`) | | 进程管理 | PM2 | | ERP 桥接 | Python 3.12 + FastAPI(内网 127.0.0.1:8080) | --- ## 2. 部署架构 ``` Internet │ ▼ Apache :443 (www.homelegance.com) ├─ /chat/api → ProxyPass → Node.js :3000 ├─ /chat/ → Alias → /redant/web/homelegance-chatbot/dist/public/ └─ / → AJP → Tomcat(原有 Dealer Portal) Node.js :3000 (PM2) ├─ PostgreSQL :5432 (chatbot schema — 自身数据库) └─ FastAPI :8080 (内网 ERP 桥接) └─ ERP PostgreSQL(只读) ``` ### 关键路径 - 代码目录:`/redant/web/homelegance-chatbot/` - ERP Bridge:`/redant/web/homelegance-chatbot/erp-bridge/` - PM2 配置:`ecosystem.config.cjs` - 环境变量:`.env.production` - Apache 配置:加入 www.homelegance.com 的 VirtualHost --- ## 3. Phase 1 — 基础部署 ### 主要变更 **`vite.config.ts`** — 移除 Manus 插件,加入 `base: "/chat/"` ```ts base: "/chat/", // 删除: vitePluginManusRuntime, jsxLocPlugin, vitePluginManusDebugCollector ``` **`client/src/App.tsx`** — 加入 wouter Router base ```tsx import { Router } from "wouter"; ``` **`client/src/main.tsx`** — API 路径使用 BASE_URL ```ts url: `${import.meta.env.BASE_URL}api/trpc` ``` **`drizzle.config.ts`** — dialect 改为 postgresql **`server/db.ts`** — MySQL → PostgreSQL 适配: - `onDuplicateKeyUpdate` → `onConflictDoUpdate` - `insertId` → `.returning({ id: table.id })` - `affectedRows` → `return 0` **`package.json`** ```json "db:push": "drizzle-kit push" ``` ### Apache 配置片段(加入现有 VirtualHost *:443) ```apache ProxyPreserveHost On ProxyPass /chat/api http://127.0.0.1:3000/api ProxyPassReverse /chat/api http://127.0.0.1:3000/api ProxyPass /chat/ ! Alias /chat /redant/web/homelegance-chatbot/dist/public Options -Indexes +FollowSymlinks AllowOverride None Require all granted RewriteEngine On RewriteCond %{REQUEST_URI} ^/chat/ RewriteCond %{REQUEST_URI} !/chat/api RewriteCond %{REQUEST_URI} !\.(js|css|png|jpg|jpeg|gif|ico|svg|woff2|woff|ttf|eot|map|json|webp|txt)$ RewriteRule ^ /redant/web/homelegance-chatbot/dist/public/index.html [L] ``` --- ## 4. Phase 2 — 修复部署问题 ### 问题与解决 | 问题 | 根因 | 解决方案 | |------|------|---------| | 页面空白 | `vitePluginManusRuntime` 注入阻塞代码 | 删除所有 Manus 插件 | | umami 400 错误 | `%VITE_ANALYTICS_ENDPOINT%` 未替换 | 从 `index.html` 删除该脚本 | | API 404 | tRPC URL `/api/trpc` 绝对路径,走到 Tomcat | 改用 `import.meta.env.BASE_URL` | | SPA fallback 返回 HTML 给 JS 文件 | `%{REQUEST_FILENAME} !-f` 检查 DocumentRoot 而非 Alias 路径 | 改用扩展名排除法 | | `startSession` 500 错误 | MySQL `insertId` 在 PostgreSQL 不存在 | 改用 Drizzle `.returning()` | | PM2 不加载 `ANTHROPIC_API_KEY` | `env_file` 在该版本 PM2 不可靠 | 改用 Node.js `fs` 直接解析 `.env.production` | ### ecosystem.config.cjs 修复 ```js const env = loadEnv(path.resolve(__dirname, ".env.production")); module.exports = { apps: [{ name: "homelegance-chat", env, ... }] }; ``` ### .env.production 必填项 ```env NODE_ENV=production PORT=3000 DATABASE_URL=postgresql://chatbot_user:@:5432/homelegance_chat JWT_SECRET=<64字符随机> ANTHROPIC_API_KEY=sk-ant-api03-... ERP_API_URL=http://127.0.0.1:8080 ERP_API_KEY=<随机> ``` --- ## 5. Phase 3 — ERP 集成 ### 架构 ``` Node.js sendMessage → 意图检测(规则正则) → FastAPI Bridge(127.0.0.1:8080) → erp_api.* 存储函数(PostgreSQL 只读账号) → 结果注入 System Prompt [ERP CONTEXT] → Claude 生成回复 ``` ### 新建文件 #### `erp-bridge/main.py` — FastAPI 桥接服务 | 端点 | 调用的 ERP 函数 | |------|--------------| | `GET /health` | — | | `POST /catalog` | `erp_api.catalog_lists(conditions jsonb, limit int)` | | `POST /contacts` | `erp_api.contact_lists(conditions jsonb, limit int)` | | `POST /orders` | `erp_api.sales_orders_lists(conditions jsonb, limit int)` | | `GET /orders/{so_id}` | `erp_api.sales_order_get(so_id text)` | | `POST /stock` | `erp_api.stock_lists(conditions jsonb, limit int)` | **返回列通过 Python `set[str]` 常量控制**,无需改查询逻辑。 #### `server/erpClient.ts` — HTTP 客户端(8 秒超时) #### `server/erpTools.ts` — 业务查询函数,返回 LLM 友好字符串 **6 个业务函数**: - `lookupOrder(soId)` — 单个订单详情 - `lookupOrdersByCustomer(cid, n)` — 客户最近 N 个订单 - `lookupOrdersByPO(poId)` — PO 号查询 - `lookupCatalog(params)` — 产品目录搜索 - `lookupStock(params)` — 库存查询 - `lookupContact(params)` — 客户资料查询 ### sendMessage 意图检测顺序 ``` 1. SO-XXXXX 正则 → lookupOrder() 2. "my orders/recent orders" → lookupOrdersByCustomer() 3. PO-XXXXX 正则 → lookupOrdersByPO() 4. "in stock/inventory" + 型号正则 → lookupStock() 5. 家具关键词 → lookupCatalog() 6. "customer/dealer/company" + 名称 → lookupContact() ``` ### ERP Bridge 部署 ```bash cd /redant/web/homelegance-chatbot/erp-bridge pip3.12 install -r requirements.txt cp .env.example .env && vi .env cp erp-bridge.service /etc/systemd/system/ systemctl daemon-reload && systemctl enable --now erp-bridge curl http://127.0.0.1:8080/health ``` **erp-bridge/.env** ```env ERP_DATABASE_URL=postgresql://chatbot_readonly:@:5432/ ERP_API_KEY=<与 chatbot 相同的 key> PORT=8080 ``` **DBA 需执行** ```sql CREATE USER chatbot_readonly WITH PASSWORD ''; GRANT SELECT ON TABLE catalog, customers, stock_po, sales_orders, sales_order_items, sales_order_note, order_status, warehouse TO chatbot_readonly; ``` --- ## 6. Phase A — 知识库(Knowledge-First) ### 设计原则 > **Knowledge Base First** — Ellie 必须先搜索 Q&A 知识库,命中则直接返回,不调用 LLM;未命中才进入 ERP 检测 → LLM 流程。 ### 新增 DB 表(drizzle/schema.ts) | 表名 | 用途 | |------|------| | `chatbot.knowledge_entries` | Q&A 知识条目(管理员维护) | | `chatbot.knowledge_suggestions` | 自动捕获的未解答问题 | | `chatbot.knowledge_products` | 从 Excel/CSV 导入的产品目录 | ### sendMessage 完整处理链 ``` 用户消息 ↓ ① 知识库搜索(keyword 匹配) 命中 → 直接返回(source: "knowledge"),useCount++ ↓ 未命中 ② Workflow Flow 引擎(意图检测) 命中 → 执行 Flow 节点,返回(source: "flow") ↓ 未命中 ③ ERP 意图检测(6种正则) 命中 → 调用 FastAPI Bridge,结果注入 System Prompt ↓ ④ Claude LLM 生成回复 ↓ ⑤ 自动记录 Suggestion(供管理员审核,持续扩充知识库) ``` ### Knowledge 路由(新增 tRPC 端点) ``` knowledge.listEntries / getEntry / createEntry / updateEntry / deleteEntry knowledge.importEntries — CSV 批量导入 knowledge.listSuggestions / promoteSuggestion / dismissSuggestion knowledge.listProducts / importProducts ``` --- ## 7. Phase B — 产品体验 ### 快速回复按钮 `startSession` 返回欢迎消息时携带 `metadata.quickReplies`: ```json { "content": "Welcome to Homelegance! I'm **Ellie**...", "metadata": { "quickReplies": ["🔥 Hot Deals", "📦 Order Status", "🛋️ Product Catalog"] } } ``` 前端 `ChatbotWidget.tsx` 读取并渲染为可点击按钮,点击后作为用户消息发送。 ### Knowledge Management 页面(3 Tab) `client/src/pages/DataSources.tsx` 重写为: **Tab 1: Data Source** — Q&A 条目 - 统计:Total / Active / Total Uses - 表格:Question | Answer | Category | Source | Uses | Status | Actions - 手动添加 / CSV 导入(自动识别 header) **Tab 2: Product** — 产品目录 - 支持 CSV 导入(model, description, categories, collection, price, availability, features, dimensions, imageUrl) - Replace All 选项 **Tab 3: Suggestions** — 自动捕获的未解答问题 - 统计:Pending / Promoted / Dismissed - 按状态过滤 - Promote(填写答案后升级为知识条目)/ Dismiss --- ## 8. Phase C — Workflow 流程引擎 ### 新文件:`server/flowEngine.ts` **5 个 Support Flow 意图模式**: | Flow ID | 触发关键词/正则 | |---------|--------------| | `check-order-status` | "order status", "check.*order", "where.*my order" | | `track-shipment` | "tracking", "track.*shipment", "where.*package" | | `submit-return` | "return", "RMA", "refund" | | `cancel-order` | "cancel.*order" | | `faq-deflection` | "payment", "warranty", "shipping.*time", "minimum.*order" | **执行逻辑**: 1. 优先读取 DB 中保存的 Flow 节点(`workflow_nodes`) 2. 若无 DB 节点,使用内置静态回复 3. 支持 `shouldEscalate` 标志(Escalation 节点触发时自动转人工) ### 与 sendMessage 的集成顺序 ``` KB 搜索 → Flow 引擎 → ERP 意图 → LLM → 记录 Suggestion ``` --- ## 9. 服务器操作速查 ### 日常部署流程 ```bash # 本地 git add . && git commit -m "..." && git push origin master # 服务器 cd /redant/web/homelegance-chatbot git pull origin master pnpm build pm2 restart homelegance-chat ``` ### DB Schema 更新(新增表后) ```bash cd /redant/web/homelegance-chatbot export $(grep -v '^#' .env.production | xargs) pnpm db:push ``` ### PM2 完整重启(env 变更后) ```bash pm2 delete homelegance-chat pm2 start ecosystem.config.cjs pm2 save pm2 env 0 | grep ANTHROPIC # 验证 ``` ### 查看日志 ```bash pm2 logs homelegance-chat --lines 50 grep -i "LLM\|error\|Chat\|KB\|Flow\|ERP" /var/log/pm2/homelegance-chat-out-0.log | tail -30 ``` ### ERP Bridge ```bash systemctl status erp-bridge journalctl -u erp-bridge -f curl -H "X-API-Key: " http://127.0.0.1:8080/health ``` --- ## 10. 待完成事项 ### 优先级高 - [ ] **ERP Bridge 部署**:在服务器上配置 `.env`,安装 systemd 服务,测试 5 个端点 - [ ] **DB Schema 推送**:`pnpm db:push` 创建 3 个新知识库表 - [ ] **导入 Q&A 知识库**:通过 Knowledge → Data Source → Import CSV 导入初始问答对 ### 优先级中 - [ ] **SSO 集成**(Phase 4):Dealer Portal 带 JWT token 跳转 → Ellie 自动识别 dealer 身份 - Portal 生成短效 JWT(5分钟),`?sso_token=` 传入 - `chat.startSession` 验证 token,提取 `customer_id`、`company_name`、`sales_rep` - Dashboard 自动显示 Customer ID / Sales Rep 列 - [ ] **产品目录导入**:将 Homelegance Excel 产品表转为 CSV,通过 Knowledge → Product 导入 - [ ] **Leads Flows / Sales Flows**:文档标注为 Pending,下一开发阶段实现 ### 优先级低 - [ ] **语义搜索升级**:当前知识库用关键词匹配,未来可接入 Embeddings(OpenAI/Anthropic)实现真正语义匹配 - [ ] **多城市部署**:6 个城市共用同一个 Anthropic API Key,各自独立 PM2 + PostgreSQL --- ## Git 提交历史(本项目) | Commit | 说明 | |--------|------| | `c64aee5` | Remove Manus dependencies from frontend build | | `e2b6e8b` | Fix API paths for /chat/ base URL deployment | | `bc0d946` | Fix Apache SPA fallback for Alias + RewriteRule conflict | | `96a20c0` | Fix SPA fallback: use extension exclusion instead of %1 capture | | `a896b48` | Fix all MySQL-specific APIs for PostgreSQL compatibility | | `d41f355` | Add ERP integration: FastAPI bridge + intent-aware context injection | | `4bfd994` | Allow erp-bridge .env.example to be tracked by git | | `25bc2c6` | Fix PM2 env loading: parse .env.production via fs instead of env_file | | _(latest)_ | Phase A/B/C: Knowledge Base, Quick Replies, Flow Engine |