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

基于Langchain的txt文本向量库搭建与检索

这里的源码主要来自于Langchain-ChatGLM中的向量库部分,做了一些代码上的修改和封装,以适用于基于问题包含数据库表描述的txt文件(文件名为库表名,文件内容为库表中的字段及描述)对数据库表进行快速检索。

中文分词类

splitter.py

from langchain.text_splitter import CharacterTextSplitter
import re
from typing import Listclass ChineseTextSplitter(CharacterTextSplitter):def __init__(self, pdf: bool = False, sentence_size: int = 100, **kwargs):super().__init__(**kwargs)self.pdf = pdfself.sentence_size = sentence_sizedef split_text1(self, text: str) -> List[str]:if self.pdf:text = re.sub(r"\n{3,}", "\n", text)text = re.sub('\s', ' ', text)text = text.replace("\n\n", "")sent_sep_pattern = re.compile('([﹒﹔﹖﹗。!?]["’”」』]{0,2}|(?=["‘“「『]{1,2}|$))')  # del :;sent_list = []for ele in sent_sep_pattern.split(text):if sent_sep_pattern.match(ele) and sent_list:sent_list[-1] += eleelif ele:sent_list.append(ele)return sent_listdef split_text(self, text: str) -> List[str]:   ##此处需要进一步优化逻辑if self.pdf:text = re.sub(r"\n{3,}", r"\n", text)text = re.sub('\s', " ", text)text = re.sub("\n\n", "", text)text = re.sub(r'([;;!?。!?\?])([^”’])', r"\1\n\2", text)  # 单字符断句符text = re.sub(r'(\.{6})([^"’”」』])', r"\1\n\2", text)  # 英文省略号text = re.sub(r'(\…{2})([^"’”」』])', r"\1\n\2", text)  # 中文省略号text = re.sub(r'([;;!?。!?\?]["’”」』]{0,2})([^;;!?,。!?\?])', r'\1\n\2', text)# 如果双引号前有终止符,那么双引号才是句子的终点,把分句符\n放到双引号后,注意前面的几句都小心保留了双引号text = text.rstrip()  # 段尾如果有多余的\n就去掉它# 很多规则中会考虑分号;,但是这里我把它忽略不计,破折号、英文双引号等同样忽略,需要的再做些简单调整即可。ls = [i for i in text.split("\n") if i]for ele in ls:if len(ele) > self.sentence_size:ele1 = re.sub(r'([,,]["’”」』]{0,2})([^,,])', r'\1\n\2', ele)ele1_ls = ele1.split("\n")for ele_ele1 in ele1_ls:if len(ele_ele1) > self.sentence_size:ele_ele2 = re.sub(r'([\n]{1,}| {2,}["’”」』]{0,2})([^\s])', r'\1\n\2', ele_ele1)ele2_ls = ele_ele2.split("\n")for ele_ele2 in ele2_ls:if len(ele_ele2) > self.sentence_size:ele_ele3 = re.sub('( ["’”」』]{0,2})([^ ])', r'\1\n\2', ele_ele2)ele2_id = ele2_ls.index(ele_ele2)ele2_ls = ele2_ls[:ele2_id] + [i for i in ele_ele3.split("\n") if i] + ele2_ls[ele2_id + 1:]ele_id = ele1_ls.index(ele_ele1)ele1_ls = ele1_ls[:ele_id] + [i for i in ele2_ls if i] + ele1_ls[ele_id + 1:]id = ls.index(ele)ls = ls[:id] + [i for i in ele1_ls if i] + ls[id + 1:]return ls

faiss向量库类

myfaiss.py

