LLM:检索增强生成(RAG)

1 Embedding技术

  简单地说,嵌入(Embedding)思想可以视为一种尝试通过用向量来表示所有东西的“本质”的方法,其特性是“相近的事物”由相近的数表示。

1.1 文本向量(Text Embedding)

  在GPT中,文本嵌入(Text Embedding)是通过将输入文本中的每个词汇或词语转换为高维向量表示的方法。这些向量捕捉了词汇的语义信息,使得模型能够理解文本的含义并生成相关的输出。通过预训练的方式,GPT模型能够学习得到通用的文本表示,从而在各种自然语言处理任务中表现出色,包括文本生成、文本分类、问答等。

1.2 使用GPT进行Embedding

  目前OpenAI官方提供的3个文本向量模型为:

模型最大向量维度可否缩减维度
text-embedding-3-small1536
text-embedding-3-large3072
text-embedding-ada-0021536

text-embedding-3-smalltext-embedding-3-large可以通过embeddings.create中的dimensions参数调整输出的文本向量的维度。一般而言,文本向量维度越小搜索越快,而维度越大搜索越准。embeddings.create接口中的参数主要包括以下几个:

  • input: string或array。当为array时,其元素可以是字符串、整数或整数组成的array。整数会被视为一个token标记,整数组成的array会被视为一个完整的字符串。一个字符串输出一个embedding向量。
  • model: OpenAI提供的embedding模型。
  • dimension: embedding向量的维度;
  • encode-format: embedding向量的编码方式,float(默认值)或base64

具体代码举例如下(关于文本向量的相似度,GPT官方建议使用余弦相似度):

from openai import OpenAI
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())  
client = OpenAI()
import numpy as np
from numpy.linalg import norm
def cos_sim(a, b):
    '''余弦距离 -- 值越接近1越相似'''
    return np.dot(a, b)/(norm(a)*norm(b))
def get_embeddings(texts, model="text-embedding-ada-002", dimensions=None):
    '''封装 OpenAI 的 Embedding 模型接口'''
    if model == "text-embedding-ada-002":
        dimensions = None
    if dimensions:
        data = client.embeddings.create(
            input=texts, model=model, dimensions=dimensions).data
    else:
        data = client.embeddings.create(input=texts, model=model).data
    return [x.embedding for x in data]

if __name__=="__main__":
    vec1=np.reshape(get_embeddings(texts="你好啊")[0],(-1,1536))
    vec2=np.reshape(get_embeddings(texts="hello")[0],(1536,-1))
    print(cos_sim(vec1,vec2))

代码运行结果如下:

[[0.84943191]]

2 向量数据库

  向量数据库是一种特殊类型的数据库,专门用于存储和检索向量数据,是为了有效处理高维数据而设计的。这里要注意一点:向量数据库本身不生成向量,向量是由 Embedding 模型产生的。目前主流的向量数据库有多种:chroma、milvus等。这里以chroma为例简单介绍。

2.1 chroma安装

chroma的安装非常简单,在Python中直接使用pip install命令安装即可。具体如下:

pip install chromadb

2.2 chroma基本操作

chroma向量数据库中的集合(collection)保存一组相关文件,可以看作一个容器,用于存储和组织特定类别或主题的数据。与collection相关的操作包括以下内容:

  • 创建集合:create_collection
  • 删除集合:delete_collection
  • 获取集合:get_collection
  • 获取并创建集合:get_or_create_collection(最常用)

在collection中可以添加add、删除delect、修改modify、插入insert、更新update向量。

2.3 chroma添加向量及查找相似向量

def get_embeddings(texts, model="text-embedding-ada-002", dimensions=None):
    if model == "text-embedding-ada-002":
        dimensions = None
    if dimensions:
        data = client.embeddings.create(
            input=texts, model=model, dimensions=dimensions).data
    else:
        data = client.embeddings.create(input=texts, model=model).data
    return [x.embedding for x in data]

chroma_client=chromadb.Client(Settings(allow_reset=True))
chroma_client.reset()
collection=chroma_client.get_or_create_collection(name="my_collection")

