LLM大语言模型(三):使用ChatGLM3-6B的函数调用功能前先学会Python的装饰器

目录

ChatGLM3-6B的函数调用模式示例

本地启动ChatGLM3-6B工具模式

如何在ChatGLM3-6B里新增一个自定义函数呢?

get_weather基于Python的装饰器实现

函数注解@register_tool

现在我们来自定义一个kuakuawo()函数


ChatGLM3-6B的函数调用模式示例

ChatGLM3-6B目前有三种使用模式:

  1. 对话模式
  2. 工具模式(也就是本文要介绍的函数调用)
  3. 代码解释器模式

函数调用模式示例:

函数调用模式介绍:

  • 首先进入Tool工具模式
  • 询问"北京今天的天气"
  • 大模型自动识别出,要调用get_weather工具(函数),且参数是"北京"
  • 大模型接着调用get_weather,入参=北京,获取到函数执行的结果
  • <|Observation|>展示的是函数的执行结果
  • 紧接着大模型根据上述内容,继续生成回答"根据APIxxxxxxxxxxxx"

本地启动ChatGLM3-6B工具模式

进入conda对应的环境

bash 复制代码
conda activate chatglm

进入composite_demo目录

bash 复制代码
cd composite_demo

修改为使用本地模型,参考LLM大语言模型(一):ChatGLM3-6B本地部署-CSDN博客

bash 复制代码
# 修改client.py
MODEL_PATH = os.environ.get('MODEL_PATH', '====你的本地模型的绝对路径====')

启动模型

bash 复制代码
# 在composite_demo目录下
streamlit run main.py

然后在页面选择Tool模式即可。

如何在ChatGLM3-6B里新增一个自定义函数呢?

首先我们看下get_weather函数是如何实现的。

在composite_demo目录下有个tool_registry.py文件,里面包含两个已经定义好的函数:

  • random_number_generator

  • get_weather

其中get_weather就是上文对话中用到的函数。

get_weather基于Python的装饰器实现

python 复制代码
@register_tool
def get_weather(
    city_name: Annotated[str, 'The name of the city to be queried', True],
) -> str:
    """
    Get the current weather for `city_name`
    """

    if not isinstance(city_name, str):
        raise TypeError("City name must be a string")

    key_selection = {
        "current_condition": ["temp_C", "FeelsLikeC", "humidity", "weatherDesc",  "observation_time"],
    }
    import requests
    try:
        resp = requests.get(f"https://wttr.in/{city_name}?format=j1")
        resp.raise_for_status()
        resp = resp.json()
        ret = {k: {_v: resp[k][0][_v] for _v in v} for k, v in key_selection.items()}
    except:
        import traceback
        ret = "Error encountered while fetching weather data!\n" + traceback.format_exc() 

    return str(ret)

get_weather功能很简洁,最终是从

bash 复制代码
https://wttr.in/{city_name}?format=j1

获取天气信息(https://wttr.in/%E5%8C%97%E4%BA%AC?format=j1

函数注解@register_tool

register_tool的功能是将自定义的函数,转化为大模型需要的格式。

python 复制代码
def register_tool(func: callable):
    tool_name = func.__name__
    tool_description = inspect.getdoc(func).strip()
    python_params = inspect.signature(func).parameters
    tool_params = []

    # 解析param的Annotation

    for name, param in python_params.items():
        annotation = param.annotation
        if annotation is inspect.Parameter.empty:
            raise TypeError(f"Parameter `{name}` missing type annotation")
        if get_origin(annotation) != Annotated:
            raise TypeError(f"Annotation type for `{name}` must be typing.Annotated")
        
        typ, (description, required) = annotation.__origin__, annotation.__metadata__
        typ: str = str(typ) if isinstance(typ, GenericAlias) else typ.__name__
        if not isinstance(description, str):
            raise TypeError(f"Description for `{name}` must be a string")
        if not isinstance(required, bool):
            raise TypeError(f"Required for `{name}` must be a bool")

        tool_params.append({
            "name": name,
            "description": description,
            "type": typ,
            "required": required
        })
    tool_def = {
        "name": tool_name,
        "description": tool_description,
        "params": tool_params
    }

    print("[registered tool] " + pformat(tool_def))
    _TOOL_HOOKS[tool_name] = func
    _TOOL_DESCRIPTIONS[tool_name] = tool_def

    return func

register_tool函数实现了装饰器,它将自定义的函数转换为tool_def dict,其中自动生成了name,description,params等信息

python 复制代码
{
    'name': 'get_weather', 
    'description': 'Get the current weather for `city_name`', 
    'params': [
        {
            'name': 'city_name', 
            'description': 'The name of the city to be queried', 
            'type': 'str', 
            'required': True
        }
    ]
}

最终通过get_tools()将自定义的函数都暴露出去。

在上述demo中,其实是demo_tool.py里调用了get_tools()获取到所有的自定义函数。

python 复制代码
def get_tools() -> dict:
    return copy.deepcopy(_TOOL_DESCRIPTIONS)

现在我们来自定义一个kuakuawo()函数

python 复制代码
@register_tool
def kuakuawo(
    name: Annotated[str, 'The name of the user', True], 
) -> str:
    """
    Generates a awesome praise for user
    """

    return f"{name} 你真的太棒了"

看看效果

参考:

  1. LLM大语言模型(一):ChatGLM3-6B本地部署-CSDN博客
  2. LLM大语言模型(二):Streamlit 无需前端经验也能画web页面-CSDN博客
相关推荐
DuoRuaiMiFa1 分钟前
ChatGPT全新功能Canvas上线:开启智能编程与写作新篇章
人工智能·chatgpt
DisonTangor4 分钟前
Windows 11将新增基于AI的搜索、生成式填充和其它AI功能
人工智能
soso19686 分钟前
【AI自然语言处理应用】通过API调用通义晓蜜CCAI-对话分析AIO应用
人工智能·自然语言·ccai
网安-搬运工9 分钟前
RAG再总结之如何使大模型更好使用外部数据:四个不同层级及查询-文档对齐策略
人工智能·自然语言处理·大模型·llm·大语言模型·ai大模型·rag
大模型八哥10 分钟前
大模型扫盲系列——大模型实用技术介绍(上)
人工智能·程序人生·ai·大模型·llm·llama·ai大模型
阿华的代码王国13 分钟前
【JavaEE】——文件IO的应用
开发语言·python
被制作时长两年半的个人练习生24 分钟前
【pytorch】权重为0的情况
人工智能·pytorch·深度学习
Elastic 中国社区官方博客40 分钟前
使用 Vertex AI Gemini 模型和 Elasticsearch Playground 快速创建 RAG 应用程序
大数据·人工智能·elasticsearch·搜索引擎·全文检索
电饭叔1 小时前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
说私域1 小时前
地理定位营销与开源AI智能名片O2O商城小程序的融合与发展
人工智能·小程序