ChatGLM-6B+LangChain实战

news2024/10/7 14:29:48

目标:原始使用ChatGLM-6B可接受的文字长度有限,打算结合LangChain实现长文本生成摘要.
方法:
step1:自定义一个GLM继承LangChain中的langchain.llms.base.LLM,load自己的模型.
step2:使用LangChain的mapreduce的方法,对文本分块,做摘要,输出结果.
使用的机器资源:T4显卡(16G显存)
附参考资料:
ChatGLM-6B:
ModelScope: ChatGLM-6B
LangChain:
LangChain: summarization
LangChain: summarize notebook

  1. glm环境准备
    在指定的python环境下确定安装好以下依赖:
# 安装pytorch
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia


# 安装modelscope
pip install modelscope==1.4.3 -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html
# 安装transformers
pip install protobuf==3.20.0 transformers==4.26.1 icetk cpm_kernels
# 安装charset-normalizer
python -m pip install charset-normalizer==2.1.0
# 安装langchain
pip install langchain
模型文件下载到/data/THUDM/chatglm-6b/下
可以使用以下代码先下载到临时目录,然后mv到自定义目录下:
from modelscope.utils.constant import Tasks
from modelscope.pipelines import pipeline
pipe = pipeline(task=Tasks.chat, model='ZhipuAI/ChatGLM-6B', model_revision='v1.0.7')
  1. ChatGLM-6B + LangChain

2.1 继承langchain.llms.base.LLM新建GLM类
重写_call方法:加载自己的模型,并限制只输出结果(chatglm原输出不是直接str,langchain中要求模型返回必须是str的结果:“”“LLM wrapper should take in a prompt and return a string.”“”)
具体代码:

from langchain import LLMChain
from langchain.text_splitter import CharacterTextSplitter
from langchain.chains.mapreduce import MapReduceChain
from langchain.prompts import PromptTemplate
from langchain.llms.base import LLM
from transformers import AutoTokenizer, AutoModel, AutoConfig
from typing import Any, Dict, List, Mapping, Optional, Tuple, Union
from torch.mps import empty_cache
import torch

class GLM(LLM):
    max_token: int = 2048
    temperature: float = 0.8
    top_p = 0.9
    tokenizer: object = None
    model: object = None
    history_len: int = 1024
    
    def __init__(self):
        super().__init__()
        
    @property
    def _llm_type(self) -> str:
        return "GLM"
            
    def load_model(self, llm_device="gpu",model_name_or_path=None):
        model_config = AutoConfig.from_pretrained(model_name_or_path, trust_remote_code=True)
        self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path,trust_remote_code=True)
        self.model = AutoModel.from_pretrained(model_name_or_path, config=model_config, trust_remote_code=True).half().cuda()

    def _call(self,prompt:str,history:List[str] = [],stop: Optional[List[str]] = None):
        response, _ = self.model.chat(
                    self.tokenizer,prompt,
                    history=history[-self.history_len:] if self.history_len > 0 else [],
                    max_length=self.max_token,temperature=self.temperature,
                    top_p=self.top_p)
        return response

2.2 实例化llm对象&加载模型

import sys

modelpath = "/data/THUDM/chatglm-6b/"
sys.path.append(modelpath)
llm = GLM()
llm.load_model(model_name_or_path = modelpath)

2.3 配合langchain输出

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document
from langchain.chains.summarize import load_summarize_chain

with open("政府工作报告.txt") as f:
    report_2023 = f.read()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_text(report_2023)
docs = [Document(page_content=t) for t in texts]
prompt_template = """对下面的文字做精简的摘要:

    {text}

    """

PROMPT = PromptTemplate(template=prompt_template, input_variables=["text"])
chain = load_summarize_chain(llm, chain_type="map_reduce", return_intermediate_steps=True, map_prompt=PROMPT, combine_prompt=PROMPT)
summ = chain({"input_documents": docs}, return_only_outputs=True)
print(summ['output_text'])

其中政府工作报告.txt来自于2023年政府工作报告_中国政府网:https://www.gov.cn/zhuanti/2023lhzfgzbg/index.htm

2.4 输出
这篇文章介绍了中国在过去五年中的经济发展成就,政府采取多项措施应对有效需求不足的问题、支持汽车消费、推进保交楼稳民生工作、加强环境保护和生态修复工作等。政府还出台了增值税留抵退税额度、降低贷款利息等减轻企业负担的措施。文章介绍了中国政府的宏观经济政策目标,包括推进中国式现代化、实现经济发展质量和数量的提升、改善民生、稳定社会大局等。新冠疫情防控政策包括疫苗迭代升级和新药研制、保障群众就医用药需求、重点做好老年人、儿童、患基础性疾病群体的疫情防控和医疗救治等。政府将着力扩大国内需求、加快建设现代化产业体系、深化国资国企改革、保护民营企业产权和企业家权益,鼓励支持民营经济和民营企业发展壮大,稳定市场预期和提振市场信心。

