年版RAG学习笔记第二期:数据导入完整流程新手必看攻略精选

2026-06-23阅读 0热度 0
学习笔记

RAG学习笔记(二)数据导入

在检索增强生成(RAG)的世界里,大模型不再是孤立的知识孤岛,而是能够与外部世界实时互动的智能体。而这种互动的基础,就在于高效、精准地将海量异构数据转化为可供大模型“理解”和“检索”的知识。
RAG学习笔记(二)数据导入
数据导入,作为RAG流程的开端,其重要性怎么强调都不为过。它不只是把数据从A点搬到B点,更是一门将原始信息转化为RAG系统可用知识的艺术。 今天我们就深入聊聊RAG中数据导入的关键技术与最佳实践,看看如何把各种形式的数据,真正变成RAG系统能读懂的知识。 **数据导入的整体原则** 在RAG数据导入的实践中,有几个核心原则需要把握。这些原则能帮我们选对工具、设计好流程,最终保证导入数据的质量和可用性。 **优先使用通用解析库与工具。** 面对五花八门的数据格式,首选自然是那些支持多种文件类型、社区活跃且维护良好的通用解析库或框架,比如LangChain、LlamaIndex。这些工具提供了标准化的接口和丰富的功能,能有效降低开发的复杂性。 **针对重要文件类型选择专用工具。** 对于PDF、图片这类内部结构复杂、或包含大量非文本信息的文件,通用工具可能会力不从心。这时候就得请出专门针对这些格式优化的工具——比如PDF解析库、OCR工具——来确保内容提取的完整性和准确性。 **深入理解文件内容的内部结构。** 不同的文件格式承载信息的方式各不一样。JSON文件是结构化的键值对,Markdown文件则通过特定语法定义了标题、段落、列表等层级关系。理解这些内部结构,有助于我们更精准地提取有效信息,同时保留语义上下文。 **复杂文档的中间格式转化。** 对于结构极其复杂或包含多种媒体类型的文档,直接解析往往效率不高。一个行之有效的策略是先把它们转化为更易于解析的中间格式——比如把含有图表的PDF转成Markdown,或用OCR把扫描件转成可编辑文本,再进行后续处理。 **大模型辅助数据解析。** 随着多模态大模型的发展,它们在理解和处理非结构化、半结构化数据方面展现出强大潜力。对于传统方法难以处理的复杂场景,可以考虑借助大模型的能力,辅助进行信息抽取、结构化转换,甚至对图表内容做语义理解。 **简单文本的读取:从基础到高效** 在RAG系统中,最基础也是最常见的数据形式就是纯文本文件,比如`.txt`。虽然看着简单,但高效地读取和处理这些文本,是构建高质量知识库的第一步。通常我们会用专门的文档加载器来做这件事,它们不仅能读文本内容,还能自动提取或允许我们添加重要的元数据。 **核心概念:Document对象与元数据** 在LangChain或LlamaIndex等主流RAG框架中,文本数据通常被封装成`Document`对象。典型的`Document`对象包含两部分: `page_content`:文档的实际文本内容,是RAG系统做语义理解和生成的基础。 `metadata`:与文档相关的元信息,比如文件路径、创建日期、作者、主题标签等。 **实践案例:企业内部知识库的文本导入** 假设一家大型科技公司想构建一个RAG系统,用来快速检索和回答员工关于公司内部规章制度、技术文档、项目报告等纯文本信息。这些文档通常以`.txt`格式存储在公司的文件服务器上。 传统做法是手动查找和阅读,效率低下还容易漏信息。通过RAG系统,员工可以直接提自然语言问题,系统则从海量文档中检索相关片段并生成回答。 要实现这个目标,数据导入阶段需要批量读取这些`.txt`文件。可以用LangChain的`DirectoryLoader`配合`TextLoader`来完成:
from langchain_community.document_loaders import DirectoryLoader, TextLoader

# 定义包含公司规章制度和技术文档的目录
data_directory = "./company_knowledge_base/policies_and_tech_docs"

# 使用DirectoryLoader加载指定目录下的所有.txt文件
# loader_cls指定使用TextLoader来处理每个文件
loader = DirectoryLoader(data_directory, glob="**/*.txt", loader_cls=TextLoader)

# 加载文档,每个文件会生成一个Document对象
documents = loader.load()

print(f"成功加载了 {len(documents)} 份文本文件。")

