使用 chatglm3-6b 调用自定义 Tool 计算两个地址的经纬度距离

前言

本文使用最新的大模型 chatglm3-6b ,调用自定义工具计算两个地址的经纬度之间的距离。

安装 11.8 的 cuda

https://pytorch.org/get-started/locally/ 中可以查看 pytorch 最常见的是支持 11.8 cuda 版本,然后进入 https://developer.nvidia.com/cuda-toolkit-archive 找到 CUDA Toolkit 11.8 进行下载,下载结束之后双击基本上是傻瓜式下一步按钮即可,不懂的可以见参考中的链接。此时重新打开命令行,查看 nvcc -V 已经变成了 11.8 版本:

yaml 复制代码
    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2022 NVIDIA Corporation
    Built on Wed_Sep_21_10:41:10_Pacific_Daylight_Time_2022
    Cuda compilation tools, release 11.8, V11.8.89
    Build cuda_11.8.r11.8/compiler.31833905_0

搭建 conda 虚拟环境

创建 3.10 的 python 版本来生成虚拟环境。

ini 复制代码
conda create -n torch-2.x-py-3.10 python=3.10

激活虚拟环境

conda activate torch-2.x-py-3.10

在浏览器 pytorch.org/get-started... 页面中找到支持 CUDA 11.8 的 pytorch2.1 命令在虚拟环境中进行安装。

perl 复制代码
pip3.exe install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

拉取项目 ChatGLM3 到本地

bash 复制代码
git clone https://github.com/THUDM/ChatGLM3

安装项目所需要的库

pip.exe install -r requirements.txt

修改模型绝对路径

huggingface.co/THUDM/chatg... 将完整的模型下载到本地,将 langchain_demo/main.py 文件改为下面的代码,其中主要修改的部分是 model_path 是模型的绝对路径,另外使用 run_tool 调用 Calculator 。

ini 复制代码
from typing import List
from ChatGLM3 import ChatGLM3
from langchain.agents import load_tools
from Tool.Calculator import Calculator
from langchain.agents import initialize_agent
from langchain.agents import AgentType


def run_tool(tools, llm, prompt_chain: List[str]):
    loaded_tolls = []
    for tool in tools:
        if isinstance(tool, str):
            loaded_tolls.append(load_tools([tool], llm=llm)[0])
        else:
            loaded_tolls.append(tool)
    agent = initialize_agent(
        loaded_tolls, llm,
        agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
        verbose=True,
        handle_parsing_errors=True
    )
    for prompt in prompt_chain:
        agent.run(prompt)


if __name__ == "__main__":
    model_path = "D:\chatglm3-6b"
    llm = ChatGLM3()
    llm.load_model(model_name_or_path=model_path)

    # calculator: 单个工具调用示例 3
    run_tool([Calculator()], llm, [
        "复兴城市家园和清河家园经的经纬度是120.15235、30.210432 和 120.1531、30.20865,计算他们之间的距离?",
    ])

将 langchain_demo/Tool/Calculator.py 改成下面的代码,主要实现了一个计算两个经纬度之间的直线距离的函数。

python 复制代码
import abc
from typing import Any
from langchain.tools import BaseTool
from math import radians, sin, cos, sqrt, atan2

class Calculator(BaseTool, abc.ABC):
    name = "Calculator"
    description = "Useful for when you need to answer questions about math"
    def __init__(self):
        super().__init__()
    async def _arun(self, *args: Any, **kwargs: Any) -> Any:
        # 用例中没有用到 arun 不予具体实现
        pass

    def haversine_distance(self,  lon1, lat1, lon2, lat2 ):
        lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2])
        dlat = lat2 - lat1
        dlon = lon2 - lon1
        a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
        c = 2 * atan2(sqrt(a), sqrt(1 - a))
        R = 6371.0 * 1000
        distance = R * c
        return distance

    def _run(self, para: str) -> str:
        A,B = para.split('-')
        lon1, lat1 = A.split(",")
        lon2, lat2 = B.split(",")
        return str(self.haversine_distance(float(lon1), float(lat1), float(lon2), float(lat2))) + "米"


