基于LangChain框架搭建知识库

基于LangChain框架搭建知识库

  • 说明
  • 流程
    • 1.数据加载
    • 2.数据清洗
    • 3.数据切分
    • 4.获取向量
    • 5.向量库保存到本地
    • 6.向量搜索
    • 7.汇总调用

说明

本文使用openai提供的embedding模型作为框架基础模型,知识库的搭建目的就是为了让大模型减少幻觉出现,实现起来也很简单,假如你要做一个大模型的客服问答系统,那么就把历史客服问答数据整理好,先做数据处理,在做数据向量化,最后保存到向量库中就可以了,下面文章中只是一个简单工作流程,只能用来参考,希望对大家有所帮助!

流程

上传知识库的文档不限于txt,pdf,markdown等数据格式,不同的数据格式用不同的方法来处理,文章内仅使用pdf文件做测试

1.数据加载

def load_data():from langchain.document_loaders.pdf import PyMuPDFLoader# 本地pdf文档路径loader = PyMuPDFLoader("./knowledge_db/pumkin_book/pumpkin_book.pdf")pdf_pages = loader.load()print(f"载入后的变量类型为:{type(pdf_pages)},", f"该 PDF 一共包含 {len(pdf_pages)} 页")pdf_page = pdf_pages[1]page_content = pdf_page.page_contentprint(f"每一个元素的类型:{type(pdf_page)}.",f"该文档的描述性数据:{pdf_page.metadata}",f"查看该文档的内容:\n{pdf_page.page_content}",sep="\n------\n")return page_content,pdf_pages

2.数据清洗

def clean_data(pdf_content):# 匹配非中文字符和换行符pattern = re.compile(r'[^\u4e00-\u9fff](\n)[^\u4e00-\u9fff]', re.DOTALL)# 将匹配到的换行符替换为空字符串new_pdf_content = re.sub(pattern, lambda match: match.group(0).replace('\n', ''), pdf_content)# 去除。和空格符号new_pdf_content = new_pdf_content.replace('。', '').replace(' ', '')return new_pdf_content

3.数据切分

def split_data(pdf_pages,new_pdf_content):'''* RecursiveCharacterTextSplitter 递归字符文本分割RecursiveCharacterTextSplitter 将按不同的字符递归地分割(按照这个优先级["\n\n", "\n", " ", ""]),这样就能尽量把所有和语义相关的内容尽可能长时间地保留在同一位置RecursiveCharacterTextSplitter需要关注的是4个参数:* separators - 分隔符字符串数组* chunk_size - 每个文档的字符数量限制* chunk_overlap - 两份文档重叠区域的长度* length_function - 长度计算函数'''from langchain.text_splitter import RecursiveCharacterTextSplitter# 知识库中单段文本长度CHUNK_SIZE = 500# 知识库中相邻文本重合长度OVERLAP_SIZE = 50# 使用递归字符文本分割器text_splitter = RecursiveCharacterTextSplitter(chunk_size=CHUNK_SIZE,chunk_overlap=OVERLAP_SIZE)text_splitter.split_text(new_pdf_content[0:1000])split_docs = text_splitter.split_documents(pdf_pages)print(f"切分后的文件数量:{len(split_docs)}")print(f"切分后的字符数(可以用来大致评估 token 数):{sum([len(doc.page_content) for doc in split_docs])}")return split_docs

4.获取向量

def gpt_config():import httpx# 使用httpx设置代理proxy = 'http://127.0.0.1:8080' # 修改为自己的代理地址proxies = {'http://': proxy, 'https://': proxy}http_client = httpx.Client(proxies=proxies, verify=True)return http_clientdef get_vector(split_docs):# from langchain.embeddings import OpenAIEmbeddingsfrom langchain_openai import OpenAIEmbeddingsfrom langchain.vectorstores.chroma import Chromafrom dotenv import load_dotenv, find_dotenv# 获取key_ = load_dotenv(find_dotenv()) # 可注释api_key = os.environ.get("OPENAI_API_KEY")http_client = gpt_config()# 官网有提供3个embedding模型,按需选择embedding = OpenAIEmbeddings(model="text-embedding-3-small",openai_api_key=api_key,http_client=http_client)# 保存路径persist_directory = './vector_db/chroma'vectordb = Chroma.from_documents(documents=split_docs[:20],  # 为了速度,只选择前 20 个切分的 doc 进行生成embedding=embedding,persist_directory=persist_directory  # 允许我们将persist_directory目录保存到磁盘上)return vectordb

