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

RAG(Retrieval-Augmented Generation,检索增强生成)流程

目录

  • 一、知识文档的准备
  • 二、OCR转换
  • 三、分词处理
  • 四、创建向量数据库
  • 五、初始化语言聊天模型
    • 1.prompt
    • 2.检索链
    • 3.对话
  • 完整代码

知识文档的准备:首先需要准备知识文档,这些文档可以是多种格式,如Word、TXT、PDF等。使用文档加载器或多模态模型(如OCR技术)将这些文档转换为可理解的纯文本数据。对于长篇文档,还需进行文档切片,以便更高效地处理和检索信息。

嵌入模型:将文本转换为向量形式,以便通过计算向量之间的差异来识别语义上相似的句子。常见的嵌入模型包括Word2Vec、BERT和GPT系列等。

向量数据库:将嵌入后的向量数据存储在向量数据库中,以便进行高效的相似性搜索。

查询检索:当用户提出查询时,系统会将查询通过嵌入模型转换为向量,然后在向量数据库中进行相似性搜索,找到与查询最相关的文档或信息。

生成回答:将检索到的相关信息与用户的查询结合,生成最终的回答。生成模型会利用检索到的信息作为上下文输入,并结合大语言模型来生成文本内容。
这里的嵌入模型用的是本地部署的ollama,也可以使用openai,但是连接不太稳定,还有阿里云的通义千问。
在这里插入图片描述

一、知识文档的准备

知识库中存放pdf等类型的文档,准备后面转换为txt文本
在这里插入图片描述
在这里插入图片描述

二、OCR转换

OCR转换会将PDF、图片这些信息提取得到TXT文本。数据质量的好坏直接影响着后面模型对话效果。因此PDF解析选用的工具必须精确且合适。
在这个例子中,我是事先将PDF用MinerU解析成markdown形式了
在这里插入图片描述
在这里插入图片描述

三、分词处理

文本分词处理(Tokenization)是自然语言处理(NLP)中的一个重要步骤,其目的是将连续的文本字符串分割成有意义的单元,这些单元通常被称为“词”或“标记”(tokens)。分词处理是文本分析的基础,因为大多数NLP任务都需要在词级别上进行操作,例如文本分类、情感分析、机器翻译等。
在这里插入图片描述
中文分词使用了jieba库
jieba 是一个非常流行的 Python 中文分词库,主要用于将中文文本切分成单个词语。它支持多种分词模式,并提供了丰富的功能来满足不同的自然语言处理需求。
主要功能和特点:
分词模式:
精确模式:将文本精确地切分成单个词语,适合用于文本分析。
全模式:将文本中所有可能的词语都扫描出来,速度非常快,但可能存在冗余数据。
搜索引擎模式:在精确模式的基础上,对长词再次进行切分,提高召回率,适合用于搜索引擎分词。
自定义词典:用户可以通过自定义词典来增加新词,以提高分词的准确性。
关键词提取:jieba 提供了基于 TF-IDF 算法的关键词提取功能,可以从文本中提取出最重要的词。
词性标注:通过 jieba.posseg 模块,可以在分词的同时获取词性信息。
并行分词:支持并行分词,以提高分词速度

四、创建向量数据库

def create_vector_store(tokenized_texts: List[List[str]], embeddings_model: OllamaEmbeddings) -> FAISS:"""将分词后的文本创建向量库"""try:# 将分词列表转换回文本processed_texts = [' '.join(tokens) for tokens in tokenized_texts]# 批量处理优化batch_size = 100  # 可以根据实际情况调整vectors = []# # 如果有 GPU# if FAISS.get_num_gpus():#     res = FAISS.StandardGpuResources()#     index = FAISS.index_cpu_to_gpu(res, 0, index)for i in tqdm(range(0, len(processed_texts), batch_size), desc="创建向量数据库"):batch = processed_texts[i:i + batch_size]# 批量创建向量vector_store = FAISS.from_texts(texts=batch,embedding=embeddings_model,metadatas=[{"index": j} for j in range(i, i + len(batch))]  # 添加元数据以追踪文档)vectors.append(vector_store)# 如果有多个批次,合并它们if len(vectors) > 1:final_vector_store = vectors[0]for v in vectors[1:]:final_vector_store.merge_from(v)else:final_vector_store = vectors[0]# 保存向量库到本地final_vector_store.save_local("resume_vectors")return final_vector_storeexcept Exception as e:print(f"创建向量库时发生错误: {str(e)}")raise