实战2
框架地址:https://github.com/noobdawn/langchain_ChatGPT

langchain+ChatGLM-6B试用
什么是langchain

ChatGLM-6B大家都知道了,是清华大学推出的有62亿参数的开源大语言模型。那么langchain是什么?langchain是一个基于语言模型的应用程序开发框架,它具有以下特点

数据感知:将语言模型与其他数据源连接在一起
自主性:允许语言模型与其环境进行交互
langchain框架是基于以上原则设计的。

因为这些特点,langchain可以实现针对特定文件的问答、聊天机器人、评估、数据增强生成等工作。

如何部署
github地址为:基于本地知识的 ChatGLM 应用实现

部署指南为:安装

因为我换了新机器,我个人遇到了【build wheel for xxx时提示找不到cl.exe】的问题,解决方法是:

装个Visual Studio,然后在Visual Studio Installer里安装组件【MSVC v142 - VS 2019 C++ x64/x86生成工具】。
注意要选择这个版本,像我之前就装了MSVC v143结果build报错了。
安装完成重启之后如果还报这个错,就找到cl.exe所在的目录,把它添加到环境变量Path里,这个目录大致是这样的:D:\VS\2019\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64
如何使用
安装完成后,执行python webui.py即可开始使用,访问本地的127.0.0.1:7860即可使用web版的界面。

  1. 首先,进入模型配置,选一个LLM模型和Embedding模型。配置好的可以用chatglm-6b,差点的就要砍精度了。Embedding模型主要是文本转向量的模型,这个我研究不多。

  2. 然后来到知识库测试界面,先新建知识库,并为其上传文档或者文档所在文件夹,等待程序将文本上下文分割并解析为向量之后进行保存好后,测试问题。这一步主要是调整知识相关度阈值,默认Score=0会回复所有检索到的知识出处,这显然是不精准的。

  3. 确定好阈值后,在model_config里进行修改,这里还可以顺便修改一下prompt模板,重启程序以令其生效;

  4. L 在对话中,配置好数据库之后提问即可。

缺陷
举例而言,我写了这样一个Q&A:

如何进行性能优化?
使用Unity的FrameDebugger查看每帧的DrawCall和使用到的模型。

但是喂给ChatGLM-6B后提供的回答会类似于:

如何进行性能优化?
1. 了解业务需求:明确优化的目标和范围
2. 设计测试用例:针对目标场景进行性能模拟,以确定系统的性能表现

云云。
在这里插入图片描述

通过这张图可以看到,这个框架的主体其实是跟LLM无关的,它只是比对和匹配文本向量的相似性,检出最相似的问句的上下文打包发给LLM进行润色。

在我的理解里,这个玩意儿不会真的把本地的数据更新进自己的模型内部,只是每次提问的时候,预先把可能存在答案的上下文作为prompt一起提交了而已,这里在model_config.py的PROMPT_TEMPLATE里也能看到。

所以它会触发以下问题:

1 当这个问题并不“独特”的时候,就会出现例子中所示的答案的杂糅。因为是打包上下文之后发给LLM润色,显然LLM理解的“性能优化”指的是一种普适性的答案,它自发的把自身语料训练出来的结果与本地知识库中项目所独有的结果进行混合,得到了似是而非的东西。
2 当知识库中的问题重复度很高的时候,或者问题过于宽泛导致命中过多,也会出现本地知识库答案的杂糅。此时问题和各个文本向量的相似性很高,回答会串味,例如,询问“如何进行性能优化”之后,就会连同“性能优化怎么查看”、“性能优化的指标是多少”等等一块返回进行回答。
3 因为是打包上下文发给LLM润色,所以这个“打包”可能会把答案截断,或者囊括了并非本问题的答案的上下文,会造成回答串味或不全。

