如何使用Nemotron为RAG构建文档处理管道
如果AI智能体能够即时解析复杂的PDF,提取嵌套表格,并像读取文本文件一样“看到”图表中的数据,会怎样?借助某机构的Nemotron RAG,您可以构建一个高吞吐量的智能文档处理管道,以高精度处理海量文档工作负载。
本文逐步介绍多模态检索管道的核心组件。首先,展示如何使用开源NeMo Retriever库,通过GPU加速微服务将复杂文档分解为结构化数据。然后,演示如何将这些数据接入Nemotron RAG模型,以确保助手提供有依据、准确且可完全追溯到源头的答案。
模型与代码快速链接
访问以下教程资源:
🧠 Hugging Face上的模型:
nvidia/llama-nemotron-embed-vl-1b-v2多模态嵌入模型nvidia/llama-nemotron-rerank-vl-1b-v2交叉编码器重排序模型- Nemotron RAG系列中的提取模型
☁️ 云端端点:
- Nemotron OCR文档提取
nvidia/llama-3.3-nemotron-super-49b-v1.5答案生成模型- 更多来自NIM的模型
🛠️ 代码与文档:
- NeMo Retriever库 (GitHub)
- 教程笔记本 Jupyter Notebook (GitHub)
前提条件
系统要求:
- Python 3.10 至 3.12 (已在3.12上测试)
- 本地模型部署需配备至少24 GB显存的某机构GPU
- 250 GB磁盘空间 (用于模型、数据集和向量数据库)
API访问:
- 某机构API密钥 (在build.nvidia.com免费获取)
Python环境:
[project]
name = "idp-pipeline"
version = "0.1.0"
description = "IDP Nemotron RAG Pipeline Demo"
requires-python = "==3.12"
dependencies = [
"ninja", "packaging", "wheel", "requests", "python-dotenv", "ipywidgets",
"markitdown", "nv-ingest==26.1.1", "nv-ingest-api==26.1.1", "nv-ingest-client==26.1.1",
"milvus-lite==2.4.12", "pymilvus", "openai>=1.51.0",
"transformers", "accelerate", "pillow", "torch", "torchvision", "timm"
]
所需时间: 完整实现约1-2小时 (如需编译flash-attn等GPU优化依赖则时间更长)
成果: 一个可用于生产环境的多模态RAG文档处理管道
为何传统OCR和纯文本处理在处理复杂文档时失效
构建管道前,需理解标准文本提取无法解决的几个核心挑战:
- 结构复杂性:文档包含矩阵和表格,数据间关系至关重要。标准PDF解析器会合并行列,破坏结构——将“型号A:最高95°C”和“型号B:最高120°C”变成不可用的文本,导致制造、合规和决策中出现错误。
- 多模态内容:关键信息存在于图表、示意图和扫描图像中,纯文本解析器会遗漏。性能趋势、诊断结果和流程图需要视觉理解。
- 引用要求:受监管行业需要精确的引用以进行审计追踪。答案需要“第4.2节,第47页”这类可追溯的引用,而不仅仅是没有出处的事实。
- 条件逻辑:“如果-那么”规则常跨多个部分。理解“0°C以下使用协议A,否则使用协议B”需要保留文档层次结构和跨页交叉引用——这对技术手册、政策和法规指南至关重要。
智能文档处理部署的关键考量
构建文档处理管道时,以下因素决定生产可行性:
- 分块大小的权衡:较小的块 (256-512 tokens) 可实现精确检索但可能丢失上下文。较大的块 (1,024-2,048 tokens) 保留上下文但降低精度。对于企业文档,512-1,024 tokens配合100-200 token重叠可平衡两者需求。
- 提取深度:决定是按页面分割内容还是保持文档完整。按页分割可实现精确引用和验证,而文档级分割则保持叙事流程和更广泛的上下文。根据是需要精确来源位置还是全面理解来选择。
- 表格输出格式:将表格转换为Markdown,以LLM原生的格式保留行列关系,显著减少纯文本线性化导致的数值幻觉。
- 库模式与容器模式:库模式 (SimpleBroker) 适用于开发和小型文档 (<100份)。生产部署需要容器模式配合Redis/Kafka,以实现跨数千份文档的水平扩展。
多模态RAG管道的组件有哪些?
在生成带引用的答案之前,智能文档处理管道包含三个主要阶段:
阶段1:提取
- 输入:PDF文件
- 输出:包含结构化条目的JSON:文本块、表格Markdown、图表图像
- 运行方式:库、自托管 (Docker) 和/或远程客户端
阶段2:嵌入
- 输入:提取的条目 (文本、表格、图表图像)
- 输出:每个条目2048维向量及原始内容
- 关键能力:多模态——可编码纯文本、纯图像或图像与文本组合
- 运行方式:本地GPU或远程NIM
阶段3:重排序
- 输入:来自嵌入搜索的Top-K候选结果
- 输出:排序后的列表 (最高相关性优先)
- 关键能力:交叉编码器;同时处理 (查询、文档、可选图像)
- 运行方式:本地GPU或远程NIM
- 重要性:过滤掉“看起来相似但错误”的结果;VLM版本还能看到图像以验证相关性
生成答案
- 输入:排名最高的文档 + 用户问题
- 输出:有依据、带引用的答案
- 关键能力:遵循严格的系统提示来引用来源、承认不确定性
- 运行方式:本地或build.nvidia.com上的NIM
构建每个管道组件的代码
提取代码示例
# 启动nv-ingest (库模式) 并连接本地客户端
print("[INFO] Starting Ingestion Pipeline (Library Mode)...")
run_pipeline(block=False, disable_dynamic_scaling=True, run_in_subprocess=True, quiet=True)
time.sleep(15) # 预热
client = NvIngestClient(
message_client_allocator=SimpleClient,
message_client_port=7671, # 默认库模式端口
message_client_hostname="localhost")
# 提交提取任务:保持表格为Markdown + 裁剪图表
ingestor = (Ingestor(client=client)
.files([PDF_PATH])
.extract(
extract_text=True,
extract_tables=True,
extract_charts=True, # 图表裁剪
extract_images=False, # 专注于图表/表格
extract_method="pdfium",
table_output_format="markdown"
))
job_results = ingestor.ingest()
extracted_data = job_results[0]
嵌入代码示例
# 向量数据库约定:2048维向量 + 原始载荷/元数据存入Milvus
HF_EMBED_MODEL_ID = "nvidia/llama-nemotron-embed-vl-1b-v2"
COLLECTION_NAME = "worldbank_peru_2017"
MILVUS_URI = "milvus_wb_demo.db"
milvus_client = MilvusClient(MILVUS_URI)
if milvus_client.has_collection(COLLECTION_NAME):
milvus_client.drop_collection(COLLECTION_NAME)
milvus_client.create_collection(collection_name=COLLECTION_NAME, dimension=2048, auto_id=True)
# 多模态编码:纯文本 vs 纯图像 vs 图像+文本
with torch.inference_mode():
if modality == "image_text":
emb = embed_model.encode_documents(images=[image_obj], texts=[content_text])
elif modality == "image":
emb = embed_model.encode_documents(images=[image_obj])
else:
emb = embed_model.encode_documents(texts=[content_text])
重排序代码示例
# 阶段1:查询嵌入 -> 从Milvus密集检索 (高召回率)
with torch.no_grad():
q_emb = embed_model.encode_queries([query])[0].float().cpu().numpy().tolist()
hits = milvus_client.search(
collection_name=COLLECTION_NAME,
data=[q_emb],
limit=retrieve_k,
output_fields=["text", "page", "source", "type", "has_image", "image_b64"])[0]
# 阶段2:VLM交叉编码器重排序 (查询 + 文档文本 + 可选文档图像) (高精度)
batch = rerank_inputs[i:i+batch_size] # 从hits构建的字典列表
inputs = rerank_processor.process_queries_documents_crossencoder(batch)
inputs = {k: v.to("cuda") if isinstance(v, torch.Tensor) else v for k, v in inputs.items()}
with torch.no_grad():
logits = rerank_model(**inputs).logits.squeeze(-1).float().cpu().numpy()
优化检索的后续步骤
智能文档处理管道上线后,通往生产环境的道路便已敞开。这套方案的优势在于其灵活性。可以尝试将新数据源连接到NeMo Retriever库,或使用专门的NIM微服务来优化检索精度。随着文档库的增长,您会发现此架构可作为构建多智能体系统的可扩展基础,从而理解企业知识的细微差别。FINISHED