自己手写了一个大模型RAG项目-05.基于知识库的大模型问答

news2024/11/23 11:27:29

大家好,我是程序锅。

github上的代码封装程度高,不利于小白学习入门。

常规的大模型RAG框架有langchain等,但是langchain等框架源码理解困难,debug源码上手难度大。

因此,我写了一个人人都能看懂、人人都能修改的大模型RAG框架代码。

整体项目结构如下图所示:手把手教你大模型RAG框架架构

手把手教你大模型RAG框架架构

整个小项目分为10个章节,和github高度封装的RAG代码不同,我们将从0到1搭建大模型RAG问答系统。

前序章节:
自己手写了一个大模型RAG项目-04.知识库构建

图1.RAG技术路线

本篇文章将介绍5.基于知识库的大模型问答,知识库构建好之后还需要通过知识检索和智能问答。

一、知识检索

首先第一个问题,为什么要做知识检索

在整个大模型RAG智能问答应用构建过程中,需要将用户的问题向量化,将向量化后的问题与知识库内的向量做匹配。

前面几篇文章已经讲述了如何构建知识库,目前需要从向量库中匹配与问题最相似的k个向量(k是一个超参数,需要根据大模型输入上下文长度来界定)

怎么匹配以及匹配的标准是什么呢?

匹配的目的就是一堆向量中找到最相似的几个向量,最简单直白的方式就是去遍历所有向量,计算问题向量与知识库所有向量之间的相似度,然后按照相似度多少,从高到低排序,取最大的几个。

匹配的标准也很简单,我采用了余弦相似度。此外可以用L2范数、内积、曼哈顿距离、p范数等等。

@classmethod
def cosine_similarity(cls, vector1: List[float], vector2: List[float]) -> float:
    """
        calculate cosine similarity between two vectors
        """
    dot_product = np.dot(vector1, vector2)
    magnitude = np.linalg.norm(vector1) * np.linalg.norm(vector2)
    if not magnitude:
        return 0
    return dot_product / magnitude
def query(self, query: str, EmbeddingModel: BaseEmbeddings, k: int = 1) -> List[str]:
      query_vector = EmbeddingModel.get_embedding(query)
      end_time = time.time()
      result = np.array([self.get_similarity(query_vector, vector)
                        for vector in self.vectors])
      print(' 检索 cost %f second' % (time.time() - end_time))
      return np.array(self.document)[result.argsort()[-k:][::-1]].tolist()    

上面代码用到了最简单的for循环对比。不过for循环对比效率太低,因此有了许多优化方法。主要可以分为索引构建、检索加速、向量数据库等。

1.索引构建

索引一般存储在磁盘的文件中,它是占用物理空间的。一般我们都将存储所有原始向量

由于原始向量维度比较高,为了减少索引占用的空间,可以采用主成分分析(PCA)对向量降维;也可以通过某些编码方式降低向量维度,比如PQ16使用16个字节编码向量、PQ8+16通过8字节来进行PQ,16个字节对第一级别量化的误差再做PQ等等。

2.检索加速

检索这一块最简单的是基于余弦相似度的暴力全量搜索。如果你只是少量检索,或者要求检索结果非常准确的话这种索引是你的首选。

在数据量大了之后,暴力搜索会很慢,因此也有一些新的搜索算法。

  • 倒排暴力检索

    具体做法是预先设定好需要把所有向量聚成多少类,每个簇下会选出一个中心向量,在每次search的时候可以找到最近的几个中心向量,然后只在这几个中心向量涉及的簇中进行搜索,这样就大大减小了搜索范围,有利于搜索效率的提升。

  • 乘积量化

    利用乘积量化的方法,改进了普通检索,将一个向量的维度切成x段,每段分别进行检索,每段向量的检索结果取交集后得出最后的TopK。

  • 图检索

    图搜索算法是一类用于遍历或搜索图的数据结构和算法,图的节点可能带有关系,这些关系可以是有向的或无向的,加权的或无权的。图检索构建索引极慢,占用内存极大,检索速度极快,10亿级别秒出检索结果,

还有很多检索加速的方法,想快速用起来,推荐使用Faiss向量检索库,一行代码即可实现上述检索功能。比如用Faiss构建倒排暴力检索,代码如下:

import faiss  
# 向量维度是128,faiss.METRIC_L2代表相似度采用欧式距离
dim, measure = 128, faiss.METRIC_L2 
#代表k-means聚类中心为4096,   
description =  'IVF4096,Flat'
index = faiss.index_factory(dim, description, measure)

3.向量数据库

向量数据库是一种专门用于存储和处理向量数据的数据库系统。它以向量为基本数据类型,将向量作为数据的主要组织形式。相比传统的关系型数据库,向量数据库具有高效的相似性搜索和高度可扩展性。

你可以理解向量数据库主要包括数据存储、索引构建和相似性搜索三个过程。并且都根据数据是高维向量这一特性,在存储、索引、检索方面都做了大量的优化。

