LangChain结合通义千问的自建知识库

news2025/2/3 19:09:41

LangChain结合通义千问的自建知识库

在使用了通义千问API了之后,下一步就是构建知识库文档,使用了比较有名的LangChian,最后成果将自己的txt生成了知识向量库,最后我还把自己的论文生成了一个知识向量库,然后问他我的创新点是啥,实话实说比我总结的好,我想这下回老师要是看不懂我论文的时候能不能直接,嗯,对吧,反正也是工作中用到还挺有意思的,能分享的部分我都分享出来了,然后这个是接着通专栏的第一篇的延申文档。


文章目录

  • LangChain结合通义千问的自建知识库
    • 1.文本切片
    • 2.读取本地Embedding模型
    • 3. 保存向量数据库
    • 4.检索数据库中的相似样本
    • 5.使用通义千问总结归纳
    • 6.额外补充 LangChain 使用通义模型进行流式输出
    • 7.目前发现的LangChain使用问题总结

1.文本切片

在构建知识库的过程中,文本切片是一项关键步骤,其目的在于将大型文档分解成更小、更易于管理的单元、提升检索效率

​ 使用LangChian库进行文本切分,实现代码如下,之后对关键代码进行详细介和API函数的参数介绍。

from langchain_community.document_loaders import UnstructuredFileLoader
# 旧版用法
# from langchain.document_loaders import UnstructuredFileLoader

from langchain.text_splitter import RecursiveCharacterTextSplitter

# 导入文本
loader = UnstructuredFileLoader("test.txt")
# 将文本转成 Document 对象
data = loader.load()
print(f'documents:{len(data)}')

# 初始化加载器
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
# 切割加载的 document
split_docs = text_splitter.split_documents(data)
print("split_docs size:",len(split_docs))
print(split_docs)
  • langchain_community.document_loaders

官网文档地址:https://python.langchain.com/docs/modules/data_connection/document_loaders

UnstructuredFileLoader主要用于加载文件中未结构化的文本,用于对未处理的文件进行一些预处理编码识别,格式规范化等,确保文本数据识别接下来的预处理,该函数可以用于读取txt文件,不能处理csv格式文件 csv格式文件请使用langchain_community.document_loaders.csv_loader加载

# 加载文档做处理文档的准备工作
loader = UnstructuredFileLoader("test.txt")
# 调用load发开始进行预处理的过程
data = loader.load()
  • langchain.text_splitter.RecursiveCharacterTextSplitter

RecursiveCharacterTextSplitter将使用UnstructuredFileLoader加载之后的样本进行切分,利于对长文本的精细化处理。

其中的两个主要参数chunk_sizechunk_overlap的作用如下

chunk_size:切割的最长长度,该长度的单位是字符不是token长度
chunk_overlap:切割的重叠长度

​ 以上两个参数均没有默认值需要手动设置

# 初始化加载器
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
# 切割加载的 document
split_docs = text_splitter.split_documents(data)

2.读取本地Embedding模型

​ 考虑到使用在线OpenAI 的Embedding模型消耗的Token过高,决定使用HuggingFaceEmbeddings加载离线的Embedding模型,代码如下。

from langchain_community.embeddings import HuggingFaceEmbeddings

model_name = r"bce-embedding-vase_v1"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': False}
hf = HuggingFaceEmbeddings(
    model_name=model_name,
    model_kwargs=model_kwargs,
    encode_kwargs=encode_kwargs
)

​ **其中model_name指代的不是模型名称,是包含训练好的模型在内的配置文件夹名称,在配置文件夹下面包含各类配置文件,且目前需要使用官方支持的模型,如果官方的不支持该模型,虽然在指定路径下存在着模型文件pytorch_model.bin,会出现以下警告信息,虽然程序没有报错,但是其没有成功加载模型,会提示找不到模型文件然后用平均策略创造了一个新的模型。**还有可能出现找不到配置文件等错误,后续评估不同Embedding模型的效果。

No sentence-transformers model found with name ernie-3.0-xbase-zh. Creating a new one with MEAN pooling.

​ 在可用其中使用最多的是bce-embedding-vase_v1模型,其是有道公司发布的一个embedding模型,基于pytorch框架编写,支持对中文和英文生成嵌入向量,链接网址如下,下载文件内容需要注册HuggingFace账号。

