开发日志.md 13 KB

Homelegance Chatbot — 开发与部署日志

记录从初始部署到 ERP 集成、知识库等完整开发过程


目录

  1. 项目概述
  2. 部署架构
  3. Phase 1 — 基础部署(MySQL → PostgreSQL)
  4. Phase 2 — 修复部署问题
  5. Phase 3 — ERP 集成(FastAPI Bridge)
  6. Phase A — 知识库(Knowledge-First)
  7. Phase B — 产品体验(快速回复按钮)
  8. Phase C — Workflow 流程引擎
  9. 服务器操作速查
  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/"

base: "/chat/",
// 删除: vitePluginManusRuntime, jsxLocPlugin, vitePluginManusDebugCollector

client/src/App.tsx — 加入 wouter Router base

import { Router } from "wouter";
<Router base="/chat"><AppRoutes /></Router>

client/src/main.tsx — API 路径使用 BASE_URL

url: `${import.meta.env.BASE_URL}api/trpc`

drizzle.config.ts — dialect 改为 postgresql

server/db.ts — MySQL → PostgreSQL 适配:

  • onDuplicateKeyUpdateonConflictDoUpdate
  • insertId.returning({ id: table.id })
  • affectedRowsreturn 0

package.json

"db:push": "drizzle-kit push"

Apache 配置片段(加入现有 VirtualHost *:443)

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

<Directory "/redant/web/homelegance-chatbot/dist/public">
    Options -Indexes +FollowSymlinks
    AllowOverride None
    Require all granted
</Directory>

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 修复

const env = loadEnv(path.resolve(__dirname, ".env.production"));
module.exports = { apps: [{ name: "homelegance-chat", env, ... }] };

.env.production 必填项

NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://chatbot_user:<pw>@<pg_host>: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 部署

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

ERP_DATABASE_URL=postgresql://chatbot_readonly:<pw>@<erp-host>:5432/<db>
ERP_API_KEY=<与 chatbot 相同的 key>
PORT=8080

DBA 需执行

CREATE USER chatbot_readonly WITH PASSWORD '<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

{
  "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. 服务器操作速查

日常部署流程

# 本地
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 更新(新增表后)

cd /redant/web/homelegance-chatbot
export $(grep -v '^#' .env.production | xargs)
pnpm db:push

PM2 完整重启(env 变更后)

pm2 delete homelegance-chat
pm2 start ecosystem.config.cjs
pm2 save
pm2 env 0 | grep ANTHROPIC   # 验证

查看日志

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

systemctl status erp-bridge
journalctl -u erp-bridge -f
curl -H "X-API-Key: <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=<jwt> 传入
    • chat.startSession 验证 token,提取 customer_idcompany_namesales_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