LLM大语言模型(十二):关于ChatGLM3-6B不兼容Langchain 的Function Call

 

背景

基于本地的ChatGLM3-6B直接开发LangChain Function Call应用,发现其输出的action和action_input非常不稳定。

表现为生成的JSON格式回答非常容易出现不规范的情况,导致LangChain的Agent执行报错,或者进入死循环。

ChatGLM3-6B不兼容Langchain 的Function Call

Langchain 作为最主流的大模型中间件开源框架,备受广大开发者的认可。

Langchain中具有一套完整的 Agent 思维,包括灵活,简单的Function Call开发框架。

ChatGLM3-6B 模型在同量级模型中有出色的Function Call能力。

但遗憾的是,其训练过程并没有与Langchain进行原生对齐。

这导致如果直接使用Langchian框架,将会遇到以下问题:

  • 无法载入ChatGLM3-6B模型,Langchain中的 LLM模型 目前仅支持在线的几个主流模型,例如ChatGPT,Bard,Claude等

  • 无法正常使用 Agent 的 Function Call 功能,ChatGLM3-6B的截断点与 Langchain 支持的并不同。

  • 提示词不同,使用 Langchain 封装的 Agent 提示词完全无法胜任ChatGLM3-6B 的 Function Call 任务。

将GLM模型接入Langchain

首先,要解决第一个痛点:ChatGLM3-6B 模型能够被 Langchain 读入并执行。

那么,我们就需要基于Langchain的LLM类完成ChatGLM3-6B的模型实现。

封装自定义LLM

class ChatGLM3(LLM):
    max_token: int = 8192
    do_sample: bool = False
    temperature: float = 0.8
    top_p = 0.8
    tokenizer: object = None
    model: object = None
    history: List = []
    tool_names: List = []
    has_search: bool = False

    def __init__(self):
        super().__init__()

    @property
    def _llm_type(self) -> str:
        return "ChatGLM3"

接着,我们要写入读入模型的方法,这与 Langchain 支持的在线模型不同,这里使用 Huggingface 的方式进行读入。

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
    ).half().cuda()

按LangChain的格式构建Tool

其中包括工具的name,description,params等信息,可以被LangChain自动识别出来,加入到prompt中

import abc

from typing import Type
from langchain.tools import BaseTool
from pydantic import BaseModel, Field


class CalculatorInput(BaseModel):
    calculation: str = Field(description="calculation to perform")


class Calculator(BaseTool, abc.ABC):
    name = "Calculator"
    description = "Useful for when you need to calculate math problems"
    args_schema: Type[BaseModel] = CalculatorInput

    def __init__(self):
        super().__init__()

    def _run(self, calculation: str) -> str:
        calculation = calculation.replace("^", "**")
        if "sqrt" in calculation:
            calculation = calculation.replace("sqrt", "math.sqrt")
        elif "log" in calculation:
            calculation = calculation.replace("log", "math.log")
        return eval(calculation)

从prompt中抽取tool信息并转换为ChatGLM能识别的结构 

然后,就是非常重要的一环。由于我们的工具调用和观察抓取与 Langchain 并不相同,我们需要对 Langchain 的提示词进行修改,并配上我们的提示词。

  • 我们先从AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION模板中截取到You have access to the following tools:\n\n")的关键词,并在合理插入已经注册的工具类型。

tool_prompts = prompt.split(
        "You have access to the following tools:\n\n")[1].split("\n\nUse a json blob")[0].split("\n")

    tool_names = [tool.split(":")[0] for tool in tool_prompts]
    self.tool_names = tool_name

增加Observation结构

由于ChatGLM3-6B拥有Observation角色,这与Langchain中原本设定的Observation截断并不相同,因此,在这里,我们需要做提取,在这段代码中,我们需要对原本Langchain中的Observation进行截断,并补

充上我们的工具观察的结果。

def _extract_observation(self, prompt: str):
    return_json = prompt.split("Observation: ")[-1].split("\nThought:")[0]
    self.history.append({
        "role": "observation",
        "content": return_json
    })
    return

将ChatGLM生成的结果转换为LangChain能识别的结构

在这,我们还需要对执行工具进行截断和填充,使得其能满足ChatGLM3-6B的思维模式

def _extract_tool(self):
        if len(self.history[-1]["metadata"]) > 0:
            metadata = self.history[-1]["metadata"]
            content = self.history[-1]["content"]
            if "tool_call" in content:
                for tool in self.tool_names:
                    if tool in metadata:
                        input_para = content.split("='")[-1].split("'")[0]
                        action_json = {
                            "action": tool,
                            "action_input": input_para
                        }
                        self.has_search = True
                        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 = False
        return f"""
Action: 
```
{json.dumps(final_answer_json, ensure_ascii=False)}
```"""

由于ChatgGLM3-6B的思维方式并没有Action: 字段,而这是langchain的截断点,因此,我们需要对其进行补充,使得Langchain能知道,此时模型进入调用工具阶段。

最后,我们要基于Langchain的构造,重写_call函数,包括历史记录,提示词等拼接内容。

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