目前国产向量数据库中,比较厉害的就是Milvus。代码中也会涉及Milvus部署使用以及在没有资源的情况下如何白嫖Zilliz(Milvus的云化版本)

二、智能问答

这一块涉及如何组织语言,将用户的问题与知识库被检索出的文本块结合起来,便于大模型更好理解用户意图,生成用户想要的结果。

业界给了它一个高大上的名字:提示工程。提示工程探讨如何设计出最佳提示词,用于指导语言模型帮助我们高效完成某项任务。

下面给个项目中提示工程的例子:

PROMPT_TEMPLATE = dict(
    RAG_PROMPT_TEMPALTE="""使用以上下文来回答用户的问题。如果你不知道答案,就说你不知道。总是使用中文回答。
        问题: {question}
        可参考的上下文:
        ···
        {context}
        ···
        如果给定的上下文无法让你做出回答,请回答数据库中没有这个内容,你不知道。
        有用的回答:""",
    InternLM_PROMPT_TEMPALTE="""先对上下文进行内容总结,再使用上下文来回答用户的问题。如果你不知道答案,就说你不知道。总是使用中文回答。
        问题: {question}
        可参考的上下文:
        ···
        {context}
        ···
        如果给定的上下文无法让你做出回答,请回答数据库中没有这个内容,你不知道。
        有用的回答:"""
)

其中question是我们问的问题,context是知识库检索到的知识。

三、运行

代码目录结构:

├─images
├─RAG #存放RAG核心代码
└─tutorial
    ├─01.如何调用大模型API
    ├─02.RAG介绍
    ├─03.部署环境准备
    ├─04.知识库构建
    ├─05.基于知识库的大模型问答
    ├─06.改进-用自己的embedding模型
    ├─07.封装镜像对外提供服务
    ├─08.改进-基于Faiss的大模型知识索引构建
    ├─09.改进-使用向量数据库
    │  └─cloud-vectordb-examples
    └─10.前端构建

其中tutorial文件夹中,进入05.基于知识库的大模型问答