# 打印其中一份文档的示例内容和元数据
if documents:
    sample_doc = documents[0]
    print("--- 示例文档内容 ---")
    print(sample_doc.page_content[:500])  # 打印前500字符
    print("--- 示例文档元数据 ---")
    print(sample_doc.metadata)
在这个案例中,`DirectoryLoader`能递归遍历指定目录,用`TextLoader`把每个`.txt`文件的内容读成`Document`对象。每个`Document`对象会自动包含文件路径作为元数据,这对于追溯信息来源或做基于路径的过滤很有用。通过这种方式,公司能高效地把分散的纯文本知识整合到RAG知识库中,为后续的检索和生成打好基础。 **结构化文本的读取:从JSON到网页** 除了简单的纯文本,RAG系统还得处理各种结构化或半结构化的数据。这些数据通常包含更丰富的语义信息和层级关系,比如JSON文件、网页内容以及Markdown文档。有效解析这些结构化数据,并将其转化为RAG系统可用的`Document`对象,是提升检索精度和生成质量的关键。 **JSON数据的处理:提取关键信息** JSON是一种轻量级的数据交换格式,广泛应用于API响应、配置文件等场景。在RAG中,我们可能需要从复杂的JSON结构中提取特定字段或组合信息作为知识。LangChain的`JSONLoader`提供了强大能力,通过`jq_schema`参数,可以像用`jq`命令行工具一样,灵活地定义如何从JSON中抽取和格式化数据。 **实践案例:电商产品评论分析** 假设一家电商公司想构建一个RAG系统,帮客服人员快速查询和总结用户对特定产品的评论。这些评论数据以JSON格式存储,每个JSON对象包含评论ID、用户ID、评论内容、评分、评论时间等字段。客服人员可能想知道“用户对产品A的负面评论有哪些?”或“关于产品B的性能问题,用户是怎么反馈的?” 要实现这个目标,需要把JSON中的评论内容及其相关元数据导入RAG系统。`JSONLoader`结合`jq_schema`可以帮助我们精确提取所需信息:
from langchain_community.document_loaders import JSONLoader
import json

# 模拟电商产品评论数据
product_reviews_data = [
    {
        "review_id": "R001",
        "product_id": "P101",
        "user_id": "U001",
        "rating": 5,
        "comment": "这款智能手表太棒了!电池续航能力超乎想象,功能也很齐全,运动监测非常准确。",
        "timestamp": "2024-05-10T10:00:00Z"
    },
    {
        "review_id": "R002",
        "product_id": "P101",
        "user_id": "U002",
        "rating": 2,
        "comment": "手表外观很好看,但是心率监测数据总是不准,而且APP经常闪退,体验很差。",
        "timestamp": "2024-05-11T11:30:00Z"
    },
    {
        "review_id": "R003",
        "product_id": "P102",
        "user_id": "U003",
        "rating": 4,
        "comment": "蓝牙耳机音质不错,连接稳定,就是佩戴时间长了耳朵有点不舒服。",
        "timestamp": "2024-05-12T14:00:00Z"
    }
]

# 将模拟数据写入JSON文件
with open("product_reviews.json", "w", encoding="utf-8") as f:
    json.dump(product_reviews_data, f, ensure_ascii=False, indent=4)

# 使用JSONLoader加载数据,并使用jq_schema提取评论内容和相关信息
# 我们将评论内容作为page_content,并将产品ID、评分和评论ID作为元数据
loader = JSONLoader(
    file_path="product_reviews.json",
    jq_schema='.[].comment',
    metadata_func=lambda record, metadata: {
        "product_id": record.get("product_id"),
        "rating": record.get("rating"),
        "review_id": record.get("review_id")
    }
)

reviews_docs = loader.load()
print(f"成功加载了 {len(reviews_docs)} 条产品评论。")

# 打印其中一条评论的示例内容和元数据
if reviews_docs:
    sample_review = reviews_docs[0]
    print("--- 示例评论内容 ---")
    print(sample_review.page_content)
    print("--- 示例评论元数据 ---")
    print(sample_review.metadata)
