当前位置: 首页 > news >正文

构建简单RAG代码实现

步骤1:文档准备与切割
假设我们有一个关于机器学习的PDF文档需要处理。

示例代码:

Python
深色版本
from llama_index import SimpleDirectoryReader

# 加载文档
documents = SimpleDirectoryReader('./data').load_data()
说明:

使用SimpleDirectoryReader加载位于指定路径下的文档。
文档被加载后,会根据特定规则进行切割成小块(chunks),如按句子或段落分割。
步骤2:文本向量化
使用预训练模型对切割后的文本块进行向量化。

示例代码:

Python
深色版本
from sentence_transformers import SentenceTransformer

# 加载预训练模型
model = SentenceTransformer('all-MiniLM-L6-v2')

# 对每个文档块进行向量化
embeddings = [model.encode(str(doc)) for doc in documents]
说明:

这里使用了SentenceTransformer中的all-MiniLM-L6-v2模型来生成文本块的向量表示。
每个文档块转换为一个固定长度的向量。
步骤3:构建索引并入库
将向量化的文本块及其元数据存入向量数据库中。

示例代码:

Python
深色版本
from faiss import IndexFlatL2

# 初始化索引
index = IndexFlatL2(embeddings[0].shape[0])

# 添加向量到索引中
for embedding in embeddings:
    index.add(embedding.reshape(1, -1))
说明:

使用Faiss创建了一个简单的索引来存储和查询向量。
将所有文档块的向量添加到索引中以便后续查询。
步骤4:问题理解与向量化
当用户提出一个问题时,首先将其转化为向量形式。

示例代码:

Python
深色版本
question = "什么是机器学习?"
question_embedding = model.encode(question)
说明:

问题“什么是机器学习?”被编码为其对应的向量表示。
步骤5:相似度搜索
在向量库中查找与问题向量最接近的文档块向量。

示例代码:

Python
深色版本
D, I = index.search(question_embedding.reshape(1, -1), k=5)  # 查找前5个最相关的文档块
说明:

search函数返回最接近问题向量的前k个文档块的距离(D)和索引(I)。
在这个例子中,k=5意味着我们将找到与问题最相关的前5个文档块。
步骤6:RAG检索增强生成
利用检索到的相关文档块作为上下文信息,结合问题生成最终答案。

示例代码:
假设我们已经有了一个支持RAG的模型和相关API调用方式:

Python
深色版本
context_texts = [documents[i].text for i in I[0]]  # 获取检索到的上下文文本
answer = rag_model.generate(question=question, context=context_texts)
print("回答:", answer)
说明:

根据索引结果获取最相关的文档块文本。
使用支持RAG的模型结合问题和这些上下文信息生成最终的回答。
以上流程展示了如何从文档准备开始,经过向量化、索引建立、问题向量化、相似度搜索到最后通过RAG方法生成答案的一个完整过程。请注意,这只是一个简化的示例,实际应用中可能需要根据具体的需求和技术栈做出相应的调整。

问题1:

之前了解到,大模型检索生成是将预料切割成问题:答案,这样键值对的形式,存储到数据库中。检索生成,输入问题,然后匹配对应问题的key,找到问题答案。这种说法正确吗?怎么看待这种说法,和你刚刚讲解的流程是有差异的

你提到的方法确实存在,并且在某些应用场景中被采用,特别是当数据集可以明确地分割为问题和答案对的形式时。这种方法通常被称为基于检索的问答系统(Retrieval-Based QA System),它与我之前描述的基于文档切割、向量化以及检索增强生成(RAG)的方法有所不同。

基于检索的问答系统(问题-答案键值对)

在这种方法中,原始数据首先会被转换成“问题:答案”这样的键值对格式,然后存储在一个数据库或搜索引擎中。当用户输入一个问题时,系统会在预定义的问题集合中查找最匹配的问题,然后返回对应的答案。这种方法的优点在于其简单直接,特别适用于FAQ(常见问题解答)等场景。

流程示例:

  1. 准备数据:将文档内容转化为问题-答案对。

    • 示例:“机器学习是什么?” -> “机器学习是一门多领域交叉学科...”
  2. 构建索引:使用文本相似度算法或者搜索引擎技术来索引这些问题。

  3. 查询处理:当接收到用户提问时,通过搜索最接近的问题来找到并返回相应的答案。

与基于文档切割、向量化及RAG方法的区别

