# GLM-4-9B-Chat-1M代码实例:调用Function Call的Python脚本
## 1. 引言:为什么需要Function Call?
想象一下,你有一个能读懂200万字文档的AI助手,但它只能回答你的问题,却不能帮你执行实际的操作。比如你想让它查天气、发邮件、或者分析数据,它只能告诉你"该怎么做",却不能"直接帮你做"。
这就是Function Call的价值所在。通过Function Call,你可以让GLM-4-9B-Chat-1M模型不仅理解你的需求,还能调用你预先定义好的函数来执行具体的任务。就像给AI装上了"手和脚",让它从单纯的聊天助手变成了能真正帮你干活的智能助手。
本文将手把手教你如何用Python脚本调用GLM-4-9B-Chat-1M的Function Call功能,让你快速上手这个强大的能力。
## 2. 环境准备与安装
在开始之前,我们需要准备好运行环境。GLM-4-9B-Chat-1M对硬件要求相对友好,但还是要确保你的设备满足基本要求。
### 2.1 硬件要求
- **显存要求**:至少18GB(FP16版本)或9GB(INT4量化版本)
- **推荐配置**:RTX 3090/4090或同等级别显卡
- **内存**:建议32GB以上系统内存
- **存储**:需要20GB以上空闲空间存放模型文件
### 2.2 软件环境安装
首先创建并激活Python虚拟环境:
```bash
# 创建虚拟环境
python -m venv glm4-env
# 激活环境(Linux/Mac)
source glm4-env/bin/activate
# 激活环境(Windows)
glm4-env\Scripts\activate
```
然后安装必要的Python包:
```bash
pip install transformers torch accelerate
```
如果你打算使用vLLM来加速推理,还可以安装:
```bash
pip install vllm
```
## 3. 基础概念:什么是Function Call?
Function Call就像教AI使用工具。你提前定义好各种工具(函数),然后告诉AI这些工具是干什么用的、怎么用。当AI理解你的需求后,它会判断是否需要使用某个工具,并生成正确的使用方式。
举个例子,你定义了一个"查天气"的函数,当用户问"今天天气怎么样?"时,AI不会直接回答"我不知道",而是会说"我需要调用查天气函数来帮你获取信息"。
GLM-4-9B-Chat-1M原生支持Function Call,你不需要额外训练,只需要按照规定的格式告诉AI有哪些函数可用即可。
## 4. 第一个Function Call示例
让我们从一个简单的例子开始,创建一个查询天气的函数。
### 4.1 定义工具函数
首先,我们定义一个模拟的天气查询函数:
```python
def get_weather(location: str, date: str = None) -> str:
"""
查询指定地点的天气情况
参数:
location: 城市名称,如"北京"、"上海"
date: 日期,格式为"YYYY-MM-DD",默认为今天
返回:
天气情况的字符串描述
"""
# 这里只是模拟实现,实际使用时可以接入真实的天气API
weather_data = {
"北京": {"today": "晴,15°C", "tomorrow": "多云,18°C"},
"上海": {"today": "小雨,20°C", "tomorrow": "阴,22°C"},
"广州": {"today": "晴,25°C", "tomorrow": "晴,27°C"}
}
if date is None:
date = "today"
else:
# 简化处理,只区分今天和明天
date = "tomorrow" if date == "2024-01-19" else "today"
if location in weather_data:
return f"{location} {date}的天气:{weather_data[location][date]}"
else:
return f"找不到{location}的天气信息"
```
### 4.2 创建工具描述
接下来,我们需要用JSON格式描述这个函数,让AI知道这个函数的存在和用法:
```python
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询指定城市的天气情况",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市名称,如北京、上海"
},
"date": {
"type": "string",
"description": "日期,格式为YYYY-MM-DD",
"nullable": True
}
},
"required": ["location"]
}
}
}
]
```
### 4.3 完整的调用代码
现在让我们把所有的代码整合起来:
```python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
# 加载模型和分词器
model_name = "THUDM/glm-4-9b-chat-1m"
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto",
trust_remote_code=True
)
# 定义对话历史
messages = [
{"role": "user", "content": "今天北京的天气怎么样?"}
]
# 第一次调用,让模型决定是否使用Function Call
response = model.chat(
tokenizer,
messages,
tools=tools,
max_length=4096
)
print("模型回复:", response)
# 如果模型决定调用函数,我们会收到一个特殊的响应
if response.tool_calls:
# 提取函数调用信息
tool_call = response.tool_calls[0]
function_name = tool_call.function.name
function_args = tool_call.function.arguments
print(f"模型决定调用函数:{function_name}")
print(f"函数参数:{function_args}")
# 执行相应的函数
if function_name == "get_weather":
# 解析参数
location = function_args.get("location")
date = function_args.get("date")
# 调用函数
weather_result = get_weather(location, date)
print(f"函数执行结果:{weather_result}")
# 将结果返回给模型
messages.append({
"role": "tool",
"content": weather_result,
"tool_call_id": tool_call.id
})
# 让模型基于函数结果生成最终回复
final_response = model.chat(
tokenizer,
messages,
max_length=4096
)
print("最终回复:", final_response)
```
## 5. 实际应用场景示例
Function Call的真正威力在于处理复杂任务。让我们看几个实用的例子。
### 5.1 数据分析场景
假设你有一个数据分析函数,可以处理CSV文件并生成统计信息:
```python
import pandas as pd
def analyze_data(file_path: str, analysis_type: str) -> str:
"""
分析CSV文件数据
参数:
file_path: CSV文件路径
analysis_type: 分析类型,如"summary", "correlation", "trend"
返回:
分析结果的字符串描述
"""
try:
df = pd.read_csv(file_path)
if analysis_type == "summary":
return f"数据概览:\n{df.describe().to_string()}"
elif analysis_type == "correlation":
return f"相关性分析:\n{df.corr().to_string()}"
else:
return "不支持的分析类型"
except Exception as e:
return f"分析失败:{str(e)}"
# 对应的工具描述
data_analysis_tool = {
"type": "function",
"function": {
"name": "analyze_data",
"description": "分析CSV文件数据,提供统计信息",
"parameters": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "CSV文件的路径"
},
"analysis_type": {
"type": "string",
"description": "分析类型:summary(概览), correlation(相关性), trend(趋势)",
"enum": ["summary", "correlation", "trend"]
}
},
"required": ["file_path", "analysis_type"]
}
}
}
```
### 5.2 邮件发送场景
再来看一个发送邮件的例子:
```python
import smtplib
from email.mime.text import MIMEText
def send_email(to_email: str, subject: str, body: str) -> str:
"""
发送电子邮件
参数:
to_email: 收件人邮箱
subject: 邮件主题
body: 邮件正文
返回:
发送结果的字符串描述
"""
# 这里需要配置你的邮箱信息
smtp_server = "smtp.example.com"
smtp_port = 587
from_email = "your_email@example.com"
password = "your_password"
try:
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = from_email
msg['To'] = to_email
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls()
server.login(from_email, password)
server.send_message(msg)
return f"邮件已成功发送至 {to_email}"
except Exception as e:
return f"邮件发送失败:{str(e)}"
# 对应的工具描述
email_tool = {
"type": "function",
"function": {
"name": "send_email",
"description": "发送电子邮件到指定地址",
"parameters": {
"type": "object",
"properties": {
"to_email": {
"type": "string",
"description": "收件人邮箱地址"
},
"subject": {
"type": "string",
"description": "邮件主题"
},
"body": {
"type": "string",
"description": "邮件正文内容"
}
},
"required": ["to_email", "subject", "body"]
}
}
}
```
## 6. 完整的多工具示例
在实际应用中,我们通常会提供多个工具供模型选择。下面是一个完整的示例,展示如何同时使用多个工具。
```python
# 定义多个工具
all_tools = [tools[0], data_analysis_tool, email_tool]
# 复杂的用户请求
messages = [
{
"role": "user",
"content": "请先分析一下sales_data.csv文件的概要信息,然后如果今天北京天气好的话,就给我的同事发邮件说明分析结果"
}
]
# 模型可能会分多个步骤来处理这个复杂请求
response = model.chat(
tokenizer,
messages,
tools=all_tools,
max_length=4096
)
print("第一步回复:", response)
# 处理模型可能发起的多个函数调用
for tool_call in response.tool_calls:
function_name = tool_call.function.name
function_args = tool_call.function.arguments
if function_name == "analyze_data":
# 处理数据分析
result = analyze_data(
function_args["file_path"],
function_args["analysis_type"]
)
messages.append({
"role": "tool",
"content": result,
"tool_call_id": tool_call.id
})
elif function_name == "get_weather":
# 处理天气查询
result = get_weather(
function_args["location"],
function_args.get("date")
)
messages.append({
"role": "tool",
"content": result,
"tool_call_id": tool_call.id
})
elif function_name == "send_email":
# 处理邮件发送
result = send_email(
function_args["to_email"],
function_args["subject"],
function_args["body"]
)
messages.append({
"role": "tool",
"content": result,
"tool_call_id": tool_call.id
})
# 继续对话,让模型基于所有函数结果生成最终回复
final_response = model.chat(
tokenizer,
messages,
max_length=4096
)
print("最终回复:", final_response)
```
## 7. 实用技巧与最佳实践
在使用Function Call时,有一些技巧可以让你的应用更加稳定和高效。
### 7.1 参数验证与错误处理
模型生成的参数可能不完全符合预期,建议添加验证逻辑:
```python
def safe_function_call(function_name, arguments, available_functions):
"""
安全的函数调用封装
参数:
function_name: 函数名称
arguments: 函数参数字典
available_functions: 可用函数映射
返回:
函数执行结果或错误信息
"""
if function_name not in available_functions:
return f"错误:函数 {function_name} 不存在"
func = available_functions[function_name]
try:
# 验证必需参数
required_params = func.__annotations__
for param in required_params:
if param != 'return' and param not in arguments:
return f"错误:缺少必需参数 {param}"
# 调用函数
result = func(**arguments)
return result
except Exception as e:
return f"函数执行错误:{str(e)}"
# 可用函数映射
available_functions = {
"get_weather": get_weather,
"analyze_data": analyze_data,
"send_email": send_email
}
```
### 7.2 性能优化建议
对于复杂的Function Call场景,可以考虑以下优化:
```python
# 使用vLLM加速推理
from vllm import LLM, SamplingParams
# 初始化vLLM
llm = LLM(
model="THUDM/glm-4-9b-chat-1m",
dtype="float16",
gpu_memory_utilization=0.9,
enable_chunked_prefill=True,
max_num_batched_tokens=8192
)
# 批量处理多个请求
sampling_params = SamplingParams(temperature=0.7, max_tokens=1024)
```
## 8. 常见问题解答
**问题1:模型不调用我期望的函数怎么办?**
这可能是因为函数描述不够清晰。确保你的函数描述准确说明了函数的用途和适用场景。你也可以在用户提问时更明确地提示模型使用特定功能。
**问题2:函数参数解析错误怎么办?**
模型生成的参数格式可能不完全正确。建议添加参数验证和错误处理逻辑,对于关键应用,可以要求用户确认参数是否正确。
**问题3:如何处理复杂的多步骤任务?**
对于需要多个函数调用的复杂任务,可以让模型分步骤执行。每次只处理一个函数调用,然后将结果反馈给模型,让它决定下一步操作。
**问题4:Function Call会影响模型的长文本能力吗?**
不会。GLM-4-9B-Chat-1M的1M token上下文长度同样适用于Function Call场景,你可以在处理超长文档的同时使用函数调用功能。
## 9. 总结
通过本文的学习,你应该已经掌握了如何使用GLM-4-9B-Chat-1M的Function Call功能。这个功能让AI模型从被动的问答工具变成了主动的任务执行者,大大扩展了应用场景。
记住几个关键点:
- **定义清晰的函数描述**:让模型准确理解每个函数的用途
- **添加完善的错误处理**:确保函数调用的稳定性
- **利用模型的长文本优势**:在处理超长文档时同样可以使用Function Call
- **循序渐进**:从简单场景开始,逐步构建复杂的多工具应用
Function Call只是GLM-4-9B-Chat-1M强大能力的冰山一角。这个模型在长文本处理、代码执行、多轮对话等方面都有出色表现,值得深入探索和使用。
现在就去尝试创建你自己的Function Call应用吧!从简单的天气查询开始,逐步构建更复杂的自动化工作流,你会发现AI助手的潜力远超你的想象。
---
> **获取更多AI镜像**
>
> 想探索更多AI镜像和应用场景?访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_source=mirror_blog_end),提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。