这里`jq_schema='.[].comment'`指示`JSONLoader`提取每个JSON对象中的`comment`字段作为`page_content`。`metadata_func`则是一个自定义函数,用来从原始JSON记录中提取`product_id`、`rating`和`review_id`作为`Document`的元数据。这样一来,RAG系统不仅能检索到评论文本,还能利用这些元数据做更精细的过滤——比如只检索评分低于3星的评论。 **网页内容的解析:从HTML到结构化信息** 互联网是个巨大的知识宝库,网页是其主要载体。把网页内容导入RAG系统,能让大模型获取最新、最多样的信息。不过,网页通常包含大量的HTML标签、广告、导航等非内容元素,需要有效的解析工具来提取核心文本信息。LangChain提供了多种网页加载器,以适应不同的解析需求。 **实践案例:在线技术文档库的知识整合** 假设一家软件公司维护着一个庞大的在线技术文档库,这些文档以网页形式发布,包含产品说明、API参考、教程等。公司希望构建一个RAG系统,帮开发者快速查找和理解这些文档。传统的搜索引擎可能无法满足开发者对特定代码示例或API参数的精确查询需求。 通过把这些在线技术文档导入RAG系统,开发者可以直接提问“如何使用API X进行身份验证?”或“产品Y的最新版本有哪些新功能?”,系统将返回相关的文档片段。 可以使用`WebBaseLoader`来加载单个技术文档页面,或者用`RecursiveURLLoader`来抓取整个文档站点:
from langchain_community.document_loaders import WebBaseLoader
import bs4

# 假设一个在线技术文档的URL
tech_doc_url = "https://docs.example.com/latest/api-reference/authentication"

# 使用WebBaseLoader加载网页内容
# bs_kwargs可以用于传递BeautifulSoup的参数,例如指定解析器
loader = WebBaseLoader(
    web_paths=[tech_doc_url],
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(["div", "article", "main"])
    )
)

docs = loader.load()
print(f"成功加载了 {len(docs)} 个网页文档。")

# 打印加载的文档内容和元数据
if docs:
    tech_doc = docs[0]
    print("--- 示例网页文档内容 (部分) ---")
    # 网页内容通常较长,这里只打印前500字符
    print(tech_doc.page_content[:500])
    print("--- 示例网页文档元数据 ---")
    print(tech_doc.metadata)
在这个案例中,我们通过`WebBaseLoader`加载了特定的技术文档网页。通过`bs_kwargs`参数,指示`BeautifulSoup`只解析`div`、`article`或`main`标签内的内容,这有助于过滤掉导航、页脚等无关信息,从而更精确地提取核心文档内容。 对于更复杂的网站结构或需要批量抓取的情况,可以考虑使用`UnstructuredLoader`或`RecursiveURLLoader`,它们提供了更高级的解析和抓取策略,以适应多样化的网页内容。 **解析图中的文字与内容:超越文本的边界** 在现实世界的知识库中,信息往往不仅仅以纯文本形式存在。图片、扫描件、演示文稿(PPT)等视觉内容中也蕴含着大量有价值的信息。为了让RAG系统能够“看到”并“理解”这些视觉信息,我们需要借助光学字符识别(OCR)技术来提取图片中的文字,甚至利用多模态大模型来理解图片本身的语义内容。 **OCR技术:将图像转化为可检索文本** OCR技术是RAG系统处理图像数据的基石。它能识别图片中的文字,并将其转换为可编辑、可搜索的文本。对于扫描的文档、图片形式的报告、甚至包含文字的图表,OCR都能发挥关键作用,把这些“不可见”的知识转化为RAG系统可处理的`page_content`。 LangChain的`UnstructuredImageLoader`结合了`unstructured`库的能力,能够方便地从图片中提取文本。此外,一些OCR引擎(如Tesseract)也可以直接集成使用。 **多模态大模型:理解图像的深层含义** 仅仅提取文字有时是不够的。举个例子,一张流程图或一张包含复杂数据可视化的图片,其真正的价值在于图表的结构、元素之间的关系以及数据所表达的趋势。这时,多模态大模型(如GPT-4V、Gemini等)的优势就凸显出来了。它们不仅能识别文字,还能理解图像的整体布局、识别对象、甚至推断图像所传达的意图,从而生成对图像内容的详细描述,极大地丰富了RAG系统的知识维度。 **实践案例:智能合同审核系统中的发片信息提取** 假设一家大型建筑公司需要处理海量的供应商发片,这些发片通常以扫描件(图片格式,如JPG或PNG)的形式存在。公司希望构建一个智能合同审核系统,能够自动从发片中提取关键信息,如供应商名称、发片号码、日期、总金额、商品明细等,并与合同条款进行比对,以加速财务审核流程。传统的人工审核效率低下且容易出错。 通过RAG系统,财务人员可以提问“请列出所有供应商A在2024年5月的发片总金额”或“发片号X的商品明细是什么?”,系统将从扫描的发片图片中提取信息并给出回答。 要实现这个目标,数据导入阶段需要从发片图片中提取文字信息。可以用`UnstructuredImageLoader`来完成初步的OCR,然后进一步利用多模态大模型对发片的结构和内容进行更深层次的理解和结构化。
from langchain_community.document_loaders import UnstructuredImageLoader
from langchain_core.documents import Document
import os