5.向量库保存到本地

def save_vector(vectordb):vectordb.persist()print(f"向量库中存储的数量:{vectordb._collection.count()}")

6.向量搜索

def search_vector(vectordb):question = '什么是机器学习'# 余弦相似度搜索search_result = vectordb.similarity_search(question, k=2) # k表示返回的相似文档数量print(f"检索到的内容数:{len(search_result)}")for i, sim_doc in enumerate(search_result):print(f"检索到的第{i}个内容: \n{sim_doc.page_content[:200]}", end="\n--------------\n")# MMR搜索# 核心思想是在已经选择了一个相关性高的文档之后,再选择一个与已选文档相关性较低但是信息丰富的文档。这样可以在保持相关性的同时,增加内容的多样性,避免过于单一的结果。mmr_docs = vectordb.max_marginal_relevance_search(question, k=2)for i, sim_doc in enumerate(mmr_docs):print(f"MMR 检索到的第{i}个内容: \n{sim_doc.page_content[:200]}", end="\n--------------\n")

7.汇总调用

def main_task():# 加载数据pdf_content,pdf_pages = load_data()# 数据清洗new_pdf_content = clean_data(pdf_content)# 切分数据split_docs = split_data(pdf_pages,new_pdf_content)# 获取向量vectordb = get_vector(split_docs)# 将向量库内容保存到本地文件中# save_vector(vectordb)# 向量搜索search_vector(vectordb)

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

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

相关文章

Ocam:高效录屏,屏幕录制最佳?

名人说::一点浩然气,千里快哉风。 ——苏轼 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、软件介绍1、Ocam2、核心特点 二、下载安装1、下载2、安装 三、使用方法 很高兴你…

【5】apollo编写python节点步骤及实例

在workspace/modules下新建包buildtool create --template component modules/test_one 编译包 buildtool build -p modules/test_two/ 增加自己的proto消息 在刚才自动生成的proto文件里面添加自己定义的消息,记得重新编译. syntax "proto2";package apollo;…

【python】美妆类商品跨境电商数据分析(源码+课程论文+数据集)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

使用RedisShake迁移自建Redis数据至阿里云Redis

一、前言 最近有个需求,需要把自建的Redis数据迁移至阿里云的Redis RDS。阿里云有官方的数据传输服务DTS(Data Transmission Service)。全量迁移是免费的,但增量迁移需要按量收费,遂放弃。经过一番搜索,发…

数据库的概念-数据库、数据库管理系统、数据库系统、数据库管理员、数据库设计人员、开发管理使用数据库系统的人员

一、数据库(DB) 1、数据库就是存储数据的仓库,只不过这个仓库是在计算机存储设备上 2、严格的说,数据库是长期存储在计算机内、有组织的、统一管理的、可共享的相关数据的集合 3、数据库应是为一个特定目标而设计、构建并装入数…

ClickHouse备份方案