from langchain.vectorstores import FAISS
from langchain.vectorstores.base import VectorStore
from langchain.vectorstores.faiss import dependable_faiss_import
from typing import Any, Callable, List, Dict
from langchain.docstore.base import Docstore
from langchain.docstore.document import Document
import numpy as np
import copy
import osclass MyFAISS(FAISS, VectorStore):def __init__(self,embedding_function: Callable,index: Any,docstore: Docstore,index_to_docstore_id: Dict[int, str],normalize_L2: bool = False,):super().__init__(embedding_function=embedding_function,index=index,docstore=docstore,index_to_docstore_id=index_to_docstore_id,normalize_L2=normalize_L2)def seperate_list(self, ls: List[int]) -> List[List[int]]:lists = []ls1 = [ls[0]]source1 = self.index_to_docstore_source(ls[0])for i in range(1, len(ls)):if ls[i - 1] + 1 == ls[i] and self.index_to_docstore_source(ls[i]) == source1:ls1.append(ls[i])else:lists.append(ls1)ls1 = [ls[i]]source1 = self.index_to_docstore_source(ls[i])lists.append(ls1)return listsdef similarity_search_with_score_by_vector(self, embedding: List[float], k: int = 4) -> List[Document]:faiss = dependable_faiss_import()# (1,1024)vector = np.array([embedding], dtype=np.float32)# 默认FALSEif self._normalize_L2:faiss.normalize_L2(vector)# shape均为(1, k)scores, indices = self.index.search(vector, k)docs = []id_set = set()# 存储关键句keysentences = []# 遍历找到的k个最近相关文档的索引# top-k是第一次的筛选条件,score是第二次的筛选条件for j, i in enumerate(indices[0]):if i in self.index_to_docstore_id:_id = self.index_to_docstore_id[i]# 执行接下来的操作else:continue# index→id→contentdoc = self.docstore.search(_id)doc.metadata["score"] = int(scores[0][j])docs.append(doc)# 其实存的都是indexid_set.add(i)docs.sort(key=lambda doc: doc.metadata['score'])return docs

嵌入检索类

embedder.py

from langchain.embeddings.huggingface import HuggingFaceEmbeddings
from langchain.document_loaders import TextLoader
from embeddings.splitter import ChineseTextSplitter
from embeddings.myfaiss import MyFAISS
import os
import torch
from config import *def torch_gc():if torch.cuda.is_available():# with torch.cuda.device(DEVICE):torch.cuda.empty_cache()torch.cuda.ipc_collect()elif torch.backends.mps.is_available():try:from torch.mps import empty_cacheempty_cache()except Exception as e:print(e)print("如果您使用的是 macOS 建议将 pytorch 版本升级至 2.0.0 或更高版本,以支持及时清理 torch 产生的内存占用。")class Embedder:def __init__(self, config):self.model = HuggingFaceEmbeddings(model_name="/home/df1500/NLP/LLM/pretrained_model/WordEmbeddings/"+config.emb_model,model_kwargs={'device': 'cuda'})self.config = configself.create_vector_score()self.vector_store = MyFAISS.load_local(self.config.db_vs_path, self.model)def load_file(self, filepath):# 对文件分词if filepath.lower().endswith(".txt"):loader = TextLoader(filepath, autodetect_encoding=True)textsplitter = ChineseTextSplitter(pdf=False, sentence_size=self.config.sentence_size)docs = loader.load_and_split(textsplitter)else:raise Exception("{}文件不是txt格式".format(filepath))return docsdef txt2vector_store(self, filepaths):# 批量建立知识库docs = []for filepath in filepaths:try:docs += self.load_file(filepath)except Exception as e:raise Exception("{}文件加载失败".format(filepath))print("文件加载完毕,正在生成向量库")vector_store = MyFAISS.from_documents(docs, self.model)torch_gc()vector_store.save_local(self.config.db_vs_path)def create_vector_score(self):if "index.faiss" not in os.listdir(self.config.db_vs_path):filepaths = os.listdir(self.config.db_doc_path)filepaths = [os.path.join(self.config.db_doc_path, filepath) for filepath in filepaths]self.txt2vector_store(filepaths)print("向量库已建立成功")def get_topk_db(self, query):related_dbs_with_score = self.vector_store.similarity_search_with_score(query, k=self.config.sim_k)topk_db = [{'匹配句': db_data.page_content, '数据库': os.path.basename(db_data.metadata['source'])[:-4], '得分': db_data.metadata['score']} for db_data in related_dbs_with_score]return topk_db

测试代码

Config是用来传参的类,这里略去定义

if __name__ == '__main__':Conf = Config()configs = Conf.get_config()embedder = Embedder(configs)query = "公司哪个月的出勤率是最高的?"topk_db = embedder.get_topk_db(query)print(topk_db)