# 假设我们有一张模拟的发片图片(实际应用中需要真实的图片文件)
# 为了演示,我们假设图片中包含以下文本:
# "供应商: ABC建筑材料有限公司发片号码: INV-202405-001日期: 2024-05-15总金额: 12500.00 元商品明细:- 水泥 100袋 @ 50元/袋 = 5000.00- 钢筋 5吨 @ 1500元/吨 = 7500.00"

# 创建一个模拟的发片图片文件(实际操作中会是真实图片)
# 这里仅为演示目的,实际不会生成图片,而是假设图片已存在并可被OCR工具处理
# 例如,你可以使用Pillow库创建一个空白图片,然后用PIL.ImageDraw添加文本来模拟
# from PIL import Image, ImageDraw, ImageFont
# img = Image.new('RGB', (800, 600), color = (255, 255, 255))
# d = ImageDraw.Draw(img)
# d.text((50,50), "供应商: ABC建筑材料有限公司发片号码: INV-202405-001日期: 2024-05-15总金额: 12500.00 元", fill=(0,0,0))
# img.sa ve("invoice_sample.png")

# 假设发片图片路径
invoice_image_path = "./invoice_sample.png"  # 实际应用中替换为真实图片路径

# 使用UnstructuredImageLoader加载图片并进行OCR
# 注意:UnstructuredImageLoader需要安装tesseract-ocr和pytesseract
# pip install unstructured "unstructured[image]" pytesseract
# sudo apt-get install tesseract-ocr

# 为了演示,我们跳过实际的图片生成和OCR过程,直接模拟OCR结果
# 实际应用中,loader.load()会执行OCR并返回Document对象
# 这里我们手动创建一个Document对象来模拟OCR后的结果
simulated_ocr_content = "供应商: ABC建筑材料有限公司发片号码: INV-202405-001日期: 2024-05-15总金额: 12500.00 元商品明细:\n- 水泥 100袋 @ 50元/袋 = 5000.00\n- 钢筋 5吨 @ 1500元/吨 = 7500.00"
invoice_doc = Document(
    page_content=simulated_ocr_content,
    metadata={
        "source": invoice_image_path,
        "file_type": "image/png",
        "extracted_by": "OCR"
    }
)

# 实际加载过程会是这样:
# loader = UnstructuredImageLoader(invoice_image_path)
# invoice_docs = loader.load()
# invoice_doc = invoice_docs[0] if invoice_docs else None

if invoice_doc:
    print("--- 模拟发片OCR提取内容 ---")
    print(invoice_doc.page_content)
    print("--- 模拟发片元数据 ---")
    print(invoice_doc.metadata)

    # 进一步利用多模态大模型进行结构化信息提取(概念性代码,需要实际调用LLM API)
    # from openai import OpenAI  # 假设使用OpenAI API
    # client = OpenAI()
    # 
    # def extract_invoice_details_with_llm(image_path, ocr_text):
    #     response = client.chat.completions.create(
    #         model="gpt-4o",  # 或其他支持多模态的LLM
    #         messages=[
    #             {
    #                 "role": "user",
    #                 "content": [
    #                     {"type": "text", "text": f"请从以下发片图片和OCR文本中提取关键信息,包括供应商名称、发片号码、日期、总金额和商品明细(名称、数量、单价、总价)。请以JSON格式返回。OCR文本:{ocr_text}"},
    #                     {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{base64_encode_image(image_path)}"}}
    #                 ]
    #             }
    #         ],
    #         response_format={ "type": "json_object" }
    #     )
    #     return json.loads(response.choices[0].message.content)
    # 
    # # 假设 base64_encode_image 是一个将图片编码为base64字符串的函数
    # extracted_data = extract_invoice_details_with_llm(invoice_image_path, invoice_doc.page_content)
    # print("--- LLM提取的发片结构化数据 ---")
    # print(extracted_data)
