liuchengsen пре 1 месец
родитељ
комит
1a33ac5636
2 измењених фајлова са 234 додато и 209 уклоњено
  1. 35 0
      database/reset_schema.sql
  2. 199 209
      docs/OPERATIONS_GUIDE.md

+ 35 - 0
database/reset_schema.sql

@@ -0,0 +1,35 @@
+-- ============================================================
+-- 数据库完全重置脚本(清空所有表和数据,重建结构)
+-- 警告:此操作不可逆,所有数据将永久丢失!
+-- 执行方式:
+--   docker exec -i pharmacopoeia-pg psql -U postgres < database/reset_schema.sql
+-- ============================================================
+
+BEGIN;
+
+-- 1. 删除所有旧表(级联删除依赖对象)
+DROP TABLE IF EXISTS public.answer_records CASCADE;
+DROP TABLE IF EXISTS public.user_progress CASCADE;
+DROP TABLE IF EXISTS public.messages CASCADE;
+DROP TABLE IF EXISTS public.conversations CASCADE;
+DROP TABLE IF EXISTS public.drug_chunks CASCADE;
+DROP TABLE IF EXISTS public.questions CASCADE;
+DROP TABLE IF EXISTS public.knowledge_points CASCADE;
+DROP TABLE IF EXISTS public.drugs CASCADE;
+DROP TABLE IF EXISTS public.users CASCADE;
+
+-- 2. 删除序列
+DROP SEQUENCE IF EXISTS public.answer_records_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.user_progress_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.messages_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.conversations_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.drug_chunks_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.questions_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.knowledge_points_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.drugs_id_seq CASCADE;
+DROP SEQUENCE IF EXISTS public.users_id_seq CASCADE;
+
+COMMIT;
+
+-- 3. 重建(直接执行 schema.sql)
+-- docker exec -i pharmacopoeia-pg psql -U postgres < database/schema.sql

+ 199 - 209
docs/OPERATIONS_GUIDE.md

@@ -1,141 +1,153 @@
 # 线上部署与数据导入完整操作方案
 
-> **适用环境**: Linux 生产服务器  
+> **适用环境**: Linux 生产服务器(当前: `iZwz92tgv6q223rdi4w8cdZ`)  
 > **项目路径**: `/opt/pharmacopoeia-ai`  
-> **药典数据源**: `/opt/2025`(DOCX 文件)  
-> **操作前提**: 已拉取最新代码,JDK 21 可用
+> **药典数据源**: `/opt/2025`(6317 个 DOCX 文件)  
+> **耗时**: 首次完整部署约 2-4 小时(主要在 DOCX 向量化)
 
 ---
 
-## 一、操作总览
+## 一、环境检查与代码拉取
 
-```
-Step 0: 确认环境(1 分钟)
-Step 1: 启动基础设施 PostgreSQL + Redis(2 分钟)
-Step 2: 初始化/迁移数据库(1 分钟)
-Step 3: 启动 Java 后端验证连通性(2 分钟)
-Step 4: 导入 Wiki 临床数据 via import_all.py(~2 分钟)
-Step 5: 导入药典 DOCX 原文 via docx_ingest.py(~数小时)
-Step 6: 验证搜索功能(2 分钟)
-Step 7: 正式启动服务(2 分钟)
+```bash
+# ============================================================
+# 1.1 基础环境确认
+# ============================================================
+java -version 2>&1
+# 期望: 21.x.x(若未安装需先装 JDK 21)
+
+python3 --version
+# 期望: 3.10+
+
+git --version
+# 基本命令
+
+# ============================================================
+# 1.2 拉取最新代码
+# ============================================================
+cd /opt/pharmacopoeia-ai
+git pull origin main
+git status
+# 期望: 无冲突,干净状态(或有新增文件)
+
+# ============================================================
+# 1.3 创建必要目录
+# ============================================================
+mkdir -p /var/log/pharmacopoeia
+mkdir -p /opt/pharmacopoeia-ai/backend-java/target
+
+# ============================================================
+# 1.4 配置环境变量(如首次部署)
+# ============================================================
+cd /opt/pharmacopoeia-ai
+if [ ! -f .env ]; then
+    cp .env.example .env
+    echo ">>> 请编辑 .env 文件,填入 QWEN_API_KEY 等真实值 <<<"
+fi
+
+# 确认关键配置已填写
+grep -E "QWEN_API_KEY|POSTGRES_PASSWORD" .env
+# QWEN_API_KEY=sk-your-real-key      ← 必须是有效值
+# POSTGRES_PASSWORD=pharma2025
 ```
 
 ---
 
-## 二、详细步骤
-
-### Step 0: 确认环境
+## 二、编译 Java 后端
 
 ```bash
