开源模型应用落地-chatglm3-6b-集成langchain(十)

一、前言

    langchain框架调用本地模型,使得用户可以直接提出问题或发送指令,而无需担心具体的步骤或流程。通过LangChain和chatglm3-6b模型的整合,可以更好地处理对话,提供更智能、更准确的响应,从而提高对话系统的性能和用户体验。


二、术语

2.1. ChatGLM3

    是智谱AI和清华大学 KEG 实验室联合发布的对话预训练模型。ChatGLM3-6B 是 ChatGLM3 系列中的开源模型,在保留了前两代模型对话流畅、部署门槛低等众多优秀特性的基础上,ChatGLM3-6B 引入了如下特性:

  1. 更强大的基础模型: ChatGLM3-6B 的基础模型 ChatGLM3-6B-Base 采用了更多样的训练数据、更充分的训练步数和更合理的训练策略。在语义、数学、推理、代码、知识等不同角度的数据集上测评显示,* ChatGLM3-6B-Base 具有在 10B 以下的基础模型中最强的性能*。
  2. 更完整的功能支持: ChatGLM3-6B 采用了全新设计的 Prompt 格式 ,除正常的多轮对话外。同时原生支持工具调用(Function Call)、代码执行(Code Interpreter)和 Agent 任务等复杂场景。
  3. 更全面的开源序列: 除了对话模型 ChatGLM3-6B 外,还开源了基础模型 ChatGLM3-6B-Base 、长文本对话模型 ChatGLM3-6B-32K 和进一步强化了对于长文本理解能力的 ChatGLM3-6B-128K。以上所有权重对学术研究完全开放 ,在填写 问卷 进行登记后亦允许免费商业使用

2.2.LangChain

    是一个全方位的、基于大语言模型这种预测能力的应用开发工具。LangChain的预构建链功能,就像乐高积木一样,无论你是新手还是经验丰富的开发者,都可以选择适合自己的部分快速构建项目。对于希望进行更深入工作的开发者,LangChain 提供的模块化组件则允许你根据自己的需求定制和创建应用中的功能链条。

    LangChain本质上就是对各种大模型提供的API的套壳,是为了方便我们使用这些 API,搭建起来的一些框架、模块和接口。

    LangChain的主要特性:
        1.可以连接多种数据源,比如网页链接、本地PDF文件、向量数据库等
        2.允许语言模型与其环境交互
        3.封装了Model I/O(输入/输出)、Retrieval(检索器)、Memory(记忆)、Agents(决策和调度)等核心组件
        4.可以使用链的方式组装这些组件,以便最好地完成特定用例。
        5.围绕以上设计原则,LangChain解决了现在开发人工智能应用的一些切实痛点。


三、前提条件 

3.1. 基础环境及前置条件

  1.  操作系统:centos7
  2.  Tesla V100-SXM2-32GB  CUDA Version: 12.2

3.2. 下载chatglm3-6b模型

从huggingface下载:https://huggingface.co/THUDM/chatglm3-6b/tree/main

从魔搭下载:魔搭社区汇聚各领域最先进的机器学习模型,提供模型探索体验、推理、训练、部署和应用的一站式服务。https://www.modelscope.cn/models/ZhipuAI/chatglm3-6b/filesicon-default.png?t=N7T8https://www.modelscope.cn/models/ZhipuAI/chatglm3-6b/files

3.3. 安装虚拟环境

conda create --name langchain python=3.10
conda activate langchain
pip install langchain accelerate 

四、技术实现

4.1. 示例一

# -*-  coding = utf-8 -*-from langchain.llms.base import LLM
from langchain import LLMChain, PromptTemplate, ConversationChain
from transformers import AutoTokenizer, AutoModelForCausalLM
from typing import List, OptionalmodelPath = "/model/chatglm3-6b"class ChatGLM3(LLM):temperature: float = 0.45top_p = 0.8repetition_penalty = 1.1max_token: int = 8192do_sample: bool = Truetokenizer: object = Nonemodel: object = Nonehistory: List = []def __init__(self):super().__init__()@propertydef _llm_type(self) -> str:return "ChatGLM3"def load_model(self, model_name_or_path=None):self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path,trust_remote_code=True)self.model = AutoModelForCausalLM.from_pretrained(model_name_or_path, trust_remote_code=True, device_map="auto").cuda()def _call(self, prompt: str, history: List = [], stop: Optional[List[str]] = ["<|user|>"]):response, self.history = self.model.chat(self.tokenizer,prompt,history=self.history,do_sample=self.do_sample,max_length=self.max_token,temperature=self.temperature,top_p = self.top_p,repetition_penalty = self.repetition_penalty)history.append((prompt, response))return responseif __name__ == "__main__":llm = ChatGLM3()llm.load_model(modelPath)template = """
问题: {question}
"""prompt = PromptTemplate.from_template(template)llm_chain = LLMChain(prompt=prompt, llm=llm)question = "广州有什么特色景点?"print(llm_chain.run(question))

