ChatGLM-6B+LangChain環(huán)境部署與使用實(shí)戰(zhàn)
目標(biāo):原始使用ChatGLM-6B可接受的文字長(zhǎng)度有限,打算結(jié)合LangChain實(shí)現(xiàn)長(zhǎng)文本生成摘要.方法:step1:自定義一個(gè)GLM繼承LangChain中的langchain.llms.base.LLM,load自己的模型.step2:使用LangChain的mapreduce的方法,對(duì)文本分塊,做摘要,輸出結(jié)果.使用的機(jī)器資源:T4顯卡(16G顯存)附參考資料:ChatGLM-6B:ModelScope: ChatGLM-6BLangChain:LangChain: summarizationLangChain: summarize notebook
- glm環(huán)境準(zhǔn)備在指定的python環(huán)境下確定安裝好以下依賴:
# 安裝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/下 可以使用以下代碼先下載到臨時(shí)目錄,然后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')
- ChatGLM-6B + LangChain
2.1 繼承l(wèi)angchain.llms.base.LLM新建GLM類重寫_call方法:加載自己的模型,并限制只輸出結(jié)果(chatglm原輸出不是直接str,langchain中要求模型返回必須是str的結(jié)果:“”“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 實(shí)例化llm對(duì)象&加載模型
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("政府工作報(bào)告.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 = """對(duì)下面的文字做精簡(jiǎn)的摘要: {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'])
其中政府工作報(bào)告.txt來(lái)自于2023年政府工作報(bào)告_中國(guó)政府網(wǎng):https://www.gov.cn/zhuanti/2023lhzfgzbg/index.htm
2.4 輸出這篇文章介紹了中國(guó)在過(guò)去五年中的經(jīng)濟(jì)發(fā)展成就,政府采取多項(xiàng)措施應(yīng)對(duì)有效需求不足的問(wèn)題、支持汽車消費(fèi)、推進(jìn)保交樓穩(wěn)民生工作、加強(qiáng)環(huán)境保護(hù)和生態(tài)修復(fù)工作等。政府還出臺(tái)了增值稅留抵退稅額度、降低貸款利息等減輕企業(yè)負(fù)擔(dān)的措施。文章介紹了中國(guó)政府的宏觀經(jīng)濟(jì)政策目標(biāo),包括推進(jìn)中國(guó)式現(xiàn)代化、實(shí)現(xiàn)經(jīng)濟(jì)發(fā)展質(zhì)量和數(shù)量的提升、改善民生、穩(wěn)定社會(huì)大局等。新冠疫情防控政策包括疫苗迭代升級(jí)和新藥研制、保障群眾就醫(yī)用藥需求、重點(diǎn)做好老年人、兒童、患基礎(chǔ)性疾病群體的疫情防控和醫(yī)療救治等。政府將著力擴(kuò)大國(guó)內(nèi)需求、加快建設(shè)現(xiàn)代化產(chǎn)業(yè)體系、深化國(guó)資國(guó)企改革、保護(hù)民營(yíng)企業(yè)產(chǎn)權(quán)和企業(yè)家權(quán)益,鼓勵(lì)支持民營(yíng)經(jīng)濟(jì)和民營(yíng)企業(yè)發(fā)展壯大,穩(wěn)定市場(chǎng)預(yù)期和提振市場(chǎng)信心。
實(shí)戰(zhàn)2框架地址:https://github.com/noobdawn/langchain_ChatGPT
langchain+ChatGLM-6B試用什么是langchainChatGLM-6B大家都知道了,是清華大學(xué)推出的有62億參數(shù)的開(kāi)源大語(yǔ)言模型。那么langchain是什么?langchain是一個(gè)基于語(yǔ)言模型的應(yīng)用程序開(kāi)發(fā)框架,它具有以下特點(diǎn)
數(shù)據(jù)感知:將語(yǔ)言模型與其他數(shù)據(jù)源連接在一起自主性:允許語(yǔ)言模型與其環(huán)境進(jìn)行交互langchain框架是基于以上原則設(shè)計(jì)的。
因?yàn)檫@些特點(diǎn),langchain可以實(shí)現(xiàn)針對(duì)特定文件的問(wèn)答、聊天機(jī)器人、評(píng)估、數(shù)據(jù)增強(qiáng)生成等工作。
如何部署github地址為:基于本地知識(shí)的 ChatGLM 應(yīng)用實(shí)現(xiàn)
部署指南為:安裝
因?yàn)槲覔Q了新機(jī)器,我個(gè)人遇到了【build wheel for xxx時(shí)提示找不到cl.exe】的問(wèn)題,解決方法是:
裝個(gè)Visual Studio,然后在Visual Studio Installer里安裝組件【MSVC v142 - VS 2019 C++ x64/x86生成工具】。注意要選擇這個(gè)版本,像我之前就裝了MSVC v143結(jié)果build報(bào)錯(cuò)了。安裝完成重啟之后如果還報(bào)這個(gè)錯(cuò),就找到cl.exe所在的目錄,把它添加到環(huán)境變量Path里,這個(gè)目錄大致是這樣的:D:\VS\2019\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64如何使用安裝完成后,執(zhí)行python webui.py即可開(kāi)始使用,訪問(wèn)本地的127.0.0.1:7860即可使用web版的界面。
首先,進(jìn)入模型配置,選一個(gè)LLM模型和Embedding模型。配置好的可以用chatglm-6b,差點(diǎn)的就要砍精度了。Embedding模型主要是文本轉(zhuǎn)向量的模型,這個(gè)我研究不多。
然后來(lái)到知識(shí)庫(kù)測(cè)試界面,先新建知識(shí)庫(kù),并為其上傳文檔或者文檔所在文件夾,等待程序?qū)⑽谋旧舷挛姆指畈⒔馕鰹橄蛄恐筮M(jìn)行保存好后,測(cè)試問(wèn)題。這一步主要是調(diào)整知識(shí)相關(guān)度閾值,默認(rèn)Score=0會(huì)回復(fù)所有檢索到的知識(shí)出處,這顯然是不精準(zhǔn)的。
確定好閾值后,在model_config里進(jìn)行修改,這里還可以順便修改一下prompt模板,重啟程序以令其生效;
L 在對(duì)話中,配置好數(shù)據(jù)庫(kù)之后提問(wèn)即可。
缺陷舉例而言,我寫了這樣一個(gè)Q&A:
如何進(jìn)行性能優(yōu)化? 使用Unity的FrameDebugger查看每幀的DrawCall和使用到的模型。
但是喂給ChatGLM-6B后提供的回答會(huì)類似于:
如何進(jìn)行性能優(yōu)化? 1. 了解業(yè)務(wù)需求:明確優(yōu)化的目標(biāo)和范圍 2. 設(shè)計(jì)測(cè)試用例:針對(duì)目標(biāo)場(chǎng)景進(jìn)行性能模擬,以確定系統(tǒng)的性能表現(xiàn)
云云。
通過(guò)這張圖可以看到,這個(gè)框架的主體其實(shí)是跟LLM無(wú)關(guān)的,它只是比對(duì)和匹配文本向量的相似性,檢出最相似的問(wèn)句的上下文打包發(fā)給LLM進(jìn)行潤(rùn)色。
在我的理解里,這個(gè)玩意兒不會(huì)真的把本地的數(shù)據(jù)更新進(jìn)自己的模型內(nèi)部,只是每次提問(wèn)的時(shí)候,預(yù)先把可能存在答案的上下文作為prompt一起提交了而已,這里在model_config.py的PROMPT_TEMPLATE里也能看到。
所以它會(huì)觸發(fā)以下問(wèn)題:
1 當(dāng)這個(gè)問(wèn)題并不“獨(dú)特”的時(shí)候,就會(huì)出現(xiàn)例子中所示的答案的雜糅。因?yàn)槭谴虬舷挛闹蟀l(fā)給LLM潤(rùn)色,顯然LLM理解的“性能優(yōu)化”指的是一種普適性的答案,它自發(fā)的把自身語(yǔ)料訓(xùn)練出來(lái)的結(jié)果與本地知識(shí)庫(kù)中項(xiàng)目所獨(dú)有的結(jié)果進(jìn)行混合,得到了似是而非的東西。2 當(dāng)知識(shí)庫(kù)中的問(wèn)題重復(fù)度很高的時(shí)候,或者問(wèn)題過(guò)于寬泛導(dǎo)致命中過(guò)多,也會(huì)出現(xiàn)本地知識(shí)庫(kù)答案的雜糅。此時(shí)問(wèn)題和各個(gè)文本向量的相似性很高,回答會(huì)串味,例如,詢問(wèn)“如何進(jìn)行性能優(yōu)化”之后,就會(huì)連同“性能優(yōu)化怎么查看”、“性能優(yōu)化的指標(biāo)是多少”等等一塊返回進(jìn)行回答。3 因?yàn)槭谴虬舷挛陌l(fā)給LLM潤(rùn)色,所以這個(gè)“打包”可能會(huì)把答案截?cái)啵蛘吣依瞬⒎潜締?wèn)題的答案的上下文,會(huì)造成回答串味或不全。
簡(jiǎn)單的說(shuō),對(duì)于我來(lái)說(shuō)我并不需要什么語(yǔ)料的潤(rùn)色、幫助我提取有用信息,因?yàn)槲医o的文檔本身就是最好的答案,所以我需要的是精確的檢索。這種截?cái)嗌舷挛陌l(fā)給LLM的架構(gòu)的三個(gè)缺陷是我無(wú)法忍受的:
- 本地知識(shí)庫(kù)干預(yù)力度不夠,由于真正需要的知識(shí)在上下文中,而上下文是以Prompt的形式嵌入其中的,導(dǎo)致獨(dú)特性不夠的問(wèn)題,大模型給出的答案會(huì)非常偏向語(yǔ)料訓(xùn)練結(jié)果。
- ChatGLM-6B的中文能力過(guò)于羸弱,邏輯能力過(guò)于差勁,有時(shí)候無(wú)法判別出兩個(gè)相似問(wèn)題的區(qū)別。
- 上下文截?cái)噙^(guò)于粗暴,對(duì)于長(zhǎng)答案支持不佳。langchain+ChatGPT其他嘗試之后我轉(zhuǎn)變思維,不再嘗試讓LLM模型去即時(shí)回答問(wèn)題,而是讓LLM即時(shí)判定問(wèn)句是否一致,再針對(duì)同義問(wèn)句匹配相同的回答。因此我個(gè)人在家又搭建了一個(gè)langchain+ChatGLM-6B的本地知識(shí)對(duì)話模型,但這個(gè)模型跟前一個(gè)模型的區(qū)別在于,我會(huì)寫好一個(gè)問(wèn)題答案對(duì):
Q:你是誰(shuí)? A:我是弱智小助理。
當(dāng)我提問(wèn)“你是什么人”的時(shí)候,內(nèi)部會(huì)使用LLM模型去一個(gè)個(gè)比對(duì)這句話和各個(gè)問(wèn)題答案對(duì)中的問(wèn)題部分是否屬于同一個(gè)意思,此處它就會(huì)比對(duì)“你是誰(shuí)”和“你是什么人”是不是同一個(gè)意思。Prompt會(huì)寫成這個(gè)樣子:
f"{original_question}\n{input_question}\n判斷上述兩句話是不是一個(gè)意思,如果是,則回答1;反之回答0。"這里再次暴露了ChatGLM-6B的羸弱,明明要求回答0或者1即可,往往會(huì)畫蛇添足地說(shuō)“是的,這兩句是一個(gè)意思”,此外它對(duì)同義句的判定也有極大的問(wèn)題,這里我們后面說(shuō)。
然后我又換了個(gè)方式,好吧,不要求你按格式回答了,你直接生成多幾個(gè)同義句,我用文本向量按最近距離匹配好了。
我尋思Judge可能確實(shí)有點(diǎn)難為它了,那么generate應(yīng)該沒(méi)問(wèn)題吧,結(jié)果還是讓我大跌眼鏡,對(duì)于“如何進(jìn)行性能優(yōu)化的流程”的問(wèn)題,ChatGLM-6B給出的回復(fù)是:
事實(shí)上,我想看到的是這樣的句子:
- 怎么發(fā)起性能優(yōu)化流程?
- 性能優(yōu)化的流程是怎么樣的?
- 我該如何啟動(dòng)性能優(yōu)化流程?
- 性能優(yōu)化流程是如何發(fā)起的?
(你要不看看你在說(shuō)什么?.jpg
因?yàn)槲乙恢痹谟肅hatGPT幫助生成代碼,所以我測(cè)試了一下ChatGPT,發(fā)現(xiàn)ChatGPT生成的同義句居然還不錯(cuò),雖然有時(shí)候會(huì)帶上人稱,比如”你如何才能啟動(dòng)性能優(yōu)化“。
事實(shí)證明,盡管ChatGPT之后,LLM人人均有不下ChatGPT-3之勇,但真用起來(lái),那還是ChatGPT好使。
如何使用OpenAI API入口:Introduction - OpenAI API
每個(gè)ChatGPT Plus用戶每月有5刀的免費(fèi)使用額度,而根據(jù)使用的GPT模型不同,收費(fèi)也不同:
模型 迅速版(每千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的原因絕對(duì)不是便宜(迫真),而是因?yàn)樗俣瓤欤覟閷?duì)話專門優(yōu)化過(guò)。而同義句的生成就也不涉及大量的知識(shí)和專業(yè)性內(nèi)容,所以直接用它。
使用的方法就很簡(jiǎn)單:
p
rompt_base_templet = """請(qǐng)為下面這段文字生成至少5個(gè)的意思完全相同的中文問(wèn)句,句子之間用回車分隔開(kāi):{question}""" gpt_engine = "text-davinci-003" max_tokens = 300 temperature = 0 ? # 獲取同義問(wèn)句 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')
感覺(jué)一句話基本大約不會(huì)超過(guò)60token,所以5個(gè)中文問(wèn)句大致就是300個(gè)token。temperature設(shè)為0是為了防止回答過(guò)于發(fā)散。
框架框架整體參考了imClumsyPanda/langchain-ChatGLM 的實(shí)現(xiàn),包括怎么用gradio創(chuàng)建webui之類的,但輕量化了很多,因?yàn)槲也⒉恍枰獌?nèi)嵌LLM,也不需要對(duì)問(wèn)句進(jìn)行分詞(都整句話直接轉(zhuǎn)換成向量了)。
這個(gè)框架的運(yùn)行結(jié)果是:
- 讀取問(wèn)題答案對(duì)
- 把問(wèn)題整理出來(lái)發(fā)給OpenAI API生成同義句
- 把同義句轉(zhuǎn)換為Document,把答案和原問(wèn)句編制到metadata里
- 用embedding model將同義句轉(zhuǎn)化為向量
- 用FAISS匹配最符合輸入的問(wèn)句
- 把結(jié)果中的metadata篩一次,合并同義句產(chǎn)生的答案
- 返回合并篩選之后的答案
值得注意的是,該方法只實(shí)現(xiàn)了一半的數(shù)據(jù)安全,其問(wèn)題還是要提交到服務(wù)器上的。所以如果有涉密需求,還是得手動(dòng)編寫同義句字典進(jìn)行搭建數(shù)據(jù)庫(kù)。
改進(jìn)
允許上傳圖片和鏈接 允許使用不經(jīng)過(guò)OpenAI的同義句字典 允許下載本地知識(shí)和字典
一些個(gè)人的想法故,本質(zhì)上而言,該方案并不能算“對(duì)話”系統(tǒng),因?yàn)長(zhǎng)LM并沒(méi)有在即時(shí)輸入端參與,而是在本地知識(shí)上傳后離線參與。
寫完之后我在思索,這玩意兒和Ctrl-F有什么區(qū)別,有沒(méi)有一種可能,我直接Ctrl+F搜索“性能優(yōu)化”也能找到我要的內(nèi)容呢?所以這是個(gè)偽命題?
后面想了想,如果知識(shí)庫(kù)很少,問(wèn)題單一的情況下確實(shí)是這樣的沒(méi)錯(cuò)。但隨著知識(shí)庫(kù)的增大,問(wèn)題的keyword也在增多,單個(gè)keyword對(duì)應(yīng)的答案內(nèi)容開(kāi)始急劇上升,假如后面有這些問(wèn)題:
使用RenderDoc怎么指導(dǎo)性能優(yōu)化? 怎么用Unity Frame Debugger優(yōu)化性能? 如何優(yōu)化冗余的資源實(shí)現(xiàn)性能提升? ……
這樣的話,Ctrl+F的實(shí)用性就大打折扣了。此外,keyword也可能會(huì)改頭換面,例如“性能優(yōu)化”實(shí)際上可以這樣問(wèn)“優(yōu)化XX的性能表現(xiàn)”,因此我認(rèn)為這個(gè)方案仍有有較大的用武之地。基于本地知識(shí)的問(wèn)答機(jī)器人langchain-ChatGLM
- linux環(huán)境部署清華大學(xué)大模型最新版 chatglm2-6b 圖文教程
- macbook安裝環(huán)境chatglm2-6b的詳細(xì)過(guò)程
- 基于本地知識(shí)的問(wèn)答機(jī)器人langchain-ChatGLM 大語(yǔ)言模型實(shí)現(xiàn)方法詳解
- ChatGPT平替-?ChatGLM多用戶并行訪問(wèn)部署過(guò)程
- ChatGPT平替-ChatGLM環(huán)境搭建與部署運(yùn)行效果
- ChatGLM?集成LangChain工具詳解
- 基于prompt?tuning?v2訓(xùn)練好一個(gè)垂直領(lǐng)域的chatglm-6b
- 最簡(jiǎn)化ChatGLM2-6b小白部署教程【windows系統(tǒng),16G內(nèi)存即可,對(duì)顯卡無(wú)要求,CPU運(yùn)行】
相關(guān)文章
詳解Python requests 超時(shí)和重試的方法
這篇文章主要介紹了詳解Python requests 超時(shí)和重試的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12Python+PuLP實(shí)現(xiàn)線性規(guī)劃的求解
線性規(guī)劃(Linear?programming),在線性等式或不等式約束條件下求解線性目標(biāo)函數(shù)的極值問(wèn)題,常用于解決資源分配、生產(chǎn)調(diào)度和混合問(wèn)題。本文將利用PuLP實(shí)現(xiàn)線性規(guī)劃的求解,需要的可以參考一下2022-04-04Python3使用TCP編寫一個(gè)簡(jiǎn)易的文件下載器功能
這篇文章主要介紹了Python3使用TCP編寫一個(gè)簡(jiǎn)易的文件下載器功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-05-05圖文詳解在Anaconda安裝Pytorch的詳細(xì)步驟
Anaconda指的是一個(gè)開(kāi)源的Python發(fā)行版本,其包含了conda、Python等180多個(gè)科學(xué)包及其依賴項(xiàng),下面這篇文章主要給大家介紹了關(guān)于在Anaconda安裝Pytorch的詳細(xì)步驟,需要的朋友可以參考下2022-07-07將python代碼打包成.exe文件直接運(yùn)行的具體步驟
小編最近收到了一個(gè)小伙伴的問(wèn)題,就是那么多有趣的代碼,怎么發(fā)給別人,讓沒(méi)有python環(huán)境的小伙伴也可以使用呢,本文小編將帶著大家探索如何將自己的python代碼打包成.exe可執(zhí)行文件,一起來(lái)看看吧2024-02-02