
今日完成
1. 技术栈确认
- Embedding:
BAAI/bge-m3int8 ONNX(544MB),本地 CPU 运行,1024 维,L2 归一化,中/日/英跨语言对齐验证通过。 - 向量库:Chroma(本地持久化,余弦距离)。
- LLM:One API → NVIDIA 远程渠道,
deepseek-ai/deepseek-v4.1-flash。 - 前端/会话管理:WordPress(待对接)。
- API:FastAPI,端口 8093,systemd 常驻。
2. 环境隔离
golforfun 旧项目和新项目分两个 venv,避免依赖冲突:
/opt/golf-rag/venv:旧项目,transformers 5.20.2。/opt/rag-new/venv:新项目,optimum + onnxruntime,不装 sentence-transformers。
3. 文档解析器
parse_pdf.py / parse_pdf_v2.py(PDF → chunk):
- 按页拆分,识别段落和表格行。
- 表格行拼表头:
Net Sales (FY2025=440, FY2026=481)。 - 清洗:去页眉页脚、合并字距问题(
K O K O P E L L I → KOKOPELLI)、合并断行段落。 - 过滤纯数字图表行。
- KOKOPELLI 财报:178 chunk(149 段落 + 29 表格行),跳过 8 个标题页。
parse_excel.py(Excel → chunk):
- 规整表:表头 + 逐行数据,每行拼成
Date: ... | Time: ... | Activity: ...。 - 合并单元格继承:只对 Date/Time 维度列生效,Details 空就空着。
- 行程表:30 chunk,无跳过。
4. 入库管道
ingest.py:
- 接入 parse_pdf_v2 和 parse_excel。
- 中文辅助映射:财务科目(Net Sales→销售额)、KPI、景点名。
- documents 存原文,embeddings 用「原文 + 中文辅助」算。
- 分批 embedding(BATCH=10),避免 OOM。
- 按 source_id 删旧再写,避免重复。
- 本次入库 185 条(PDF 155 + Excel 30),collection 总数 188。
5. 检索与生成
rag_core.py:
ask(query, top_k, where)对外接口。- build_prompt 带 source_type/page/row/table_type,模型能区分
[actual]和[forecast]。 - SYSTEM_PROMPT 明确规则:优先用 actual、不编造、标引用。
- max_tokens=2000 + 空内容容错(finish_reason=’length’ 时返回明确提示)。
- config.py:集中配置,.env 读令牌,chmod 600。
6. 黄金测试集
golden_set.json + eval_golden.py:
- 4 条测试:营业利润、销售额、归母净利润、operating profit。
- 4/4 通过,跨语言检索验证。
7. FastAPI 服务
api.py:
POST /api/ask:接收{text, top_k, where},返回{answer, sources}。GET /api/health:健康检查。- CORS 开放(验证期)。
- systemd 服务 rag-api,端口 8093,Restart=on-failure,TimeoutStartSec=120。
8. 验证结果
| 问题 | 结果 |
|---|---|
| Net Sales 是多少 | ✅ 481(FY2026 Q1 实际值),正确排除 p36 预测值 |
| EBITDA 是多少 | ✅ 58 百万日元(+574.3%),actual/forecast 区分正确 |
| 第2天下午去哪 | ✅ 祇园 + 伏见稻荷大社,中文辅助生效 |
| 营业利润是多少 | ✅ 100 亿日元,跨语言命中日文 営業利益 |
当前架构
WordPress(待接) ↓ POST /api/ask FastAPI(127.0.0.1:8093) ↓ rag_core.ask() ├─ bge-m3 int8 embedding(本地 CPU) ├─ Chroma 检索(PDF 155 + Excel 30) └─ One API → deepseek-v4.1-flash → NVIDIA 远程
已知问题(不紧急)
- PDF 表格列名部分错位:p27 的
FY2025=+41, FY2026=+9.3%应为Change=+41, YoY=+9.3%,但数字对了,模型靠量级和[actual]标签绕过。 - p36 表头不完整:col1=1,758, col2=2,000 缺 FY2025/FY2026 列名,但
[forecast]标签让模型知道是预测值。 - 不同 PDF 需调规则:guess_columns、is_table_header 是针对 KOKOPELLI 写的,新 PDF 格式不同需重新调,或引入 agent 做语义映射。
- 内存紧张:golforfun + rag-api 同时跑,available 1.4Gi,swap 1.7Gi。验证期建议停 golforfun。
接下来的 Task
高优先级
- ☐ nginx 反代 + HTTPS:子域(如 rag.golforfun.net)→ 127.0.0.1:8093,Let’s Encrypt DNS-01 证书。参考 golforfun 项目的踩坑清单(DNS 传播、certbot manual、tailscaled 占 443)。
- ☐ WordPress 对接:Codex 侧写 POST /api/ask 调用 + 会话保存(父 post 存会话、子 post 存每轮消息)。
- ☐ 权限过滤接入:build_access_filter(user_context) 策略函数,当前 public/registered 两档,where 参数已透传。
- ☐ 会话入库:一问一答作为一个 chunk,异步批量写 Chroma,metadata 带 session_id、user_id、turn_index。
中优先级
- ☐ Word/PPT 解析:用 MarkItDown 或 python-docx/python-pptx,输出统一
{text, aux, meta},接入 ingest.py。 - ☐ 表格列名映射修复:parse_pdf_v2.py 的占位逻辑,让 col1/col2 变成 FY2025/FY2026。
- ☐ 内存优化:停 golforfun 或迁到另一台;或换更小的 embedding 模型(multilingual-e5-small,约 500MB)。
低优先级(验证期后)
- ☐ agent 表格映射:规则解析失败时调 LLM 做语义映射,处理不同公司财报。
- ☐ 视频/音频入库:faster-whisper CPU 转录,按时间窗口切 chunk。
- ☐ 图片入库:视觉模型生成描述,描述文本入库。
- ☐ URL 入库:ChromeRAG 抽正文,按 heading 拆。
- ☐ K 线图:前端展示 + 代码算指标 + 文本 RAG 补新闻,不塞进文本 RAG。
参考资料
- 旧项目复盘:https://helloai.jp/archives/2984
- 踩坑清单:拆条按子条款、关键词硬过滤、with_structured_output 不可用、评分死循环、timeout=300、proxy_read_timeout 300s、Restart=on-failure。
- 文件路径:
/opt/rag-new/(bge_m3.py、rag_core.py、api.py、parse_pdf_v2.py、parse_excel.py、ingest.py、eval_golden.py、config.py、.env)、/opt/rag-nvidia/data/(koko.pdf、VIP Trip to Japan.xlsx)。
一句话总结:PDF + Excel 入库、跨语言检索、actual/forecast 区分、FastAPI 服务全部跑通,Net Sales 和 EBITDA 答对,systemd 常驻。下一步是 nginx + WordPress 对接 + 权限过滤 + 会话入库。


讨论
订阅评论 RSS加入讨论
分享你的想法与经验,也可以登录后参与讨论。
使用 WordPress 登录