documents=['hello','你吃早饭了吗?',"今天考了多少分?","侬好吗?"]
#向collection中添加向量
collection.add(embeddings=get_embeddings(documents),
            documents=documents,
            ids=["id1", "id2",'id3','id4'])
#查找与“你好”最相近的向量
results=collection.query(
    query_embeddings=get_embeddings(["你好"]),
    n_results=2)
print(results['documents'][0])

其输出内容为:

[‘侬好吗?’, ‘hello’]

注意:chroma等其他向量数据库能快速定位相似变量,是因为这类数据库通常执行的是近似查找,而非精确查找。

3 检索增强生成

  检索增强生成(Retrieval-Augmented Generation, RAG)是一种结合了信息检索和自然语言生成的技术。其基本思想是利用信息检索的技术,从大规模语料库(存储在向量数据库)中检索出与当前任务相关的文本片段,并将这些文本片段作为输入提供给生成模型,以引导生成模型产生更准确、更相关的文本输出。其基本框架为:在这里插入图片描述

下面给出一个具体的代码案例:

from pdfminer.high_level import extract_pages
from pdfminer.layout import LTTextContainer
import re
import chromadb
from chromadb.config import Settings
from openai import OpenAI
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) 
client=OpenAI()
#从pdf中提取文档
def extract_text_from_pdf(filename,page_numbers=None,min_line_length=5):
    paragaphs=[]
    full_text=''
    for i,page_layout in enumerate(extract_pages(filename)):
        if page_numbers and i not in page_numbers:
            continue
        for element in page_layout:
            if isinstance(element,LTTextContainer):
                full_text+=element.get_text()+'\n'
    buffer=''
    for text in full_text.split('\n'):
        if len(text)>1 and bool(re.search(r'\b[A-Za-z]+\b',text)):
            buffer+=(' '+text) if not text.endswith('-') else text.strip('-')
        elif buffer:
            paragaphs.append(buffer.lstrip(' '))
            buffer=''
    if buffer:
        paragaphs.appen(buffer)
    return paragaphs
#定义embedding函数
def get_embeddings(texts, model="text-embedding-ada-002", dimensions=None):
    if model == "text-embedding-ada-002":
        dimensions = None
    if dimensions:
        data = client.embeddings.create(
            input=texts, model=model, dimensions=dimensions).data
    else:
        data = client.embeddings.create(input=texts, model=model).data
    return [x.embedding for x in data]
#修改prompt模版
def bulid_prompt(prompt_template, **kwargs):
    prompt=prompt_template
    for k,v in kwargs.items():
        if isinstance(v,str):
            val=v
        elif isinstance(v,list) and all(isinstance(x,str) for x in v):
            val='\n'.join(v)
        else:
            val=str(v)
        prompt=prompt.replace(f"__{k.upper()}__",val)
    return prompt
#调用大模型
def get_completions(prompt,model='gpt-3.5-turbo'):
    response=client.chat.completions.create(
        model=model,
        messages=[{"role":"user","content":prompt}],
        temperature=0.5,
    )
    return response.choices[0].message.content
    
prompt_template = """
你是一个问答机器人。
你的任务是根据下述给定的已知信息回答用户问题。
确保你的回复完全依据下述已知信息。不要编造答案。
如果下述已知信息不足以回答用户的问题,请直接回复"我无法回答您的问题"。

已知信息:
__INFO__

用户问:
__QUERY__

请用中文回答用户问题。
"""
class RAG_BOT():
    def __init__(self):
        chroma_client=chromadb.Client(Settings(allow_reset=True))
        self.collection=chroma_client.get_or_create_collection(name="my_collection")
    def add_documents(self,documents):
        self.collection.add(documents=documents,
                            embeddings=get_embeddings(documents),
                            ids=["id"+str(i) for i in range(len(documents))])
    def query(self,user_query,top_n=2):
        results=self.collection.query(query_embeddings=get_embeddings([user_query]),n_results=top_n)
        prompt=bulid_prompt(prompt_template,query=user_query,info=results['documents'])
        return get_completions(prompt)

documents=extract_text_from_pdf('/Users/sherry/Downloads/llama2.pdf')

rag_bot=RAG_BOT()
rag_bot.add_documents(documents)
print(rag_bot.query("llama2有多少参数?"))