调用结果:

4.2. 示例二

# -*-  coding = utf-8 -*-from langchain.llms.base import LLM
from langchain import LLMChain, ConversationChain
from langchain.prompts import SystemMessagePromptTemplate, HumanMessagePromptTemplate, ChatPromptTemplate
from transformers import AutoTokenizer, AutoModelForCausalLM
from typing import List, OptionalmodelPath = "/model/chatglm3-6b"class ChatGLM3(LLM):temperature: float = 0.45top_p = 0.8repetition_penalty = 1.1max_token: int = 8192do_sample: bool = Truetokenizer: object = Nonemodel: object = Nonehistory: List = []def __init__(self):super().__init__()@propertydef _llm_type(self) -> str:return "ChatGLM3"def load_model(self, model_name_or_path=None):self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path,trust_remote_code=True)self.model = AutoModelForCausalLM.from_pretrained(model_name_or_path, trust_remote_code=True, device_map="auto").cuda()def _call(self, prompt: str, history: List = [], stop: Optional[List[str]] = ["<|user|>"]):# print(f'prompt: {prompt}')# print(f'history: {history}')response, self.history = self.model.chat(self.tokenizer,prompt,history=self.history,do_sample=self.do_sample,max_length=self.max_token,temperature=self.temperature,top_p = self.top_p,repetition_penalty = self.repetition_penalty)history.append((prompt, response))return responseif __name__ == "__main__":llm = ChatGLM3()llm.load_model(modelPath)template = "你是一个数学专家,很擅长解决复杂的逻辑推理问题。"system_message_prompt = SystemMessagePromptTemplate.from_template(template)human_template = "问题: {question}"human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)prompt_template = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])llm_chain = LLMChain(prompt=prompt_template, llm=llm)print(llm_chain.run(question="若一个三角形的两条边长度分别为3和4,且夹角为直角,最后一条边的长度是多少?"))

调用结果:


五、附带说明

5.1. 示例中ChatGLM3可以扩展,实现更复杂的功能

参见官方示例:

ChatGLM3.py

