LV020-文档处理
想让 AI 真正“懂”我们的知识?关键在于如何把杂乱无章的文档变成结构化、可检索的智能资产。
让模型 "读懂" 海量文本的关键在于将非结构化文档转化为易于检索的向量形式。具体流程通常包括:文档分片、向量化 和 索引构建 三个步骤。
一、文档分片(Chunking)
首先将长文档切分为较小的段落或片段,以适应模型上下文窗口限制。常见的分片策略是按固定字数或句子数切分,并在片段间引入重叠(overlap)以保留上下文连贯。例如,可将每篇博客按段落拆分成长度约 500 字的片段并保留前一片段的末句作为重叠。分片的目的在于减少每个输入片段的 "噪音",突出相关信息,并确保后续 embedding 过程能捕捉局部语义。
下面是一个 Python 示例:
# -*- coding: utf-8 -*-
# 假设 texts 列表包含若干长文档字符串
texts = ["""
人工智能(Artificial Intelligence),英文缩写为AI。是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新技术科学。
人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、
图像识别、自然语言处理和专家系统等。
"""]
chunk_size = 100 # 每个片段约 100 字符
overlap = 20 # 重叠部分长度
documents = []
for text in texts:
# 简单按照固定长度切分,并添加重叠
chunks = [text[i:i+chunk_size] for i in range(0, len(text), chunk_size - overlap)]
documents.extend(chunks)
print(f"切分后得到 {len(documents)} 个文档片段")
print(f"documents={documents}")【例】运行结果如下:
E:\AI\ai-llm-demo [master ≡ +1 ~0 -0 !]> python test.py
切分后得到 3 个文档片段
documents=['\n人工智能(Artificial Intelligence),英文缩写为AI。是研究、开发用于模拟、延伸和扩展人的 智能的理论、方法、技术及应用系统的一门新技术科学。\n人工智能是计算机科学的一个分支,它', '学。\n人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、\n图像识别、自然语言处理和专家系统等。\n', '别、自然语言处理和专家系统等。\n']上面的代码演示了将文档列表按固定长度切分片段。在实际应用中,可以使用现有工具如 LangChain 或 LlamaIndex 提供的文本分割器,这些工具支持按句子、段落甚至编程代码单元进行智能切分,并可配置重叠大小。例如,LlamaIndex 默认采用 1024 tokens 的块大小并附带一定重叠。
二、向量化(Vectorization)
对每个文档片段,通过预训练的 文本嵌入模型 提取向量表示。嵌入模型可以选择通用的预训练模型(如 sentence-transformers 系列)或领域专用模型。若使用 OpenAI 的 API,也可以采用诸如 text-embedding-ada-002 等模型获取向量。向量化后的结果是一个高维向量(数百维到上千维不等),捕捉了文本片段的语义特征。这些向量将作为 "知识" 的表征被存储备用。
我这里在本地使用ollama运行了一个 qwen3-embedding:0.6b 模型,我们可以用 Python 写一个示例:
# -*- coding: utf-8 -*-
# https://ollama.com/blog/embedding-models
from ollama import embed
# 示例使用
texts = ["""
人工智能(Artificial Intelligence),英文缩写为AI。是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新技术科学。
人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、
图像识别、自然语言处理和专家系统等。
"""]
def split_documents(texts, chunk_size=100, overlap=20):
"""
将文本列表按照指定大小切分成文档片段
Args:
texts (list): 文本列表,每个元素是一个长文档字符串
chunk_size (int): 每个片段的字符数
overlap (int): 片段之间的重叠字符数
Returns:
list: 切分后的文档片段列表
"""
documents = []
for text in texts:
# 简单按照固定长度切分,并添加重叠
chunks = [text[i:i+chunk_size] for i in range(0, len(text), chunk_size - overlap)]
documents.extend(chunks)
return documents
def get_embedding(text, model_name="qwen3-embedding:0.6b"):
"""
使用 Ollama 获取文本的向量表示
Args:
text (str): 输入文本
model_name (str): 使用的预训练模型名称
Returns:
list: 文本的向量表示
"""
try:
response = embed(model=model_name, input=text)
return response['embeddings'][0]
except Exception as e:
print(f"获取 embedding 时出错: {e}")
return None
documents = split_documents(texts, chunk_size=100, overlap=20)
print(f"切分后得到 {len(documents)} 个文档片段")
print(f"documents={documents}")
print()
# 获取每个文本的向量表示
embeddings_list = []
for i, text in enumerate(documents):
print(f"正在获取文本 {i+1} 的向量表示...")
print(f"文本内容: {text}")
embedding = get_embedding(text)
if embedding is not None:
embeddings_list.append(embedding)
print(f"向量维度: {len(embedding)}")
print("-" * 50)
else:
print(f"获取文本 '{text}' 的向量表示失败")
embeddings_list.append(None)【例】qwen3-embedding:0.6b 默认是1024维度的。
E:\AI\ai-llm-demo [master ≡ +1 ~0 -0 !]> python test.py
切分后得到 3 个文档片段
documents=['\n人工智能(Artificial Intelligence),英文缩写为AI。是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新技术科学。\n人工智能是计算机科学的一个分支,它', '学。\n人工智能是计算机科学的一个分 支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言 识别、\n图像识别、自然语言处理和专家系统等。\n', '别、自然语言处理和专家系统等。\n']
正在获取文本 1 的向量表示...
文本内容:
人工智能(Artificial Intelligence),英文缩写为AI。是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新技术科学。
人工智能是计算机科学的一个分支,它
向量维度: 1024
--------------------------------------------------
正在获取文本 2 的向量表示...
文本内容: 学。
人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器, 该领域的研究包括机器人、语言识别、
图像识别、自然语言处理和专家系统等。
向量维度: 1024
--------------------------------------------------
正在获取文本 3 的向量表示...
文本内容: 别、自然语言处理和专家系统等。
向量维度: 1024
--------------------------------------------------在实际场景中,应考虑批量请求以提高向量提取的效率,并留意 API 调用的费用。同时需要为每个向量保存元数据,例如该片段所属的文档 ID、段落位置等,以便检索结果用于生成答案时可以定位来源。
注意:使用的时候要选支持embedding的模型。我这里用了QwenLM/Qwen3-Embedding:
Model Type Models Size Layers Sequence Length Embedding Dimension MRL Support Instruction Aware Text Embedding Qwen3-Embedding-0.6B 0.6B 28 32K 1024 Yes Yes Text Embedding Qwen3-Embedding-4B 4B 36 32K 2560 Yes Yes Text Embedding Qwen3-Embedding-8B 8B 36 32K 4096 Yes Yes
三、构建索引
将得到的向量集合插入到选定的向量数据库中,建立索引以支持相似度检索。多数向量数据库提供便捷的方法插入批量向量并自动构建索引。例如,使用 Chroma 向量库,可以这样创建索引并存储向量:
# 安装 Chroma 数据库的 Python 库(需要在有网络的环境执行)
# pip install chromadb
from chromadb import Client
client = Client()
collection = client.create_collection("knowledge_base")
# 批量插入向量及其关联的文本或元数据
collection.add(
embeddings=embeddings,
documents=documents,
ids=[f"doc_{i}" for i in range(len(documents))]
)以上代码演示了使用 Chroma 创建一个名为"knowledge_base"的集合,并添加向量数据和对应文本。在添加时我们为每个向量指定了一个 ID,用于将检索结果与原始内容关联。不同的向量数据库添加向量的方式会有所区别,但本质都是将文本向量及其标识存储起来,供后续相似度搜索。
这个示例并不完整,可以看这个:01_quick_start/20_Embedding/15_chromdb.py
四、总结
经过以上三步,我们就将文档转化为了 AI 知识库。当用户提问时,RAG 流程会将问题向量化,在向量数据库中检索语义相似的几个片段,作为上下文提供给 LLM 生成答案。这种方式使得 LLM 的回答既基于自身掌握的语言知识,又参考了检索到的权威资料,从而提高准确性和可信度。
参考资料: