diff --git a/README.md b/README.md index 715ae50..b95aa34 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,8 @@ crm-new/ │ ├── set-public-url.js # 更新 LibreDesk app.root_url │ ├── import-kb-helpcenter.js # 旧 KB -> 帮助中心文章(幂等) │ ├── verify-rag.js # 临时助手 + preview,验证检索/引用 +│ ├── export-kb-snapshot.sh # 导出 kb_docs 快照 +│ ├── import-kb-snapshot.sh # 无旧 bridge 时导入 KB 快照 │ ├── smoke.sh │ └── serve-web.sh # 仅本地预览 demo 页面 ├── web/ # 站点接入:ai-snippet.js + demo.html(widget JWT 演示) @@ -93,7 +95,9 @@ crm-new/ │ ├── environments.md # 本地开发 vs 测试/生产:RPC/Cloudflare 隧道差异 │ ├── human-routing.md # Email/WhatsApp 人工团队分配 │ └── plan-a.md # 方案 A:bridge 接管 AI 编排进度 -└── deploy/nginx.conf.example +├── deploy/ +│ ├── nginx.conf.example +│ └── seeds/kb_docs.sql.gz # KB 快照(361 chunks:292 parent + 69 child) services/public-gateway/ # 公网路径白名单反向代理(仅 webhook/帮助中心) ``` diff --git a/deploy/seeds/kb_docs.sql.gz b/deploy/seeds/kb_docs.sql.gz new file mode 100644 index 0000000..322259d Binary files /dev/null and b/deploy/seeds/kb_docs.sql.gz differ diff --git a/docs/go-live.md b/docs/go-live.md index 1cf29f3..fb5a07c 100644 --- a/docs/go-live.md +++ b/docs/go-live.md @@ -162,10 +162,9 @@ node scripts/configure-email.js ### 6.3 数据准备 -```bash -# 全量商品页站点地图(每周/商品大更新后) -node scripts/build-site-map.js www us +#### 有旧 bridge / 旧 products 库时 +```bash # 重建 KB parent-child 索引(KB 更新后;会先备份旧表) bash scripts/rebuild-kb-index.sh @@ -173,6 +172,43 @@ bash scripts/rebuild-kb-index.sh node scripts/upgrade-kb-schema.js ``` +#### 测试/生产没有旧 bridge 时(推荐) + +不要运行 `rebuild-kb-index.sh`。直接导入仓库里的 KB 快照: + +```bash +# 默认导入到 crmnew-postgres / bridge 库 +bash scripts/import-kb-snapshot.sh + +# 或导入到 products 库 +TARGET_PG_DB=products bash scripts/import-kb-snapshot.sh + +# 验证 +docker exec crmnew-postgres psql -U crmnew -d bridge -tAc \ + "select count(*), count(*) filter (where chunk_type='parent'), count(*) filter (where chunk_type='child') from kb_docs;" +``` + +预期: + +``` +361 | 292 | 69 +``` + +然后把测试环境 `.env` 的 `RAG_PG_URL` 指向该库,例如: + +```env +RAG_PG_URL=postgres://crmnew:@postgres:5432/bridge +``` + +> 快照文件:`deploy/seeds/kb_docs.sql.gz`(只包含 `kb_docs` 知识库,不含邮件/客户数据) +> 当前环境如需重新生成:`bash scripts/export-kb-snapshot.sh` + +#### 全量商品页站点地图 + +```bash +node scripts/build-site-map.js www us +``` + ### 6.4 RPC 隧道(仅本地开发) > 测试/生产不需要这一步;直接配置内网 RPC 地址即可。 diff --git a/docs/runbook.md b/docs/runbook.md index ab39b7b..81e1c12 100644 --- a/docs/runbook.md +++ b/docs/runbook.md @@ -54,11 +54,15 @@ node scripts/setup-defaults.js # Twenty:创建初始 workspace + 在库内生成 API key(不走 UI) node scripts/twenty-bootstrap.js -# 重建 KB parent-child 索引(旧 bridge indexer + 回填 text_tsv,自动备份) +# 有旧 bridge 时:重建 KB parent-child 索引(自动备份) bash scripts/rebuild-kb-index.sh -# 升级旧 kb_docs 支持 Hybrid RAG(text_tsv/parent_id/chunk_type) -node scripts/upgrade-kb-schema.js +# 没有旧 bridge 时:直接导入 KB 快照(测试/生产常用) +bash scripts/import-kb-snapshot.sh +# 或指定目标库:TARGET_PG_DB=products bash scripts/import-kb-snapshot.sh + +# 从当前环境重新生成快照(可选) +bash scripts/export-kb-snapshot.sh # 全量商品页站点地图(官网 sitemap → bridge 库) node scripts/build-site-map.js www us diff --git a/scripts/export-kb-snapshot.sh b/scripts/export-kb-snapshot.sh new file mode 100755 index 0000000..de0ce11 --- /dev/null +++ b/scripts/export-kb-snapshot.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# 从已有环境导出 KB(kb_docs)快照,供没有旧 bridge 的测试/生产环境导入。 +# 用法: bash scripts/export-kb-snapshot.sh [输出文件] +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +OUT="${1:-$ROOT/deploy/seeds/kb_docs.sql.gz}" +SRC_CONTAINER="${SOURCE_PG_CONTAINER:-crm-postgres}" +SRC_DB="${SOURCE_PG_DB:-products}" +SRC_USER="${SOURCE_PG_USER:-postgres}" +mkdir -p "$(dirname "$OUT")" +docker exec "$SRC_CONTAINER" pg_dump -U "$SRC_USER" -d "$SRC_DB" \ + -t kb_docs --no-owner --no-privileges | gzip -9 > "$OUT" +echo "[export-kb] $SRC_CONTAINER/$SRC_DB.kb_docs -> $OUT ($(du -h "$OUT" | cut -f1))" diff --git a/scripts/import-kb-snapshot.sh b/scripts/import-kb-snapshot.sh new file mode 100755 index 0000000..4a87f07 --- /dev/null +++ b/scripts/import-kb-snapshot.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# 在没有旧 bridge 的环境导入 KB 快照(默认导入 crmnew-postgres/bridge)。 +# 用法: +# bash scripts/import-kb-snapshot.sh [seed.sql.gz] +# FORCE=1 bash scripts/import-kb-snapshot.sh # 覆盖已有 kb_docs(会 DROP) +set -euo pipefail +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SEED="${1:-$ROOT/deploy/seeds/kb_docs.sql.gz}" +TARGET_CONTAINER="${TARGET_PG_CONTAINER:-crmnew-postgres}" +TARGET_DB="${TARGET_PG_DB:-bridge}" +TARGET_USER="${TARGET_PG_USER:-crmnew}" + +if [ ! -f "$SEED" ]; then echo "seed not found: $SEED" >&2; exit 1; fi + +# 确保数据库存在 +if ! docker exec "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d postgres -tAc \ + "SELECT 1 FROM pg_database WHERE datname='$TARGET_DB'" | grep -q 1; then + docker exec "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d postgres -c "CREATE DATABASE \"$TARGET_DB\"" +fi + +docker exec "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d "$TARGET_DB" -c \ + "CREATE EXTENSION IF NOT EXISTS vector;" >/dev/null + +# 旧 dump 带 tsv trigger,先确保函数存在 +docker exec -i "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d "$TARGET_DB" >/dev/null <<'SQL' +CREATE OR REPLACE FUNCTION public.kb_docs_tsv_update() RETURNS trigger AS $$ +BEGIN + NEW.text_tsv := to_tsvector('english', + coalesce(NEW.question,'') || ' ' || coalesce(NEW.answer,'') || ' ' || + coalesce(array_to_string(NEW.keywords,' '),'') || ' ' || + coalesce(NEW.title,'') || ' ' || coalesce(NEW.section,'')); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; +SQL + +EXISTS=$(docker exec "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d "$TARGET_DB" -tAc \ + "SELECT to_regclass('public.kb_docs') IS NOT NULL") +if [ "$EXISTS" = "t" ]; then + if [ "${FORCE:-0}" != "1" ]; then + echo "[import-kb] kb_docs already exists in $TARGET_DB; refusing to overwrite. Set FORCE=1 to drop it." >&2 + exit 1 + fi + echo "[import-kb] FORCE=1: dropping existing kb_docs in $TARGET_DB" + docker exec "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d "$TARGET_DB" -c "DROP TABLE IF EXISTS kb_docs CASCADE" >/dev/null +fi + +gunzip -c "$SEED" | docker exec -i "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d "$TARGET_DB" -v ON_ERROR_STOP=1 >/dev/null + +COUNT=$(docker exec "$TARGET_CONTAINER" psql -U "$TARGET_USER" -d "$TARGET_DB" -tAc "SELECT count(*) FROM kb_docs") +echo "[import-kb] imported kb_docs rows=$COUNT into $TARGET_CONTAINER/$TARGET_DB" +echo "[import-kb] 提示: bridge 的 RAG_PG_URL 应指向该库(容器内通常是 postgres://...@postgres:5432/$TARGET_DB)" diff --git a/scripts/rebuild-kb-index.sh b/scripts/rebuild-kb-index.sh index 2131bcd..0cf5df9 100755 --- a/scripts/rebuild-kb-index.sh +++ b/scripts/rebuild-kb-index.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# 仅当存在旧 bridge 容器/旧 products 库时使用。 +# 没有旧 bridge 的测试/生产环境请用: bash scripts/import-kb-snapshot.sh # 重建旧 KB 的 parent-child 索引(调用旧 bridge 容器里的 indexer),再回填 text_tsv。 # 旧表会由 indexer 归档为 kb_docs_vN;额外先做一份 kb_docs_backup_ 备份。 set -euo pipefail