​ 网址:https://huggingface.co/maidalun1020

在这里插入图片描述

3. 保存向量数据库

​ 使用langchain_community.vectorstores.Chroma保存知识向量库,其保存的完整代码如下,关键行解释在后。

官方文档地址:https://api.python.langchain.com/en/latest/vectorstores/langchain_community.vectorstores.chroma.Chroma.html#

from langchain_community.vectorstores import Chroma
from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings
import sentence_transformers
from langchain_community.document_loaders import UnstructuredFileLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 导入文本
loader = UnstructuredFileLoader("test.txt")
data = loader.load()

# 文本切分
text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=0)
split_docs = text_splitter.split_documents(data)

model_name = r"bce-embedding-vase_v1"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': False}
embeddings = HuggingFaceEmbeddings(
    model_name=model_name,
    model_kwargs=model_kwargs,
    encode_kwargs=encode_kwargs
)

#保存向量数据库部分

# 初始化数据库
db = Chroma.from_documents(split_docs, embeddings,persist_directory="./chroma/news_test")
# 持久化
db.persist()
# 对数据进行加载
db = Chroma(persist_directory="./chroma/news_test", embedding_function=embeddings)

  • 初始化数据库

​ 使用Chroma.from_documents来初始化也就生成一个词向量数据库,他对原始文档中的数据进行处理并通过模型映射成向量 ,其中split_docs为切分之后的文本,embeddings为初始化之后的模型

db = Chroma.from_documents(split_docs, embeddings,persist_directory="./chroma/news_test")
  • 持久化

​ 在实例化了一个用于初始化向量数据库的类之后,需要调用persist函数对其进行保存,之后再使用的时候加载之前初始化得到的向量数据库即可,不需要重新初始化,也就是通过模型生成向量数据库。

db.persist()
  • 对数据进行加载

persist_directory该变量为初始化数据库中指定的路径,embedding_function表示使用的embedding模型,如果不对已经生成的向量数据库添加新的文档则不需要指定。

db = Chroma(persist_directory="./chroma/news_test", embedding_function=embeddings)

4.检索数据库中的相似样本

​ 在使用大语言模型对数据库中的内容进行总结归纳之前,需要去搜被切分的文本中哪些文本于问题相似,然后将搜索到的相似的样本和问题发给大模型大模型在根据相似样本和问题得到总结。在代码中使用到的是similarity_search其作用是需要对搜索到的相似文本进行输出的时候采用。

from langchain_community.vectorstores import Chroma
from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings
import IPython
import sentence_transformers
from langchain_community.document_loaders import UnstructuredFileLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain_community.llms import Tongyi

model_name = r"bce-embedding-vase_v1"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': False}
embeddings = HuggingFaceEmbeddings(
    model_name=model_name,
    model_kwargs=model_kwargs,
    encode_kwargs=encode_kwargs
)

db = Chroma(persist_directory="./chroma/news_test", embedding_function=embeddings)
question = "浩浩的科研笔记的原力等级"
# 寻找四个相似的样本
similarDocs = db.similarity_search(question,k=4)
print(similarDocs)

5.使用通义千问总结归纳

​ 在使用LangChain的过程中,使用langchain.chains.RetrievalQA对从向量数据库中检索出来的类似样本进行总结归纳。自建的知识库文本如下:

CSDN中浩浩的科研笔记博客的作者是陈浩,博客的地址为 www.chen-hao.blog.csdn.net。
其原力等级为5级,在其学习评价中,其技术能力超过了99.6%的同码龄作者,且超过了97.9%的研究生用户。
该博客中包含了,单片机,深度学习,数学建模,优化方法等,相关的博客信息,其中访问量最多的博客是《Arduino 让小车走实现的秘密 增量式PID 直流减速编码电机》。
其个人能力主要分布在Python,和Pytorch方面,其中python相对最为擅长,希望可以早日成为博客专家。

​ 提问问题:

浩浩的科研笔记的原力等级是多少?

​ 代码实现:

from langchain_community.vectorstores import Chroma
from langchain_community.embeddings.huggingface import HuggingFaceEmbeddings
from langchain.chains import RetrievalQA
from langchain_community.llms import Tongyi

