智能知识库构建指南:向量模型、文本大模型与Elasticsearch多路召回的实战技术解析
近期小鹿的项目组在研究RAG(检索增强生成)技术的应用与实战,小鹿在上一篇文章中提到了RAG技术的一些基本概念,而这篇文章小鹿主要是想记录一下从零到有完成一个基本的RAG开发流程,文章中的代码语言选择是Java,基于langchain4j框架。
什么是向量模型?和文本大模型有什么区别?
- 向量模型 (Embedding Model): 向量模型,也称为嵌入模型,其核心作用是将文本(可以是词语、句子、段落甚至整个文档)转换成数值向量。这个向量能够捕捉到文本的语义信息。这意味着,语义上越相似的文本,它们被向量模型转换后得到的向量在空间中就越接近。
- 核心功能: 语义表示和语义相似度计算。向量模型主要用于理解文本的含义,并衡量不同文本之间的语义相似程度。
- 输出: 向量(通常是高维度的数值数组)。
- 应用场景: 语义搜索、相似度匹配、聚类、分类、推荐系统等,尤其在检索增强生成 (RAG) 系统中用于文档的向量化和相似文档检索。
- 例子: 代码中使用的 bge-base-zh-v1.5 就是一个本地的向量模型,它将中文文本转换为向量。
- 文本大模型 (Large Language Model, LLM): 文本大模型,例如 GPT-3, ChatGPT, DeepSeek-V3 等,是基于深度学习(通常是 Transformer 架构)构建的生成式模型。它们经过海量文本数据的训练,学会了理解和生成人类语言。
- 核心功能: 文本生成、文本理解、对话、翻译、摘要、问答等复杂的自然语言处理任务。LLM 的目标是理解语言的结构和含义,并在此基础上生成连贯、有逻辑的文本。
- 输出: 文本(例如,对用户问题的回答、文章、代码等)。
- 应用场景: 聊天机器人、内容创作、代码生成、文本摘要、机器翻译、智能助手等。
- 例子: 代码中使用的
deepseek-ai/DeepSeek-V3
就是一个文本大模型,用于根据上下文生成对话回复。
主要区别总结:
特性 | 向量模型 (Embedding Model) | 文本大模型 (LLM) |
---|---|---|
核心目的 | 语义表示和相似度计算 | 文本生成和理解 |
输出类型 | 向量 | 文本 |
主要应用 | 语义搜索、RAG 检索 | 文本生成、对话、问答等 |
模型类型 | 通常是编码器模型 | 通常是解码器或编码器-解码器模型 |
复杂程度 | 相对简单 | 非常复杂 |
简单来说:
- 向量模型 像是一个语义编码器,它把文本“编码”成向量,方便计算机理解文本的含义和相似性。
- 文本大模型 像是一个智能的语言生成器,它能理解你的指令,并用人类语言进行回应、创作等。
在 RAG 系统 中,向量模型 负责检索相关的文档片段,而 文本大模型 负责根据检索到的片段和用户问题生成最终答案。它们是 RAG 系统中两个互补但功能不同的核心组件。
为什么要用向量模型
使用向量模型的主要目的是为了实现语义搜索和语义相似度匹配,这在信息检索和 RAG 系统中至关重要。
- 超越关键词匹配: 传统的关键词搜索依赖于字面匹配,例如,搜索 "苹果手机",可能无法很好地匹配到包含 "iPhone" 但不包含 "苹果手机" 的文档,即使它们指的是同一事物。向量模型则可以捕捉到文本的深层语义,即使关键词不同,只要语义相似,也能被检索出来。
- 理解查询意图: 向量模型可以更好地理解用户的查询意图。例如,用户搜索 "推荐几部好看的科幻电影",向量模型能够理解用户想要的是科幻类型的电影推荐,而不仅仅是字面上包含 "科幻电影" 这几个词的文本。
- 提高检索相关性: 通过向量相似度计算,可以更准确地找到与用户查询在语义上最相关的文档片段,从而提高检索结果的质量和用户满意度。
- 支持复杂查询: 向量模型可以支持更复杂的查询,例如多轮对话的上下文理解、跨语言检索等。
在 RAG 系统中,向量模型的作用尤为关键:
- 文档向量化: 将知识库中的文档片段转换成向量,构建向量索引,方便快速检索。
- 查询向量化: 将用户提出的问题也转换成向量。
- 相似度检索: 通过计算查询向量和文档向量之间的相似度,找到知识库中与用户问题语义最相关的文档片段,作为 LLM 的上下文信息。
多路召回是什么
多路召回 (Multi-way Recall) 是一种提高信息检索系统召回率的策略,特别是在 RAG 系统中非常重要。
- 召回率 (Recall): 指检索系统能够返回的相关文档占所有真正相关文档的比例。召回率越高,说明系统漏掉的相关文档越少。
多路召回的核心思想是: 使用多种不同的检索方法 (或“多路”),从知识库中尽可能多地召回所有可能相关的文档,然后再对这些召回的结果进行排序和筛选,最终提供给用户或 LLM。
常见的召回策略包括:
- 关键词检索 (Keyword Search): 基于关键词匹配的传统检索方法,例如示例代码中的
keywordSearchByEs
方法。优点是速度快,实现简单;缺点是语义理解能力弱,容易漏掉语义相关但关键词不匹配的文档。 - 向量检索 (Vector Search): 基于向量相似度计算的语义检索方法,例如示例代码中的
vectorSearchByEs
方法。优点是语义理解能力强,可以找到语义相关的文档;缺点是计算量相对较大,对向量模型和相似度度量的选择比较敏感。 - 元数据过滤 (Metadata Filtering): 基于文档的元数据 (例如,作者、日期、标签等) 进行过滤和检索。
- 全文检索 (Full-text Search): 对文档的全文内容进行索引和检索,通常也使用倒排索引等技术。
如何将一个文件转化成为我的一个知识库
将一个文件转化为知识库,并利用 Elasticsearch (ES) 构建 RAG 系统的基本流程如下:
-
文档加载 (Document Loading):
- 目的: 从各种文件格式 (PDF, TXT, DOCX, 网页等) 中读取文档内容。
- 工具: Langchain4j 提供了
FileSystemDocumentLoader
(用于本地文件系统) 和UrlDocumentLoader
(用于网页 URL) 等文档加载器。对于不同类型的文件,可能需要选择不同的加载器或使用第三方库进行解析。
-
文档解析 (Document Parsing):
- 目的: 将加载的文档内容解析成结构化的文本格式,例如去除格式标记、提取文本内容等。
- 工具: Langchain4j 提供了
ApacheTikaDocumentParser
(基于 Apache Tika,支持多种文档格式) 和TextDocumentParser
(用于纯文本文件) 等文档解析器。
-
文档分片 (Document Splitting/Sharding):
-
目的: 将大型文档分割成更小的文本片段 (TextSegment)。
-
原因:
- 模型输入长度限制: LLM 通常有输入文本长度的限制 (例如,Token 数量限制)。将文档分片可以确保每个片段的长度在模型可接受的范围内。
- 检索精度: 更小的片段可能包含更集中的信息,有助于提高检索的精度。
- 上下文相关性: 在 RAG 系统中,通常会将检索到的文档片段作为 LLM 的上下文信息。过长的上下文可能会稀释关键信息,甚至引入噪声。
-
策略:
常见的文档分片策略包括:
- 固定大小分片: 将文档按固定字符数或 Token 数分割,例如示例代码中使用的
DocumentSplitters.recursive(300, 50)
,将文档递归地分割成大小为 300 字符,重叠 50 字符的片段。 - 按语义分片: 尝试根据文档的语义结构 (例如,段落、句子、章节) 进行分片,以保持片段的语义完整性。
- 固定大小分片: 将文档按固定字符数或 Token 数分割,例如示例代码中使用的
-
工具: Langchain4j 提供了
DocumentSplitters
工具类,包含多种文档分片器,例如RecursiveDocumentSplitter
,FixedSizeDocumentSplitter
,SentenceSplitter
等。
-
-
向量化 (Embedding Generation):
- 目的: 将文档片段转换成向量表示,以便进行语义搜索。
- 工具: 使用向量模型 (例如,示例代码中的
OnnxEmbeddingModel
) 将TextSegment
列表中的文本片段向量化。
-
向量存储 (Vector Storage) 和索引 (Indexing):
- 目的: 将文档片段的向量表示和原始文本存储到向量数据库中,并建立索引,以便高效地进行相似度检索。
- 工具: Elasticsearch (ES) 在这里充当向量数据库的角色。Langchain4j 提供了
ElasticsearchEmbeddingStore
,方便将向量数据存储到 Elasticsearch 中。 - Elasticsearch 的作用:
- 向量数据库: Elasticsearch 可以存储和索引向量数据,并提供高效的向量相似度搜索功能。
- 关键词检索: Elasticsearch 也擅长关键词检索,可以用于实现多路召回中的关键词检索策略。
- 可扩展性: Elasticsearch 是一个分布式搜索引擎,具有良好的可扩展性和高可用性,可以处理大规模的知识库。
- 成熟的生态: Elasticsearch 生态系统完善,工具丰富,易于集成和管理。
-
构建知识库索引:
- 在 Elasticsearch 中创建索引 (例如,示例代码中的
products-vector
索引),配置向量字段的映射 (Langchain4j 的ElasticsearchEmbeddingStore
默认会处理)。 - 将向量化后的文档片段和原始文本批量索引到 Elasticsearch 中。
- 在 Elasticsearch 中创建索引 (例如,示例代码中的
总结:
- 文件 -> 知识库: 文件经过加载、解析、分片、向量化等步骤,最终变成存储在向量数据库 (例如 Elasticsearch) 中的向量化文档片段集合,这就是知识库的创建流程。
- Elasticsearch 的作用: Elasticsearch 在这个过程中主要充当向量数据库和关键词搜索引擎的角色,用于存储、索引和检索知识库中的文档片段,为 RAG 系统提供高效的检索能力。
易错点:中文分词器和文档分片是一个概念吗
不是。中文分词器不是用来解决文档分片问题的。 中文分词器 和 文档分片 是两个不同目的和不同阶段的处理步骤,虽然它们都与文档处理有关,但解决的问题不一样。
- 中文分词器 (Chinese Word Segmenter):
- 目的: 解决中文文本的索引和检索问题。中文文本不像英文那样天然地用空格分隔单词,而是由连续的汉字组成。为了让搜索引擎 (例如 Elasticsearch) 能够理解中文文本的语义,需要使用中文分词器将连续的汉字序列切分成有意义的词语 (例如,"我爱自然语言处理" -> "我" / "爱" / "自然语言处理")。
- 作用: 提高中文关键词检索的准确性。分词后,搜索引擎才能基于词语进行索引和检索,而不是基于单个汉字,从而更准确地匹配用户查询。
- 例子: 示例代码中使用的
ik
分词器就是 Elasticsearch 中常用的中文分词器插件。
- 文档分片 (Document Splitting/Sharding):
- 目的: 解决文档过长的问题,主要目的是为了适应 LLM 的输入长度限制、提高检索精度和上下文相关性。
- 作用: 将大型文档分割成更小的、更易于处理和检索的文本片段。
- 例子: 示例代码中使用的
DocumentSplitters.recursive(300, 50)
就是一种文档分片策略。
关系:
- 先后顺序: 通常情况下,先进行文档分片,将文档分割成片段后,再对每个片段进行向量化 (如果需要向量检索) 和 关键词索引 (如果需要关键词检索,并且是中文文本,则需要使用中文分词器)。
- 独立性: 中文分词器和文档分片是相对独立的步骤。文档分片策略的选择与是否使用中文分词器没有直接关系。即使是英文文档,也可能需要进行文档分片。而即使处理英文文档,如果需要进行中文关键词检索,也可能需要使用中文分词器 (例如,如果英文文档中包含了中文内容)。
总结:
- 中文分词器: 用于处理中文文本,提高关键词检索的准确性。
- 文档分片: 用于处理长文档,使其适应 LLM 的输入限制,并提高检索精度和上下文相关性。