1.3 元数据(Metadata)管理

第一部分:元数据(Metadata)在RAG中的核心作用

在RAG中,元数据是"关于数据块的数据"。它不仅仅是附加信息,而是实现精准检索、可信溯源和高效过滤的关键。

核心价值:

1.增强检索精度 :在检索时,可以同时根据查询的语义(向量相似度)和元数据(如文档类型、日期、作者)进行过滤,确保返回的上下文更相关、更精准

  • 例如:"查找张三在2023年发布的财务报告中关于AI投资的章节。" 这里"张三"、"2023年"、"财务报告"都可以作为元数据过滤器。

2.实现可信溯源:这是RAG系统的"生命线"。当大模型生成答案时,必须能够指出答案的来源文档、具体页码甚至段落。这能:

  • 增加用户信任:用户可以核对原文。
  • 方便错误排查:当答案有误时,可快速定位问题源。
  • 满足合规要求:许多行业(如金融、法律)要求信息来源可追溯。

3.优化分块与上下文管理:元数据可以帮助理解文档结构(如章节标题),从而指导更合理的分块,或在回答时提供更丰富的上下文。

第二部分:需要保留的关键元数据字段

根据源文档类型,需要提取和保留的元数据通常包括:

类别 元数据字段 说明与示例
基础标识 source 文档唯一标识,如文件路径、URL、数据库ID。
document_id 内部为文档分配的唯一ID。
title / filename 文档标题或文件名。
author 文档作者。
created_date / last_modified 创建或最后修改日期。
内容定位 page_number 至关重要。文本块所在的起始页码(有时也需结束页码)。
chunk_id / chunk_index 文档内分块的顺序索引(如 0, 1, 2...)。
section_header 该块所属的章节或小标题。
paragraph_index 在页面或章节内的段落索引。
文档属性 document_type 文档类型,如 pdfword网页邮件
tags / keywords 用户或系统为文档添加的标签。
language 文档语言。
summary 文档摘要(通常用于文档级元数据)。

第三部分:如何在分块过程中保留这些信息

这是技术实现的核心。关键思想是:在文本被切割成块的同时,必须为每一块生成并绑定其对应的元数据。

1. 分块前的元数据提取

在文档加载(使用LangChainDocumentLoaderLlamaIndexReader等工具)后,首先提取文档级元数据

代码实现:

python 复制代码
# 使用自己的PDF文件
from langchain_community.document_loaders import PyPDFLoader
import pprint

# 请将下面的路径替换为您自己的PDF文件路径
pdf_path = "2506.10380v2.pdf"  # 替换为您的PDF文件路径

try:
    # 使用PyPDFLoader加载PDF
    print("加载PDF文件...")
    loader = PyPDFLoader(pdf_path)
    documents = loader.load()
    
    print(f"\n成功加载了 {len(documents)} 个Document对象")
    print("每个Document对应PDF的一页\n")
    
    # 查看第一个Document对象
    print("=== 第一个Document对象的内容预览 ===")
    if len(documents) > 0:
        first_doc = documents[0]
        
        # 显示前300个字符的内容
        content_preview = first_doc.page_content[:300]
        print(f"内容预览:\n{content_preview}...\n")
        
        print("=== 第一个Document对象的元数据 ===")
        pprint.pprint(first_doc.metadata)
        print()
        
        # 显示所有元数据键的详细信息
        print("=== 所有元数据字段的解释 ===")
        for key, value in first_doc.metadata.items():
            if key == 'source':
                print(f"- {key}: 文档来源路径 - {value}")
            elif key == 'page':
                print(f"- {key}: 页码(从0开始)- {value}")
            else:
                print(f"- {key}: {value}")
        
        # 演示如何提取和使用这些元数据
        print("\n=== 使用元数据进行分块 ===")
        print("在实际的RAG应用中,分块时会继承这些元数据。")
        print("例如:")
        print(f"源文件: {first_doc.metadata['source']}")
        print(f"页码: {first_doc.metadata['page']}")
        
    # 如果有更多页,显示第二页的元数据作为示例
    if len(documents) > 1:
        print(f"\n=== 第二页的元数据作为对比 ===")
        print(f"页码: {documents[1].metadata.get('page')}")
        
except FileNotFoundError:
    print(f"错误: 找不到文件 '{pdf_path}'")
    print("请将 pdf_path 变量替换为您自己的PDF文件路径")
except Exception as e:
    print(f"加载PDF时出错: {e}")

结果:

bash 复制代码
加载PDF文件...

成功加载了 20 个Document对象
每个Document对应PDF的一页

=== 第一个Document对象的内容预览 ===
内容预览:
TableRAG: A Retrieval Augmented Generation Framework for
Heterogeneous Document Reasoning
Xiaohan Yu∗, Pu Jian∗, Chong Chen/envel⌢pe
Huawei Cloud BU, Beijing
{yuxiaohan5, jinapu2, chenchong55}@huawei.com
https://github.com/yxh-y/TableRAG
Abstract
Retrieval-Augmented Generation (RAG) has
demonstrated...

=== 第一个Document对象的元数据 ===
{'arxivid': 'https://arxiv.org/abs/2506.10380v2',
 'author': 'Xiaohan Yu; Pu Jian; Chong Chen',
 'creationdate': '',
 'creator': 'arXiv GenPDF (tex2pdf:)',
 'doi': 'https://doi.org/10.48550/arXiv.2506.10380',
 'license': 'http://arxiv.org/licenses/nonexclusive-distrib/1.0/',
 'page': 0,
 'page_label': '1',
 'producer': 'pikepdf 8.15.1',
 'ptex.fullbanner': 'This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live '
                    '2025) kpathsea version 6.4.1',
 'source': '2506.10380v2.pdf',
 'title': 'TableRAG: A Retrieval Augmented Generation Framework for '
          'Heterogeneous Document Reasoning',
 'total_pages': 20,
 'trapped': '/False'}

=== 所有元数据字段的解释 ===
- producer: pikepdf 8.15.1
- creator: arXiv GenPDF (tex2pdf:)
- creationdate: 
- author: Xiaohan Yu; Pu Jian; Chong Chen
- doi: https://doi.org/10.48550/arXiv.2506.10380
- license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
- ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
- title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
- trapped: /False
- arxivid: https://arxiv.org/abs/2506.10380v2
- source: 文档来源路径 - 2506.10380v2.pdf
- total_pages: 20
- page: 页码(从0开始)- 0
- page_label: 1

=== 使用元数据进行分块 ===
在实际的RAG应用中,分块时会继承这些元数据。
例如:
源文件: 2506.10380v2.pdf
页码: 0

=== 第二页的元数据作为对比 ===
页码: 1

此时,一个基础的Document对象可能已有pagesource信息。

2. 分块时保留和继承元数据

使用分块器(如RecursiveCharacterTextSplitterSemanticSplitter)时,必须确保在切割文本时,新产生的文本块能正确继承并更新其来源块的元数据

重点与难点: page_number****等定位信息的处理

  • 简单场景(按页分块):如果整个页面作为一个块,则直接继承该页的页码。
  • 复杂场景(跨页或页内细分)
    • 策略1:记录起始和结束位置 :除了page_number,还可添加start_char/end_char(在页面文本中的字符偏移量),或start_index/end_index
    • 策略2:使用重叠分块并标注 :如果块A在第1页末尾和第2页开头,可以将其page_number标记为[1, 2], 并在块内容中插入软标记如[接上页]
    • 策略3:保留上下文窗口 :分块时设置chunk_overlap(如200字符),这不仅能保持语义连贯,也能让边界信息(如页码)在重叠区得到体现。

代码实现:

python 复制代码
"""
RAG系统中文档分块与元数据继承示例
本代码展示如何使用RecursiveCharacterTextSplitter对PDF文档进行分块,并自动继承元数据
"""

import os
from pathlib import Path
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter


def main():
    print("=" * 70)
    print("RAG系统分块与元数据继承演示")
    print("=" * 70)
    
    pdf_path = '2506.10380v2.pdf'
 
    try:
        # 1. 加载PDF文档
        print(f"\n📥 正在加载PDF文档...")
        loader = PyPDFLoader(pdf_path)
        documents = loader.load()
        
        print(f"✅ 加载成功!文档包含 {len(documents)} 页")
        
        # 显示前几页的元数据
        print(f"\n📋 原始文档元数据示例:")
        for i in range(min(3, len(documents))):  # 显示前3页
            doc = documents[i]
            print(f"\n第 {i+1} 页元数据:")
            for key, value in doc.metadata.items():
                print(f"  {key}: {value}")
            
            # 显示内容预览
            content_preview = doc.page_content[:150].replace('\n', ' ')
            print(f"  内容预览: {content_preview}...")
        
        if len(documents) > 3:
            print(f"\n... 还有 {len(documents)-3} 页未显示")
        
        # 2. 使用RecursiveCharacterTextSplitter进行分块
        print(f"\n" + "=" * 70)
        print("开始文档分块处理...")
        print("=" * 70)
        
        # 创建分块器
        text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=500,       # 每个块的最大字符数
            chunk_overlap=100,    # 块之间的重叠字符数
            separators=["\n\n", "\n", "。", "!", "?", ",", " ", ""],
            length_function=len,
            add_start_index=True  # 添加起始索引元数据
        )
        
        print(f"\n🔪 正在使用RecursiveCharacterTextSplitter进行分块...")
        chunks = text_splitter.split_documents(documents)
        
        print(f"✅ 分块完成!生成 {len(chunks)} 个文本块")
        
        # 3. 展示分块后的元数据继承情况
        print(f"\n" + "=" * 70)
        print("分块后元数据继承分析")
        print("=" * 70)
        
        # 显示一些示例块
        print(f"\n📊 前5个文本块的详细信息:")
        for i in range(min(5, len(chunks))):
            chunk = chunks[i]
            print(f"\n--- 块 #{i+1} ---")
            
            # 内容预览
            content = chunk.page_content
            if len(content) > 200:
                content_preview = content[:200] + "..."
            else:
                content_preview = content
            
            print(f"内容 ({len(content)} 字符):")
            print(f"  {content_preview}")
            
            # 元数据信息
            print(f"元数据:")
            for key, value in chunk.metadata.items():
                print(f"  {key}: {value}")
            
            # 特别说明元数据继承
            source = chunk.metadata.get('source', '未知')
            page = chunk.metadata.get('page', '未知')
            start_index = chunk.metadata.get('start_index', '未知')
            
            print(f"✅ 继承自: {source} 的第 {page + 1 if isinstance(page, int) else page} 页")
            if start_index != '未知':
                print(f"📏 在原始文本中的起始位置: {start_index}")
        
        # 4. 元数据分析报告
        print(f"\n" + "=" * 70)
        print("元数据分析报告")
        print("=" * 70)
        
        # 统计元数据字段
        metadata_fields = {}
        for chunk in chunks:
            for key in chunk.metadata.keys():
                metadata_fields[key] = metadata_fields.get(key, 0) + 1
        
        print(f"\n📈 元数据字段统计 (共 {len(chunks)} 个块):")
        for field, count in sorted(metadata_fields.items()):
            percentage = (count / len(chunks)) * 100
            print(f"  {field}: {count} 个块 ({percentage:.1f}%)")
        
        # 分析页码分布
        page_numbers = {}
        for chunk in chunks:
            page = chunk.metadata.get('page')
            if page is not None:
                page_numbers[page] = page_numbers.get(page, 0) + 1
        
        if page_numbers:
            print(f"\n📄 页码分布 (从0开始计数):")
            for page in sorted(page_numbers.keys()):
                print(f"  第 {page + 1} 页: {page_numbers[page]} 个块")
        
        # 检查是否有跨页块
        print(f"\n🔄 分块重叠分析:")
        print(f"  块大小 (chunk_size): {text_splitter._chunk_size} 字符")
        print(f"  重叠大小 (chunk_overlap): {text_splitter._chunk_overlap} 字符")
        print(f"  分块器通过重叠确保语义连续性")
        
        # 5. 演示如何在实际应用中使用这些元数据
        print(f"\n" + "=" * 70)
        print("实际应用示例")
        print("=" * 70)
        
        print(f"\n💡 在RAG系统中,这些元数据将被用于:")
        print(f"  1. 向量化存储: 将块的文本内容转换为向量,同时保存元数据")
        print(f"  2. 检索增强: 查询时可以根据元数据过滤 (如特定页码、文档来源)")
        print(f"  3. 答案溯源: 生成答案时引用来源文档和具体页码")
        print(f"  4. 权限控制: 根据文档元数据控制访问权限")
        
        # 模拟检索场景
        print(f"\n🔍 模拟检索场景:")
        print(f"  假设用户查询: '文档中提到的关键概念是什么?'")
        print(f"  检索系统会:")
        print(f"    1. 计算查询向量")
        print(f"    2. 在向量库中查找相似向量")
        print(f"    3. 返回最相关的文本块及其元数据")
        
        # 示例检索结果
        if len(chunks) > 0:
            example_chunk = chunks[0]
            print(f"\n  示例检索结果:")
            print(f"    文本: {example_chunk.page_content[:100]}...")
            print(f"    来源: {example_chunk.metadata.get('source')}")
            print(f"    页码: {example_chunk.metadata.get('page', 0) + 1}")
            print(f"    起始位置: {example_chunk.metadata.get('start_index', 0)}")
        
        
        print(f"\n🎉 演示完成!")
        
    except FileNotFoundError:
        print(f"\n❌ 错误: 找不到文件 '{pdf_path}'")
        print("请确保PDF文件在当前目录")
    except Exception as e:
        print(f"\n❌ 处理过程中发生错误: {e}")
        print("请确保已安装所需库: pip install langchain langchain-community pypdf")