简单的说,对于我来说我并不需要什么语料的润色、帮助我提取有用信息,因为我给的文档本身就是最好的答案,所以我需要的是精确的检索。这种截断上下文发给LLM的架构的三个缺陷是我无法忍受的:

  1. 本地知识库干预力度不够,由于真正需要的知识在上下文中,而上下文是以Prompt的形式嵌入其中的,导致独特性不够的问题,大模型给出的答案会非常偏向语料训练结果。
  2. ChatGLM-6B的中文能力过于羸弱,逻辑能力过于差劲,有时候无法判别出两个相似问题的区别。
  3. 上下文截断过于粗暴,对于长答案支持不佳。
    langchain+ChatGPT
    其他尝试
    之后我转变思维,不再尝试让LLM模型去即时回答问题,而是让LLM即时判定问句是否一致,再针对同义问句匹配相同的回答。因此我个人在家又搭建了一个langchain+ChatGLM-6B的本地知识对话模型,但这个模型跟前一个模型的区别在于,我会写好一个问题答案对:
Q:你是谁?
A:我是弱智小助理。

当我提问“你是什么人”的时候,内部会使用LLM模型去一个个比对这句话和各个问题答案对中的问题部分是否属于同一个意思,此处它就会比对“你是谁”和“你是什么人”是不是同一个意思。Prompt会写成这个样子:

f"{original_question}\n{input_question}\n判断上述两句话是不是一个意思,如果是,则回答1;反之回答0。"
这里再次暴露了ChatGLM-6B的羸弱,明明要求回答0或者1即可,往往会画蛇添足地说“是的,这两句是一个意思”,此外它对同义句的判定也有极大的问题,这里我们后面说。

然后我又换了个方式,好吧,不要求你按格式回答了,你直接生成多几个同义句,我用文本向量按最近距离匹配好了。
在这里插入图片描述

我寻思Judge可能确实有点难为它了,那么generate应该没问题吧,结果还是让我大跌眼镜,对于“如何进行性能优化的流程”的问题,ChatGLM-6B给出的回复是:
在这里插入图片描述

事实上,我想看到的是这样的句子:

  1. 怎么发起性能优化流程?
  2. 性能优化的流程是怎么样的?
  3. 我该如何启动性能优化流程?
  4. 性能优化流程是如何发起的?

在这里插入图片描述