使用接入了Langchain的ChatGLM3-6B模型

在完成了上述工作之后,我们就已经拥有了支持Langchain的ChatGLM3-6B模型,我们在main.py中对其进行了简单调用

if __name__ == "__main__":
    llm = ChatGLM3()
    llm.load_model(MODEL_PATH)
    prompt = hub.pull("hwchase17/structured-chat-agent")

    # for single parameter without history

    tools = [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)

注意事项

到此为止,你已经简单实现了使用LangChain调用ChatGLM3-6B模型来实现工具调用和其他基本用法。但是,在更多探索之前,请一定要看这部分的内容。这将能为你之后的开发减少不必要的麻烦。

使用LLMChain的工具

在官方的实现方案中,暂时不能解决在工具中仍然需要调用正常的LLMChain的操作,这意味着你在工具的设计中不能再次调用大模型进行更多操作,例如参数解析等,典型的错误例子为

LLMMathChain

如果使用官方Demo调用这个工具,则必然遇到以下错误:

line 120, in _process_llm_result

raise ValueError(f"unknown format from LLM: {llm_output}")

ValueError: unknown format from LLM: Action:

{"action": "Calculator", "action_input": "23*23"}

这是因为在模型构建的过程中,模型会解析到tools,而在tools中的常规调用模型并没有修改模型的系统提示词,模型还会尝试调用工具,这在常规的Chain中是错误的。

无效的参数和固定的参数

  • ChatGLM3-6B必须使用结构化的Agent,在Langchain中,我们只适配了AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION

  • 如果使用LLMSingleActionAgent来构建,stop参数无效。

  • 使用Tool.from_function时,args_schema无效。

  • 每次创建一个新的Tools,都必须有同名的yaml,或者自己实现传入格式化的工具说明。

兼容OpenAI API

官方的OpenAI API格式的demo,目前无法适配Langchain的工具。

 参考

  1. GitHub - THUDM/ChatGLM-6B: ChatGLM-6B: An Open Bilingual Dialogue Language Model | 开源双语对话语言模型
  2.  LLM大语言模型(十一):基于自定义的ChatGLM3-6B构建LangChain的chain-CSDN博客
  3. LLM大语言模型(十):LangChain自定义Agent使用自定义的LLM-CSDN博客
  4. LLM大语言模型(九):LangChain封装自定义的LLM-CSDN博客
  5. LLM大语言模型(八):ChatGLM3-6B使用的tokenizer模型BAAI/bge-large-zh-v1.5-CSDN博客
  6. LLM大语言模型(七):部署ChatGLM3-6B并提供HTTP server能力
  7. LLM大语言模型(四):在ChatGLM3-6B中使用langchain_chatglm3-6b langchain-CSDN博客
  8. LLM大语言模型(一):ChatGLM3-6B本地部署-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQLAlchemy的使用

SQLAlchemy中filter函数的使用 https://blog.csdn.net/m0_67093160/article/details/133318889 创建临时字段 select id , CONCAT(‘内容’) AS fullname from example_table;

设计模式之外观模式

1、详细介绍 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它为子系统的一组接口提供了一个统一的入口点&#xff08;外观类&#xff09;。外观模式简化了客户端与子系统之间的交互&#xff0c;屏蔽了子系统内部的复杂性&#xff0c;使客户…

【Unity】UnityEvent(一)

​UnityEvent----高效管理游戏事件的利器 在游戏开发中&#xff0c;事件系统是实现各种功能的关键组成部分。它允许我们将不同对象之间的交互解耦&#xff0c;使得代码更加模块化和易于维护。而UnityEvent作为Unity引擎提供的一种强大的事件系统工具&#xff0c;为开发者提供了…

c++ - 模板(一)

文章目录 一、函数模板 一、函数模板 1、概念 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定 类型版本。 2、原理 函数模板是一个蓝图&#xff0c;它本身并不是函数&#xff0c;是编译器用…

宜搜科技死磕港交所上市:从搜索引擎到广告投放,业绩疲态凸显

近日&#xff0c;宜搜科技控股有限公司&#xff08;下称“宜搜科技”&#xff09;向港交所递交招股书&#xff0c;计划在香港主板上市&#xff0c;中银国际为其独家保荐人。 值得注意的是&#xff0c;宜搜科技已在资本市场辗转多年。该公司曾于2014年向纽交所递交上市申请&…

Web3与传统互联网:挑战、融合与共生

引言 Web3技术正以惊人的速度改变着我们的互联网体验。作为一个基于区块链的去中心化互联网模型&#xff0c;Web3不仅带来了创新和变革&#xff0c;还引发了与传统互联网之间的对比和讨论。本文将深入探讨Web3与传统互联网之间的关系&#xff0c;挑战&#xff0c;以及可能的融…

智慧火电厂合集 | 数字孪生助推能源革命

火电厂在发电领域中扮演着举足轻重的角色。主要通过燃烧如煤、石油或天然气等化石燃料来产生电力。尽管随着可再生能源技术的进步导致其比重有所减少&#xff0c;但直至 2023 年&#xff0c;火电依然是全球主要的电力来源之一。 通过图扑软件自主研发 HT for Web 产品&#xf…

