该方案把 PDF、图片和表格逐页转成图像,由 VLM 生成摘要及关键词,再将向量写入 PostgreSQL 和 pgvector。统一的视觉抽取层可绕过不同文件解析器带来的格式差异。
要构建一套有效的语义检索 pipeline,如果输入数据的格式不一致,就会极具挑战,其中包括:
结构化与非结构化附件混合存在
传统的 chunking 方法难以应对这种情况,因为不同文件的内容结构差异很大。为了提升检索质量,需要在生成 embedding 之前,先提取出有意义的文本表示。
为了处理异构输入格式,pipeline 经过重新设计,使用 Vision Language Model(VLM)作为提取层。
系统不再依赖传统 parser,而是将文档的每一页转换为图片,再交给 VLM 独立处理。
上传文档附件
提取页面,并将每一页转换为图片
将图片编码为 Base64 格式
将图片发送给 VLM,生成摘要并提取关键词
为生成的摘要创建 embedding
使用 pgvector 将 embedding 存储到 PostgreSQL
由 AI Agent 通过语义搜索进行检索
每一页都会被视为一个独立的 chunk。
async def vlm_inference(self, vlm_req: VLMRequest, file: UploadFile) -> list[str]:
img_list = await extract_content(file, True)
results = []
for idx, img in enumerate(img_list):
# Save image for inspection
image_path = save_dir / f"page_{idx}.png"
img.save(image_path)
print(f"Saved image: {image_path}")
# Convert to base64 for VLM
img_base64 = image_to_base64(img)
client = OllamaClient()
result = await client.vlm_inference(
vlm_req=vlm_req,
image_base64=img_base64,
)
results.append(result)
return results
async def vlm_inference(
self,
vlm_req: VLMRequest,
image_base64: str
) -> str:
payload = {
"model": vlm_req.model,
"messages": [
{
"role": "user",
"content": vlm_req.prompt,
"images": [image_base64],
}
],
"stream": False,
"think": vlm_req.thinking,
}
response = requests.post(
f"{LLM_BASE_URL}/api/chat",
json=payload,
timeout=300
)
response.raise_for_status()
print(response.json())
return response.json()['message']['content']
按页进行 chunking 的优势在于,它既避免了针对不同文档编写复杂的解析逻辑,又保留了原始文件的视觉上下文。
提取出的页面图片会通过 Ollama API 发送给 VLM。
async def vlm_inference(
self,
vlm_req: VLMRequest,
image_base64: str
) -> str:
payload = {
"model": vlm_req.model,
"messages": [
{
"role": "user",
"content": vlm_req.prompt,
"images": [image_base64],
}
],
"stream": False,
"think": vlm_req.thinking,
}
response = requests.post(
f"{LLM_BASE_URL}/api/chat",
json=payload,
timeout=300
)
response.raise_for_status()
return response.json()['message']['content']
最初使用的提取模型是:Qwen3.5:20B。然而,在处理数千个附件时,其推理延迟过高。
因此,pipeline 改用以下模型进行优化:
Qwen3.5:4B。这个更小的模型在以下方面实现了更好的平衡:
提取质量
Qwen 模型的推理模式带来了一个实际问题。
启用 thinking 后:
模型会消耗额外的 token 进行内部推理
过长的生成过程会耗尽输出 token 预算
部分页面会返回空摘要,因为模型在达到最大输出长度后就停止了
提高 token 上限并不可取,因为:
系统需要处理数千个附件
更长的输出会增加推理成本
存储需求会显著增加
因此,系统关闭了推理模式。
关闭 thinking 后:
响应延迟得到改善
输出变得更加简洁
重要关键词仍然得以保留
检索性能仍处于可接受水平
VLM 完成提取后,生成的摘要会被转换为 embedding。
这些 embedding 使用 pgvector 存储在 PostgreSQL 中。基于 VLM 的提取方案可以从异构文档中生成一致的文本表示,显著提升了语义检索性能。
现在,AI Agent 可以从以下内容中检索相关信息:
混合格式附件
而无须为每一种文件类型分别开发 parser。
其中最关键的设计决策,是将 VLM 用作通用提取层,把非结构化的视觉信息转换为可搜索的语义表示。
若要采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。