model_name = r"bce-embedding-vase_v1"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': False}
embeddings = HuggingFaceEmbeddings(
    model_name=model_name,
    model_kwargs=model_kwargs,
    encode_kwargs=encode_kwargs
)

db = Chroma(persist_directory="./chroma/news_test", embedding_function=embeddings)

retriever = db.as_retriever()
qa = RetrievalQA.from_chain_type(llm=Tongyi(), retriever=retriever)

query = "浩浩的科研笔记的原力等级是多少?"
print(qa.run(query))

在这里插入图片描述

  • retriever = db.as_retriever()创建一个检索器,其作用是在数据库中于问题相似的样本片段,默认搜索的样本为4,其和配置详细参数参考官方文档.

​ 文档地址为:https://api.python.langchain.com/en/latest/vectorstores/langchain_community.vectorstores.chroma.Chroma.html#langchain_community.vectorstores.chroma.Chroma.as_retriever

6.额外补充 LangChain 使用通义模型进行流式输出

​ 目前位置,使用LangChain对通义千问的支持性仍然不高,官方文档的所有例程都是OpenAI模型,所以想使用多轮对话,或者流式输出等都有各种各样的BUG,其中我找到了使用流式输出的解决办法,但是依旧需要对按照好的库文件进行更改。

​ 这里是将官方的流式输出代码,换成Tongyi模型,官方代码里使用的模型是OpenAI,

from langchain.prompts import ChatPromptTemplate
from langchain_community.llms import Tongyi


llm = Tongyi(streaming=True, max_tokens=2048)

prompt = ChatPromptTemplate.from_messages(
    [("system", "你是一个专业的AI助手。"), ("human", "{query}")]
)
llm_chain = prompt | llm

ret = llm_chain.stream({"query": "你是谁?"})
for token in ret:
    print(token, end="", flush=True)
print()

​ 在使用LangChain中的Tongyi模型进行流式输出时,按照官方的代码直接运行会报一个类型错误:

TypeError: Additional kwargs key output_tokens already exists in left dict and value has unsupported type <class 'int'>.

​ 其指向的错误文件路径如下

C:\Users\Chenhao\AppData\Local\Programs\Python\Python39\lib\site-packages\langchain_core\utils\_merge.py

​ 点开文件里面内容如下,其主要作用合并两个字典,然后处理字典中键值冲突的问题,之后将该BUG在stakflow上提问,得到了回复,根据测试直接让merge_dicts返回该字典即{'input_tokens': 530, 'output_tokens': 2, 'total_tokens': 532},该BUG目前还没有修复。

from __future__ import annotations

from typing import Any, Dict


def merge_dicts(left: Dict[str, Any], right: Dict[str, Any]) -> Dict[str, Any]:
    """Merge two dicts, handling specific scenarios where a key exists in both
    dictionaries but has a value of None in 'left'. In such cases, the method uses the
    value from 'right' for that key in the merged dictionary.

    Example:
        If left = {"function_call": {"arguments": None}} and
        right = {"function_call": {"arguments": "{\n"}}
        then, after merging, for the key "function_call",
        the value from 'right' is used,
        resulting in merged = {"function_call": {"arguments": "{\n"}}.
    """
    merged = left.copy()
    for k, v in right.items():
        if k not in merged:
            merged[k] = v
        elif merged[k] is None and v:
            merged[k] = v
        elif v is None:
            continue
        elif merged[k] == v:
            continue
        elif type(merged[k]) != type(v):
            raise TypeError(
                f'additional_kwargs["{k}"] already exists in this message,'
                " but with a different type."
            )
        elif isinstance(merged[k], str):
            merged[k] += v
        elif isinstance(merged[k], dict):
            merged[k] = merge_dicts(merged[k], v)
        elif isinstance(merged[k], list):
            merged[k] = merged[k] + v
        else:
            raise TypeError(
                f"Additional kwargs key {k} already exists in left dict and value has "
                f"unsupported type {type(merged[k])}."
            )

    return merged

​ 修改之后的文件如下,由于修改的是库文件中的代码,所以会有确认提示,在修改了之后在运行上流式输出的代码即可,前提是已经申请成果,且配置好了相关的API-KEY