if __name__ == "__main__":
    # 检查必要的库是否已安装
    try:
        import langchain_community
        import pypdf
        main()
    except ImportError:
        print("❌ 缺少必要的库")
        print("请先安装所需库:")
        print("  pip install langchain langchain-community pypdf")
        print("\n或者使用以下命令安装所有依赖:")
        print("  pip install langchain langchain-community pypdf chromadb")

结果:

bash 复制代码
======================================================================
RAG系统分块与元数据继承演示
======================================================================

📥 正在加载PDF文档...
✅ 加载成功!文档包含 20 页

📋 原始文档元数据示例:

第 1 页元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 0
  page_label: 1
  内容预览: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning Xiaohan Yu∗, Pu Jian∗, Chong Chen/envel⌢pe Huawei Cloud BU, ...

第 2 页元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 1
  page_label: 2
  内容预览: As illustrated in Figure 1, the RAG approach com- putes percentage over the top-N most relevant chunks rather than the full table, and thus results in...

第 3 页元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 2
  page_label: 3
  内容预览: Document chunking Document-oriented Database Table Schema Extraction Relational Database Table Parsing Retrival Results Table Schema {     "table_name...

... 还有 17 页未显示

======================================================================
开始文档分块处理...
======================================================================

🔪 正在使用RecursiveCharacterTextSplitter进行分块...
✅ 分块完成!生成 163 个文本块

======================================================================
分块后元数据继承分析
======================================================================

📊 前5个文本块的详细信息:

--- 块 #1 ---
内容 (455 字符):
  TableRAG: A Retrieval Augmented Generation Framework for
Heterogeneous Document Reasoning
Xiaohan Yu∗, Pu Jian∗, Chong Chen/envel⌢pe
Huawei Cloud BU, Beijing
{yuxiaohan5, jinapu2, chenchong55}@huawei....
元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 0
  page_label: 1
  start_index: 0
✅ 继承自: 2506.10380v2.pdf 的第 1 页
📏 在原始文本中的起始位置: 0

--- 块 #2 ---
内容 (460 字符):
  when applied to heterogeneous documents,
comprising both textual and tabular compo-
nents, existing RAG approaches exhibit critical
limitations. The prevailing practice of flatten-
ing tables and chun...
元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 0
  page_label: 1
  start_index: 372
✅ 继承自: 2506.10380v2.pdf 的第 1 页
📏 在原始文本中的起始位置: 372

--- 块 #3 ---
内容 (455 字符):
  dress these challenges, we propose TableRAG,
an SQL-based framework that unifies textual
understanding and complex manipulations over
tabular data. TableRAG iteratively operates in
four steps: context...
元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 0
  page_label: 1
  start_index: 744
✅ 继承自: 2506.10380v2.pdf 的第 1 页
📏 在原始文本中的起始位置: 744

--- 块 #4 ---
内容 (468 字符):
  benchmark designed to evaluate the multi-hop
heterogeneous reasoning capabilities. Experi-
mental results demonstrate that TableRAG con-
sistently outperforms existing baselines on both
public dataset...
元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 0
  page_label: 1
  start_index: 1109
✅ 继承自: 2506.10380v2.pdf 的第 1 页
📏 在原始文本中的起始位置: 1109

--- 块 #5 ---
内容 (479 字符):
  ing over both unstructured text and structured tabu-
lar data, presents substantial challenges. Tables are
characterized by interdependent rows and columns,
while natural language texts are sequential...
元数据:
  producer: pikepdf 8.15.1
  creator: arXiv GenPDF (tex2pdf:)
  creationdate: 
  author: Xiaohan Yu; Pu Jian; Chong Chen
  doi: https://doi.org/10.48550/arXiv.2506.10380
  license: http://arxiv.org/licenses/nonexclusive-distrib/1.0/
  ptex.fullbanner: This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1
  title: TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning
  trapped: /False
  arxivid: https://arxiv.org/abs/2506.10380v2
  source: 2506.10380v2.pdf
  total_pages: 20
  page: 0
  page_label: 1
  start_index: 1525
✅ 继承自: 2506.10380v2.pdf 的第 1 页
📏 在原始文本中的起始位置: 1525

======================================================================
元数据分析报告
======================================================================

📈 元数据字段统计 (共 163 个块):
  arxivid: 163 个块 (100.0%)
  author: 163 个块 (100.0%)
  creationdate: 163 个块 (100.0%)
  creator: 163 个块 (100.0%)
  doi: 163 个块 (100.0%)
  license: 163 个块 (100.0%)
  page: 163 个块 (100.0%)
  page_label: 163 个块 (100.0%)
  producer: 163 个块 (100.0%)
  ptex.fullbanner: 163 个块 (100.0%)
  source: 163 个块 (100.0%)
  start_index: 163 个块 (100.0%)
  title: 163 个块 (100.0%)
  total_pages: 163 个块 (100.0%)
  trapped: 163 个块 (100.0%)

📄 页码分布 (从0开始计数):
  第 1 页: 11 个块
  第 2 页: 11 个块
  第 3 页: 7 个块
  第 4 页: 11 个块
  第 5 页: 11 个块
  第 6 页: 9 个块
  第 7 页: 10 个块
  第 8 页: 10 个块
  第 9 页: 13 个块
  第 10 页: 13 个块
  第 11 页: 3 个块
  第 12 页: 9 个块
  第 13 页: 10 个块
  第 14 页: 6 个块
  第 15 页: 10 个块
  第 16 页: 1 个块
  第 17 页: 7 个块
  第 18 页: 5 个块
  第 19 页: 3 个块
  第 20 页: 3 个块

🔄 分块重叠分析:
  块大小 (chunk_size): 500 字符
  重叠大小 (chunk_overlap): 100 字符
  分块器通过重叠确保语义连续性

======================================================================
实际应用示例
======================================================================

💡 在RAG系统中,这些元数据将被用于:
  1. 向量化存储: 将块的文本内容转换为向量,同时保存元数据
  2. 检索增强: 查询时可以根据元数据过滤 (如特定页码、文档来源)
  3. 答案溯源: 生成答案时引用来源文档和具体页码
  4. 权限控制: 根据文档元数据控制访问权限

🔍 模拟检索场景:
  假设用户查询: '文档中提到的关键概念是什么?'
  检索系统会:
    1. 计算查询向量
    2. 在向量库中查找相似向量
    3. 返回最相关的文本块及其元数据

  示例检索结果:
    文本: TableRAG: A Retrieval Augmented Generation Framework for
Heterogeneous Document Reasoning
Xiaohan Yu...
    来源: 2506.10380v2.pdf
    页码: 1
    起始位置: 0

🎉 演示完成!
3. 结构化文档的特殊处理

对于PDF中的表格、Word中的标题层级、HTML的DOM结构

  • 使用专用解析器 :如PyMuPDFpdfplumberBeautifulSoup,它们能提取更丰富的结构信息。
  • 将结构作为元数据 :将"标题层级"(H1, H2, H3)作为元数据,分块时可以将小标题下的所有内容作为一个块,并记录其parent_headings
  • 表格处理 :可以尝试将整个表格作为一个独立的块,并添加元数据{"content_type": "table"}, 或将其转换为文本描述(如"下表显示了2023年Q1-Q4的销售额...")。

第四部分:存储与检索阶段的元数据应用

存储(向量数据库)

将文本块向量化时,必须将元数据与向量一并存储。主流向量数据库都支持此功能。

  • ChromaDBmetadata字段。
  • Pinecone: 每个向量可以附带丰富的元数据。
  • Weaviate : 使用自定义的Class模式来定义属性(即元数据)。
  • Qdrant : 支持payload
检索

这是元数据价值最大化的环节。通常采用**"向量相似度搜索 + 元数据过滤"**的混合检索模式。

代码实现:

python 复制代码
"""
RAG系统:从PDF读取、分块到向量数据库存储的完整流程
演示元数据如何与向量一并存储
"""

import os
import uuid
from pathlib import Path
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
import chromadb

def main():
    print("=" * 80)
    print("RAG系统:PDF读取 → 分块 → 向量数据库存储完整流程")
    print("=" * 80)
    
    # 1. 查找PDF文件
    
    pdf_path = '2506.10380v2.pdf'
    
    print(f"\n📄 处理文件: {pdf_path}")
    
    try:
        # 2. 加载PDF文档
        print("\n📥 正在加载PDF文档...")
        loader = PyPDFLoader(pdf_path)
        documents = loader.load()
        
        print(f"✅ 加载成功!文档包含 {len(documents)} 页")
        
        # 3. 分块处理
        print("\n✂️ 正在分块文档...")
        text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=800,
            chunk_overlap=100,
            separators=["\n\n", "\n", "。", "!", "?", ",", " ", ""],
            length_function=len,
            add_start_index=True
        )
        
        chunks = text_splitter.split_documents(documents)
        print(f"✅ 分块完成!生成 {len(chunks)} 个文本块")
        
        # 显示示例块的元数据
        print("\n📋 示例块的元数据:")
        for i in range(min(3, len(chunks))):
            chunk = chunks[i]
            print(f"\n块 #{i+1}:")
            print(f"  内容长度: {len(chunk.page_content)} 字符")
            print(f"  元数据: {chunk.metadata}")
        
        # 4. 初始化嵌入模型
        print("\n🧠 正在初始化嵌入模型...")
        # 使用轻量级的sentence-transformers模型
        embeddings = HuggingFaceEmbeddings(
            model_name="paraphrase-multilingual-MiniLM-L12-v2",
            model_kwargs={'device': 'cpu'},
            encode_kwargs={'normalize_embeddings': False}
        )
        
        # 测试嵌入模型
        test_text = "这是一个测试句子"
        test_vector = embeddings.embed_query(test_text)
        print(f"✅ 嵌入模型初始化成功!向量维度: {len(test_vector)}")
        
        # 5. 初始化Chroma向量数据库
        print("\n💾 正在初始化向量数据库...")
        
        # 创建持久化的chroma客户端
        persist_directory = "./chroma_db"
        chroma_client = chromadb.PersistentClient(path=persist_directory)
        
        # 创建或获取集合
        collection_name = "pdf_documents"
        try:
            collection = chroma_client.get_collection(name=collection_name)
            print(f"✅ 连接到现有集合: {collection_name}")
            print(f"   集合中现有文档数量: {collection.count()}")
        except:
            collection = chroma_client.create_collection(
                name=collection_name,
                metadata={"description": "存储PDF文档分块的向量数据库"}
            )
            print(f"✅ 创建新集合: {collection_name}")
        
        # 6. 处理每个块:生成向量并存储到数据库
        print("\n🚀 开始处理每个块并存储到向量数据库...")
        
        processed_count = 0
        skipped_count = 0
        
        for i, chunk in enumerate(chunks):
            try:
                # 生成唯一的ID
                chunk_id = str(uuid.uuid4())
                
                # 提取文本内容
                text_content = chunk.page_content
                
                # 生成向量
                vector = embeddings.embed_query(text_content)
                
                # 准备元数据
                metadata = {
                    **chunk.metadata,
                    "chunk_id": i,
                    "text_length": len(text_content),
                    "document_name": Path(pdf_path).name
                }
                
                # 添加页码的友好显示(从1开始)
                if 'page' in metadata:
                    metadata['page_human'] = metadata['page'] + 1
                
                # 存储到向量数据库
                collection.add(
                    ids=[chunk_id],
                    embeddings=[vector],
                    metadatas=[metadata],
                    documents=[text_content]
                )
                
                processed_count += 1
                
                if (i + 1) % 10 == 0:
                    print(f"  已处理 {i+1}/{len(chunks)} 个块...")
                    
            except Exception as e:
                print(f"  警告: 处理块 {i+1} 时出错: {e}")
                skipped_count += 1
                continue
        
        print(f"\n✅ 处理完成!")
        print(f"   成功处理: {processed_count} 个块")
        print(f"   跳过: {skipped_count} 个块")
        
        # 7. 验证存储结果
        print("\n🔍 验证向量数据库中的内容...")
        total_count = collection.count()
        print(f"   集合 '{collection_name}' 中总共有 {total_count} 个向量")
        
        # 获取一些示例记录
        if total_count > 0:
            results = collection.peek(limit=min(3, total_count))
            
            print("\n📊 向量数据库中的示例记录:")
            for i, (id, metadata, document) in enumerate(zip(results['ids'], results['metadatas'], results['documents'])):
                print(f"\n记录 #{i+1}:")
                print(f"  ID: {id}")
                print(f"  元数据: {metadata}")
                print(f"  内容预览: {document[:150]}...")
        
        # 8. 演示检索功能
        print("\n" + "=" * 80)
        print("演示:元数据过滤检索")
        print("=" * 80)
        
        # 演示基本检索
        test_queries = [
            "文档的主要内容是什么?",
            "总结关键点",
            "作者是谁?"
        ]
        
        print(f"\n📝 测试查询:")
        for query in test_queries:
            print(f"  - {query}")
        
        # 选择一个查询进行演示
        demo_query = test_queries[0]
        print(f"\n🔍 执行查询: '{demo_query}'")
        
        try:
            # 将查询转换为向量
            query_vector = embeddings.embed_query(demo_query)
            
            # 在向量数据库中搜索
            search_results = collection.query(
                query_embeddings=[query_vector],
                n_results=3
            )
            
            print(f"✅ 找到 {len(search_results['ids'][0])} 个相关结果:")
            
            for i, (id, distance, metadata, document) in enumerate(zip(
                search_results['ids'][0],
                search_results['distances'][0],
                search_results['metadatas'][0],
                search_results['documents'][0]
            )):
                print(f"\n结果 #{i+1}:")
                print(f"  ID: {id}")
                print(f"  距离分数: {distance:.4f}")
                print(f"  来源: {metadata.get('source', '未知')}")
                print(f"  页码: {metadata.get('page_human', metadata.get('page', '未知'))}")
                print(f"  内容: {document[:200]}...")
                
        except Exception as e:
            print(f"检索时出错: {e}")
        
        # 9. 演示元数据过滤
        print("\n" + "=" * 80)
        print("演示:带元数据过滤的检索")
        print("=" * 80)
        
        # 获取文档的页码范围
        if len(documents) > 0:
            first_page = 0
            last_page = len(documents) - 1
            
            print(f"\n📄 文档页码范围: 第 {first_page + 1} 页 到 第 {last_page + 1} 页")
            
            # 演示按页码过滤
            print(f"\n🔍 演示:检索第1页的内容")
            
            try:
                # 进行元数据过滤查询
                filter_results = collection.query(
                    query_texts=[demo_query],
                    n_results=3,
                    where={"page": 0}  # 过滤条件:只要第1页(page从0开始)
                )
                
                print(f"✅ 在第1页找到 {len(filter_results['ids'][0])} 个相关结果:")
                
                for i, (id, distance, metadata, document) in enumerate(zip(
                    filter_results['ids'][0],
                    filter_results['distances'][0],
                    filter_results['metadatas'][0],
                    filter_results['documents'][0]
                )):
                    print(f"\n结果 #{i+1}:")
                    print(f"  页码: {metadata.get('page_human', metadata.get('page', '未知'))}")
                    print(f"  内容: {document[:200]}...")
                    
            except Exception as e:
                print(f"过滤检索时出错: {e}")
        
        # 10. 显示数据库文件大小
        print(f"\n💾 数据库已自动保存到: {persist_directory}")
        if os.path.exists(persist_directory):
            total_size = sum(f.stat().st_size for f in Path(persist_directory).rglob('*') if f.is_file())
            print(f"📊 数据库文件大小: {total_size / 1024 / 1024:.2f} MB")
        
        print("\n" + "=" * 80)
        print("🎉 流程完成!")
        print("=" * 80)
        
        print(f"\n📋 总结:")
        print(f"  1. 加载了 {len(documents)} 页PDF文档")
        print(f"  2. 生成了 {len(chunks)} 个文本块")
        print(f"  3. 存储了 {processed_count} 个向量到数据库")
        print(f"  4. 数据库位置: {persist_directory}")
        print(f"  5. 集合名称: {collection_name}")
        
        print(f"\n💡 你可以使用以下代码重新加载数据库:")
        print(f"""
        import chromadb
        
        # 连接到持久化的数据库
        chroma_client = chromadb.PersistentClient(path="{persist_directory}")
        
        # 获取集合
        collection = chroma_client.get_collection(name="{collection_name}")
        
        print(f"集合中有 {{collection.count()}} 个向量")
        
        # 查询示例
        results = collection.query(
            query_texts=["你的查询"],
            n_results=5
        )
        """)
        
    except FileNotFoundError:
        print(f"\n❌ 错误: 找不到文件 '{pdf_path}'")
    except ImportError as e:
        print(f"\n❌ 缺少必要的库: {e}")
        print("请运行: pip install langchain langchain-community pypdf chromadb sentence-transformers")
    except Exception as e:
        print(f"\n❌ 处理过程中发生错误: {e}")
        import traceback
        traceback.print_exc()