其输出结果为:

根据已知信息,Llama 2 模型有三个变种,参数量分别为 7B、13B 和 70B。

参考资料

  1. https://zhuanlan.zhihu.com/p/647646322
  2. https://guangzhengli.com/blog/zh/vector-database/
  3. https://blog.csdn.net/shebao3333/article/details/130593519

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Web Animations API 动画

Element.animate() dom.animate动画可以避免污染dom原有的css动画 参考资料 Element.animate() - Web API 接口参考 | MDN Element: getAnimations() method - Web APIs | MDN .tunnel{width:200px;height:200px;background-color:#38f;}<div class"tunnel" …

QT 实现无边框可伸缩变换有阴影的QDialog弹窗

实现无标题栏窗口的拖拽移动、调节窗口大小以及边框阴影效果。初始化时进行位或操作&#xff0c;将这些标志合并为一个值&#xff0c;并将其设置为窗口的标志。这些标志分别表示这是一个对话框、无边框窗口、有标题栏、有最小化按钮和最大化按钮。 setWindowFlags(Qt::Dialog |…

【微服务】——Nacos注册中心

这里写自定义目录标题 1.认识和安装Nacos2.服务注册到nacos1&#xff09;引入依赖2&#xff09;配置nacos地址3&#xff09;重启 3.服务分级存储模型3.1.给user-service配置集群3.2.同集群优先的负载均衡 4.权重配置5.环境隔离5.1.创建namespace5.2.给微服务配置namespace 6.Na…

蓝桥杯真题:货物摆放

import java.util.ArrayList;public class Main {public static void main(String args[]) {//常规思路/*long num 2021041820210418l;int count 0;for ( long i 1 ; i < num ; i ){for ( long j 1 ; j < num ; j ){for ( long k 1 ; k < num ; k ){if ( i * j *…

《C Prime Plus》02

1. UNIX 系统 C语言因UNIX系统而生&#xff0c;也因此而流行&#xff0c;所以我们从UNIX系统开始&#xff08;注意&#xff1a;我们提到的UNIX还包含其他系统&#xff0c;如FreeBSD&#xff0c;它是UNIX的一个分支&#xff0c;但是由于法律原因不使用该名称&#xff09;。 UN…

蓝桥杯练习——拼出一个未来

选中 index.html 右键启动 Web Server 服务&#xff08;Open with Live Server&#xff09;&#xff0c;让项目运行起来。接着&#xff0c;打开环境右侧的【Web 服务】&#xff0c;就可以在浏览器中看到如下效果&#xff1a; 目标 完善 js/index.js 的 TODO 部分&#xff0c;实…

概率、似然、极大似然估计

概率、似然、极大似然估计 概率&#xff1a;特定情况下某事件发生的可能性&#xff08;参数已知&#xff0c;事件发生的可能性&#xff09;似然&#xff1a;根据已经确定的结果推测产生这个结果的可能的环境&#xff08;事件发生的可能性已知&#xff0c;参数未知&#xff0c;推…

生成式AI的情感实验——AI能否产生思想和情感?

机器人能感受到爱吗&#xff1f;这是一个很好的问题&#xff0c;也是困扰了科学家们很多年的科学未解之谜。虽然我们尚未准备好向智能机器赋予情感&#xff0c;但智能机器却已经可以借助生成式人工智能&#xff08;AI&#xff09;来帮助我们表达自己的情感。 自然情感表达 AI正…

个人医疗开支预测项目

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 项目背景 随着医疗成本的持续上涨&#xff0c;个人医疗开支成为一个重要议题。理解影响医疗费用的多种因素对于医疗保险公司、政府机构以及个人…

Rust---复合数据类型之字符串与切片(2)

目录 字符串操作删除 (Delete)连接 (Concatenate) 字符串转义 前情回顾: Rust—复合数据类型之字符串&#xff08;1&#xff09; 字符串操作 删除 (Delete) 删除方法仅适用于 String 类型&#xff0c;分别是&#xff1a; pop()&#xff0c;remove()&#xff0c;truncate()&a…

【嵌入式DIY实例】-使用SCT-013 传感器测量交流电流

使用SCT-013 传感器测量交流电流 文章目录 使用SCT-013 传感器测量交流电流1、SCT-013介绍2、硬件准备2、如何计算电气设备消耗的电流3、代码实现SCT-013电流互感器在家用电能表中很常见。 它是一种无需断开电路即可测量导线中电流的组件。在本文中,我们将介绍如何使用 Arduin…

GraalVM运行模式和企业级应用

文章目录 GraalVM运行模式JIT模式AOT模式 GraalVM的问题和解决方案GraalVM企业级应用传统架构的问题Serverless架构函数计算Serverless应用场景Serverless应用 GraalVM内存参数 GraalVM运行模式 JIT模式 JIT&#xff08; Just-In-Time &#xff09;模式 &#xff0c;即时编译模…

绩效考核存在合理性、公平性、客观性吗?

目录 一、绩效考核流于形式&#xff1a;没有实际考核过 二、考核结果的确定: 主管一人说了算 三、考核结果&#xff1a; 与绩效奖金挂钩吗&#xff1f; 四、考核的滥用&#xff1a;成为公司排挤迫使员工离职的手段 五、公司说&#xff1a; 让你滚蛋&#xff0c;谁还会发你奖…

4.3学习总结

[HNCTF 2022 WEEK2]Canyource&#xff08;无参数&#xff09; 通过这题又接触了一种无参数RCE的方法&#xff0c;前面学习的getallheaders只有在apache环境下才能使用&#xff0c;具有一定的局限性 这里是利用php函数来构造读取flag的方法 localeconv() – 函数返回一个包含本…

满足小体积/低功耗/低成本需求,世强硬创推出CGM解决方案

随着CGM的普及与更多具备性价比的国产产品上市&#xff0c;越来越多的企业开始布局CGM市场。 为此全球领先的硬件创新研发和供应服务平台世强硬创面向硬科技企业推出CGM&#xff08;连续血糖监测&#xff09;解决方案。 该方案可一站式解决企业开发需求&#xff0c;包括系统整…

基于8B10B的GT收发器PHY层设计(3)PHY层设计

文章目录 前言一、设计框图二、PHY层基本传输协议三、PHY_TX模块3.1、模块接口3.2、组帧状态机描述3.3、数据大小端问题3.4、字节对齐 四、PHY_RX模块4.1、模块接口4.2、大小端转换4.3、起始位4.4、结束位4.5、axis数据流恢复 五、LFSR伪随机码六、链路空闲时期处理 前言 上一…

瀚海贫者福,铜子恣意游

上学时打饭追求性价比的习惯一直不改&#xff0c;半个大鱼头三块钱&#xff0c;一份豆腐一块钱&#xff0c;还有一个红烧茄子2块5&#xff0c;再加三毛钱的饭&#xff0c;共6块8毛钱&#xff0c;早晚餐也会有这类性价比高又营养的选择&#xff0c;科大食堂现在越来越人性化&…

路径规划——曲线拟合详解(一):多项式轨迹与QP优化(minimum-snap算法核心部分)

前言 历经一个多星期时间&#xff0c;我们在路径规划——搜索算法部分讲解了7种常见的路径搜索算法&#xff0c;每一种算法的链接放在下面了&#xff0c;有需要的朋友点击跳转即可&#xff1a; 路径规划——搜索算法详解&#xff08;一&#xff09;&#xff1a;Dijkstra算法详…

uniapp切换中英文

一、安装 npm install uni-i18n --save 二、创建中英文切换的文件 1.英文en.js文件 2.中文zh_CN.js文件 三、 main.js中引用 // Vue i18n 国际化 import VueI18n from /common/vue-i18n.min.js; Vue.use(VueI18n);// i18n 部分的配置&#xff0c;引入语言包&#xff0c;注意路…

代码随想录第29天|491.递增子序列 46.全排列 47.全排列 II

目录&#xff1a; 491.递增子序列 46.全排列 47.全排列 II 491.递增子序列 491. 非递减子序列 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 回溯算法精讲&#xff0c;树层去重与树枝去重 | LeetCode&#xff1a;491.递增子序列_哔哩哔哩_bili…