在这个案例中,我们首先通过OCR技术将发片图片转化为文本。然后,可以进一步利用多模态大模型,结合OCR文本和原始图片,对发片的关键字段进行结构化提取。 这种结合OCR和LLM的方法,能有效处理复杂、非标准格式的视觉文档,把非结构化的图像信息转化为RAG系统可用的结构化知识,极大地提升了自动化处理能力。 **PDF文档的解析:复杂结构的挑战与应对** PDF是RAG数据导入中一个常见的挑战。PDF文件可以包含纯文本、图片、表格、矢量图形等多种元素,而且其内部结构复杂,文本流可能并非线性的,这使得从中准确提取内容并保留其逻辑结构变得困难。针对不同类型的PDF,我们需要选择不同的解析策略和工具。 **PDF的类型与解析策略** PDF大致可以分为三类:可搜索PDF(Searchable PDF)、图像PDF(Image-only PDF)与混合PDF(Hybrid PDF)。 **解析工具的选择** 针对PDF的复杂性,业界涌现出多种解析工具,各有侧重: - **轻量级文本提取工具**(如`PyPDFLoader`、`PDFMiner`):适用于从可搜索PDF中快速提取纯文本内容,但可能丢失格式和结构信息。 - **结构化解析工具**(如`UnstructuredPDFLoader`):旨在保留PDF的结构信息,如标题、段落、列表、表格等。它通常会结合OCR技术处理图像部分。 - **基于规则的解析**:通过预定义的规则和模式来识别和提取PDF中的特定信息,适用于结构相对固定的文档,如发片、合同等。 - **基于深度学习的解析**:利用深度学习模型对复杂和多变的文档结构有更好的适应性。 - **基于多模态大模型的解析**:结合视觉和语言理解能力,对PDF中的图表、图片和文本进行综合理解,尤其适用于需要语义理解的复杂文档。 **实践案例:企业年度报告的知识整合** 一家大型跨国企业每年都会发布详细的年度报告,这些报告通常是包含大量图表、表格和文字的PDF文件。企业希望构建一个RAG系统,使分析师能够快速查询和比较不同年份的财务数据、市场分析和战略规划。例如,分析师可能想知道“过去三年研发投入的变化趋势”或“2023年各区域市场份额的增长情况”。 由于年度报告PDF的复杂性(包含文本、表格、图表),我们需要一个能够全面解析并保留结构信息的工具。`UnstructuredPDFLoader`是一个很好的选择,它能够处理复杂的PDF布局,并尝试提取结构化元素。
from langchain_community.document_loaders import UnstructuredPDFLoader
from langchain_core.documents import Document
import os

# 假设我们有一个模拟的企业年度报告PDF文件
# 实际应用中,这个PDF文件会包含多页,有文本、表格和图表
# 为了演示,我们假设PDF中包含以下内容:
# 页面1:公司简介和2023年业绩概述
# 页面2:财务报表(表格形式)
# 页面3:市场份额图表和分析

# 创建一个模拟的PDF文件路径
annual_report_pdf_path = "./annual_report_2023.pdf"  # 实际应用中替换为真实PDF路径

# 由于无法直接在沙盒中创建复杂的PDF文件,这里我们模拟UnstructuredPDFLoader的输出
# 假设它能提取出以下结构化内容
simulated_pdf_content = [
    Document(
        page_content="## 2023年公司年度报告\n### 业绩概述\n2023年,本公司在复杂多变的市场环境中取得了显著的业绩增长。全年实现营业收入XX亿元,同比增长YY%。净利润达到ZZ亿元,创历史新高。",
        metadata={"source": annual_report_pdf_path, "page": 1, "category": "Title"}
    ),
    Document(
        page_content="| 项目 | 2023年 | 2022年 | 2021年 |\n|---|---|---|---|\n| 营业收入 | 100亿 | 80亿 | 60亿 |\n| 净利润 | 10亿 | 8亿 | 6亿 |\n| 研发投入 | 1.5亿 | 1.2亿 | 1亿 |",
        metadata={"source": annual_report_pdf_path, "page": 2, "category": "Table"}
    ),
    Document(
        page_content="### 市场份额分析\n2023年,我们在A区域的市场份额增长了5%,B区域保持稳定,C区域略有下降。图表显示了各区域市场份额的详细分布。",
        metadata={"source": annual_report_pdf_path, "page": 3, "category": "Text"}
    )
]