执行:python test.py,即可针对知识库开展大模型问答(前提条件:完成04.知识构建

好了,我们已经做出了一个最简单的基于RAG的大模型问答。下一章将介绍不调用接口,使用自己部署的embedding模型。

最后,我撰写的人工智能应用相关的博客及配套代码均整理放置在Github:ai-app,有需要的朋友自取。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1633454.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

03-JAVA设计模式-解析器模式

解释器模式 什么是解析器模式 在Java中,解释器模式(Interpreter Pattern)是一种行为设计模式,它给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子…

unity3d使用3D WebView播放网页中的视频

Unity2021.3.35f1,硬件ESP32-Cam,3D WebView插件 1.新建工程,导入3D WebView for Winfows和3D WebView for Android 2.打开场景Assets\Vuplex\WebView\Demos\Scenes\2_CanvasWebViewDemo 3.修改Canvas的Render Mode为Screen Space-Camera&am…

30秒出服装设计稿,森马用Serverless+AIGC 整“新活”!

“创新项目如何去赋能我们的业务,这件事情在森马很重要。阿里云函数计算帮我们屏蔽掉了想把AI落地到实际业务场景中 GPU 算力资源储备、采购成本、技术门槛等很多难题,从而迅速做出决策,快人一步站在正确的起点,体验新技术对整个服…

『春招实习』2023年3月春招实习求职经历

『春招实习』2023年3月春招实习求职经历 简介货拉拉一面杭州吉里一面传墨科技一面 简介 3月初我便开始陆续投递简历,直观的感受就是【投递的太晚了】,很多公司很早就开始招聘实习生了。 但是自己一直在担心没准备好,所以就想着再准备一天就投…

数据结构单链表”质检员“*2

1.随机链表的逻辑结构复制 原题链接: . - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode-cn.com/problems/copy-list-with…

机器学习:深入解析SVM的核心概念(问题与解答篇)【三、核函数】

核函数 **问题一:为什么说是有限维就一定存在高维空间可分呢?**原始空间与特征空间为什么映射到高维空间可以实现可分核函数的作用 **问题二:最终怎么得到函数**从对偶问题到决策函数的步骤:结论 **问题三:为什么说特征…

Kafka 3.x.x 入门到精通(03)——Kafka基础生产消息

Kafka 3.x.x 入门到精通(03)——对标尚硅谷Kafka教程 2. Kafka基础2.1 集群部署2.2 集群启动2.3 创建主题2.4 生产消息2.4.1 生产消息的基本步骤2.4.2 生产消息的基本代码2.4.3 发送消息2.4.3.1 拦截器2.4.3.1.1 增加拦截器类2.4.3.1.2 配置拦截器 2.4.3…

c#数据库:1.c#创建并连接数据库

安装软件:SQL Server Management Studio Management Studio Visual Studio 2022 启动服务: 打开SQL Server Management Studio Management Studio ,连接到服务器(GUANZU是我的计算机名) 新建数据库,随便起个名字叫aq: c#代码: using System; using System.Collections.Gener…

UG NX二次开发(C++)-获取模型中所有的拉伸(Extrude)特征

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、在UG 12中创建几个拉伸特征3、UFun中获取对象类型4、通过NXOpen过渡5.测试结果1、前言 在采用UG NX二次开发时,有时需要在模型中获取特定的对象,比如拉伸特征、关联特征等等。但是通过…

大数据分析与应用实验(黑龙江大学)

实验一 Hadoop伪分布式实验环境搭建与WordCount程序 一、实验目的 1、学习搭建Hadoop伪分布式实验环境 2、在伪分布式实验环境下运行WordCount程序 二、实验内容 1、搭建Hadoop伪分布式实验环境,并安装Eclipse。 2、在Eclipse环境下,编写并执行Wor…

面试题:分布式消息中间件 MQ

MQ官网文档: RabbitMQ:https://www.rabbitmq.com/docs RocketMQ:https://rocketmq.apache.org/zh/docs/ Kafka:https://kafka.apache.org/documentation/ DDMQ:https://base.xiaojukeji.com/docs/ddmq 面试题&#xff…

【LeetCode周赛】第 395 场周赛

目录 3131. 找出与数组相加的整数 I 简单3132. 找出与数组相加的整数 II 中等3133. 数组最后一个元素的最小值 中等3134. 找出唯一性数组的中位数 困难 3131. 找出与数组相加的整数 I 简单 3131. 找出与数组相加的整数 I 分析: 将两个数组中最小的两个值相减即可。…

你的动漫AI女友 Anime gf :自定义创建各种独特个性、语言风格的虚拟角色

一个本地且开源的 CharacterAI 替代工具 Anime gf,提供了一个用户友好的界面,允许用户在桌面上与虚拟角色互动。你可以自定义创建各种角色,让每个虚拟角色都有自己的独特个性和语言风格,可以接入OpenAI、Anthropic、Mistral和 Tog…

Faststone Capture:一触即发的效率革命【AI写作】

首先,这篇文章是基于笔尖AI写作进行文章创作的,喜欢的宝子,也可以去体验下,解放双手,上班直接摸鱼~ 按照惯例,先介绍下这款笔尖AI写作,宝子也可以直接下滑跳过看正文~ 笔尖Ai写作:…

XY_RE复现(二)

一,何须相思煮余年 0x55 0x8b 0xec 0x81 0xec 0xa8 0x0 0x0 0x0 0xa1 0x0 0x40 0x41 0x0 0x33 0xc5 0x89 0x45 0xfc 0x68 0x9c 0x0 0x0 0x0 0x6a 0x0 0x8d 0x85 0x60 0xff 0xff 0xff 0x50 0xe8 0x7a 0xc 0x0 0x0 0x83 0xc4…

【中级软件设计师】上午题12-软件工程(3):项目活动图、软件风险、软件评审、软件项目估算

【中级软件设计师】上午题12-软件工程(3) 1 软件项目估算1.1 COCOMO估算模型1.2 COCOMOⅡ模型 2 进度管理2.1 gantt甘特图2.2 pert图2.3 项目活动图2.3.1 画项目图 3 软件配置管理4 软件风险4.1 风险管理4.2 风险识别4.3 风险预测4.4 风险评估4.5 风险控…

大模型(LLM)调用API论文研究合集

1、API-BLEND: A Comprehensive Corpora for Training and Benchmarking API LLMs 中文标题:API-BLEND: 一个用于训练和评测 API 语言模型的全面语料库 简介:随着大型语言模型(LLM)的发展,它们需要能够有效地利用各种工具和应用程序接口(API)来完成复杂…

GNU Radio之OFDM Channel Estimation底层C++实现

文章目录 前言一、 OFDM Channel Estimation 模块简介二、C 具体实现1、初始化和配置参数2、forecast 函数3、计算载波偏移量4、提取信道响应5、核心的数据处理任务 前言 OFDM Channel Estimation 模块的功能是根据前导码(同步字)估计 OFDM 的信道和粗略…

Java:SpringBoot如何优化启动速度

一、yml中设置懒加载 spring:main:lazy-initialization: true 二、SpringBoot启动类中添加注解 Indexed (Spring5才有该注解) Indexed EnableAsync RestController SpringBootApplication(exclude {WxMaAutoConfiguration.class}) EnableTransactionM…

web服务的部署及高级优化

搭建web服务器 1.1、配置主机IP以及软件仓库搭建 [rootserver129 ~]# vmset.sh 100 //主机IP配置为172.25.254.100 1.2、查看搭建web服务器所需的软件包 [rootserver100 ~]# dnf search nginx 名称 精准匹配:nginx nginx.x86_64 : A high performance web serve…