from __future__ import annotations

from typing import Any, Dict

def merge_dicts(left: Dict[str, Any], right: Dict[str, Any]) -> Dict[str, Any]:
    merged = {'input_tokens': 530, 'output_tokens': 2, 'total_tokens': 532}
    return merged

7.目前发现的LangChain使用问题总结

  1. LangChain对通义千问API的支持较弱,难以使用LangChain实现多轮对话,和流式输出,所有的官网文档例程都是基于OpenAI

  2. LangChain在读取文件的时候时候不能保存特殊符号例如-在被加载近文本读取器的时候被识别为非法字符转换为\n

  3. LangChain使用Hungingface查找相同样本的时候,使用的模型似乎需要官方的认可才可以,且并不容易找到对应的支持模型的名单,也就是需要自己尝试

  4. LangChain只能读取CSV还有txt,其他的需要先转成这两个格式,无法直接输入World然后读取其内容和图片。

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

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

相关文章

测试环境搭建整套大数据系统(一:基础配置,修改hostname,hosts,免密,时间同步)

一&#xff1a;使用服务器配置。 二&#xff1a;修改服务器名称hostname&#xff0c;hosts。 在 Linux 系统中&#xff0c;hostname 和 /etc/hosts 文件分别用于管理主机名和主机名解析。 在三台服务器上&#xff0c;分别执行以下命令。 vim /etc/hostnamexdso-hadoop-test-0…

Linux内核调参常用整理

一、【写在前面】 Linux内核调参是一个重要知识&#xff0c;这篇文章总结一下常见的参数用法。 调参位置在 /etc/sysctl.conf中或者sysctl.d 区别是&#xff1a; /etc/sysctl.conf 文件&#xff1a; 这是默认的主配置文件&#xff0c;包含了系统上所有的 sysctl 参数配置。所…

maven打包spring项目

常用的Maven命令如下 命令 说明mvn clean 清理Maven 项目。会删除目标路径(一般是target目录)Maven生成的打包文件,编译文件。mvn package 打包Maven项目,会生成jar 或者war文件。mvn test 执行test目录下的测试用例。mvn deploy 发布依赖到远端mvn site 生成…

Leetcode206:反转链表

一、题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表 示例&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]输入&#xff1a;head [] 输出&#xff1…

面试经典 150 题 -- 滑动窗口 (总结)

面试经典150题链接 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 209 . 长度最小的子数组 思路 : 滑动窗口的思想&#xff0c;取ij0,向后遍历j,记录前缀和[l,r]为s,如果s>target,那么左端点向右移动&#xff0c;直到s…

net 一台路由器如何让两个不同网段的终端可以通信。

# 终端设备自己设置就行了 # 路由器的设置 The device is running! #################################################### <Huawei> Feb 1 2024 21:21:09-08:00 Huawei %%01IFPDT/4/IF_STATE(l)[0]:Interface GigabitEt hernet0/0/0 has turned into UP state. <…

Linux系统——防火墙

一、防火墙的认识 引言 安全技术 入侵检测系统&#xff08;Intrusion Detection Systems&#xff09;&#xff1a;特点是不阻断任何网络访问&#xff0c;量化、定位来自内外网络的威胁情况&#xff0c;主要以提供报警和事后监督为主&#xff0c;提供有针对性的指导措施和安全…

POI word操作,如何使表格单元格文本内容垂直/水平居中(两行代码解决)

垂直居中&#xff1a;cell本身就有垂直对齐的api&#xff0c;一行代码就够。 水平居中&#xff1a;一般方式行不通&#xff0c;网上苦找了许多方式&#xff0c;代码都太长了&#xff0c;&#xff0c;忒麻烦。于是我突发奇想&#xff0c;发现可以利用paragraph的水平居中对齐方…

Flask 入门3:Flask 请求上下文与请求

1. 前言 Flask 在处理请求与响应的过程&#xff1a; 首先我们从浏览器发送一个请求到服务端&#xff0c;由 Flask 接收了这个请求以后&#xff0c;这个请求将会由路由系统接收。然后在路由系统中&#xff0c;还可以挂入一些 “勾子”&#xff0c;在进入我们的 viewFunction …

