RAG实现原理与案例穿刺

1、RAG: 检索增强生成(Retrieval Augmented Generation),简称 RAG

2、实现原理框架图: 

3、流程主要节点:

大流程小流程释义涉及的相关技术补充
提问前切片将文档切分为很多片段。分片可以有很多方式,如按照字数、按照段落、按照标题、按照页码等。

常见的切片手段:

1、固定长度切片

2、窗口函数切片

3、标题切片

4、语义切片

索引通过Embedding将片段文本转换为向量。并且将文本和向量片段都存储在向量数据库中。

向量:有大小和方向的量

示例:

[0.5] 这是一个一维向量 ;  数学表示一条横线的坐标轴。

[0.22,1.36]  这是一个二维向量;数学表示x,y坐标系。

[1.0, 23.3 ,5.77, -6.22, -3.6]    这是一个5维向量 ;发挥想象力.

Embedding: 将文本转化向量的过程。

这里的算法可以METB排行榜:

https://huggingface.co/spaces/mteb/leaderboard

image.png

向量数据库:存储原始文本和向量的数据库。

image.png

提问后召回搜索与用户问题相关的过程。用户问题发给embedding模型,转化为向量,发给向量数据库,查询最为相关的几个问题答案。向量间的相似度常见的算法:

余弦相似度:测量向量空间中两个向量之间角度的余弦。取值范围为-1到1,其中1表示相同向量,0表示正交向量,-1表示完全相反的向量。角度越小相似度越高。

image.png

欧氏距离:测量向量空间中两个向量之间的直线距离。它的范围从 0 到无穷大,其中 0 表示相同的向量,较大的值表示越来越不相似的向量。距离越小,相似度越高。

image.png

点积:测量两个向量的幅值与它们之间角度的余弦的乘积。范围为-∞到∞,其中正值表示指向相同方向的向量,0表示正交向量,负值表示指向相反方向的向量。乘积越大,相似度越高。

image.png

召回阶段的相似度算法成本低、耗时短、准确率低,适合做初步筛选
重排基于召回的10个片段中,选择2-3个与用户问题最相似的作为重拍的结果。(为了提升查找效率)使用cross-encoder的算法cross-encoder算法成本高、耗时长、准确率高
生成结合LLM大模型,prompt提示词生成用户需要的答案。

4、采用ChromaDB向量数据库的示例代码

原始语料:

#中华人民共和国的国都
中华人民共和国的国都现在迁都在长沙。长沙是一座没有历史的新的城市,在沙漠地带上建立起来的。

#美食
长沙的美食有仙人掌、仙人球、还有嫩叶子。

#娱乐
长沙的娱乐只有骑单车这一项活动,这里的人民都热爱骑自行车。

切片代码:

from typing import Any
from typing_extensions import Literal
def read_data() -> str:
    with open("./data.md","r",encoding="utf-8") as file:
        return file.read()
def get_chunkds() -> list[str]:
    content: str = read_data()
    print(str)
    chunks: list[str] = content.split('\n\n')

    result: list[Any] = []
    header: Literal[''] = ""
    for chunk in chunks:
        if chunk.startswith('#'):
            header += f"{chunk}\n"
        else:
            result.append(f"{header}{chunk}")
            header: Literal[''] = ""
    return chunks
if __name__ == "__main__":
    chunks: list[str]  = get_chunkds()
    for c in chunks:
        print(c)
        print("---------------------")

存入向量数据库chromadb代码:

import os
import chunk
import chromadb
chromadb_client = chromadb.PersistentClient("./chroma2.db")
chromadb_collection = chromadb_client.get_or_create_collection("changshacity2")


def create_database() -> None:
    for idx,c in enumerate(chunk.get_chunkds()):
        print(f"Process: {c}")
        # embedding = embed(c,store=True)
        # print(embedding)
        try:
            chromadb_collection.upsert(
                ids=[str(idx)],  
                documents=[c]   
            )
            print(f"第 {idx} 条数据插入成功")
        except Exception as e:
            print(f"第 {idx} 条数据插入失败: {str(e)}")
            raise

if __name__ == "__main__":
    create_database()
    print("执行完毕")

召回片段向量:

import chromadb
from chromadb.config import Settings

# 初始化 ChromaDB 客户端(0.5.3 版本推荐显式指定设置)
client = chromadb.Client(
    Settings(
        persist_directory="./chroma2.db",  # 数据存储路径
        is_persistent=True  # 启用持久化存储
    )
)
# 获取已存在的集合(假设集合名为"my_collection")
collection = client.get_collection(name="changshacity2")
def query_with_distance(query_text: str, n_results: int = 3) -> list[dict]:
    """
    在 ChromaDB 0.5.3 中查询并返回包含距离的结果
    参数:
        query_text: 查询文本
        n_results: 期望返回的结果数量

    返回:
        包含 id、文档内容和距离的字典列表
    """
    # 执行查询,通过 include 参数指定返回距离
    results = collection.query(
        query_texts=[query_text],  # 查询文本(列表形式)
        n_results=n_results  # 返回的结果数量
    )
    # 格式化结果:将原始结果转换为更易读的字典列表
    formatted_results = []
    # 0.5.3 版本中,results 的每个字段是二维列表(外层对应查询文本索引)
    for i in range(len(results["ids"][0])):
        formatted_results.append({
            "id": results["ids"][0][i],
            "document": results["documents"][0][i],
            "distance": results["distances"][0][i]  # 距离值(越小相似度越高)
        })

    return formatted_results

# 示例用法
if __name__ == "__main__":
    # 要查询的文本
    query_text = "中国的国都在哪"
    # 获取查询结果(包含距离)
    similar_docs = query_with_distance(query_text, n_results=3)
    # 打印结果
    print(f"查询文本: {query_text}\n")
    for idx, doc in enumerate(similar_docs, 1):
        print(f"结果 {idx}:")
        print(f"ID: {doc['id']}")
        print(f"文档内容: {doc['document'][:100]}...")  # 只显示前100个字符
        print(f"距离(相似度): {doc['distance']:.4f}")  # 保留4位小数
        print("-" * 60)

召回输出的结果:

使用Chromadb的关键点在于依赖,注意以下几个版本安装

pip install numpy==1.26.4

pip install onnxruntime==1.16.3 

pip install chromadb==0.5.3 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值