if __name__ == "__main__":
    # 检查必要的库
    required_libs = ['langchain', 'langchain_community', 'pypdf', 'chromadb', 'sentence_transformers']
    
    missing_libs = []
    for lib in required_libs:
        try:
            __import__(lib.replace('-', '_'))
        except ImportError:
            missing_libs.append(lib)
    
    if missing_libs:
        print("❌ 缺少必要的库:")
        for lib in missing_libs:
            print(f"  - {lib}")
        print(f"\n请运行: pip install {' '.join(missing_libs)}")
    else:
        main()

结果:

bash 复制代码
================================================================================
RAG系统:PDF读取 → 分块 → 向量数据库存储完整流程
================================================================================

📄 处理文件: 2506.10380v2.pdf

📥 正在加载PDF文档...
✅ 加载成功!文档包含 20 页

✂️ 正在分块文档...
✅ 分块完成!生成 98 个文本块

📋 示例块的元数据:

块 #1:
  内容长度: 788 字符
  元数据: {'producer': 'pikepdf 8.15.1', 'creator': 'arXiv GenPDF (tex2pdf:)', 'creationdate': '', 'author': 'Xiaohan Yu; Pu Jian; Chong Chen', 'doi': 'https://doi.org/10.48550/arXiv.2506.10380', 'license': 'http://arxiv.org/licenses/nonexclusive-distrib/1.0/', 'ptex.fullbanner': 'This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1', 'title': 'TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning', 'trapped': '/False', 'arxivid': 'https://arxiv.org/abs/2506.10380v2', 'source': '2506.10380v2.pdf', 'total_pages': 20, 'page': 0, 'page_label': '1', 'start_index': 0}