ClickHouse备份方案主要包括以下几种方法: 一、使用clickhouse-backup工具: (参考地址:https://blog.csdn.net/qq_43510111/article/details/136570850) **安装与配置:**首先从GitHub获取clickhouse-bac…

利用MSSQL模拟提权

点击星标,即时接收最新推文 本文选自《内网安全攻防:红队之路》 扫描二维码五折购书 利用MSSQL模拟提权 在MS SQL数据库,可以使用EXECUTE AS语句,以其他用户的上下文执行SQL查询。需要注意的是只有明确授予模拟(Impers…

38.MessageToMessageCodec线程安全可被共享Handler

handler被注解@Sharable修饰的。 这样的handler,创建一个实例就够了。例如: ByteToMessageCodec的子类不能被@Sharable修饰 如果自定义类是MessageToMessageCodec的子类就是线程共享的,可以被@Sharable修饰的 package com.xkj.protocol;import com.xkj.message.Message; i…

Go日常分享 - error类型是指针类型吗?

背景 这个问题的产生来源于小泉在开发rpc接口时返回error遇到的问题,开发时想在defer里对err进行最终的统一处理赋值,发现外层接收一直都未生效。问题可以简化为成下面的小demo。 func returnError() error {var err errordefer func() {//err errors…

在 Oracle Linux 8.9 上安装中文和日文字体的完整指南

在 Oracle Linux 8.9 上安装中文和日文字体的完整指南 在 Oracle Linux 8.9 上安装中文和日文字体的完整指南前提条件安装步骤1. 更新系统2. 安装字体包安装中文字体安装日文字体 3. 安装字体配置工具4. 更新字体缓存5. 验证安装 可能遇到的问题及解决方案结语 在 Oracle Linux…

(一)SvelteKit教程:hello world

(一)SvelteKit教程:hello world sveltekit 的官方教程,在这里:Creating a project • Docs • SvelteKitCreating a project • Docs • SvelteKit 我们可以按照如下的步骤来创建一个项目: npm create s…

CentOs7 安装单机版redis

1.安装依赖 redis是由C语言开发,因此安装之前必须要确保服务器已经安装了gcc,可以通过如下命令查看机器是否安装: gcc -v如果没有安装则通过以下命令安装: yum install -y gcc如果安装gcc依赖报错则执行yum升级命令 # 先执行升…

NSIS 入门教程 (三)

引言 在教程的第二部分中,我们为安装程序增加了一个卸载程序,并查看了一些其他的向导页面以及安装部分的选择。第三部分的目标是使安装程序的外观更加现代化。 更现代的外观 为了给安装程序一个更现代的外观,我们要启用现代用户界面。要提…

Shell编辑之条件语句

一,条件测试操作 1:文件测试 文件测试操作用来检查文件的各种属性,如文件是否存在、是否可读、是否为空等。常用的文件测试操作符包括: -e 文件存在性测试-f 是否为普通文件-d 是否为目录-r 是否可读-w 是否可写-x 是否可执行-s…

学懂C#编程:常用高级技术——委托(Delegate)的概念及详细使用讲解

目录 委托的概念 常用应用场景 优势 C#中的委托(Delegate)是一种引用类型,它允许你封装一个方法的引用。委托类似于函数指针,但提供了更强大和类型安全的功能。委托在C#中扮演着多重角色,常用于实现回调方法、事件…

【栈和队列】

目录 1,栈(Stack) 1.1 概念 1.2 栈的使用 1.3 栈的模拟实现 1.4 栈的应用场景 1.5 概念区分 1.6 使用链表来实现栈 2, 队列(Queue) 2.1 概念 2.2 队列的使用 2.3 队列模拟实现 3,双端队列 (Deque) 4&…

【计算机组成原理】部分题目汇总

计算机组成原理 部分题目汇总 一. 简答题 RISC和CICS 简要说明,比较异同 RISC(精简指令集)注重简单快速的指令执行,使用少量通用寄存器,固定长度指令,优化硬件性能,依赖软件(如编译…

递归调用,将源路径下所有文件文件夹复制到目标路径中.

其实代码demo很简洁&#xff0c;只是逻辑有点绕&#xff0c;主要是要一层一层调用自己&#xff0c;要清楚当前是第几层调用&#xff0c;及递归调用时进的点和出的点在哪儿&#xff0c;一切就清晰明了了。 /// <summary>/// 删除指定目录下面的所有文件和文件夹/// </s…

C++学习合集

#整理到一块&#xff0c;方便查东西&#xff0c;顺便补充一些之前没有学习到的东西# 变量 char--1字节 short--2字节 int-4字节 long--4字节 long long(int)--8字节&#xff1b;准确来说变量的大小取决于编译器&#xff0c;1字节8个二进制位&#xff0c;其中最高位为符号位…

关于Mysql 的on duplicate key update操作,导致主键不连续自增的问题

一 相关说明 在实际的开发中,经常会遇到这样的场景:若数据库里面不存在数据,则插入;若存在,则更新。在Mysql中,可以使用ON DUPLICATE KEY UPDATE,一步就能完成上述操作。简单说,就是数据库中存在某个记录时,执行这个语句会更新,而不存在这条记录时,就会插入。 需要说…