(你要不看看你在说什么?.jpg

因为我一直在用ChatGPT帮助生成代码,所以我测试了一下ChatGPT,发现ChatGPT生成的同义句居然还不错,虽然有时候会带上人称,比如”你如何才能启动性能优化“。

事实证明,尽管ChatGPT之后,LLM人人均有不下ChatGPT-3之勇,但真用起来,那还是ChatGPT好使。

如何使用OpenAI API
入口:Introduction - OpenAI API

每个ChatGPT Plus用户每月有5刀的免费使用额度,而根据使用的GPT模型不同,收费也不同:

模型 迅速版(每千token) 完整版(每千token)
GPT-4 8K Context 0.03$ 0.06$
GPT-4 32K Context 0.06$ 0.12$
GPT-3.5-Turbo 0.002$ -
选择使用GPT-3.5的原因绝对不是便宜(迫真),而是因为它速度快,且为对话专门优化过。而同义句的生成就也不涉及大量的知识和专业性内容,所以直接用它。

使用的方法就很简单:

p

rompt_base_templet = """请为下面这段文字生成至少5个的意思完全相同的中文问句,句子之间用回车分隔开:{question}"""
gpt_engine = "text-davinci-003"
max_tokens = 300
temperature = 0# 获取同义问句
def get_synonymous_question(question : str) -> list:
    openai.api_key = api_key
    prompt = prompt_base_templet + question
    response = openai.Completion.create(
        engine=gpt_engine,
        prompt=prompt,
        max_tokens=max_tokens,
        temperature=temperature,
        n = output_num
    )
    generate_text = response.choices[0].text.strip()
    return generate_text.split('\n')

感觉一句话基本大约不会超过60token,所以5个中文问句大致就是300个token。temperature设为0是为了防止回答过于发散。

框架
框架整体参考了imClumsyPanda/langchain-ChatGLM 的实现,包括怎么用gradio创建webui之类的,但轻量化了很多,因为我并不需要内嵌LLM,也不需要对问句进行分词(都整句话直接转换成向量了)。

这个框架的运行结果是:

  1. 读取问题答案对
  2. 把问题整理出来发给OpenAI API生成同义句
  3. 把同义句转换为Document,把答案和原问句编制到metadata里
  4. 用embedding model将同义句转化为向量
  5. 用FAISS匹配最符合输入的问句
  6. 把结果中的metadata筛一次,合并同义句产生的答案
  7. 返回合并筛选之后的答案
    在这里插入图片描述

值得注意的是,该方法只实现了一半的数据安全,其问题还是要提交到服务器上的。所以如果有涉密需求,还是得手动编写同义句字典进行搭建数据库。

改进

允许上传图片和链接
允许使用不经过OpenAI的同义句字典
允许下载本地知识和字典

一些个人的想法
故,本质上而言,该方案并不能算“对话”系统,因为LLM并没有在即时输入端参与,而是在本地知识上传后离线参与。

写完之后我在思索,这玩意儿和Ctrl-F有什么区别,有没有一种可能,我直接Ctrl+F搜索“性能优化”也能找到我要的内容呢?所以这是个伪命题?

后面想了想,如果知识库很少,问题单一的情况下确实是这样的没错。但随着知识库的增大,问题的keyword也在增多,单个keyword对应的答案内容开始急剧上升,假如后面有这些问题:

使用RenderDoc怎么指导性能优化?
怎么用Unity Frame Debugger优化性能?
如何优化冗余的资源实现性能提升?
……

这样的话,Ctrl+F的实用性就大打折扣了。此外,keyword也可能会改头换面,例如“性能优化”实际上可以这样问“优化XX的性能表现”,因此我认为这个方案仍有有较大的用武之地。
基于本地知识的问答机器人langchain-ChatGLM
在这里插入图片描述

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

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

相关文章

Web前端 Day 5

js初体验 使得代码可以具有某些行为 <body><button>点击我变成粉色</button><script>const btn document.querySelector(button)btn.addEventListener(click, () > {btn.style.backgroundColor pink ​})</script> </body> 效果图…

Maven详见及在Idea中的使用方法[保姆级包学包会]

文章目录 Maven详解1.1 目标1.2 Maven概括1.3 多模块开发1.3.1 pom.xml1.3.2 生命周期1.3.3 依赖特性(多模块1)1.3.4 继承特性(多模块2)1.3.5 dependencyManagement标签1.3.6 Maven-聚合(多模块3)聚合 1.3.6.1聚合总结 Maven详解 1.1 目标 maven是什么?maven能干什么?maven…

java并发编程 10:AQS

目录 什么是AQS原理 什么是AQS juc包的结构如下图&#xff1a; AQS就是AbstractQueuedSynchronizer&#xff0c;是个抽象类&#xff0c;实现了自己的一些方法。它是阻塞式锁和相关的同步器工具的框架。很多并发类都是基于它实现的&#xff0c;如&#xff1a;ReentrantLock、Co…

【力扣刷题 | 第十八天】

目录 前言&#xff1a; 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 134. 加油站 - 力扣&#xff08;LeetCode&#xff09; 总结&#xff1a; 前言&#xff1a; 今天随机刷题&#xff0c;不对题型做具体的要求 1005. K 次取反后最大化的数组和 …

Spring5学习笔记--Maven

Spring5学习笔记--Maven Maven高级1 分模块开发1.1 分模块开发设计1.2 分模块开发实现1.2.1 环境准备1.2.2 抽取domain层步骤1:创建新模块步骤2:项目中创建domain包步骤3:删除原项目中的domain包步骤4:建立依赖关系步骤5:编译maven_02_ssm项目步骤6:将项目安装本地仓库 1.2.3 抽…

揭秘GPT-4;Adobe Firefly AI 扩大测试规模

&#x1f989; AI新闻 &#x1f680; Adobe Firefly AI 扩大测试规模&#xff0c;支持100多种语言的输入 摘要&#xff1a;Adobe宣布扩大测试规模&#xff0c;Adobe Firefly AI现在支持100多种语言的 prompts 输入。网页测试版Firefly已经扩充了罗马尼亚语等多种语言&#xf…

layui选项卡演示

layui选项卡演示 .1 引入layui2. 选项卡演示实列3.js分离的代码4运行结果 在前端开发中&#xff0c;选项卡常用于展示多个内容模块&#xff0c;提供用户友好的界面交互方式。layui作为一款简洁易用的前端框架&#xff0c;提供了丰富的组件库&#xff0c;其中包括了强大且易用的…

Html基础知识学习——css精灵

这里写自定义目录标题 定义示例一示例二 定义 将网页用到的图片放在一张图片上&#xff0c;进行定位展示 优点:防止网页http请求次数过多&#xff0c;从而提高页面性能 缺点&#xff1a;降低开发效率。维护难度加大 示例一 使用图 网页制作图 <!DOCTYPE html> <…

AcWing 1273. 天才的记忆—RMQ

题目链接: AcWing 1273. 天才的记忆 问题描述 RMQ是用来求解静态区间最大/小值的算法&#xff0c;静态空间就是数组里的数不会变&#xff0c;动态空间最大/小值可以用线段树或者树状数组来求解。 RMQ算法有点类似与区间DP&#xff0c;RMQ算法的时间复杂度为 O ( n l o g n ) …

三菱 FX三菱PLC以太网通信程序

捷米特三菱FX转以太网通讯处理器是一款经济型的以太网通讯处理器&#xff0c;是为满足日益增多的工厂设备信息化需求&#xff08;设备网络监控和生产管理&#xff09;而设计&#xff0c;用于三菱FX1S/1N/2N/3S/3G/3GA/3GC/3U/3UC系列、汇川、士林AX、禾川、维控等PLC以太网数据…

【算法和数据结构】347、LeetCode前 K 个高频元素

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;首先我们使用一个哈希表记录每个元素出现的频率。再设置一个优先队列&#xff0c;并将数组中元素出现的…

C语言实现扫雷【经典】

前言   本篇文章要实现的是扫雷游戏&#xff0c;其代码实现与上一篇的三子棋游戏类同&#xff0c;都是在棋盘的基础上&#xff0c;与电脑进行对抗&#xff0c;不同的是&#xff0c;扫雷游戏一开始电脑就已经随机布置好了所有“雷”。 请戳 --->三子棋 扫雷游戏 1. 扫雷游…

【Visual Studio】VTK 显示小球例子,在 Windows 上使用 Visual Studio 配合 Qt 构建 VTK

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 关于更多此例子的资料&#xff0c;可以参考&#xff1a;【Visual Studio】在 Windows 上使用 Visual Studio 配合 Qt 构建 VTK。 文章目录 版本环境VTKTest.…

Nginx upstream 负载均衡配置

[toc] ## 问题: 自7/4 以来, 所有设备同时出现 Network Error, 导致业务无法正常进行, 频率 3次/每分钟; ## 现场情况及原因分析: 3楼: 8条产线 4楼: 20条产线 5楼: 5条产线 点数: 33条线 * 平均 (5台工位 1台电视看板 3台测试仪 ) ≈ 300 - Nginx 日志占用: access 日志 …

【MySQL备份与还原、索引、视图】练习

一、备份与还原 /***************************样例表***************************/CREATE DATABASE booksDB;use booksDB;CREATE TABLE books(bk_id INT NOT NULL PRIMARY KEY,bk_title VARCHAR(50) NOT NULL,copyright YEAR NOT NULL);INSERT INTO booksVALUES (11078, Lear…

UNIX网络编程卷一 学习笔记 第二十三章 高级SCTP套接字编程

SCTP是一个面向消息的协议&#xff0c;递送给用户的是部分的或完整的消息。只有当发送大消息时&#xff0c;在对端才会递送部分的消息。部分消息被递送给应用后&#xff0c;多个部分消息组合成单个完整消息不由SCTP负责。在SCTP应用进程看来&#xff0c;一个消息既可由单个输入…

线性代数的一些小细节

1 .矩阵的满足结合律&#xff0c;但不满足交换律 验证和证明如下图&#xff1a; 如下&#xff0c;UWQ三个矩阵的2种结合&#xff0c;证明矩阵乘法满足结合律 下图中&#xff0c;AB 和BA的值可能是不同的&#xff08;相同的条件是图中相互对应的4项相同&#xff0c;即对称矩阵…

防范 XSS 攻击的措施

防范 XSS 攻击的措施 XSS&#xff08;Cross-site scripting&#xff09;攻击是一种常见的网络安全漏洞&#xff0c;它可以通过注入恶意代码来攻击用户的计算机和浏览器&#xff0c;从而窃取用户的敏感信息或执行恶意操作。本篇文章将介绍防范 XSS 攻击的措施&#xff0c;并提供…

Spring设计模式及部分技术讲解

讲师:邓澎波 Spring面试专题 1.Spring应该很熟悉吧?来介绍下你的Spring的理解 有些同学可能会抢答,不熟悉!!! 好了,不开玩笑,面对这个问题我们应该怎么来回答呢?我们给大家梳理这个几个维度来回答 1.1 Spring的发展历程 先介绍Spring是怎么来的,发展中有哪些核心的节…

Linux文件

目录 系统级I/O 简介 接口 文件描述符fd 重定向 缓冲区 文件系统 软硬链接 动静态库 静态函数库 动态库 系统级I/O 简介 输入/输出&#xff08;I/O&#xff09;是在主存和外部设备&#xff08;磁盘驱动器、终端和网络&#xff09;之间复制数据的过程。输入操作是…