# 实际加载过程会是这样:
# loader = UnstructuredPDFLoader(annual_report_pdf_path, mode="elements")  # mode="elements"尝试保留结构
# annual_report_docs = loader.load()

annual_report_docs = simulated_pdf_content  # 使用模拟数据进行演示
print(f"成功加载了 {len(annual_report_docs)} 个PDF文档片段。")

# 打印加载的文档内容和元数据
for doc in annual_report_docs:
    print("--- 文档片段内容 ---")
    print(doc.page_content)
    print("--- 文档片段元数据 ---")
    print(doc.metadata)
我们模拟了`UnstructuredPDFLoader`解析年度报告PDF后的输出。它能够把PDF中的标题、段落和表格等元素识别并提取为独立的`Document`对象,并且附带页码和元素类型等元数据。 对于图表,虽然直接提取图像内容并进行语义理解仍是挑战,但可以通过结合多模态大模型(如前一节所述)来生成图表的文字描述,从而将其纳入RAG知识库。 **表格类数据的导入:结构化信息的利器** 表格是组织结构化数据最常见的方式之一,无论是CSV文件、数据库表,还是PDF中嵌入的表格,都蕴含着丰富的、可量化的信息。 **CSV文件的处理:行式数据的快速摄入** CSV文件因其简洁性而广泛用于数据交换。在RAG中,CSV文件中的每一行通常代表一个独立的记录,例如产品信息、客户数据、交易记录等。 LangChain的`CSVLoader`能够方便地把CSV文件中的每一行转换成一个`Document`对象,并自动将列名和对应的值作为`page_content`,同时将行号等作为元数据。 **实践案例:供应链管理中的库存数据查询** 假设一家大型制造企业使用RAG系统来管理其全球供应链的库存数据。这些库存数据定期从各个仓库的系统中导出为CSV文件,包含产品ID、仓库地点、当前库存量、上次更新时间等信息。 供应链经理可能需要快速查询“某个特定产品在所有仓库的总库存量”或“哪些仓库的某个产品库存低于安全阈值”。 通过将这些CSV库存数据导入RAG系统,经理可以直接提问“产品A在上海仓库的库存是多少?”或“请列出所有库存低于100件的螺丝型号及其所在仓库。”
from langchain_community.document_loaders import CSVLoader
import os

# 模拟供应链库存数据
# product_id,warehouse_location,current_stock,last_updated
# P001,Shanghai,1500,2024-06-10
# P002,Shenzhen,800,2024-06-10
# P001,Guangzhou,700,2024-06-09
# P003,Shanghai,50,2024-06-11
# P002,Chongqing,1200,2024-06-11

# 将模拟数据写入CSV文件
csv_data = """product_id,warehouse_location,current_stock,last_updated
P001,Shanghai,1500,2024-06-10
P002,Shenzhen,800,2024-06-10
P001,Guangzhou,700,2024-06-09
P003,Shanghai,50,2024-06-11
P002,Chongqing,1200,2024-06-11"""

with open("supply_chain_inventory.csv", "w", encoding="utf-8") as f:
    f.write(csv_data)

# 使用CSVLoader加载CSV文件
loader = CSVLoader(file_path="supply_chain_inventory.csv")
inventory_docs = loader.load()
print(f"成功加载了 {len(inventory_docs)} 条库存记录。")

# 打印其中一条记录的示例内容和元数据
if inventory_docs:
    sample_inventory = inventory_docs[0]
    print("--- 示例库存记录内容 ---")
    print(sample_inventory.page_content)
    print("--- 示例库存记录元数据 ---")
    print(sample_inventory.metadata)

# 也可以指定某一列作为source元数据
loader_with_source = CSVLoader(
    file_path="supply_chain_inventory.csv",
    source_column="product_id"  # 将product_id列的值作为source元数据
)
inventory_docs_with_source = loader_with_source.load()

if inventory_docs_with_source:
    sample_inventory_with_source = inventory_docs_with_source[0]
    print("--- 示例库存记录内容 (source_column) ---")
    print(sample_inventory_with_source.page_content)
    print("--- 示例库存记录元数据 (source_column) ---")
    print(sample_inventory_with_source.metadata)
