欢迎光临
我们一直在努力

LangChain Document和递归字符文本分割器 概念与实战

一、什么是Doument?

  Document 是 LangChain 统一的文档标准载体。 简单理解:把一段文本 + 附属信息打包成一个标准化对象,整个 LangChain 生态(加载器、文本分割、向量库、检索、RAG)全部统一使用这个格式。

二、两大核心属性

  • page_content 需要进行嵌入、检索的原始文本。
  • metadata(元数据) 用来记录来源信息,检索后用来溯源、过滤。 常见存入:文件名、文件类型、页码、章节、时间等。
  • 三、核心作用(RAG 流程里至关重要)

    1. 统一标准,打通各个组件

          文件加载器(TextLoader/PyPDFLoader)输出 List[Document]

                                              ↓

          文本分割器接收 List[Document],输出切分后的 List[Document]

                                              ↓

          向量数据库接收 List[Document],存入向量库

    如果没有 Document,文本只是零散字符串,文件来源、页码信息很容易丢失。

    2. 保护溯源信息(metadata)

           举个场景:用户提问,向量库检索到一段相关文本。 只拿到文本,你不知道这段文字来自哪个文件第几页; 依靠 metadata,你可以在回答末尾输出。

    3. 支持检索过滤

          存入向量库后,可以基于 metadata 做筛选: 只检索某一类文件、某个时间段文档。

    四、加载器及文档切割的简单应用

      1、实例代码:TextLoader  加载.txt和.md文件

    from langchain_community.document_loaders import TextLoader

    loader = TextLoader(
    file_path="data/text.txt", # .txt和.md文件均可
    encoding="utf-8",
    )

    documents = loader.load()

    print(f"文档数量:{len(documents)}")
    print(f"文档内容:\\n{documents[0].page_content}")
    print(f"元数据:{documents[0].metadata}")

    2、实例代码:PyPDFLoader 加载.pdf文件

    from langchain_community.document_loaders import PyPDFLoader

    loader=PyPDFLoader(
    file_path="data/text.pdf"
    )

    documents=loader.load()

    print("切割成了几个文档:",len(documents))

    # 文档的内容
    for document in documents:
    print(document.page_content[-20:])
    # 文档的元数据
    print(document.metadata)
    print("当前页码:",document.metadata['page'])

    五、文本分割器RecursiveCharacterTextSplitter递归字符文本分割器

    1、是什么?

    它的核心作用:按优先级递归使用分隔符切割文本

    默认分隔符优先级从高到低: \\n\\n(段落) → \\n(换行) → (空格) → (空字符)

    可自定义,区别于普通字符分割器:不会粗暴一刀切,尽可能保证语义完整性。

    2、作用?

    RAG 中必不可少的一环,用来把长 Document 拆成多个小块 Document。

    为什么必须分割?

  • Embedding 模型有最大输入长度限制,超长文本无法向量化;
  • 向量检索是小段文本匹配,整篇文档塞入向量库,容易出现匹配不准、信息混杂;
  • 切块后检索,能精准定位局部相关内容,提升问答效果。
  • 3、核心参数(常用)

    文本切分最重要的两个参数是:

    参数

    作用

    chunk_size

    每个文档块允许的最大长度

    chunk_overlap

    相邻文档块之间重复保留的长度

    text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=300, # 每个文本块最大字符长度
    chunk_overlap=50, # 相邻块重叠字符数量
    length_function=len, # 用什么统计长度,默认统计字符数
    separators=["\\n\\n", "\\n", " ", ""] # 自定义分隔符优先级
    )

    chunk_overlap 重叠作用:防止段落被切断、上下文丢失,保证块之间信息连贯。

    4、简单实例应用

    from idlelib.iomenu import encoding
    from pathlib import Path

    from langchain_community.document_loaders import TextLoader, PyPDFLoader
    from langchain_core.documents import Document
    from langchain_text_splitters import RecursiveCharacterTextSplitter

    def split_documents(ducoments:list[Document])->list[Document]:
    splitter = RecursiveCharacterTextSplitter(
    chunk_size=200,
    chunk_overlap=30,
    add_start_index=True, # 每一个大文档的起始位置,假如一个文件被切割成了多个document,它指的是一个document
    separators=["\\n\\n", "\\n", "。", "!", "?", ";", ",", " ", ""]
    )

    chunks = splitter.split_documents(ducoments)
    for index,chunk in enumerate(chunks,start=1):
    chunk.metadata['chunk_id']=index
    return chunks

    def load_knowledge_base(dictory)->list[Document]:
    all_documents=[]
    for f in dictory.rglob("*"):
    if f.is_dir():
    continue
    file_suffix=f.suffix
    file_path=dictory.name+"/"+f.name
    if file_suffix in ['.txt','.md']:
    loader=TextLoader(
    file_path=file_path,
    encoding="utf-8"
    )

    docs=loader.load()

    for document in docs:
    document.metadata["file_name"] = file_path
    document.metadata["file_type"] = file_suffix

    all_documents.extend(docs)
    elif file_suffix=='.pdf':
    loader=PyPDFLoader(
    file_path=file_path
    )

    docs = loader.load()

    for document in docs:
    document.metadata["file_name"] = file_path
    document.metadata["file_type"] = file_suffix

    all_documents.extend(docs)

    return all_documents

    def main():
    path=Path("data")
    # 先将文档切分
    documents=load_knowledge_base(path)
    print("文档切分的个数:",len(documents))
    #再将文档继续切分
    chunks=split_documents(documents)
    for chunk in chunks:
    print("~"*30)
    metadata=chunk.metadata
    print(f"当前是第{metadata['chunk_id']}片段,内容是{chunk.page_content[:20]}")
    print("当前的片段来自于"+chunk.metadata.get("file_name"))

    if __name__ == '__main__':
    main()

    赞(0)
    未经允许不得转载:171主机测评 » LangChain Document和递归字符文本分割器 概念与实战
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址