模块三:二分——162.寻找峰值

文章目录 题目描述算法原理解法一&#xff1a;暴力查找解法二&#xff1a;二分查找 代码实现解法一&#xff1a;暴力查找解法二&#xff1a;CJava 题目描述 题目链接&#xff1a;162.寻找峰值 根据题意&#xff0c;需要使用O(log N)的时间复杂度来解决&#xff0c;得出本道题…

对浅拷贝的理解

问题背景 我之前一直以为浅拷贝出来的新对象和旧对象的引用地址是相同的&#xff0c;但是通过Object和发现浅拷贝的新对象和旧对象的引用地址不同&#xff01;&#xff01; const obj1 { name: "Alice", test: { age: 12 } };const obj4 Object.assign({}, obj1);…

linux中 虚拟机 修改时间 centos7

方法1 &#xff1a;虚拟机内 设置 方法2 代码实现 timedatectl set-timezone "Asia/Shanghai"

iOS 17上如何恢复数据?iOS 17 数据恢复软件

“您好&#xff0c;我正在为我的 iPhone 寻找一款iOS 17 数据恢复软件。升级到 iOS 17 后&#xff0c;我丢失了 iPhone 上的所有照片、联系人和消息。有什么建议吗&#xff1f;” ——丹尼 iOS 17数据恢复软件下载 升级到iOS 17后如何恢复丢失的数据&#xff1f;由于在 iPhone…

Django中的事务

1 开启全局的事务 DATABASES {default: {ENGINE: django.db.backends.mysql, # 使用mysql数据库NAME: tracerbackend, # 要连接的数据库USER: root, # 链接数据库的用于名PASSWORD: 123456, # 链接数据库的用于名HOST: 192.168.1.200, # mysql服务监听的ipPORT: 3306, …

目标检测——小麦穗头数据集

一、重要性及意义 小麦穗头检测在农业领域具有重要意义&#xff0c;主要体现在以下几个方面&#xff1a; 首先&#xff0c;小麦穗头检测可以帮助农民和植物科学家准确评估作物的健康状况和成熟度。通过对小麦穗部的形态特征进行测量和分析&#xff0c;可以及时发现作物生长过…

应用在防蓝光显示器中的LED防蓝光灯珠

相比抗蓝光眼镜、防蓝光覆膜、软体降低蓝光强度这些“软”净蓝手段&#xff0c;通过对LED的发光磷粉进行LED背光进行技术革新&#xff0c;可实现硬件“净蓝”。其能够将90%以上的有害蓝光转换为450nm以上的长波低能光线&#xff0c;从硬件的角度解决了蓝光危害眼睛的问题&#…

python+django校园社交高校交友网站2x7r5.

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台&#xff0c;设计的基本思路是&#xff1a; 前端&#xff1a;vue.jselementui 框架&#…

【机器学习】深度神经网络(DNN):原理、应用与代码实践

深度神经网络&#xff08;DNN&#xff09;&#xff1a;原理、应用与代码实践 一、深度神经网络&#xff08;DNN&#xff09;的基本原理二、DNN的优缺点分析三、DNN的代码实践四、总结与展望 在人工智能与机器学习的浪潮中&#xff0c;深度神经网络&#xff08;Deep Neural Netw…

Spring Boot 集成 EasyExcel 3.x

Spring Boot 集成 EasyExcel 3.x Spring Boot 集成 EasyExcel 3.x 本章节将介绍 Spring Boot 集成 EasyExcel&#xff08;优雅实现Excel导入导出&#xff09;。 &#x1f916; Spring Boot 2.x 实践案例&#xff08;代码仓库&#xff09; 介绍 EasyExcel 是一个基于 Java 的、…

【注解和反射】什么时候类会和不会被初始化?

继上一篇博客【注释和反射】类加载的过程-CSDN博客 目录 四、什么时候类会被初始化&#xff08;主动引用&#xff09;&#xff1f; 测试 五、什么情况下不会发生类的初始化&#xff08;被动引用&#xff09;&#xff1f; 测试 四、什么时候类会被初始化&#xff08;主动引用…

<网络> HTTP

目录 前言&#xff1a; 一、再谈协议 &#xff08;一&#xff09;认识URL &#xff08;二&#xff09;Encode 和 Decode 二、HTTP 协议 &#xff08;一&#xff09;协议格式 &#xff08;二&#xff09;见一见请求 &#xff08;三&#xff09;见一见响应 三、模拟实现响…

模块化 DeFi L2 “Mode” 整合 Covalent Network(CQT),以获 Web3 最大数据集的支持

Covalent Network&#xff08;CQT&#xff09;&#xff0c;作为 Web3 领先的数据层&#xff0c;宣布其统一 API 将与 Mode 集成&#xff0c;以加快其基于以太坊构建的专注于 DeFi 的模块化 Layer2 方案的数据访问速度。这一战略合作将通过为开发者提供更强大的工具和能力&#…