import ast
import json
from langchain.llms.base import LLM
from transformers import AutoTokenizer, AutoModel, AutoConfig
from typing import List, Optionalclass ChatGLM3(LLM):max_token: int = 8192do_sample: bool = Truetemperature: float = 0.8top_p = 0.8tokenizer: object = Nonemodel: object = Nonehistory: List = []has_search: bool = Falsedef __init__(self):super().__init__()@propertydef _llm_type(self) -> str:return "ChatGLM3"def load_model(self, 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, device_map="auto").eval()def _tool_history(self, prompt: str):ans = []tool_prompts = prompt.split("You have access to the following tools:\n\n")[1].split("\n\nUse a json blob")[0].split("\n")tools_json = []for tool_desc in tool_prompts:name = tool_desc.split(":")[0]description = tool_desc.split(", args:")[0].split(":")[1].strip()parameters_str = tool_desc.split("args:")[1].strip()parameters_dict = ast.literal_eval(parameters_str)params_cleaned = {}for param, details in parameters_dict.items():params_cleaned[param] = {'description': details['description'], 'type': details['type']}tools_json.append({"name": name,"description": description,"parameters": params_cleaned})ans.append({"role": "system","content": "Answer the following questions as best as you can. You have access to the following tools:","tools": tools_json})dialog_parts = prompt.split("Human: ")for part in dialog_parts[1:]:if "\nAI: " in part:user_input, ai_response = part.split("\nAI: ")ai_response = ai_response.split("\n")[0]else:user_input = partai_response = Noneans.append({"role": "user", "content": user_input.strip()})if ai_response:ans.append({"role": "assistant", "content": ai_response.strip()})query = dialog_parts[-1].split("\n")[0]return ans, querydef _extract_observation(self, prompt: str):return_json = prompt.split("Observation: ")[-1].split("\nThought:")[0]self.history.append({"role": "observation","content": return_json})returndef _extract_tool(self):if len(self.history[-1]["metadata"]) > 0:metadata = self.history[-1]["metadata"]content = self.history[-1]["content"]lines = content.split('\n')for line in lines:if 'tool_call(' in line and ')' in line and self.has_search is False:# 获取括号内的字符串params_str = line.split('tool_call(')[-1].split(')')[0]# 解析参数对params_pairs = [param.split("=") for param in params_str.split(",") if "=" in param]params = {pair[0].strip(): pair[1].strip().strip("'\"") for pair in params_pairs}action_json = {"action": metadata,"action_input": params}self.has_search = Trueprint("*****Action*****")print(action_json)print("*****Answer*****")return f"""
Action: 
```
{json.dumps(action_json, ensure_ascii=False)}
```"""final_answer_json = {"action": "Final Answer","action_input": self.history[-1]["content"]}self.has_search = Falsereturn f"""
Action: 
```
{json.dumps(final_answer_json, ensure_ascii=False)}
```"""def _call(self, prompt: str, history: List = [], stop: Optional[List[str]] = ["<|user|>"]):if not self.has_search:self.history, query = self._tool_history(prompt)else:self._extract_observation(prompt)query = ""_, self.history = self.model.chat(self.tokenizer,query,history=self.history,do_sample=self.do_sample,max_length=self.max_token,temperature=self.temperature,)response = self._extract_tool()history.append((prompt, response))return response

main.py

"""
This script demonstrates the use of the LangChain's StructuredChatAgent and AgentExecutor alongside various toolsThe script utilizes the ChatGLM3 model, a large language model for understanding and generating human-like text.
The model is loaded from a specified path and integrated into the chat agent.Tools:
- Calculator: Performs arithmetic calculations.
- Weather: Provides weather-related information based on input queries.
- DistanceConverter: Converts distances between meters, kilometers, and feet.The agent operates in three modes:
1. Single Parameter without History: Uses Calculator to perform simple arithmetic.
2. Single Parameter with History: Uses Weather tool to answer queries about temperature, considering the
conversation history.
3. Multiple Parameters without History: Uses DistanceConverter to convert distances between specified units.
4. Single use Langchain Tool: Uses Arxiv tool to search for scientific articles.Note:
The model calling tool fails, which may cause some errors or inability to execute. Try to reduce the temperature
parameters of the model, or reduce the number of tools, especially the third function.
The success rate of multi-parameter calling is low. The following errors may occur:Required fields [type=missing, input_value={'distance': '30', 'unit': 'm', 'to': 'km'}, input_type=dict]The model illusion in this case generates parameters that do not meet the requirements.
The top_p and temperature parameters of the model should be adjusted to better solve such problems.Success example:*****Action*****{'action': 'weather','action_input': {'location': '厦门'}
}*****Answer*****{'input': '厦门比北京热吗?','chat_history': [HumanMessage(content='北京温度多少度'), AIMessage(content='北京现在12度')],'output': '根据最新的天气数据,厦门今天的气温为18度,天气晴朗。而北京今天的气温为12度。所以,厦门比北京热。'
}****************"""import osfrom langchain import hub
from langchain.agents import AgentExecutor, create_structured_chat_agent, load_tools
from langchain_core.messages import AIMessage, HumanMessagefrom ChatGLM3 import ChatGLM3
from tools.Calculator import Calculator
from tools.Weather import Weather
from tools.DistanceConversion import DistanceConverterMODEL_PATH = os.environ.get('MODEL_PATH', 'THUDM/chatglm3-6b')if __name__ == "__main__":llm = ChatGLM3()llm.load_model(MODEL_PATH)prompt = hub.pull("hwchase17/structured-chat-agent")# for single parameter without historytools = [Calculator()]agent = create_structured_chat_agent(llm=llm, tools=tools, prompt=prompt)agent_executor = AgentExecutor(agent=agent, tools=tools)ans = agent_executor.invoke({"input": "34 * 34"})print(ans)# for singe parameter with historytools = [Weather()]agent = create_structured_chat_agent(llm=llm, tools=tools, prompt=prompt)agent_executor = AgentExecutor(agent=agent, tools=tools)ans = agent_executor.invoke({"input": "厦门比北京热吗?","chat_history": [HumanMessage(content="北京温度多少度"),AIMessage(content="北京现在12度"),],})print(ans)# for multiple parameters without historytools = [DistanceConverter()]agent = create_structured_chat_agent(llm=llm, tools=tools, prompt=prompt)agent_executor = AgentExecutor(agent=agent, tools=tools)ans = agent_executor.invoke({"input": "how many meters in 30 km?"})print(ans)# for using langchain toolstools = load_tools(["arxiv"], llm=llm)agent = create_structured_chat_agent(llm=llm, tools=tools, prompt=prompt)agent_executor = AgentExecutor(agent=agent, tools=tools)ans = agent_executor.invoke({"input": "Describe the paper about GLM 130B"})print(ans)

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

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

相关文章

构建企业信息安全防护体系:以电子文档安全为核心

随着信息社会的飞速发展与企业信息化建设的深入&#xff0c;企业的商业机密已从传统的纸质文件转向各类电子文档&#xff0c;如CAD图纸、Office文档等。这些数字化的信息载体在提升工作效率、便捷信息流转的同时&#xff0c;也成为了企业内部数据安全面临的主要挑战。如何有效地…

基于springboot实现中药实验管理系统设计项目【项目源码+论文说明】

基于springboot实现中药实验管理系统设计演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了中药实验管理系统的开发全过程。通过分析中药实验管理系统管理的不足&#xff0c;创建了一个计算机管理中药实验管…

LeetCode-2385. 感染二叉树需要的总时间【树 深度优先搜索 广度优先搜索 二叉树】

LeetCode-2385. 感染二叉树需要的总时间【树 深度优先搜索 广度优先搜索 二叉树】 题目描述&#xff1a;解题思路一&#xff1a;记录父节点 DFS解题思路二&#xff1a;解题思路三&#xff1a;深度优先搜索建图 广度优先搜索求感染时间【最容易理解】 题目描述&#xff1a; 给…

实现Spring底层机制(三)

文章目录 阶段4—实现BeanPostProcessor机制1.文件目录2.初始化方法实现1.编写初始化接口InitializingBean.java2.MonsterService.java实现初始化接口3.容器中的createBean方法增加初始化逻辑&#xff0c;判断对象类型是否是InitializingBean的子类型&#xff0c;如果是&#x…

FRP远程连接

前言 通过frp和跳板机完成局域网服务器访问。工具地址&#xff1a;https://github.com/fatedier/frp 配置frp过程 下载frp工具&#xff0c;下载地址如下&#xff1a; https://github.com/fatedier/frp/releases 这里我选择了v0.57.0 解压到本地路径 tar -zxvf xxxxxx.tar.gz配…

python爬虫学习第二十八天-------了解scrapy(二十八天)

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

接口测试和Mock学习路线(中)

1.什么是 swagger Swagger 是一个用于生成、描述和调用 RESTful 接口的 WEB 服务。 通俗的来讲&#xff0c;Swagger 就是将项目中所有想要暴露的接口展现在页面上&#xff0c;并且可以进行接口调用和测试的服务。 现在大部分的项目都使用了 swagger&#xff0c;因为这样后端…

fakak详解(2)

Kafka和Flume整合 Kafka与flume整合流程 Kafka整合flume流程图 flume主要是做日志数据(离线或实时)地采集。 图-21 数据处理 图-21显示的是flume采集完毕数据之后&#xff0c;进行的离线处理和实时处理两条业务线&#xff0c;现在再来学习flume和kafka的整合处理。 配置fl…

微信小程序开发工具的使用,各个配置文件详解,小程序开发快速入门

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

redis单线程模型

工作原理 在Redis中&#xff0c;当两个客户端同时发送相同的请求时&#xff0c;Redis采用单线程模型来处理所有的客户端请求&#xff0c;会依次处理这些请求&#xff0c;每个请求都会按照先后顺序被执行&#xff0c;不会同时处理多个请求。使得Redis能够避免多线程并发访问数据…

大语言模型应用指南:以ChatGPT为起点,从入门到精通的AI实践教程

目录 前言ChatGPT问世和发展展望未来大语言模型应用指南 特点大语言模型应用指南 主要内容 前言 在20世纪末和21世纪初&#xff0c;人类经历了两次信息革命的浪潮。 第一次是互联网时代的兴起&#xff0c;将世界各地连接在一起&#xff0c;改变了人们获取信息和交流的方式。 …

函数式接口及Stream流式计算

一、什么是函数式接口 只有一个方法的接口&#xff0c;例如 FunctionalInterface public interface Runnable { public abstract void run(); }二、Function函数式接口&#xff1a;有一个输入参数&#xff0c;有一个输出 三、断定型接口&#xff1a;有一个输入参数&#xf…

《ElementPlus 与 ElementUI 差异集合》el-select 显示下拉列表在 Cesium 场景中无法监听关闭

前言 仅在 Element UI 时有此问题&#xff0c;Element Plus 由于内部结构差异较大&#xff0c;不存在此问题。详见《el-select 差异点&#xff0c;如&#xff1a;高、宽、body插入等》&#xff1b; 问题 点击空白处&#xff0c;下拉列表可监听并关闭&#xff1b;但在 Cesium…

【js】解决自动生成颜色时相邻颜色视觉相似问题的技术方案

解决自动生成颜色时相邻颜色视觉相似问题的技术方案 在进行大规模颜色生成时&#xff0c;特别是在数据可视化、用户界面设计等应用领域&#xff0c;一个常见的挑战是确保相邻颜色在视觉上具有足够的区分度。本文介绍的方法通过结合黄金分割比与饱和度、亮度的周期性变化&#…

数据分析_时间维度对比及变化可视化分析(Pandas和Matplotlib)

数据分析_时间维度对比及变化可视化分析(Pandas和Matplotlib) 分析维度包括: 各年度合计销量 各年度合计销售额 各年度平均每公斤销售额 各月度销量对比 各月度销售额变化 构建测试数据 这里你可以了解到: 如何生成时间相关的数据。 如何从列表&#xff08;可迭代对象…

Linux多进程(二)进程通信方式一 管道

管道的是进程间通信&#xff08;IPC - InterProcess Communication&#xff09;的一种方式&#xff0c;管道的本质其实就是内核中的一块内存(或者叫内核缓冲区)&#xff0c;这块缓冲区中的数据存储在一个环形队列中&#xff0c;因为管道在内核里边&#xff0c;因此我们不能直接…

Vue 双向绑定、diff和nextTick原理

前言 什么是虚拟dom virtual DOM 虚拟DOM&#xff0c;用普通js对象来描述DOM结构&#xff0c;因为不是真实DOM&#xff0c;所以称之为虚拟DOM。 虚拟 dom 是相对于浏览器所渲染出来的真实 dom而言的&#xff0c;在react&#xff0c;vue等技术出现之前&#xff0c;我们要改变页面…

LabVIEW专栏八、类

该章目的是可以开发仪器类。 一、类的概述 一般来说类有三大特性&#xff0c;封装&#xff0c;继承和多态。 在实际项目中&#xff0c;最主要是继承和多态&#xff0c;要搞清楚这两者的概念和在LabVIEW中是怎样应用的。在LabVIEW中&#xff0c;面向对象编程用到的就是LabVIE…

SAM在低阶自适应航空土地覆盖分类中的应用2024.01

GEOSCIENCE AND REMOTE SENSING LETTERS 2024.01 提出了一种新的语义分割模型&#xff0c;该模型结合了SAM的图像编码器和低秩自适应方法(LoRA)&#xff0c;用于航空图像的特征提取和微调。我们还使用了一个辅助CNN编码器来促进下游适应&#xff0c;并补充ViT编码器在密集视觉…

机器学习模型效果不好及其解决办法

当训练出来的机器学习模型效果不佳时&#xff0c;可能涉及多个方面的原因。为了改善模型的效果&#xff0c;需要系统地检查和分析问题的根源&#xff0c;并采取相应的措施进行优化。 一、数据问题 数据质量 检查数据是否干净、完整&#xff0c;是否存在噪声、异常值或缺失值。…