-# 0.1 确认 Java 版本
-java -version
-# 期望: java version "21.x.x"
+cd /opt/pharmacopoeia-ai/backend-java
 
-# 如果 JAVA_HOME 未设置:
+# 2.1 设置 JDK 21
 export JAVA_HOME=/usr/lib/jvm/jdk-21
-export PATH=$JAVA_HOME/bin:$PATH
+# 如果不知道 JDK 路径,用 update-alternatives 查找:
+# update-alternatives --list java
 
-# 0.2 确认项目目录
-cd /opt/pharmacopoeia-ai
-git status
-ls data-pipeline/ backend-java/ deploy/ database/
-
-# 0.3 确认数据源存在
-ls /opt/2025/output*/品种正文/*.docx | head -5
-# 应能看到 DOCX 文件
-
-# 0.4 创建日志目录
-mkdir -p /var/log/pharmacopoeia
+# 2.2 编译打包
+mvn clean package -DskipTests -q
 
-# 0.5 确认 .env 配置
-cat .env | grep QWEN_API_KEY
-# 确保 QWEN_API_KEY 已填写真实的 DashScope API Key
-# 如果 .env 不存在,复制模板:
-# cp .env.example .env && vim .env
+# 确认 jar 包生成
+ls -lh target/pharmacopoeia-ai-1.0.0.jar
+# 期望: ~50MB jar 文件
 ```
 
 ---
 
-### Step 1: 启动基础设施
+## 三、启动基础设施(PostgreSQL + Redis)
 
 ```bash
 cd /opt/pharmacopoeia-ai/deploy
 
-# 启动 PostgreSQL + Redis
+# 3.1 拉取镜像并启动
+docker-compose pull
 docker-compose up -d
 
-# 等待健康检查通过(约 15 秒)
+# 3.2 等待健康检查通过
+echo "等待 PostgreSQL 就绪..."
 sleep 15
 docker-compose ps
 # pharmacopoeia-pg     Up (healthy)
 # pharmacopoeia-redis  Up (healthy)
 
-# 验证 PG 连接
+# 3.3 验证 PG 连接
 docker exec pharmacopoeia-pg pg_isready -U postgres
-# 输出: /var/run/postgresql:5432 - accepting connections
+# /var/run/postgresql:5432 - accepting connections
 ```
 
 ---
 
-### Step 2: 初始化/迁移数据库
+## 四、初始化数据库
 
 ```bash
 cd /opt/pharmacopoeia-ai
 
-# 2.1 导入表结构(首次部署)
+# ============================================================
+# 4.1 【首次部署 或 Schema 变更时】完全重置数据库
+# 警告:这会删除所有旧数据,之后必须重新导入
+# ============================================================
+docker exec -i pharmacopoeia-pg psql -U postgres -d pharmacopoeia < database/reset_schema.sql
+
+# 4.2 导入最新表结构
 docker exec -i pharmacopoeia-pg psql -U postgres -d pharmacopoeia < database/schema.sql
 
-# 2.2 执行 json → jsonb 迁移(如果是旧库升级)
-docker exec -i pharmacopoeia-pg psql -U postgres -d pharmacopoeia < database/migrate_json_to_jsonb.sql
+# ============================================================
+# 4.3 【如果是旧库升级,不想丢数据】仅执行迁移
+# ============================================================
+# docker exec -i pharmacopoeia-pg psql -U postgres -d pharmacopoeia < database/migrate_json_to_jsonb.sql
 
-# 2.3 确认表已创建
+# 4.4 验证表结构
 docker exec pharmacopoeia-pg psql -U postgres -d pharmacopoeia -c "\dt"
-# 期望看到: drugs, drug_chunks, knowledge_points, questions, conversations, messages, users, user_progress, answer_records
-```
+# 期望 9 张表
 
 ---
 
-### Step 3: 启动 Java 后端(验证连通性)
+## 五、安装 Python 依赖
 
 ```bash
-cd /opt/pharmacopoeia-ai/backend-java
-
-# 3.1 编译打包
-export JAVA_HOME=/usr/lib/jvm/jdk-21
-mvn clean package -DskipTests -q
-# 输出: BUILD SUCCESS
-
-# 3.2 临时启动验证(前台运行,Ctrl+C 可停止)
-java -jar target/pharmacopoeia-ai-1.0.0.jar
-
-# 或以后台方式启动:
-# nohup java -Xms512m -Xmx2g -Dfile.encoding=UTF-8 \
-#   -jar target/pharmacopoeia-ai-1.0.0.jar \
-#   > /var/log/pharmacopoeia/backend.log 2>&1 &
-
-# 3.3 验证健康检查
-curl http://localhost:9000/api/v1/health
-# 期望: {"status":"UP"}
+# 5.1 安装数据管道依赖
+pip3 install httpx sqlalchemy asyncpg psycopg2-binary python-docx
 
-# 3.4 验证当前数据量(此时应为零)
-curl http://localhost:9000/api/v1/admin/stats
-# 期望: {"total_drugs":0, "total_chunks":0, "total_queries":0, ...}
+# 5.2 验证安装
+python3 -c "import httpx, sqlalchemy, docx; print('OK')"
+# 输出: OK
 ```
 
 ---
 
-### Step 4: 导入 Wiki 临床数据
+## 六、导入 Wiki 临床数据(快速,~2 分钟)
 
-**数据来源**: `data-pipeline/data/wiki_merged.json`(13 个药品的维基百科临床专著,含概述/适应症/药理/不良反应等)+ `sample_drugs.json`(4 个药典示例)+ `drug_guides.json`(4 个用药指导)
+**数据内容**: 13 个药品的维基百科临床专著(概述/适应症/药理/不良反应等)+ 4 个药典示例 + 4 个用药指导
 
 ```bash
 cd /opt/pharmacopoeia-ai/data-pipeline
 
-# 4.1 安装 Python 依赖
-pip install httpx sqlalchemy asyncpg psycopg2-binary python-docx
+# 6.1 加载环境变量
+set -a
+source ../.env
+set +a
 
-# 4.2 执行导入
-python import_all.py
+# 6.2 执行导入
+python3 import_all.py
 ```
 
 **预期输出**:
@@ -147,140 +159,140 @@ python import_all.py
    ⏭️ drug_index.json — 跳过
    ⏭️ catalog_volume1.json — 跳过
    ...
+📦 共 3 个文件待导入
+🚀 正在导入: sample_drugs.json ...
 🎉 全部导入完成!
 ```
 
-**耗时**: 约 1-2 分钟(~200 个 chunk 向量化)
-
 **验证**:
 ```bash
-curl http://localhost:9000/api/v1/admin/stats
-# total_drugs 应为 21 左右
-
-# 验证甲硝唑、布洛芬等已入库
-curl -s http://localhost:9000/api/v1/drug/search?keyword=甲硝唑 | python3 -m json.tool | head -20
+docker exec pharmacopoeia-pg psql -U postgres -d pharmacopoeia -c "
+SELECT COUNT(*) AS drugs FROM drugs WHERE is_active=TRUE;
+SELECT COUNT(*) AS chunks FROM drug_chunks WHERE vec IS NOT NULL;
+"
+# drugs: ~21, chunks: ~200
 ```
 
 ---
 
-### Step 5: 导入药典 DOCX 原文
+## 七、导入药典 DOCX 原文(完整,~2-4 小时)
 
-**数据来源**: `/opt/2025/` 下 6317 个 DOCX 文件(2025 年版中国药典全文)
+**数据内容**: `/opt/2025/` 下 6317 个 DOCX 文件(2025 年版中国药典四部全文)
 
 ```bash
 cd /opt/pharmacopoeia-ai/data-pipeline
 
-# 5.1 确认环境变量
-export DOCX_SOURCE_DIR=/opt/2025
-export QWEN_API_KEY=$(grep QWEN_API_KEY ../.env | cut -d= -f2)
+# 7.1 加载环境变量(如果上面已做可跳过)
+set -a
+source ../.env
+set +a
+
+# 7.2 确认数据源
+ls /opt/2025/output2/品种正文/*.docx | wc -l
+# 期望: 2930(二部化学药最多)
+
+# 7.3 在 screen 中运行(防止 SSH 断连中断)
+screen -S docx-ingest
+
+# 设置环境(screen 内需要重新加载)
+export QWEN_API_KEY=$(grep QWEN_API_KEY /opt/pharmacopoeia-ai/.env | cut -d= -f2)
+export POSTGRES_HOST=localhost
+export POSTGRES_PORT=5432
+export POSTGRES_DB=pharmacopoeia
+export POSTGRES_USER=postgres
+export POSTGRES_PASSWORD=$(grep POSTGRES_PASSWORD /opt/pharmacopoeia-ai/.env | cut -d= -f2)
 
-# 5.2 执行导入(建议在 screen/tmux 中运行,防止断连)
-screen -S ingest
-python docx_ingest.py
-# Ctrl+A D 分离 screen,screen -r ingest 重新连接
+# 执行导入(默认路径 /opt/2025)
+python3 docx_ingest.py
+
+# Ctrl+A D 分离 screen
+# screen -r docx-ingest 重新连接查看进度
 ```
 
-**预期输出**:
+**进度监控**(另开终端):
+```bash
+# 每 60 秒查看入库进度
+watch -n 60 "docker exec pharmacopoeia-pg psql -U postgres -d pharmacopoeia -t -c 'SELECT NOW() AS time, COUNT(*) AS chunks FROM drug_chunks;'"
+```
+
+**预期结果**:
 ```
 📂 扫描 DOCX 文件...
    发现 6317 个 DOCX 文件
-📦 解析完成: 6xxx 个有效条目 (跳过 xx 个)
+📦 解析完成: ~6300 个有效条目
    分类分布:
      化学药: 2930
      中药: 2276
-     通则: 473
+     通则: 689
      药用辅料: 387
      ...
-🚀 第 1/13x 批 (50 个药品) ...
-  ✂️ 250 个 chunks,向量化中...
-    向量化: 10/250
-    向量化: 20/250
-    ...
-  ✅ 入库: 50 药品, 250 chunks
-
-🚀 第 2/13x 批 ...
+🎉 全部完成!新增药品 ~6300 个, chunks ~35000 条
 ```
 
-**耗时估算**:
-
-| 阶段 | 数量 | 耗时 |
-|------|------|------|
-| 解析 DOCX | 6317 个 | ~5 分钟 |
-| 向量化 | ~35,000 个 chunk / 10 条每批 = 3500 次 API 调用 | ~2-3 小时 |
-| 写入 PG | ~35,000 行 | ~5 分钟 |
-| **合计** | | **约 2-4 小时** |
+---
 
-**断点续传**: 脚本使用 `ON CONFLICT DO NOTHING`,重复运行不会产生重复数据。如果中途中断,重新运行即可从断点继续(已入库的会被跳过)。
+## 八、启动 Java 后端服务
 
-**监控进度**:
 ```bash
-# 另一个终端,每隔 30 秒查看入库量
-watch -n 30 "docker exec pharmacopoeia-pg psql -U postgres -d pharmacopoeia -c 'SELECT COUNT(*) AS total_chunks FROM drug_chunks;'"
+cd /opt/pharmacopoeia-ai/backend-java
+
+# 8.1 设置环境变量
+export POSTGRES_PASSWORD=$(grep POSTGRES_PASSWORD /opt/pharmacopoeia-ai/.env | cut -d= -f2)
+export QWEN_API_KEY=$(grep QWEN_API_KEY /opt/pharmacopoeia-ai/.env | cut -d= -f2)
+
+# 8.2 启动服务
+nohup java -Xms512m -Xmx2g -Dfile.encoding=UTF-8 \
+    -jar target/pharmacopoeia-ai-1.0.0.jar \
+    > /var/log/pharmacopoeia/backend.log 2>&1 &
+
+# 8.3 等待启动
+sleep 10
+
+# 8.4 验证
+curl -s http://localhost:9000/api/v1/health
+# {"status":"UP"}
+
+curl -s http://localhost:9000/api/v1/admin/stats | python3 -m json.tool
+# {"total_drugs": ~6300, "total_chunks": ~35000, ...}
 ```
 
 ---
 
-### Step 6: 验证搜索功能
+## 九、验证搜索功能
 
 ```bash
-# 6.1 确认数据量
-curl -s http://localhost:9000/api/v1/admin/stats | python3 -m json.tool
-# total_drugs: ~6300+, total_chunks: ~35000+
+# 9.1 药品搜索
+curl -s "http://localhost:9000/api/v1/drug/search?keyword=布洛芬" | python3 -m json.tool | head -20
 
-# 6.2 测试药品搜索
-curl -s "http://localhost:9000/api/v1/drug/search?keyword=布洛芬" | python3 -m json.tool | head -30
-
-# 6.3 测试 AI 问答(非流式)
+# 9.2 AI 问答
 curl -s -X POST http://localhost:9000/api/v1/chat/ask \
   -H "Content-Type: application/json" \
-  -d '{"message":"布洛芬缓释胶囊的用法用量"}' | python3 -m json.tool | head -50
-
-# 6.4 测试 AI 问答(流式 SSE)
-curl -N -X POST http://localhost:9000/api/v1/chat/stream \
-  -H "Content-Type: application/json" \
-  -d '{"message":"甲硝唑的不良反应有哪些"}'
+  -d '{"message":"布洛芬缓释胶囊的用法用量"}' | python3 -m json.tool | head -30
 
-# 6.5 验证 Wiki 数据(临床专著格式)
-curl -s "http://localhost:9000/api/v1/drug/search?keyword=二甲双胍" | python3 -m json.tool | head -20
+# 9.3 分类树
+curl -s http://localhost:9000/api/v1/drug/category/tree | python3 -m json.tool | head -15
 
-# 6.6 测试分类树
-curl -s http://localhost:9000/api/v1/drug/category/tree | python3 -m json.tool | head -20
+# 9.4 Wiki 数据(临床专著)
+curl -s "http://localhost:9000/api/v1/drug/search?keyword=甲硝唑" | python3 -m json.tool | head -15
 ```
 
 ---
 
-### Step 7: 正式启动服务
+## 十、设置开机自启(可选)
 
 ```bash
-# 7.1 关闭临时 Java 进程
-pkill -f pharmacopoeia-ai-1.0.0.jar
-
-# 7.2 使用 supervisor 管理(推荐)
-cp deploy/supervisord-java.conf /etc/supervisor/conf.d/pharmacopoeia.conf
-
-# 编辑 supervisor 配置,填入真实环境变量
-vim /etc/supervisor/conf.d/pharmacopoeia.conf
-# 修改 environment 行:
-#   POSTGRES_PASSWORD="实际密码",
-#   QWEN_API_KEY="实际的Key"
-
-supervisorctl reread
-supervisorctl update
-supervisorctl start pharmacopoeia-backend
-
-# 7.3 或者用 systemd
-cat > /etc/systemd/system/pharmacopoeia.service << 'EOF'
+# 10.1 创建 systemd 服务
+cat > /etc/systemd/system/pharmacopoeia.service << 'SERVICEOF'
 [Unit]
 Description=Pharmacopoeia AI Backend
 After=network.target docker.service
+Requires=docker.service
 
 [Service]
 Type=simple
 User=root
 WorkingDirectory=/opt/pharmacopoeia-ai/backend-java
-Environment="JAVA_HOME=/usr/lib/jvm/jdk-21"
-Environment="POSTGRES_PASSWORD=pharma2025"
-Environment="QWEN_API_KEY=sk-your-key"
+EnvironmentFile=/opt/pharmacopoeia-ai/.env
 ExecStart=/usr/lib/jvm/jdk-21/bin/java -Xms512m -Xmx2g -Dfile.encoding=UTF-8 -jar target/pharmacopoeia-ai-1.0.0.jar
 Restart=always
 RestartSec=10
@@ -289,86 +301,64 @@ StandardError=append:/var/log/pharmacopoeia/backend-error.log
 
 [Install]
 WantedBy=multi-user.target
-EOF
+SERVICEOF
 
+# 10.2 启用
 systemctl daemon-reload
 systemctl enable pharmacopoeia
 systemctl start pharmacopoeia
 systemctl status pharmacopoeia
 
-# 7.4 最终验证
-curl http://localhost:9000/api/v1/health
+# 10.3 Docker 容器也设置自启
+cd /opt/pharmacopoeia-ai/deploy
+# 已在 docker-compose.yml 中默认 restart: (无),
+# 可加 restart: always 后 docker-compose up -d 生效
 ```
 
 ---
 
-## 、故障排查
+## 十一、故障排查
 
 ### PG 连接失败
 ```bash
-docker logs pharmacopoeia-pg --tail 20
-docker exec pharmacopoeia-pg pg_isready -U postgres
-```
-
-### Embedding API 报错
-```bash
-# 检查 QWEN_API_KEY 是否正确
-grep QWEN_API_KEY /opt/pharmacopoeia-ai/.env
-# 手动测试 API
-curl -X POST https://dashscope.aliyuncs.com/api/v1/services/embeddings/text-embedding/text-embedding \
-  -H "Authorization: Bearer $QWEN_API_KEY" \
-  -H "Content-Type: application/json" \
-  -d '{"model":"text-embedding-v3","input":{"texts":["测试"]},"parameters":{"text_type":"query"}}'
+docker logs pharmacopoeia-pg --tail 30
+docker start pharmacopoeia-pg
 ```
 
-### Java 后端启动失败
+### Java 启动失败
 ```bash
-# 查看错误日志
-tail -100 /var/log/pharmacopoeia/backend-error.log
-# 常见原因: PG 未启动、端口被占用、API Key 无效
+tail -50 /var/log/pharmacopoeia/backend-error.log
+# 常见: PG 未启动 → 检查 Step 三
+# 常见: API Key 无效 → 检查 .env 中的 QWEN_API_KEY
 ```
 
-### DOCX 导入中断恢复
+### DOCX 导入中断
 ```bash
-# docx_ingest.py 使用 ON CONFLICT DO NOTHING,直接重新运行即可
-cd /opt/pharmacopoeia-ai/data-pipeline
-python docx_ingest.py
+# 直接重新运行即可(ON CONFLICT DO NOTHING,不重复写入)
+screen -r docx-ingest
+# 如果 screen 已丢失,重新执行 Step 七
 ```
 
 ### 搜索无结果
 ```bash
-# 确认数据已入库
+# 确认数据状态
 docker exec pharmacopoeia-pg psql -U postgres -d pharmacopoeia -c "
-SELECT COUNT(*) AS drugs FROM drugs WHERE is_active=TRUE;
-SELECT COUNT(*) AS chunks FROM drug_chunks WHERE vec IS NOT NULL;
-SELECT name FROM drugs WHERE name LIKE '%布洛芬%' LIMIT 5;
+SELECT 'drugs' AS tbl, COUNT(*) FROM drugs WHERE is_active=TRUE
+UNION ALL
+SELECT 'chunks', COUNT(*) FROM drug_chunks WHERE vec IS NOT NULL;
 "
-# 如果 drugs 有数据但搜索无结果,检查 vec 列是否为 NULL:
-# SELECT drug_id, vec IS NULL FROM drug_chunks LIMIT 5;
+# drugs 和 chunks 都应为 >0
 ```
 
 ---
 
-## 四、数据导入决策表
+## 快速参考
 
-| 场景 | 导入内容 | 命令 | 耗时 |
-|------|----------|------|------|
-| 快速验证 | Wiki (21 条) | `python import_all.py` | 2 分钟 |
-| 完整部署 | Wiki + 6317 DOCX | `python import_all.py && python docx_ingest.py` | 2-4 小时 |
-| 增量更新 | 仅新增 DOCX | `python docx_ingest.py` | 首次长/后续短 |
-| 清空重建 | 全部重来 | `TRUNCATE drug_chunks, drugs CASCADE;` 然后重新导入 | 2-4 小时 |
-
----
-
-## 五、关键路径汇总
-
-```
-部署路径:     /opt/pharmacopoeia-ai/
-DOCX 源:      /opt/2025/output*/.../*.docx (6317 个)
-PG 容器:      pharmacopoeia-pg (5432)
-Redis 容器:   pharmacopoeia-redis (6379)
-Java 后端:    http://localhost:9000
-API 前缀:     /api/v1
-Supervisor:   /etc/supervisor/conf.d/pharmacopoeia.conf
-日志:         /var/log/pharmacopoeia/
-```
+| 路径/命令 | 用途 |
+|-----------|------|
+| `/opt/pharmacopoeia-ai/` | 项目根目录 |
+| `/opt/2025/` | DOCX 药典数据源 |
+| `docker-compose ps` | 查看 PG/Redis 状态 |
+| `screen -r docx-ingest` | 重连 DOCX 导入任务 |
+| `http://localhost:9000/api/v1/health` | 健康检查 |
+| `/var/log/pharmacopoeia/backend.log` | Java 日志 |