使用 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.

参考

相关推荐
IT古董1 分钟前
【机器学习】机器学习中用到的高等数学知识-8. 图论 (Graph Theory)
人工智能·机器学习·图论
曼城周杰伦11 分钟前
自然语言处理:第六十三章 阿里Qwen2 & 2.5系列
人工智能·阿里云·语言模型·自然语言处理·chatgpt·nlp·gpt-3
余炜yw1 小时前
【LSTM实战】跨越千年,赋诗成文:用LSTM重现唐诗的韵律与情感
人工智能·rnn·深度学习
莫叫石榴姐1 小时前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
96771 小时前
对抗样本存在的原因
深度学习
如若1232 小时前
利用 `OpenCV` 和 `Matplotlib` 库进行图像读取、颜色空间转换、掩膜创建、颜色替换
人工智能·opencv·matplotlib
YRr YRr2 小时前
深度学习:神经网络中的损失函数的使用
人工智能·深度学习·神经网络
ChaseDreamRunner2 小时前
迁移学习理论与应用
人工智能·机器学习·迁移学习
Guofu_Liao2 小时前
大语言模型---梯度的简单介绍;梯度的定义;梯度计算的方法
人工智能·语言模型·矩阵·llama
我爱学Python!2 小时前
大语言模型与图结构的融合: 推荐系统中的新兴范式
人工智能·语言模型·自然语言处理·langchain·llm·大语言模型·推荐系统