在这个案例中,`CSVLoader`把CSV的每一行转换成一个`Document`,`page_content`包含了该行的所有列信息。通过`source_column`参数,我们可以把CSV中的特定列(如`product_id`)提升为`Document`的`source`元数据,这在后续检索时非常有用,可以直接根据产品ID进行过滤。 对于更复杂的CSV文件,例如包含多行标题或非标准分隔符的,可能需要结合`UnstructuredCSVLoader`或进行预处理。 **数据库数据的导入:实时与动态知识** 企业数据往往存储在各种关系型数据库(如MySQL, PostgreSQL, SQL Server)或NoSQL数据库中。直接从数据库导入数据,能够确保RAG系统获取到最新、最权威的信息,尤其适用于需要实时更新或动态查询的场景。LlamaIndex等框架提供了`DatabaseReader`或类似的连接器,可以直接与数据库交互,执行SQL查询并将结果转换为`Document`对象。 **实践案例:客户关系管理(CRM)系统中的客户信息查询** 一家金融服务公司希望构建一个RAG系统,帮其客户经理快速获取客户的综合信息,包括客户基本资料、历史交易记录、服务偏好等。这些数据分散在公司的CRM数据库中。客户经理可能需要查询“客户张三最近一年的投资产品有哪些?”或“客户李四的风险承受能力等级是多少?” 通过RAG系统,客户经理可以直接提问,系统从数据库中检索相关信息并生成摘要。这避免了客户经理在多个系统之间切换,提高了工作效率。
# 概念性代码,实际需要安装数据库驱动和配置连接信息
# from llama_index.readers.database import DatabaseReader
# from sqlalchemy import create_engine, text
# 
# # 假设数据库连接信息
# DATABASE_URL = "mysql+mysqlconnector://user:password@localhost/crm_db"
# 
# # 创建数据库引擎
# engine = create_engine(DATABASE_URL)
# 
# # 定义SQL查询,提取客户信息
# # 实际应用中,查询可能更复杂,涉及多表联接
# query = text("SELECT customer_id, name, email, phone, risk_level, recent_transactions FROM customers WHERE customer_id = :customer_id")
# 
# # 使用DatabaseReader加载数据
# # reader = DatabaseReader(engine=engine)
# # docs = reader.load_data(query=query, query_params={"customer_id": "C001"})
# 
# # 模拟从数据库加载的数据
# simulated_db_data = [
#     Document(
#         page_content="客户ID: C001姓名: 张三邮箱: zhangsan@example.com电话: 13812345678风险等级: 中等最近交易: 购买了股票基金A和债券基金B",
#         metadata={
#             "source": "crm_db",
#             "customer_id": "C001",
#             "name": "张三"
#         }
#     )
# ]
# 
# # 打印加载的文档内容和元数据
# if simulated_db_data:
#     sample_customer_doc = simulated_db_data[0]
#     print("--- 示例客户信息内容 ---")
#     print(sample_customer_doc.page_content)
#     print("--- 示例客户信息元数据 ---")
#     print(sample_customer_doc.metadata)
在这个概念性案例中,`DatabaseReader`能够执行SQL查询,并将查询结果的每一行转换成一个`Document`对象。通过把数据库中的结构化数据转化为RAG系统可用的格式,我们能够构建出能够实时响应、动态更新的知识库,极大地扩展了RAG系统的应用范围。 **PDF中表格的提取:复杂文档的结构化挑战** PDF文件中嵌入的表格是RAG数据导入中一个特殊的挑战。与纯文本不同,表格具有二维结构,行和列的语义关系至关重要。直接的文本提取工具往往会破坏这种结构,导致数据难以理解。因此,需要专门的工具来识别、提取并结构化PDF中的表格。 `PDFPlumber`和`Camelot`是两个常用的Python库,它们能够识别PDF中的表格边界,并以结构化的方式(如Pandas DataFrame)提取表格内容。提取出的表格数据可以进一步转换为文本格式,或作为独立的`Document`对象导入RAG系统。 **写在最后** 数据导入是RAG系统构建的基石,其质量直接决定了RAG应用的性能和可靠性。从简单的纯文本到复杂的PDF和数据库,RAG系统需要处理的数据类型日益多样化。通过选择合适的工具、遵循最佳实践,并充分利用LangChain、LlamaIndex等框架以及多模态大模型的能力,我们能够高效地把各种形式的原始数据转化为RAG系统可用的知识。
免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

相关阅读

更多
欢迎回来 登录或注册后,可保存提示词和历史记录
登录后可同步收藏、历史记录和常用模板
注册即表示同意服务条款与隐私政策