五、初始化语言聊天模型

刚刚就是制作了向量数据库,这是大模型的第一步,下面还需要有明确的提示词prompt

1.prompt

在这里插入图片描述

2.检索链

检索链(Retrieval Chain)是一种在信息检索和自然语言处理中使用的技术流程,主要用于从大规模数据集中高效地找到与用户查询最相关的信息片段或文档

在这里插入图片描述

3.对话

使用一个while循环始终在对话中
在这里插入图片描述
在这里插入图片描述

完整代码

import os
import jieba
import re
from typing import List
import pdf
# from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.llms import Ollama
from tqdm import tqdm  from loguru import logger
from magic_pdf.data.data_reader_writer import FileBasedDataWriter
from magic_pdf.pipe.UNIPipe import UNIPipeimport nltk
# 下载punkt
nltk.download('punkt')# 设置 OpenAI API 密钥
# os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
# 创建 OpenAI API 密钥
api_key = "sk-xxx"
os.environ["OPENAI_API_KEY"] = api_key# 定义简历文件夹路径
resume_folder = "./data/demo"# 读取 PDF 文件并提取文本
# def extract_text_from_pdfs(folder_path):
#     texts = []
#     for filename in os.listdir(folder_path):
#         if filename.endswith(".pdf"):
#             with open(os.path.join(folder_path, filename), "rb") as file:
#                 reader = PyPDF2.PdfReader(file)
#                 text = ""
#                 for page in reader.pages:
#                     text += page.extract_text()
#                 texts.append(text)
#     return texts# 读取markdown文件并提取文本
def extract_text_from_markdown(folder_path):texts = []for filename in os.listdir(folder_path):if filename.endswith(".md"):with open(os.path.join(folder_path, filename), "r", encoding="utf-8") as file:text = file.read()texts.append(text)return textsdef clean_text(text: str) -> str:"""清理文本,移除特殊字符和多余的空白"""# 替换多个空白字符为单个空格text = re.sub(r'\s+', ' ', text)# 移除特殊字符,保留中文、英文、数字和基本标点text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9.,!?;:,。!?;:]', ' ', text)return text.strip()def tokenize_texts(texts: List[str]) -> List[List[str]]:"""对文本进行分词处理""Args:texts: 要处理的文本列表Returns:处理后的分词列表"""tokenized_texts = []for text in texts:# 清理文本cleaned_text = clean_text(text)# 分别处理中文和英文words = []# 使用jieba进行中文分词segments = jieba.cut(cleaned_text)# 过滤空字符串和纯空白字符words = [word for word in segments if word.strip()]# 移除停用词(可选)# words = [word for word in words if word not in stopwords]tokenized_texts.append(words)return tokenized_textsdef create_vector_store(tokenized_texts: List[List[str]], embeddings_model: OllamaEmbeddings) -> FAISS:"""将分词后的文本创建向量库"""try:# 将分词列表转换回文本processed_texts = [' '.join(tokens) for tokens in tokenized_texts]# 批量处理优化batch_size = 100  # 可以根据实际情况调整vectors = []# # 如果有 GPU# if FAISS.get_num_gpus():#     res = FAISS.StandardGpuResources()#     index = FAISS.index_cpu_to_gpu(res, 0, index)for i in tqdm(range(0, len(processed_texts), batch_size), desc="创建向量数据库"):batch = processed_texts[i:i + batch_size]# 批量创建向量vector_store = FAISS.from_texts(texts=batch,embedding=embeddings_model,metadatas=[{"index": j} for j in range(i, i + len(batch))]  # 添加元数据以追踪文档)vectors.append(vector_store)# 如果有多个批次,合并它们if len(vectors) > 1:final_vector_store = vectors[0]for v in vectors[1:]:final_vector_store.merge_from(v)else:final_vector_store = vectors[0]# 保存向量库到本地final_vector_store.save_local("resume_vectors")return final_vector_storeexcept Exception as e:print(f"创建向量库时发生错误: {str(e)}")raise# 提取简历文本
resume_texts = extract_text_from_markdown(resume_folder)
# resume_texts = extract_text_from_pdfs(resume_folder)
print("简历文本提取完成")# 简历文本分词
tokenized_texts = tokenize_texts(resume_texts)
print(f"简历文本分词完成,共处理 {len(tokenized_texts)} 份文档")# 可以打印一些统计信息(可选)
for i, tokens in enumerate(tokenized_texts):print(f"文档 {i+1} 分词数量: {len(tokens)}")# 创建 OpenAI 嵌入
embeddings = OllamaEmbeddings(model="nomic-embed-text:latest",base_url='xxx')
print("ollama 嵌入完成~")# 创建向量库
vector_store = create_vector_store(tokenized_texts, embeddings)
print("向量库创建完成")# Initialize OpenAI model
# from langchain_community.chat_models import ChatOpenAI
# llm = ChatOpenAI(model='gpt-4o', temperature=0.1, api_key=os.environ.get("OPENAI_API_KEY"))from langchain_community.llms import Ollama
llm = Ollama(model="llama3.3:70b", temperature=0.1, num_ctx=60000,base_url='xxx')# Update imports
from langchain.chains import RetrievalQA  # Changed from create_retrieval_qa_chain
from langchain.prompts import PromptTemplate  # Import the necessary classPROMPT_TEMPLATE = """
已知信息:{context}"你是一个核聚变、人工智能、科学计算领域的人才鉴别专家,你具备管理大量简历的能力;请注意我向你提供了很多简历PDF文件,但每个PDF文件对应一个候选人,包括候选人的姓名、年龄、技能、经历、项目、成果等内容,请仔细识别各个信息。 \
现在需要你帮我分析每个候选人的详细信息,包括:年龄、教育程度、专业技能、职业履历、项目背景、研究成果、获得荣誉、发展潜力,然后帮我完成以下两个功能: \
1.当我给出开展项目的描述信息时,你能帮我准确地按照适配项目的优先级推荐相关候选人,每次允许按照优先级顺序推荐多个候选人,并且详细给出推荐原因,使用markdown的表格形式给出,包括以下信息:姓名、年龄、专业技能、推荐原因; \
2.当我需要分析一个候选人时,请你能进行客观、准确的评估,先描述其主要信息,然后按照:专业能力、科研成果、项目成绩、发展潜力、综合能力进行评分,每项总分100,结果以markown形式给出。 \
请务必注意每个简历仅对应一个候选人,切记不要混淆各个人的信息;1个候选人只需引用1次相关文档即可,仔细识别每个文档中候选人的姓名。"请回答以下问题:{question}
"""
# 创建提示模板
prompt_template = PromptTemplate(input_variables=["context", "question"],template=PROMPT_TEMPLATE
)# 创建检索链
chain_type_kwargs = {"prompt": prompt_template,"document_variable_name": "context",
}# 创建检索链
qa = RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",retriever=vector_store.as_retriever(),chain_type_kwargs=chain_type_kwargs,
)def chat_loop():print("\n欢迎使用简历分析助手!")print("输入 'quit' 或 'exit' 结束对话")while True:# Get user inputuser_input = input("\n请输入您的问题: ").strip()# Check if user wants to exitif user_input.lower() in ['quit', 'exit']:print("感谢使用,再见!")breakif user_input:try:# Get the responseresult = qa.run(user_input)print("\n回答:")print(result)except Exception as e:print(f"发生错误: {str(e)}")continueif __name__ == "__main__":chat_loop()

相关文章:

RAG(Retrieval-Augmented Generation,检索增强生成)流程

目录 一、知识文档的准备二、OCR转换三、分词处理四、创建向量数据库五、初始化语言聊天模型1.prompt2.检索链3.对话 完整代码 知识文档的准备:首先需要准备知识文档,这些文档可以是多种格式,如Word、TXT、PDF等。使用文档加载器或多模态模型…...

【Python学习(六)——While、for、循环控制、指数爆炸】

Python学习(六)——While、for、循环控制、指数爆炸 本文介绍了While、for、循环控制、指数爆炸,仅作为本人学习时记录,感兴趣的初学者可以一起看看,欢迎评论区讨论,一起加油鸭~~~ 心中默念:Py…...

解释一下:运放的输入失调电流

输入失调电流 首先看基础部分:这就是同相比例放大器 按照理论计算,输入VIN=0时,输出VOUT应为0,对吧 仿真与理论差距较大,有200多毫伏的偏差,这就是输入偏置电流IBIAS引起的,接着看它的定义 同向和反向输入电流的平均值,也就是Ib1、Ib2求平均,即(Ib1+Ib2)/2 按照下面…...

力扣hot100——二分查找

35. 搜索插入位置 class Solution { public:int searchInsert(vector<int>& a, int x) {if (a[0] > x) return 0;int l 0, r a.size() - 1;while (l < r) {int mid (l r 1) / 2;if (a[mid] < x) l mid;else r mid - 1;}if (a[l] x) return l;else …...

PHP 使用集合 处理复杂数据 提升开发效率

在 PHP 中&#xff0c;集合&#xff08;Collections&#xff09;通常是通过数组或专门的集合类来实现的。 集合&#xff08;Collection&#xff09;是一种高级的数据结构&#xff0c;可以提供比普通数组更强大的操作和功能&#xff0c;特别是当你需要更复杂的数据处理时。 La…...

Unity 对Sprite或者UI使用模板测试扣洞

新建两个材质球&#xff1a; 选择如下材质 设置如下参数&#xff1a; 扣洞图片或者扣洞UI的材质球 Sprite或者UI的材质球 新建一个单独Hole的canvas&#xff0c;将SortOrder设置为0&#xff0c;并将原UI的canvans的SortOrder设置为1 对2DSprite则需要调整下方的参数 hole的O…...

unity学习3:如何从github下载开源的unity项目

目录 1 网上别人提供的一些github的unity项目 2 如何下载github上的开源项目呢&#xff1f; 2.1.0 下载工具 2.1.1 下载方法1 2.1.2 下载方法2&#xff08;适合内部项目&#xff09; 2.1.3 第1个项目 和第4项目 的比较 第1个项目 第2个项目 第3个项目 2.1.4 下载方法…...

PHP后执行php.exe -v命令报错并给出解决方案

文章目录 一、执行php.exe -v命令报错解决方案 一、执行php.exe -v命令报错 -PHP Warning: ‘C:\windows\SYSTEM32\VCRUNTIME140.dll’ 14.38 is not compatible with this PHP build linked with 14.41 in Unknown on line 0 解决方案 当使用PHP8.4.1时遇到VCRUNTIME140.dll…...

CDP集群安全指南-动态数据加密

[〇]关于本文 集群的动态数据加密主要指的是加密通过网络协议传输的数据&#xff0c;防止数据在传输的过程中被窃取。由于大数据涉及的主机及服务众多。你需要更具集群的实际环境来评估需要为哪些环节实施动态加密。 这里介绍一种通过Cloudera Manager 的Auto-TLS功能来为整个…...

【shell编程】报错信息:Undefined Variable(包含6种解决方法)

大家好&#xff0c;我是摇光~ 当Shell脚本报错“Undefined Variable”时&#xff0c;是未定义变量的意思。 以下是对每个可能原因及其对应详细解决方案的详细解释&#xff1a; 原因1&#xff1a;拼写错误 原因&#xff1a; 脚本中变量名的拼写在使用和定义时不一致。例如&…...

Dubbo扩展点加载机制

加载机制中已经存在的一些关键注解&#xff0c;如SPI、©Adaptive> ©Activateo然后介绍整个加载机制中最核心的ExtensionLoader的工作流程及实现原理。最后介绍扩展中使用的类动态编译的实 现原理。 Java SPI Java 5 中的服务提供商https://docs.oracle.com/jav…...

unity学习7:unity的3D项目的基本操作: 坐标系

目录 学习参考 1 unity的坐标系 1.1 左手坐标系 1.2 左手坐标系和右手坐标系的区别 1.3 坐标系的原点(0,0,0) 2 坐标系下的具体xyz坐标 2.1 position这里的具体xyz坐标值 2.2 父坐标 2.3 世界坐标和相对坐标 2.3.1 世界坐标 2.3.2 相对坐标 2.4 父物体&#xff0c;…...

PyTorch框架——基于深度学习EfficientDeRain神经网络AI去雨滴图像增强系统

第一步&#xff1a;EfficientDeRain介绍 EfficientDeRain 是一个针对单张图像去雨的开源项目&#xff0c;该项目由清华大学的研究团队提出&#xff0c;主要用于处理图像中的雨水干扰&#xff0c;恢复图像的真实场景 核心功能 图像去雨&#xff1a;EfficientDeRain 通过学习像素…...

写一个类模板三个模板参数K,V,M,参数是函数(函数参数、lambda传参、函数指针)

cal是类的成员函数。cal的3个入参是func1(K&#xff09;&#xff0c;func2&#xff08;K&#xff0c;V&#xff09;&#xff0c;func3(K&#xff0c;V&#xff0c;M)&#xff0c;请写出cal&#xff0c;并在main函数中调用cal 在您给出的要求中&#xff0c;cal成员函数并不直接…...

国内Ubuntu环境Docker部署Stable Diffusion入坑记录

国内Ubuntu环境Docker部署Stable Diffusion入坑记录 本文旨在记录使用dockerpython进行部署 stable-diffusion-webui 项目时遇到的一些问题&#xff0c;以及解决方案&#xff0c;原项目地址: https://github.com/AUTOMATIC1111/stable-diffusion-webui 问题一览&#xff1a; …...

现代光学基础6

总结自老师的ppt yt6 半导体激光器开卷考试学习资料 目录 半导体激光器边发射半导体激光器垂直腔面发射激光器&#xff08;VCSEL&#xff09;激光产生条件&#xff08;激光原理&#xff09;半导体激光器的水容器模型有源半导体区域类型和载流子注入发光二极管&#xff08;L…...

解决HBuilderX报错:未安装内置终端插件,是否下载?或使用外部命令行打开。

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 错误描述 在HBuilderX中执行npm run build总是提醒下载插件&#xff1b;图示如下&#xff1a; 但是&#xff0c;下载总是失败。运行项目时候依然弹出上述提醒。 解决方案 …...

基于Java的超级玛丽游戏的设计与实现【源码+文档+部署讲解】

目 录 1、绪论 1.1背景以及现状 1.2 Java语言的特点 1.3 系统运行环境及开发软件&#xff1a; 1.4 可行性的分析 1.4.1 技术可行性 1.4.2 经济可行性 1.4.3 操作可行性 2、 需求分析 2.1 用户需求分析 2.2功能需求分析 2.3界面设计需求分析…...

Spring Boot项目中使用单一动态SQL方法可能带来的问题

1. 查询计划缓存的影响 深入分析 数据库系统通常会对常量SQL语句进行编译并缓存其执行计划以提高性能。对于动态生成的SQL语句&#xff0c;由于每次构建的SQL字符串可能不同&#xff0c;这会导致查询计划无法被有效利用&#xff0c;从而需要重新解析、优化和编译&#xff0c;…...

conan从sourceforge.net下载软件失败

从sourceforge.net下载软件&#xff0c;经常会没有开始下载就返回了。 原因是&#xff1a; 自动选择的镜像站不能打开。 在浏览器中&#xff0c;我们可以手动选择站点尝试&#xff0c;但是conan就不行了。 手动选择一个站点&#xff0c;能够有文件保存窗口弹出&#xff0c;之后…...

通过爬虫方式实现视频号助手发布视频

1、将真实的cookie贴到解压后目录中cookie.txt文件里,修改python代码里的user_agent和video_path, cover_path等变量的值,最后运行python脚本即可; 2、运行之前根据import提示安装一些常见依赖,比如requests等; 3、2025年1月份最新版; 代码如下: import json import…...

springboot525基于MVC框架自习室管理和预约系统设计与实现(论文+源码)_kaic

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装自习室管理和预约系统软件来发挥其高效地信息处理的作用&am…...

“大数据+职业本科”:VR虚拟仿真实训室的发展前景

在新时代背景下&#xff0c;随着科技的飞速进步和产业结构的不断升级&#xff0c;职业教育正迎来前所未有的变革。“大数据职业本科”的新型教育模式&#xff0c;结合VR&#xff08;虚拟现实&#xff09;技术的广泛应用&#xff0c;为实训教学开辟了崭新的道路&#xff0c;尤其…...

Python 数据可视化的完整指南

目录 一、为什么选择 Python 进行数据可视化? 二、常用 Python 可视化库及其特点 三、常用图表类型及其代码示例 折线图:用于展示数据随时间或其他连续变量的变化趋势。 柱状图:用于比较不同类别的数据大小。 散点图:用于展示两个变量之间的关系,并发现数据中的模式…...

滑动窗口。

1456 定长子串中元音的最大数目 采用滑动窗口。每次移动一个位置&#xff0c;判断当前窗口内的子串内目标元素的个数&#xff0c;若比之前更大就更新结果。 如何判断是否更新结果&#xff1f;也即&#xff0c;如何判断当前窗口内所含目标元素个数&#xff0c;是否为遍历到这个…...

【Python运维】用Python和Ansible实现高效的自动化服务器配置管理

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着云计算和大规模数据中心的兴起,自动化配置管理已经成为现代IT运维中不可或缺的一部分。通过自动化,企业可以大幅提高效率,降低人为错…...

Chapter4.2:Normalizing activations with layer normalization

文章目录 4 Implementing a GPT model from Scratch To Generate Text4.2 Normalizing activations with layer normalization 4 Implementing a GPT model from Scratch To Generate Text 4.2 Normalizing activations with layer normalization 通过层归一化&#xff08;La…...

EA工具学习使用笔记 ———— 插入图片或UI

文章目录 介绍导入使用方法一方法二方法3介绍 在使用EA的过程中,我们可以EA的图像管理器自定义图像,从而创建有吸引力的图表。也可以通过图像管理器快速扩展可用图像的范围。方法是导入一个捆绑的基于uml的图像剪辑艺术集合作为图像库文件。EA的图像库下载链接为: 导入 Doc…...

[2474].第04节:Activiti官方画流程图方式

我的后端学习大纲 Activiti大纲 1.安装位置&#xff1a; 2.启动&#xff1a;...

JVM和异常

Java 虚拟机&#xff08;Java Virtual Machine&#xff0c;简称 JVM&#xff09; 概述 JVM 是运行 Java 字节码的虚拟计算机&#xff0c;它是 Java 程序能够实现 “一次编写&#xff0c;到处运行&#xff08;Write Once, Run Anywhere&#xff09;” 特性的关键所在。Java 程…...