相比之下,基于文档切割、向量化及RAG的方法更加灵活,尤其适合处理那些没有预先定义好问题答案对的大规模非结构化数据集。

  • 数据灵活性:前者依赖于预先定义好的问题答案对,而后者可以直接从大量未结构化的文档中提取信息。

  • 回答质量:基于RAG的方法能够结合多个相关文档片段的信息来生成更全面的答案,而不是局限于预先设定的答案。

  • 适用范围:基于检索的方法更适合用于FAQ等有限范围内的问答任务;而基于RAG的方法则更适用于开放域问答、知识库问答等需要综合多种信息来源的任务。

总结

两种方法各有优劣,选择哪一种取决于具体的应用需求:

  • 如果你的应用场景是围绕一组固定的常见问题和答案设计的,那么基于检索的问答系统可能是一个高效的选择。
  • 如果你需要处理大量的非结构化文本数据,并希望从中动态生成高质量的回答,那么基于文档切割、向量化及RAG的方法可能是更好的选择。

两者并不是互相排斥的,实际上,在一些复杂的系统中,可能会结合使用这两种方法以达到最佳效果。例如,先用基于检索的方法快速定位到相关的文档或章节,再利用基于RAG的方法深入分析这些文档内容以生成最终的答案。

问题2:

rag中我们通常说的向量检索和关键字检索,向量检索是不是我们上文中从向量库中检索的流程是一致吗?不一致的话给出实现过程和demo。关键字检索是如何实现的?和向量检索有什么区别?给出demo和过程

确实,向量检索和关键字检索是两种不同的信息检索方法,它们各自适用于不同类型的应用场景,并且在实现方式上也存在显著差异。

向量检索
定义:向量检索基于文本的语义表示(即向量),通过计算查询与文档之间的相似度来返回最相关的文档。这种方法特别适合处理模糊匹配、语义相似性搜索等复杂查询。

实现过程:

数据预处理:对原始文本进行清洗、分词等操作。
向量化:使用预训练的语言模型将文本转换为固定长度的向量。
索引构建:使用如Faiss或Milvus这样的工具为这些向量建立索引。
查询处理:将用户的查询也转换为向量,并在索引中查找最近邻向量。
示例代码(简化版):

Python
深色版本
from sentence_transformers import SentenceTransformer
import faiss

# 加载模型并生成文档向量
model = SentenceTransformer('all-MiniLM-L6-v2')
documents = ["机器学习是一门多领域交叉学科...", "深度学习是机器学习的一个子集..."]
doc_embeddings = [model.encode(doc) for doc in documents]

# 创建Faiss索引
index = faiss.IndexFlatL2(doc_embeddings[0].shape[0])
for emb in doc_embeddings:
    index.add(emb.reshape(1, -1))

# 查询处理
query = "什么是机器学习?"
query_embedding = model.encode(query)
D, I = index.search(query_embedding.reshape(1, -1), k=2)  # 返回最接近的两个文档

# 输出结果
for idx in I[0]:
    print(f"相关文档: {documents[idx]}")
关键字检索
定义:关键字检索依赖于精确匹配用户查询中的关键词到文档中的词语。它更适合于那些需要高精度匹配的场景,比如特定术语的查找。

实现过程:

数据预处理:包括去除停用词、词干提取等步骤。
倒排索引构建:创建一个映射,其中每个关键词指向包含该词的所有文档ID列表。
查询处理:解析用户输入的查询,直接从倒排索引中查找对应的文档ID。
示例代码(简化版,使用Python标准库):

Python
深色版本
from collections import defaultdict

# 构建倒排索引
inverted_index = defaultdict(list)
documents = {
    0: "机器学习是一门多领域交叉学科",
    1: "深度学习是机器学习的一个子集"
}
for doc_id, text in documents.items():
    words = text.split()
    for word in words:
        inverted_index[word].append(doc_id)

# 查询处理
def search(query):
    terms = query.split()
    result_docs = set(range(len(documents)))  # 初始包含所有文档
    for term in terms:
        if term in inverted_index:
            result_docs &= set(inverted_index[term])  # 取交集
        else:
            return []  # 如果任意一个词不存在,则无结果
    return [documents[doc_id] for doc_id in result_docs]

# 测试查询
query = "机器 学习"
print("查询结果:", search(query))
主要区别
灵活性:向量检索能够捕捉文本间的语义关系,而关键字检索则侧重于词汇级别的精确匹配。
性能:对于大规模数据集,向量检索可能需要更多的计算资源来维持索引结构;关键字检索通常更快,尤其是在使用优化的数据结构如Trie树或B树时。
适用场景:向量检索适合于探索式搜索和推荐系统,关键字检索则更适合于快速定位特定信息。
这两种方法可以根据具体需求单独使用或结合使用,以达到最佳的信息检索效果。

