在 V1 纯文本 RAG 基础上重构的多模态版本。V2 使用 LangChain 统一 Document、VectorStore 与 Retriever, 保留原有的跨语言文本检索与 Reranker,同时从 PDF 中提取手册图片并与 Chunk 建立关联。 最终由 Qwen-VL 同时读取 Rerank 后的文本与候选图片,并在确有帮助时把正确示意图展示在回答中。
V1 的核心能力是“中文问题 → 英文手册向量检索 → Reranker → 中文回答”, 但手册中大量信息依赖示意图,例如拖车钩位置、轮毂螺母拧紧顺序、仪表盘图标和操作部件位置。 V2 在保留稳定文本检索链路的基础上,让最终生成模型能够读取与命中 Chunk 对应的手册图片。
| 能力 | V1 | V2 |
|---|---|---|
| 检索框架 | 直接调用 Chroma | LangChain VectorStore / Retriever |
| 知识输入 | 纯文本 Chunk | 文本 Chunk + 对应手册图片 |
| 最终模型 | 文本 LLM | Qwen-VL 多模态模型 |
| 图片展示 | 不支持生成阶段识图 | LLM 判断是否需要展示,并选择相关图片 |
| 历史会话 | 共用 SQLite chat.db,可同时显示文字与 V2 图片回答 | |
文本继续沿用 V1 已验证过的句子级 Chunking。新增图片处理后,PDF 中的图片通过 PyMuPDF 独立提取,
再根据 PDF 页码与 Chunk 建立关联。图片本身不写入文本向量,只将 image_ids 保存在 Chunk metadata 中。
{
"chunk_id": 430,
"start_page": 255,
"end_page": 256,
"word_count": 180,
"text": "...",
"image_ids": [
"page_255_img_01",
"page_255_img_02",
"page_256_img_01"
]
}
当前版本属于 Text-led Multimodal RAG:文本负责“找到正确页面”, Qwen-VL 负责“理解页面中的图片”。因此暂时不需要为整套图片单独建立视觉向量库。
V2 将原来手写的 Embedding、Chroma Query 和结果整理流程,改写为 LangChain 的标准抽象。
每个 Chunk 转换为 Document,正文放在 page_content,
页码、Chunk ID 和图片 ID 保存在 metadata。
chunks_multimodal.json
↓
LangChain Document
↓
Qwen Text Embedding
↓
langchain_chroma.Chroma
↓
VectorStore.as_retriever()
↓
List[Document]
Chroma 通过 persist_directory 持久化到服务器本地,因此部署时可以直接加载已经生成好的向量库,
无需重新处理整本手册。
Question ↓ Qwen Text Embedding ↓ LangChain Chroma Retriever ↓ Vector Top 20 ↓ Qwen Text Reranker ↓ Top 5 Documents ↓ 读取 Top 5 的 image_ids ↓ 图片去重 ↓ Top 5 Text + Candidate Images ↓ Qwen-VL ↓ Chinese Answer + PDF Citation ↓ 可选:展示相关手册图片
Vector Retrieval 仍以召回率为优先,先获得较大的候选集,再通过 Reranker 提高最终上下文精度。 图片只在 Rerank 完成后收集,避免把 Vector Top 20 对应的大量无关图片全部发送给视觉模型。
候选图片不会直接以真实文件名暴露给模型。系统会为每次请求建立临时别名:
IMG_1 → page_226_img_03 IMG_2 → page_229_img_02 IMG_3 → page_230_img_01
Qwen-VL 只使用类似 [[SHOW_IMAGES:IMG_1]] 的控制标记选择图片,
后端再将临时编号映射回真实文件并生成前端图片 HTML。
这样可以减少模型把内部图片文件名直接写进正文的问题。
如果纯文字已经足够回答,则返回 SHOW_IMAGES:none;
对位置、顺序、图标外观或操作动作有明显帮助时,才展示手册示意图。
V2 保留 Retrieval、Rerank 和 Generation 的耗时与 Token 统计,并增加候选图片数量, 用于观察视觉输入带来的额外成本。
[RAG] vector_candidates=20 rerank_docs=5 candidate_images=18 retrieval=0.547s rerank=0.729s rerank_tokens=5930 [LLM] input_tokens=3374 output_tokens=259 total_tokens=3633 generation=4.192s
与 V1 相比,Reranker 成本基本保持一致,新增消耗主要来自 Qwen-VL 的视觉输入。 多张低分辨率手册线稿不会让 Token 数量失控,但候选图片过多仍可能影响模型选图稳定性, 因此图片筛选数量仍是后续可优化方向。
StreamingResponse 实现流式回答。chat.db,历史记录可以跨版本查看。/manual-images/ 静态路由提供。camry-v1.garwin.duckdns.org
↓
Nginx
↓
127.0.0.1:8001
↓
V1 Text RAG
camry-v2.garwin.duckdns.org
↓
Nginx
↓
127.0.0.1:8003
↓
V2 Multimodal LangChain RAG
↓
共享 SQLite chat.db
两个版本同时部署在 Linux 云服务器,由 systemd 保持 FastAPI 服务常驻, Nginx 负责 HTTPS、统一认证和反向代理。V1 与 V2 使用独立服务端口,但共用历史会话数据库。
当前主要问题仍可以由文本 Retriever 先定位到正确页面,再把对应图片交给 Qwen-VL 判断。 这样既保留 V1 已验证过的文本检索质量,又能以较小改动增加多模态能力。
如果后续加入“用户上传仪表盘照片 → 在手册图库中寻找相似图标”这类需求, 再增加视觉 Embedding 与图片向量库会更有价值。
V2 的重点不是简单“把项目改成 LangChain”,而是用 LangChain 统一 Document、VectorStore 和 Retriever, 同时保留已经验证有效的 Qwen Embedding 与 Reranker。 在此基础上,项目增加 PDF 图片抽取、Chunk-Image 关联、Qwen-VL 多模态生成、 模型选图与前端图片展示,将 V1 的纯文本 RAG 扩展成可处理图文手册的多模态 RAG。