小白水平理解面试经典题目_数组类Leetcode 412. Fizz Buzz【数学解法】

412 FizzBuzz 小白渣翻译&#xff1a; 给定一个整数 n &#xff0c;返回一个字符串数组 answer &#xff08;从 1 开始索引&#xff09;&#xff0c;其中&#xff1a; answer[i] “FizzBuzz” 如果 i 能被 3 和 5 整除。answer[i] “Fizz” 如果 i 能被 3 整除。answer[i]…

【gulp+jq+html】添加环境变量,并在js中使用(判断环境,更改api接口域名)+ 附gulpfile.js代码

参考博文&#xff1a; gulp分离环境 gulp中如何配置环境变量 gulp环境变量配置 1、安装cross-env插件 npm install cross-env -d2、package.json更改scripts "scripts": {"clean": "gulp clean","serve:test": "cross-env NODE…

IP协议(2) 和 数据链路层协议基础

IP协议续 1.路由选择 在复杂的网络结构中,我们需要找到一个通往终点的路线,这就是路由选择 举个例子:我们在没有手机导航之前,想去一个地方得是到一个地方问一下路的方式最终找到目的地 路由的过程,其实就是样子问路的过程 1.当IP数据包到达路由器的时候,会查看目的IP 2.路由器…

HAL库配置PWM模式

一、什么是PWM 脉冲宽度调制(PWM)&#xff0c;是英文“Pulse Width Modulation”的缩写&#xff0c;简称脉宽调制。通过控制高低电平在一个周期内的占比从而输出一定的电压。 向上计数原理介绍 ​PWM的一个周期 定时器从0开始向上计数 当0-t1段,定时器计数器TIMx_CNT值小于…

Springboot-前后端分离——第三篇(三层架构与控制反转(IOC)-依赖注入(DI)的学习)

本篇主要对ControllerServiceDAO三层结构以及控制反转&#xff08;IOC&#xff09;与DI&#xff08;依赖注入&#xff09;进行总结。 目录 一、三层架构&#xff1a; Controller/Service/DAO简介&#xff1a; 二、控制反转(IOC)-依赖注入(DI): 概念介绍&#xff1a; DOC与…

学校如何提升教学效率?这种方法要牢记!

随着教育信息化的发展&#xff0c;学校管理也逐渐借助先进的技术手段实现智能化、高效化。在线巡课系统作为其中的重要组成部分&#xff0c;为学校领导提供了便捷而有效的管理工具。 客户案例 中小学校长办公室 在中小学校长办公室&#xff0c;校长通过在线巡课系统可以实时查…

js 设置、获取、删除标签属性以及H5自定义属性

1. 设置标签属性 使用setAttribute()(‘属性名’, ‘属性值’)方法可以添加、修改、删除属性。   下面的demo是为input添加、修改、删除value属性&#xff1a; 1.1. HTML <input type"text" class"input"> <input type"text" class…

apk反编译修改教程系列---修改apk的默认颜色 布局颜色 手机电脑同步演示【十】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…

centos7 安装 java17 安装 idea

删除旧版本的java或者说是自带的&#xff0c;免得干扰 查找java [wanglcentos7 java]$ rpm -qa|grep javajava-1.8.0-openjdk-1.8.0.262.b10-1.el7.x86_64 javapackages-tools-3.4.1-11.el7.noarch tzdata-java-2020a-1.el7.noarch python-javapackages-3.4.1-11.el7.noarch …

获取响应请求头里的信息

如图所示这是一个导出excel的接口&#xff0c;后端响应头部&#xff0c;要获取Content-Disposition里的值&#xff0c; 由于命名问题&#xff0c;没有办法用res.Content-Disposition的方式获取它的值 按理来说使用res[Content-Disposition]就可以获取到&#xff0c;但是咩有&…

MySql主从同步,同步SQL_ERROR 1032解决办法

1.登录从库 mysql -u root -p 2.输入命令查看状态 SHOW SLAVE STATUS\G; 3.找到对应的错误数据位置 Slave_IO_Running: YesSlave_SQL_Running: NoReplicate_Do_DB: app_push_centerReplicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Tabl…