问题3:

实际生产过程中,向量检索内容和关键字检索内容都是在数据库中存储的。这两种数据业界分别采用什么样的数据库存储?原因是什么?

在实际生产环境中,向量检索和关键字检索的内容通常存储于不同的数据库或数据管理系统中,以优化各自的性能和满足特定需求。以下是业界常用的解决方案及其背后的原因:

向量检索

常用数据库/工具

  • Faiss:由Facebook AI Research开发的高效相似度搜索库,专门用于大规模向量搜索。它支持多种索引类型,如IVF(Inverted File)、HNSW(Hierarchical Navigable Small World Graphs)等,能够显著加速最近邻搜索。
  • Milvus:一个开源的向量数据库,旨在管理、存储和搜索大规模向量数据集。Milvus提供了丰富的API接口,易于与现有系统集成,并且支持多种索引技术来提高查询效率。
  • Pinecone:一种云端向量数据库服务,专为实时应用程序设计,特别适合需要快速响应的应用场景。

原因

  • 高效性:这些工具专门为处理高维向量数据设计,采用了先进的算法和技术来加快相似度计算的速度。
  • 可扩展性:它们可以轻松地水平扩展,适应不断增长的数据规模。
  • 灵活性:支持多种距离度量方法(如欧几里得距离、余弦相似度),适用于不同类型的向量数据。

关键字检索

常用数据库/工具

  • Elasticsearch:一个基于Lucene的搜索引擎,广泛应用于全文搜索场景。它支持复杂的查询语法、分词、过滤等功能,非常适合处理关键字检索任务。
  • Solr:另一个流行的开源搜索引擎平台,提供了强大的文本分析能力,以及分布式搜索功能,适合构建大型搜索应用。
  • 传统关系型数据库(如MySQL, PostgreSQL):虽然不是专门为全文搜索设计,但通过添加全文索引插件或使用内置的全文搜索功能,也能有效地支持关键字检索。

原因

  • 精确匹配:这些工具擅长执行精确的关键字匹配,能够快速返回包含特定词汇的所有文档。
  • 丰富查询功能:提供强大的查询语言和过滤选项,允许用户进行复杂查询操作。
  • 易用性和成熟度:这类系统已经非常成熟,拥有良好的社区支持和大量的使用案例,易于部署和维护。

总结

选择合适的数据库主要取决于应用的具体需求。对于向量检索来说,重点在于如何高效地执行相似度搜索,因此倾向于选择那些专门为处理高维向量设计的数据库或工具。而对于关键字检索,则更关注于精确匹配和快速定位,这使得像Elasticsearch这样的全文搜索引擎成为理想的选择。同时,考虑到系统的可扩展性和灵活性,企业可能会根据实际情况组合使用这两种技术,以达到最佳效果。例如,在一些高级的信息检索系统中,可能会先利用向量检索缩小候选范围,再通过关键字检索进一步筛选结果。

深度搜索

相关文章:

  • java常见面试场景题
  • nodejs各版本下载地址 —— 筑梦之路
  • 【Java】泛型与集合篇 —— 泛型
  • virt-io 如何运行在 kvm windows 虚拟机上
  • rust学习三、基本类型
  • Spring框架基本使用(Maven详解)
  • 【二分搜索 C/C++】洛谷 P1873 EKO / 砍树
  • SAM C++ TensorRT(实时图像分割)
  • 【有啥问啥】DeepSeek 技术原理详解
  • vue取消全选功能按钮注意事项
  • java机器学习计算指标动态阈值
  • Jackson使用
  • 点击unity资源文件自动展开左侧的文件路径
  • StableDiffusion学习笔记——4、模型下载和学习
  • 算法系列之搜索算法-广度优先搜索BFS
  • 提示工程(Prompt Engineering)的进阶策略与实践指南
  • 关于uniApp的面试题及其答案解析
  • 【Python】yield函数
  • 遥感与GIS在滑坡、泥石流风险普查中的实践技术应用
  • 【Linux AnolisOS】配置Linux固定ip地址。然后在Windows上连接使用linux中docker容器里的redis和nacos。
  • 织梦做的网站如何去掉index/软文营销的特点
  • 网站建设设计方案格式/今天的新闻最新消息
  • 免费做网站表白/打开百度网页
  • 武汉网站建设管理登录/怎么去优化关键词
  • 免费做三级网站/手机seo关键词优化
  • 建设工程质量安全管理协会网站/农产品网络营销推广方案