if __name__ == "__main__":
    calculator_tool = Calculator()
    result = calculator_tool.run("120.15235,30.210432-120.1531,30.20865")
    print(result)

启动 main.py ,可以看到打印下面的结果,大模型从输入中提取出来了两个经纬度,并且传入到了自定义的计算距离的工具,可以返回结果为 210.849 米 ,下面是整个思考和结论过程:

vbnet 复制代码
Loading checkpoint shards: 100%|██████████| 7/7 [00:03<00:00,  2.21it/s]
> Entering new AgentExecutor chain...
======
System: Respond to the human as helpfully and accurately as possible. You have access to the following tools:

Calculator: Useful for when you need to answer questions about math, args: {{'para': {{'title': 'Para', 'type': 'string'}}}}

Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).

Valid "action" values: "Final Answer" or Calculator

Provide only ONE action per $JSON_BLOB, as shown:

```
{
  "action": $TOOL_NAME,
  "action_input": $INPUT
}
```

Follow this format:

Question: input question to answer
Thought: consider previous and subsequent steps
Action:
```
$JSON_BLOB
```
Observation: action result
... (repeat Thought/Action/Observation N times)
Thought: I know what to respond
Action:
```
{
  "action": "Final Answer",
  "action_input": "Final response to human"
}
```

Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.
Thought:
Human: 复兴城市家园和清河家园经的经纬度是120.15235、30.210432 和 120.1531、30.20865,计算他们之间的距离?


======
Action: 
```
{"action": "Calculator", "action_input": "120.15235,30.210432-120.1531,30.20865"}
```
Observation: 210.84897095947352米
Thought:======
System: Respond to the human as helpfully and accurately as possible. You have access to the following tools:

Calculator: Useful for when you need to answer questions about math, args: {{'para': {{'title': 'Para', 'type': 'string'}}}}

Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).

Valid "action" values: "Final Answer" or Calculator

Provide only ONE action per $JSON_BLOB, as shown:

```
{
  "action": $TOOL_NAME,
  "action_input": $INPUT
}
```

Follow this format:

Question: input question to answer
Thought: consider previous and subsequent steps
Action:
```
$JSON_BLOB
```
Observation: action result
... (repeat Thought/Action/Observation N times)
Thought: I know what to respond
Action:
```
{
  "action": "Final Answer",
  "action_input": "Final response to human"
}
```

Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation:.
Thought:
Human: 复兴城市家园和清河家园经的经纬度是120.15235、30.210432 和 120.1531、30.20865,计算他们之间的距离?

This was your previous work (but I haven't seen any of it! I only see what you return as final answer):

Action: 
```
{"action": "Calculator", "action_input": "120.15235,30.210432-120.1531,30.20865"}
```
Observation: 210.84897095947352米
Thought:
======

Action: 
```
{"action": "Final Answer", "action_input": "复兴城市家园和清河家园之间的距离约为210.849米。"}
```

> Finished chain.

参考

相关推荐
攻城狮_Dream几秒前
“探索未来医疗:生成式人工智能在医疗领域的革命性应用“
人工智能·设计·医疗·毕业
学习前端的小z30 分钟前
【AIGC】如何通过ChatGPT轻松制作个性化GPTs应用
人工智能·chatgpt·aigc
埃菲尔铁塔_CV算法1 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法
EasyCVR1 小时前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
打羽毛球吗️1 小时前
机器学习中的两种主要思路:数据驱动与模型驱动
人工智能·机器学习
好喜欢吃红柚子1 小时前
万字长文解读空间、通道注意力机制机制和超详细代码逐行分析(SE,CBAM,SGE,CA,ECA,TA)
人工智能·pytorch·python·计算机视觉·cnn
小馒头学python1 小时前
机器学习是什么?AIGC又是什么?机器学习与AIGC未来科技的双引擎
人工智能·python·机器学习
神奇夜光杯2 小时前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
正义的彬彬侠2 小时前
《XGBoost算法的原理推导》12-14决策树复杂度的正则化项 公式解析
人工智能·决策树·机器学习·集成学习·boosting·xgboost
Debroon2 小时前
RuleAlign 规则对齐框架:将医生的诊断规则形式化并注入模型,无需额外人工标注的自动对齐方法
人工智能