块 #2:
  内容长度: 773 字符
  元数据: {'producer': 'pikepdf 8.15.1', 'creator': 'arXiv GenPDF (tex2pdf:)', 'creationdate': '', 'author': 'Xiaohan Yu; Pu Jian; Chong Chen', 'doi': 'https://doi.org/10.48550/arXiv.2506.10380', 'license': 'http://arxiv.org/licenses/nonexclusive-distrib/1.0/', 'ptex.fullbanner': 'This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1', 'title': 'TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning', 'trapped': '/False', 'arxivid': 'https://arxiv.org/abs/2506.10380v2', 'source': '2506.10380v2.pdf', 'total_pages': 20, 'page': 0, 'page_label': '1', 'start_index': 699}

块 #3:
  内容长度: 798 字符
  元数据: {'producer': 'pikepdf 8.15.1', 'creator': 'arXiv GenPDF (tex2pdf:)', 'creationdate': '', 'author': 'Xiaohan Yu; Pu Jian; Chong Chen', 'doi': 'https://doi.org/10.48550/arXiv.2506.10380', 'license': 'http://arxiv.org/licenses/nonexclusive-distrib/1.0/', 'ptex.fullbanner': 'This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1', 'title': 'TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning', 'trapped': '/False', 'arxivid': 'https://arxiv.org/abs/2506.10380v2', 'source': '2506.10380v2.pdf', 'total_pages': 20, 'page': 0, 'page_label': '1', 'start_index': 1387}

