AI大模型全栈工程师课程笔记 - RAG 检索增强生成
文章目录
-
- \1. RAG
- \2. 构建流程
-
- 2.1 文档加载与切分
- 2.2 传统检索引擎
- 2.3 LLM接口封装
- 2.4 构建prompt
- \3. 向量检索
- \4. 向量数据库
- \5. 基于向量检索的RAG
- \6. 进阶知识
-
- 6.1 文本分割粒度
- 6.2 检索后再排序
- 6.3 测试
1. RAG
RAG(Retrieval Augmented Generation),通过检索获取一些信息,传给大模型,提高回复的准确性。
一般流程:
- 离线步骤:文档加载切片 -> 向量化 -> 存入向量数据库
- 在线步骤:用户提问 -> 向量化 ->检索 -> 组装提示词 -> LLM -> 输出回复
2. 构建流程
相关环境
代码语言:javascript
复制
pip install pdfminer.six # pdf解析
pip install openai -U # openai-1.3.7
2.1 文档加载与切分
代码语言:javascript
复制
import pathlib
def extract_text_from_pdf(filename, page_numbers=None, min_line_length=1):'''从 PDF 文件中(按指定页码)提取文字'''paragraphs = []buffer = ''full_text = ''# 提取全部文本for i, page_layout in enumerate(extract_pages(filename)):# 如果指定了页码范围,跳过范围外的页if page_numbers is not None and i not in page_numbers:continuefor element in page_layout:if isinstance(element, LTTextContainer):full_text += element.get_text() + '\n'# 按空行分隔,将文本重新组织成段落lines = full_text.split('\n')for text in lines:if len(text) >= min_line_length:buffer += (' ' + text) if not text.endswith('-') else text.strip('-')elif buffer:paragraphs.append(buffer)buffer = ''if buffer:paragraphs.append(buffer)return paragraphs
代码语言:javascript
复制
paragraphs = extract_text_from_pdf(pathlib.Path(__file__).parent.absolute() / "llama2.pdf", min_line_length=10)
2.2 传统检索引擎
- 安装 ElasticSearch
代码语言:javascript
复制
pip install elasticsearch8
pip install nltk
代码语言:javascript
复制
from elasticsearch8 import Elasticsearch, helpers
from nltk.stem import PorterStemmer
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
import nltk
import reimport warnings
warnings.simplefilter("ignore") #屏蔽 ES 的一些Warningsnltk.download('punkt') # 英文切词、词根、切句等方法
nltk.download('stopwords') # 英文停用词库def to_keywords(input_string):'''(英文)文本只保留关键字'''# 使用正则表达式替换所有非字母数字的字符为空格no_symbols = re.sub(r'[^a-zA-Z0-9\s]', ' ', input_string)word_tokens = word_tokenize(no_symbols)stop_words = set(stopwords.words('english'))ps = PorterStemmer()# 去停用词,取词根filtered_sentence = [ps.stem(w) for w in word_tokens if not w.lower() in stop_words]return ' '.join(filtered_sentence)
- 切分文档存入 Es
代码语言:javascript
复制
# 1. 创建Elasticsearch连接
es = Elasticsearch(hosts=['http://localhost:9200'], # 服务地址与端口# http_auth=("elastic", "*****"), # 用户名,密码
)# 2. 定义索引名称
index_name = "string_index"# 3. 如果索引已存在,删除它(仅供演示,实际应用时不需要这步)
if es.indices.exists(index=index_name):es.indices.delete(index=index_name)# 4. 创建索引
es.indices.create(index=index_name)# 5. 灌库数据
actions = [{"_index": index_name,"_source": {"keywords": to_keywords(para),"text": para}}for para in paragraphs
]# 6. 批量存储Es
helpers.bulk(es, actions)
- 关键字检索
代码语言:javascript
复制
def search(es, index_name, query_string, top_n=3):# ES 的查询语言search_query = {"match": {"keywords": to_keywords(query_string)}}res = es.search(index=index_name, query=search_query, size=top_n)return [hit["_source"]["text"] for hit in res["hits"]["hits"]]results = search(es, "string_index", "how many parameters does llama 2 have?", 2)
for r in results:print(r + "\n")
搜索llama2有多少参数
,找到了相关的文档,输出:
代码语言:javascript
复制
Llama 2 comes in a range of parameter sizes—7B, 13B,
and 70B—as well as pretrained and fine-tuned variations.1. Llama 2, an updated version of Llama 1, trained on a new mix of publicly available data.
We also increased the size of the pretraining corpus by 40%, doubled the context length of the model, and adopted grouped-query attention (Ainslie et al., 2023).
We are releasing variants of Llama 2 with 7B, 13B, and 70B parameters. We have also trained 34B variants, which we report on in this paper but are not releasing.§
2.3 LLM接口封装
代码语言:javascript
复制
from openai import OpenAI
import os
# 加载环境变量
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv('../utils/.env')) # 读取本地 .env 文件,里面定义了 OPENAI_API_KEYclient = OpenAI(api_key=os.getenv("OPENAI_API_KEY"),base_url=os.getenv("OPENAI_API_BASE")
)def get_completion(prompt, model="gpt-3.5-turbo"):'''封装 openai 接口'''messages = [{"role": "user", "content": prompt}]response = client.chat.completions.create(model=model,messages=messages,temperature=0, # 模型输出的随机性,0 表示随机性最小)return response.choices[0].message.content
2.4 构建prompt
代码语言:javascript
复制
def build_prompt(prompt_template, **kwargs):'''将 Prompt 模板赋值'''prompt = prompt_templatefor k, v in kwargs.items():if isinstance(v,str):val = velif isinstance(v, list) and all(isinstance(elem, str) for elem in v):val = '\n'.join(v)else:val = str(v)prompt = prompt.replace(f"__{k.upper()}__",val)return prompt
代码语言:javascript
复制
prompt_template = """你是一个问答机器人。你的任务是根据下述给定的已知信息回答用户问题。确保你的回复完全依据下述已知信息。不要编造答案。如果下述已知信息不足以回答用户的问题,请直接回复"我无法回答您的问题"。已知信息:__INFO__用户问:__QUERY__请用中文回答用户问题。"""user_query = "how many parameters does llama 2 have?"# 1. 检索
search_results = search(es, "string_index", user_query, 2)# 2. 构建 Prompt
prompt = build_prompt(prompt_template, info=search_results, query=user_query)
print("===Prompt===")
print(prompt)# 3. 调用 LLM
response = get_completion(prompt)
print("===回复===")
print(response)
提示词如下:
在这里插入图片描述
GPT输出:
代码语言:javascript
复制
Llama 2有7B、13B和70B三种参数大小的变体。
传统的关键字检索,对同一个语义的不同描述,可能检索不到结果
3. 向量检索
- 把一个词句映射到 n 维空间的一个向量
- 构建句对(相似和不相似),训练双塔式模型 https://www.sbert.net
- 向量相似度: 余弦距离
dot(a, b)/(norm(a)*norm(b))
欧式距离norm(np.asarray(a)-np.asarray(b))
向量化
代码语言:javascript
复制
def get_embeddings(texts, model="text-embedding-ada-002"):'''封装 OpenAI 的 Embedding 模型接口'''data = client.embeddings.create(input = texts, model=model).datareturn [x.embedding for x in data]
test_query = ["测试文本"]
vec = get_embeddings(test_query)
print(vec[0][:10]) # 1536 维向量 [-0.0072620222344994545, -0.006227712146937847, -0.010517913848161697, 0.001511403825134039, -0.010678159072995186, 0.029252037405967712, -0.019783001393079758, 0.0053937085904181, -0.017029697075486183, -0.01215678546577692]
4. 向量数据库
代码语言:javascript
复制
# pip install chromadbimport chromadb
from chromadb.config import Settingsclass MyVectorDBConnector:def __init__(self, collection_name, embedding_fn):chroma_client = chromadb.Client(Settings(allow_reset=True))# 为了演示,实际不需要每次 reset()chroma_client.reset()# 创建一个 collectionself.collection = chroma_client.get_or_create_collection(name="demo")self.embedding_fn = embedding_fndef add_documents(self, documents, metadata={}):'''向 collection 中添加文档与向量'''self.collection.add(embeddings=self.embedding_fn(documents), # 每个文档的向量documents=documents, # 文档的原文ids=[f"id{i}" for i in range(len(documents))] # 每个文档的 id)def search(self, query, top_n):'''检索向量数据库'''results = self.collection.query(query_embeddings=self.embedding_fn([query]),n_results=top_n)return resultsparagraphs = extract_text_from_pdf(pathlib.Path(__file__).parent.absolute() / "llama2.pdf", page_numbers=[2, 3], min_line_length=10)# 创建一个向量数据库对象
vector_db = MyVectorDBConnector("demo", get_embeddings)
# 向向量数据库中添加文档
vector_db.add_documents(paragraphs)user_query = "Llama 2有多少参数"
results = vector_db.search(user_query, 2) # 查询最相似的2个for para in results['documents'][0]:print(para+"\n")
- FAISS: Meta开源的向量检索引擎 https://github.com/facebookresearch/faiss
- Pinecone: 商用向量数据库,只有云服务 https://www.pinecone.io/
- Milvus: 开源向量数据库,同时有云服务 https://milvus.io/ (选项全都是Y)
- Weaviate: 开源向量数据库,同时有云服务 https://weaviate.io/
- Qdrant: 开源向量数据库,同时有云服务 https://qdrant.tech/
- PGVector: Postgres的开源向量检索引擎 https://github.com/pgvector/pgvector
- RediSearch: Redis的开源向量检索引擎 https://github.com/RediSearch/RediSearch
- ElasticSearch 也支持向量检索 https://www.elastic.co/enterprise-search/vector-search
5. 基于向量检索的RAG
代码语言:javascript
复制
class RAG_Bot:def __init__(self, vector_db, llm_api, n_results=2):self.vector_db = vector_dbself.llm_api = llm_apiself.n_results = n_resultsdef chat(self, user_query):# 1. 检索search_results = self.vector_db.search(user_query,self.n_results)# 2. 构建 Promptprompt = build_prompt(prompt_template, info=search_results['documents'][0], query=user_query)# 3. 调用 LLMresponse = self.llm_api(prompt)return response# 创建一个RAG机器人
bot = RAG_Bot(vector_db,llm_api=get_completion
)user_query="llama 2有多少参数?"
response = bot.chat(user_query)
print(response) # Llama 2有7B、13B和70B参数的变体。
可以替换其他的 embedding、LLM
代码语言:javascript
复制
# pip install sentence_transformers
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('BAAI/bge-large-zh-v1.5')
query_vec = model.encode(query, normalize_embeddings=True)
不是每个 Embedding 模型都对 余弦距离
和 欧氏距离
同时有效 哪种相似度计算有效要阅读模型的说明(通常都支持余弦距离计算)
6. 进阶知识
6.1 文本分割粒度
- 太大,检索不精准,太小,信息不全
- 问题的答案跨越两个片段
改进方法:
- 按一定粒度,部分重叠式的切割文本,使上下文更完整
6.2 检索后再排序
最合适的答案,有时候不一定排在检索结果的最前面
- 检索的时候,多召回一些文本
- 再用排序模型对 query 和 召回的 doc 进行打分排序
代码语言:javascript
复制
user_query="how safe is llama 2"
search_results = semantic_search(user_query,5) # 召回文档model = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2', max_length=512)
scores = model.predict([(user_query, doc) for doc in search_results['documents'][0]])
# 按得分排序
sorted_list = sorted(zip(scores,search_results['documents'][0]), key=lambda x: x[0], reverse=True)
for score, doc in sorted_list:print(f"{score}\t{doc}\n")
6.3 测试
为了成为更好的 AI大模型 开发者,这里为大家提供了总的路线图。它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
经典书籍阅读
阅读AI大模型经典书籍可以帮助读者提高技术水平,开拓视野,掌握核心技术,提高解决问题的能力,同时也可以借鉴他人的经验。对于想要深入学习AI大模型开发的读者来说,阅读经典书籍是非常有必要的。
实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
面试资料
我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】
相关文章:

AI大模型全栈工程师课程笔记 - RAG 检索增强生成
文章目录 \1. RAG\2. 构建流程 2.1 文档加载与切分2.2 传统检索引擎2.3 LLM接口封装2.4 构建prompt \3. 向量检索\4. 向量数据库\5. 基于向量检索的RAG\6. 进阶知识 6.1 文本分割粒度6.2 检索后再排序6.3 测试 1. RAG RAG(Retrieval Augmented Generation&#…...
【时时三省】c语言例题----华为机试题<进制转换>
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1,题目 HJ5 进制转换 描述 写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。 数据范围:保证结果在 1≤n≤231−1 1≤n≤231−1…...

根据NVeloDocx Word模板引擎生成Word(四)
前面介绍了《E6低代码开发平台》的Word模版引擎NVeloDocx,实现了表单的基本字段、子表、单张图片、二维码、条形码怎么基于NVelocity脚本输出到Word文件,都是些比较简单且常用的需求。 本篇介绍怎么基于NVeloDocx在Word中插入图表,目前只支持…...

C++笔记---stack和queue
1. stack的介绍及重要接口 stack---栈,是一种“先进后出,后进先出”的数据结构。 此处的stack是STL库中定义的一个类模板,用于实例化出存储各种类型数据的栈。 bool empty() const;判断栈是否为空(空true/非空false)size_t size() const;返…...
springboot Rabbit MQ topic 配置文件绑定队列和交换机
Spring Boot 中如何将队列和交换机绑定(含实例讲解) 在使用 Spring Boot 开发高并发的秒杀系统或者其他场景时,RabbitMQ 是常用的消息队列中间件之一。本文将详细讲解如何在配置类中通过代码将队列与交换机绑定,并指定路由键来实…...
Visual Studio 2019密钥
Visual Studio 2019 Enterprise(企业版):BF8Y8-GN2QH-T84XB-QVY3B-RC4DF Visual Studio 2019 Professional(专业版):NYWVH-HT4XC-R2WYW-9Y3CM-X4V3Y...
【三元组枚举中点】【树状数组】个人练习-Leetcode-1395. Count Number of Teams
题目链接:https://leetcode.cn/problems/count-number-of-teams/description/ 题目大意:给一个数组rating[],求符合以下任一条件的三元组i, j, k的个数 rating[i] < rating[j] < rating[k]rating[i] > rating[j] > rating[k] …...
Anaconda 中遇到CondaHTTPError: HTTP 404 NOT FOUND for url的问题及解决办法
最近在跑一个开源项目遇到了以下问题,查了很多资料都大(抄)同(来)小(抄)异(去)的,解决不了根本问题,费了很大的劲终于得以解决,记录如…...
数据库系统 第51节 数据库事务管理
数据库事务管理是数据库管理系统(DBMS)中用于确保数据完整性和一致性的一组机制。事务是一组不可分割的操作序列,这些操作要么全部成功,要么全部失败。以下是数据库事务管理的关键组成部分的详细叙述: 1. 事务隔离级别…...

分解+优化+组合+对比!核心无忧!VMD-SSA-Transformer-LSTM多变量时间序列光伏功率预测
分解优化组合对比!核心无忧!VMD-SSA-Transformer-LSTM多变量时间序列光伏功率预测 目录 分解优化组合对比!核心无忧!VMD-SSA-Transformer-LSTM多变量时间序列光伏功率预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.…...

二十三种设计模式之建造者模式(类比汽车制造厂好理解一些)
目录 1. 设计模式的分类 2. 定义 3. 建造者模式通常包含以下几个角色 4. 示例代码 5. 建造者模式的主要优点 1. 设计模式的分类 创建型模式(五种):工厂方法模式、单例模式、抽象工厂模式、原型模式、建造者模式。 结构型模式(七种):适配器模式、代…...
macos 系统文件操作时提示 Read-only file system 解决方法
这个情况是因为文件系统为只读, 需要我们执行一下命令重新将系统文件挂载为读写模式, 命令如下: sudo mount -uw / 这里的 mount 就是硬盘挂载命令, 后面的 -uw选项说明如下, 最后的 / 表示的是跟目录, 可以指定要修改的挂载路径,也可以默认. -u -u标志表示应更改已装载文…...
银行业务架构指导应用架构规划及设计方法
摘要 业务架构指导应用架构设计方法是指依托业务架构设计成果,开展应用架构应用划分设计、IT服务分层设计和数据模型设计的方法。通过业务架构指导应用架构设计,以IT研发项目驱动的方式,由IT系统落地业务架构设计成果,实现对业务流程快速拼接和产品灵活配置的支持,从而提升…...

最全面IO流介绍
1.字符集介绍 标准ASCII字符集:使用1个字节存储一个字符,首尾是0,总可以表示128个字符。是美国信息交换标准代码,包含英文、符号等等。 GBK汉字编码字符集,包含2万多个汉字等字符,GBK中一个中文字符编码成…...

fastadmin 文件上传腾讯云
1-安装腾讯云SDK composer require qcloud/cos-sdk-v5 2-腾讯云配置 <?phpnamespace app\common\controller;use Qcloud\Cos\Client; use think\Controller; use think\Db;class Tencent extends Controller {/*** 上传文件* param $config* param $key* return array*/p…...

《机器学习》—— PCA降维
文章目录 一、PCA降维简单介绍二、python中实现PCA降维函数的介绍三、代码实现四、PCA降维的优缺点 一、PCA降维简单介绍 PCA(主成分分析,Principal Component Analysis)是一种常用的数据降维技术。它通过线性变换将原始数据转换到新的坐标系…...

植物三萜皂苷生物合成途径及调控机制研究进展-文献精读48
摘要 三萜皂苷(triterpenoids saponins)是由三萜皂苷元和一个或多个糖基和/或其他化学基团缩合而成的一系列结构多样的天然化合物[1], 主要分布在五加科、蝶形花科、石竹科、桔梗科、毛茛科、玄参科、葫芦科等植物中[2]. 植物中三萜皂苷常分布在特定的器官和组织, 如人参(Pana…...

server 2016搭建FTP服务
目录 一、实验环境 二、在server 2016上面安装FTP服务 三、在server 2016上面配置FTP服务 四、创建用户(也可创建用户组,给用户组赋予权限) 一、实验环境 windows server 2016用于安装ftp服务 windows 10作为客户端进行测试。 二、在s…...
物理学基础精解【4】
文章目录 运动和力质点运动机械运动的参考系运动的相对性运动学中坐标系 参考文献 运动和力 质点运动 一个物体相对于另一个物体的位置或一个物体的某些部分相对于其他部分的位置 ,随着时间而变化的过程,叫机械运动 。质点是一个物理学中的理想化模型&…...
【区块链 + 人才服务】Blockchain Workshop- 区块链编程实践平台 | FISCO BCOS应用案例
Blockchain Workshop v2.0(以下简称 BCW v2.0)是点宽网络科技有限公司升级的全新区块链实践教育平台产品。 BCW v2.0 区块链实践教育平台面向高校区块链专业人才培养,用于区块链专业技术学习和智能合约编程学习,平台基于 FISCO BC…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

路由基础-路由表
本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中,往往存在多个不同的IP网段,数据在不同的IP网段之间交互是需要借助三层设备的,这些设备具备路由能力,能够实现数据的跨网段转发。 路由是数据通信网络中最基…...
【java】【服务器】线程上下文丢失 是指什么
目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失? 直观示例说明 为什么上下文如此重要? 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程,代码应该如何实现 推荐方案:使用 ManagedE…...
MySQL基本操作(续)
第3章:MySQL基本操作(续) 3.3 表操作 表是关系型数据库中存储数据的基本结构,由行和列组成。在MySQL中,表操作包括创建表、查看表结构、修改表和删除表等。本节将详细介绍这些操作。 3.3.1 创建表 在MySQL中&#…...
数据库优化实战指南:提升性能的黄金法则
在现代软件系统中,数据库性能直接影响应用的响应速度和用户体验。面对数据量激增、访问压力增大,数据库性能瓶颈经常成为项目痛点。如何科学有效地优化数据库,提升查询效率和系统稳定性,是每位开发与运维人员必备的技能。 本文结…...
Faiss vs Milvus 深度对比:向量数据库技术选型指南
Faiss vs Milvus 深度对比:向量数据库技术选型指南 引言:向量数据库的时代抉择 在AI应用爆发的今天,企业和开发者面临着如何存储和检索海量向量数据的重大技术选择。作为当前最受关注的两大解决方案,Faiss和Milvus代表了两种不同…...