相关文章:

基于Langchain的txt文本向量库搭建与检索

这里的源码主要来自于Langchain-ChatGLM中的向量库部分,做了一些代码上的修改和封装,以适用于基于问题和包含数据库表描述的txt文件(文件名为库表名,文件内容为库表中的字段及描述)对数据库表进行快速检索。 中文分词…...

vue2-router

1.基础 1.1.安装 npm install vue-router3.6.5 1.2.引入 import VueRouter from "vue-router" 1.3.注册 Vue.use(VueRouter) 1.4.创建 const router new VueRouter({routes: [{path:/page1, page1},{path:/page2, page2}]} ) 1.5.引用 new Vue({render: h >…...

css新闻链接案例

利用html和css构建出新闻链接案例,使用渐变色做出背景色变化 background: linear-gradient(to bottom, rgb(137, 210, 251), rgb(238, 248, 254), white); 利用背景图片,调整位置完成 dd { height: 28px; line-height: 28px; background-image: url(./图…...

Android wifi连接和获取IP分析

wifi 连接&获取IP 流程图 代码流程分析 一、关联阶段 1. WifiSettings.submit – > WifiManager WifiSettings 干的事情比较简单,当在dialog完成ssid 以及密码填充后,直接call WifiManager save 即可WifiManager 收到Save 之后,就开…...

MLIR笔记(5)

4.3.4. 图区域 在MLIR中,区域里类似图的语义由RegionKind::Graph来表示。对没有控制流的并发语义,以及通用有向图数据结构的建模,图区域是合适的。图区域适用于表示耦合值之间的循环关系,这些关系没有基本的序。例如,…...

abapgit 安装及使用

abapgit 需求 SA[ BASIS 版本 702 及以上 版本查看路径如下: 安装步骤如下: 1. 下载abapgit 独立版本 程序 链接如下:raw.githubusercontent.com/abapGit/build/main/zabapgit_standalone.prog.abap 2.安装开发版本 2.1 在线安装 前置条…...

园区无线覆盖方案(智慧园区综合解决方案)

​ 李经理正苦恼头疼的工业园区数字化改造项目。近年企业快速增长,园区内Argent工业设备激增,IT部门应接不暇。为确保生产系统稳定运行,IT管理团队经过反复摸索,决定进行全面的数字化升级。然而改造之艰巨远超想象——混杂的接入环境、复杂的专线部署、长达数月的建设周期,种种…...

配置中心--Spring Cloud Config

目录 概述 环境说明 步骤 创建远端git仓库 准备配置文件 配置中心--服务端 配置中心--客户端 配置中心的高可用 配置中心--服务端 配置中心--客户端 消息总线刷新配置 配置中心--服务端 配置中心--客户端 概述 因为微服务架构有很多个服务,手动一个一…...

笔记-模拟角频率和数字角频率的关系理解

先建议阅读前人此文(点击这里),有助于理解。 模拟频率:f 模拟角频率:Ω 数字角频率:ω 其中:在模拟信号中Ω 2πf 正弦波表示:sin(2πft) sin(Ωt) 数字信号就是离散的&#xff…...

Zookeeper+Kafka集群

注:本章使用的Kafka为2.7.0版本 Zookeeper概述 1.Zookeeper定义 Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。 2.Zookeeper工作机制 Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理…...

Sunshine+Moonlight+Android手机串流配置(局域网、无手柄)

目录 前言Sunshine(服务端)ApplicationConfigurationGeneralAdvance Moonlight(客户端)配对打开虚拟手柄串流按键调整退出串流 原神,启动! 前言 写这篇文章单纯是因为搜来搜去没有很符合我需求的教程&#…...

从顺序表中删除具有最小值的元素(假设唯一) 并由函数返回被删元素的值。空出的位 置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。

题目描述:从顺序表中删除具有最小值的元素(假设唯一) 并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。 bool DeleteMin(SqList &L,int &min){if(L.length 0)return false;min L…...

详解—[C++ 数据结构]—AVL树

目录 一.AVL树的概念 二、AVL树节点的定义 三、AVL树的插入 3.1插入方法 四、AVL树的旋转 1. 新节点插入较高左子树的左侧---左左:右单旋 2. 新节点插入较高右子树的右侧---右右:左单旋 3.新节点插入较高左子树的右侧---左右:先左单旋…...

卷积神经网络(CNN):乳腺癌识别.ipynb

文章目录 一、前言一、设置GPU二、导入数据1. 导入数据2. 检查数据3. 配置数据集4. 数据可视化 三、构建模型四、编译五、训练模型六、评估模型1. Accuracy与Loss图2. 混淆矩阵3. 各项指标评估 一、前言 我的环境: 语言环境:Python3.6.5编译器&#xf…...

有文件实体的后门无文件实体的后门rootkit后门

有文件实体后门和无文件实体后门&RootKit后门 什么是有文件的实体后门: 在传统的webshell当中,后门代码都是可以精确定位到某一个文件上去的,你可以rm删除它,可以鼠标右键操作它,它是有一个文件实体对象存在的。…...

GPT实战系列-大模型训练和预测,如何加速、降低显存

GPT实战系列-大模型训练和预测,如何加速、降低显存 不做特别处理,深度学习默认参数精度为浮点32位精度(FP32)。大模型参数庞大,10-1000B级别,如果不注意优化,既耗费大量的显卡资源,…...

SQL Sever 基础知识 - 数据排序

SQL Sever 基础知识 - 二 、数据排序 二 、对数据进行排序第1节 ORDER BY 子句简介第2节 ORDER BY 子句示例2.1 按一列升序对结果集进行排序2.2 按一列降序对结果集进行排序2.3 按多列对结果集排序2.4 按多列对结果集不同排序2.5 按不在选择列表中的列对结果集进行排序2.6 按表…...

vscode配置使用 cpplint

标题安装clang-format和cpplint sudo apt-get install clang-format sudo pip3 install cpplint标题以下settings.json文件放置xxx/Code/User目录 settings.json {"sync.forceDownload": false,"workbench.sideBar.location": "right","…...

C++ 系列 第四篇 C++ 数据类型上篇—基本类型

系列文章 C 系列 前篇 为什么学习C 及学习计划-CSDN博客 C 系列 第一篇 开发环境搭建(WSL 方向)-CSDN博客 C 系列 第二篇 你真的了解C吗?本篇带你走进C的世界-CSDN博客 C 系列 第三篇 C程序的基本结构-CSDN博客 前言 面向对象编程(OOP)的…...

C++ 指针详解

目录 一、指针概述 指针的定义 指针的大小 指针的解引用 野指针 指针未初始化 指针越界访问 指针运算 二级指针 指针与数组 二、字符指针 三、指针数组 四、数组指针 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 指针与数组 一维数组 字符数组…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

图解JavaScript原型:原型链及其分析 | JavaScript图解

​​ 忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...

6.9-QT模拟计算器

源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...

负载均衡器》》LVS、Nginx、HAproxy 区别

虚拟主机 先4&#xff0c;后7...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学

一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件&#xff0c;其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时&#xff0c;价带电子受激发跃迁至导带&#xff0c;形成电子-空穴对&#xff0c;导致材料电导率显著提升。…...

LeetCode - 148. 排序链表

目录 题目 思路 基本情况检查 复杂度分析 执行示例 读者可能出的错误 正确的写法 题目 148. 排序链表 - 力扣&#xff08;LeetCode&#xff09; 思路 链表归并排序采用"分治"的策略&#xff0c;主要分为三个步骤&#xff1a; 分割&#xff1a;将链表从中间…...

OCC笔记:TDF_Label中有多个相同类型属性

注&#xff1a;OCCT版本&#xff1a;7.9.1 TDF_Label中有多个相同类型的属性的方案 OCAF imposes the restriction that only one attribute type may be allocated to one label. It is necessary to take into account the design of the application data tree. For exampl…...

Go 并发编程基础:select 多路复用

select 是 Go 并发编程中非常强大的语法结构&#xff0c;它允许程序同时等待多个通道操作的完成&#xff0c;从而实现多路复用机制&#xff0c;是协程调度、超时控制、通道竞争等场景的核心工具。 一、什么是 select select 类似于 switch 语句&#xff0c;但它用于监听多个通…...