🧠 正在初始化嵌入模型...
/Users/caotianchen.1/Desktop/pyproject/test2/pdf.py:57: LangChainDeprecationWarning: The class `HuggingFaceEmbeddings` was deprecated in LangChain 0.2.2 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-huggingface package and should be used instead. To use it run `pip install -U :class:`~langchain-huggingface` and import as `from :class:`~langchain_huggingface import HuggingFaceEmbeddings``.
  embeddings = HuggingFaceEmbeddings(
✅ 嵌入模型初始化成功!向量维度: 384

💾 正在初始化向量数据库...
✅ 创建新集合: pdf_documents

🚀 开始处理每个块并存储到向量数据库...
  已处理 10/98 个块...
  已处理 20/98 个块...
  已处理 30/98 个块...
  已处理 40/98 个块...
  已处理 50/98 个块...
  已处理 60/98 个块...
  已处理 70/98 个块...
  已处理 80/98 个块...
  已处理 90/98 个块...

✅ 处理完成!
   成功处理: 98 个块
   跳过: 0 个块

🔍 验证向量数据库中的内容...
   集合 'pdf_documents' 中总共有 98 个向量

📊 向量数据库中的示例记录:

记录 #1:
  ID: 8806c97b-c448-40d6-a8aa-8cdbcaabec46
  元数据: {'trapped': '/False', 'producer': 'pikepdf 8.15.1', 'start_index': 0, 'doi': 'https://doi.org/10.48550/arXiv.2506.10380', 'source': '2506.10380v2.pdf', 'page_label': '1', 'total_pages': 20, 'document_name': '2506.10380v2.pdf', 'page_human': 1, 'page': 0, 'title': 'TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning', 'creator': 'arXiv GenPDF (tex2pdf:)', 'text_length': 788, 'chunk_id': 0, 'license': 'http://arxiv.org/licenses/nonexclusive-distrib/1.0/', 'ptex.fullbanner': 'This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1', 'arxivid': 'https://arxiv.org/abs/2506.10380v2', 'creationdate': '', 'author': 'Xiaohan Yu; Pu Jian; Chong Chen'}
  内容预览: TableRAG: A Retrieval Augmented Generation Framework for
Heterogeneous Document Reasoning
Xiaohan Yu∗, Pu Jian∗, Chong Chen/envel⌢pe
Huawei Cloud BU, ...

记录 #2:
  ID: d4c9869c-546d-415f-87c4-9ad48630ac64
  元数据: {'license': 'http://arxiv.org/licenses/nonexclusive-distrib/1.0/', 'chunk_id': 1, 'text_length': 773, 'creationdate': '', 'document_name': '2506.10380v2.pdf', 'title': 'TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning', 'arxivid': 'https://arxiv.org/abs/2506.10380v2', 'trapped': '/False', 'page_label': '1', 'ptex.fullbanner': 'This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1', 'producer': 'pikepdf 8.15.1', 'source': '2506.10380v2.pdf', 'doi': 'https://doi.org/10.48550/arXiv.2506.10380', 'page_human': 1, 'page': 0, 'creator': 'arXiv GenPDF (tex2pdf:)', 'total_pages': 20, 'author': 'Xiaohan Yu; Pu Jian; Chong Chen', 'start_index': 699}
  内容预览: of LLMs in multi-hop, global queries. To ad-
dress these challenges, we propose TableRAG,
an SQL-based framework that unifies textual
understanding an...

记录 #3:
  ID: 9efee4fc-ea98-4806-ac56-acd8cafda204
  元数据: {'creator': 'arXiv GenPDF (tex2pdf:)', 'chunk_id': 2, 'license': 'http://arxiv.org/licenses/nonexclusive-distrib/1.0/', 'doi': 'https://doi.org/10.48550/arXiv.2506.10380', 'author': 'Xiaohan Yu; Pu Jian; Chong Chen', 'document_name': '2506.10380v2.pdf', 'ptex.fullbanner': 'This is pdfTeX, Version 3.141592653-2.6-1.40.28 (TeX Live 2025) kpathsea version 6.4.1', 'source': '2506.10380v2.pdf', 'title': 'TableRAG: A Retrieval Augmented Generation Framework for Heterogeneous Document Reasoning', 'page_human': 1, 'text_length': 798, 'start_index': 1387, 'arxivid': 'https://arxiv.org/abs/2506.10380v2', 'trapped': '/False', 'total_pages': 20, 'creationdate': '', 'page': 0, 'page_label': '1', 'producer': 'pikepdf 8.15.1'}
  内容预览: ment question answering.
1 Introduction
Heterogeneous document-based question answer-
ing (Chen et al., 2020), which necessitates reason-
ing over bot...

================================================================================
演示:元数据过滤检索
================================================================================

📝 测试查询:
  - 文档的主要内容是什么?
  - 总结关键点
  - 作者是谁?

🔍 执行查询: '文档的主要内容是什么?'
✅ 找到 3 个相关结果:

结果 #1:
  ID: 32b64797-b5e7-417b-9733-29cfe9075f0b
  距离分数: 14.5852
  来源: 2506.10380v2.pdf
  页码: 8
  内容: ReAct across different domains.
knowledge base, and the most relevant document
chunks are subsequently incorporated into the gen-
eration process (Gao et al., 2023; Zhu et al., 2024;
Borgeaud et al., ...

结果 #2:
  ID: 9efee4fc-ea98-4806-ac56-acd8cafda204
  距离分数: 14.7981
  来源: 2506.10380v2.pdf
  页码: 1
  内容: ment question answering.
1 Introduction
Heterogeneous document-based question answer-
ing (Chen et al., 2020), which necessitates reason-
ing over both unstructured text and structured tabu-
lar data,...

结果 #3:
  ID: 202b69e3-2ed7-4a18-85bb-e9be6c3d98a4
  距离分数: 16.1048
  来源: 2506.10380v2.pdf
  页码: 1
  内容: comprehension of tables, such as direct answer
extraction (Pasupat and Liang, 2015a; Zhu et al.,
2021). When applied to extensive documents that
interleave textual and tabular elements, existing
RAG m...

================================================================================
演示:带元数据过滤的检索
================================================================================

📄 文档页码范围: 第 1 页 到 第 20 页

🔍 演示:检索第1页的内容
✅ 在第1页找到 3 个相关结果:

结果 #1:
  页码: 1
  内容: ment question answering.
1 Introduction
Heterogeneous document-based question answer-
ing (Chen et al., 2020), which necessitates reason-
ing over both unstructured text and structured tabu-
lar data,...

结果 #2:
  页码: 1
  内容: of LLMs in multi-hop, global queries. To ad-
dress these challenges, we propose TableRAG,
an SQL-based framework that unifies textual
understanding and complex manipulations over
tabular data. TableRA...

结果 #3:
  页码: 1
  内容: comprehension of tables, such as direct answer
extraction (Pasupat and Liang, 2015a; Zhu et al.,
2021). When applied to extensive documents that
interleave textual and tabular elements, existing
RAG m...

💾 数据库已自动保存到: ./chroma_db
📊 数据库文件大小: 1.43 MB

================================================================================
🎉 流程完成!
================================================================================

📋 总结:
  1. 加载了 20 页PDF文档
  2. 生成了 98 个文本块
  3. 存储了 98 个向量到数据库
  4. 数据库位置: ./chroma_db
  5. 集合名称: pdf_documents

💡 你可以使用以下代码重新加载数据库:

        import chromadb
        
        # 连接到持久化的数据库
        chroma_client = chromadb.PersistentClient(path="./chroma_db")
        
        # 获取集合
        collection = chroma_client.get_collection(name="pdf_documents")
        
        print(f"集合中有 {collection.count()} 个向量")
        
        # 查询示例
        results = collection.query(
            query_texts=["你的查询"],
            n_results=5
        )

最佳实践与建议

  1. 标准化与一致性:为所有文档定义统一的元数据Schema。
  2. 平衡粒度:元数据不是越多越好。根据业务需求(检索、过滤、溯源)决定必要的字段。
  3. 在提示词中利用元数据 :将检索到的块的元数据(特别是sourcepage)插入给大模型的提示词中,要求它引用来源。
    示例提示词:"请根据以下上下文回答问题。如果答案来自上下文,请注明出处。\n上下文:[文本块内容]\n来源:{source}, 第{page}页\n问题:{query}"
  4. 验证与测试:务必检查分块后,尤其是跨页分块后,元数据(特别是页码)是否准确。构建一些需要精准溯源的测试用例。
  5. 考虑多索引:对于某些元数据(如作者、日期),如果经常用于等值过滤,可以考虑在向量数据库之外建立辅助索引(如传统数据库),进行高效的预过滤。

总结

RAG中的元数据管理是一个系统工程 ,贯穿文档加载、分块、存储和检索全流程。page_number****和 source是最核心的溯源元数据。成功的实现意味着:用户在得到AI生成的答案时,总能看到一个可靠的"参考文献",点击即可定位到原文的确切位置,从而构建起可信、可控的智能问答系统。

相关推荐
田井中律.5 小时前
知识图谱(一)
人工智能·知识图谱
Allen_LVyingbo8 小时前
具备安全护栏与版本化证据溯源的python可审计急诊分诊平台复现
开发语言·python·安全·搜索引擎·知识图谱·健康医疗
北京地铁1号线1 天前
1.2 文本分块策略(Chunking)
知识图谱·文档分块
KG_LLM图谱增强大模型1 天前
知识图谱+大模型“驱动的生物制药企业下一代主数据管理:Neo4j知识图谱与GraphRAG及GenAI的深度整合
人工智能·大模型·知识图谱
淬炼之火1 天前
笔记:场景图生成综述(Scene Understanding)
图像处理·笔记·计算机视觉·知识图谱·场景感知
北京地铁1号线1 天前
1.1 文档解析:PDF/Word/HTML的结构化提取
开发语言·知识图谱·文档解析
Allen_LVyingbo1 天前
面向“病历生成 + CDI/ICD”多智能体系统的选型策略与落地实践(三)
算法·自然语言处理·性能优化·知识图谱·健康医疗·柔性数组
高洁011 天前
AI智能体搭建(2)
人工智能·深度学习·算法·机器学习·知识图谱
P-ShineBeam2 天前
引导式问答-对话式商品搜索-TRACER
人工智能·语言模型·自然语言处理·知识图谱