跳到主要内容

DeepSeek Function calling功能详解

课程说明:

  体验课时间有限,若想深度学习大模型技术,欢迎大家报名由我主讲的《2025大模型Agent智能体开发实战》(春季班)

d0c81dfe43a1becced8c07db33c3a787_

《2025大模型Agent智能体开发实战》(春季班) 为【100+小时】体系大课,总共20大模块精讲精析,零基础直达大模型企业级应用!

img

重磅新增DeepSeek+QwQ+OpenAI responses API+MCP技术应用与智能体开发相关实战内容:

image-20250318200619255

此外,若是对大模型底层原理感兴趣,也欢迎报名由我和菜菜老师共同主讲的《2025大模型原理与实战课程》(3月班)

8ac8006d9de5c40971271ac7e0273bf

两门大模型课程春季班目前上新特惠中,立减2000起,合购还有更多优惠哦~详细信息扫码添加助教,回复“大模型”,即可领取课程大纲&查看课程详情👇

3af67537da57cc7fc39a9c3ebdeecdd

DeepSeek智能体开发实战

Part 2.DeepSeek Function calling功能详解

一、DeepSeek在线API接入指南

1.DeepSeek账号注册与API获取

  在调用DeepSeek API之前,需要先完成注册,并获取对应的API-KEY。DeepSeek官网地址:https://www.deepseek.com/

image-20250327173819455

点击API开放平台,开始注册。注册完成后即可进入到个人主页,可在其中进行充值:

image-20250107155925049

目前DeepSeek按照统一模型名称进行命名,其中deepseek-chat指的是最新版DeepSeek-V3-0324模型,而deepseek-reasoner则指的是最新版DeepSeek-R1模型。其中两款模型定价如下:

image-20250327173652790

目前API调用暂时不限速:

image-20250107160659366

且模型调用风格和OpenAI完全一致,而deepseek-chat模型还支持Function calling、提示词缓存、Json Output等Agent开发关键功能。

image-20250107161014344 image-20250107161058708

需要注意的是,deepseek-reasoner(DeepSeek-R1)模型并不支持Function calling、提示词缓存、Json Output等功能:

image-20250327174215476

2.DeepSeek API-KEY获取与DeepSeek-V3-0324模型调用流程

  接下来需要在官网申请API-KEY:https://platform.deepseek.com/api_keys

image-20250107162553252 image-20250107162642821

由于DeepSeek采用OpenAI风格API,因此需要先安装OpenAI库:

!pip install openai

然后按照如下代码进行调用:

import openai
openai.__version__
from openai import OpenAI
ds_api_key = 'YOUR_DS_API_KEY'
import os
ds_api_key = os.getenv("DS_API_KEY")
# 实例化客户端
client = OpenAI(api_key=ds_api_key,
base_url="https://api.deepseek.com")
# 调用 deepseekv3 模型
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "user", "content": "你好,好久不见!"}
]
)

本节公开课仍然采用chat.completions进行模型调用,而目前OpenAI已发布最新版Responses API,后续各大厂商或许会兼容Responses API进行模型调用。

# 输出生成的响应内容
print(response.choices[0].message.content)

模型完整回复内容如下:

response

同样,我们也可以按照如下方式查看DeepSeek目前支持的模型范围:

models_list = client.models.list()
models_list.data

  DeepSeek v3 模型属于聊天补全(chat completion)模型,模型提供了多种参数,帮助开发者定制化模型的生成行为。以下是对主要参数的详细解释,以及如何在 Python 中使用这些参数进行请求。

3.DeepSeek API调用过程中参数介绍

3.1 核心参数:messages参数

  messages 参数是 DeepSeek v3 模型 API 中必填的参数之一,用于定义聊天上下文,包括用户的输入、系统的指令、助手的回复等。通过 messages 数组,模型可以理解当前对话的背景,从而生成更加连贯的响应。根据不同的使用场景,messages 包含多种类型的消息,例如 system messageuser messageassistant message。下面是对 messages 参数及其各个子类型的详细解释。

3.1.1 System message

  system message 用于设置系统消息,通常由开发者设定,以指导模型如何进行对话。这类消息可以定义规则或约束,并提供有关对话的背景信息。

  • content (必填):系统消息的内容,可以是字符串或数组。如果是数组,可能包含多个类型的内容(如文本、图像)。
  • role (必填):此处角色为 system,表明这是系统发出的消息。
  • name (可选):提供系统消息发送者的名称,尤其适用于区分多个具有相同角色的参与者。

示例: FENCE0

# 定义一个字典,键为'system_message',用于存储系统消息
system_message = {
# 'role'键对应的值是一个字符串"system",表示消息的发送者是系统
"role": "system",
# 'content'键对应的值是一个字符串,表示系统消息的内容
"content": "你是一位大学教授。"
}
3.1.2 User message

user message 表示用户发给模型的消息,是对话的核心部分之一。它定义了用户的输入内容,模型根据这些内容生成响应。

  • content (必填):用户消息的内容,通常为文本或图像链接的数组。对于支持图像输入的模型,如 DeepSeek v2.5 ,还可以传递图像。
    • 文本内容:单纯的字符串形式,用户输入的文本。
    • 数组形式的内容:由文本或图像链接组成的数组,可以同时传递多张图像或多段文本内容。
  • role (必填):角色为 user,表示该消息来自用户。
  • name (可选):可以为用户指定一个名称,用于区分多个具有相同角色的用户。

示例: FENCE0

# 创建用户消息
user_message = {
"role": "user",
"content": "你好,请介绍下你自己。"
}
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
system_message,
user_message
]
)
# 输出生成的响应内容
print(response.choices[0].message.content)
  • 测试切换角色
system_message = {"role": "system","content": "你是一名马戏团小丑。"}
user_message = {"role": "user","content": "请帮我介绍下什么是机器学习。"}
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
system_message,
user_message
]
)

print(response.choices[0].message.content)

3.2 模型其他参数介绍

DeepSeek-v3模型 参数汇总表

参数名类型必填/可选默认值说明
modelstring必填指定要使用的模型 ID,例如 deepseek-chatdeepseek-reasoner
storeboolean or null可选false是否存储本次对话的输出,供模型精炼或评估产品使用。
metadataobject or null可选null开发者自定义的标签和值,用于过滤仪表盘中的补全结果。
frequency_penaltynumber or null可选0数值在 -2.02.0 之间,正值减少重复生成内容的可能性。
logit_biasmap可选null调整某些特定 tokens 出现的可能性,值在 -100100 之间。
logprobsboolean or null可选false是否返回生成的每个 token 的对数概率。
top_logprobsinteger or null可选null指定返回最有可能出现的前几个 tokens 及其概率,需开启 logprobs
max_completion_tokensinteger or null可选null指定模型生成的最大 token 数,包括可见文本和推理 tokens。
ninteger or null可选1每个输入生成的对话补全选项数量,值越大,生成的回复越多。
presence_penaltynumber or null可选0数值在 -2.02.0 之间,正值鼓励生成新的主题和内容。
response_formatobject可选null指定生成结果的格式,可以设置为 json_schema 以确保结构化输出,或 json_object 用于 JSON 格式。
seedinteger or null可选null保持生成的一致性,重复相同请求将尽量生成相同的结果。
service_tierstring or null可选auto指定服务延迟等级,适用于付费订阅用户,默认为 auto
stopstring / array / null可选null最多指定 4 个序列,API 遇到这些序列时会停止生成进一步的 tokens。
streamboolean or null可选false是否启用流式响应,若启用,生成的 tokens 将逐步返回。
stream_optionsobject or null可选null流式响应的选项,仅当 streamtrue 时设置。
temperaturenumber or null可选1控制生成输出的随机性,值越高生成的文本越随机。建议调整此值或 top_p,而不是同时调整。
top_pnumber or null可选1使用核采样方法,选择最有可能的 tokens,总概率达到 top_p 百分比。建议与 temperature 二选一。
toolsarray可选null模型可以调用的工具列表,目前仅支持函数调用。
userstring可选null表示最终用户的唯一标识符,用于监控和检测滥用行为。

参数解释:

  1. 模型和输出相关参数

    • model 是必填参数,决定使用哪个模型(如 deepseek-chat deepseek-code)。
    • store 控制是否存储生成的对话结果,便于后续模型训练或评估。
    • metadata 用于添加开发者自定义的标签,便于在仪表盘中过滤补全结果。
    • max_completion_tokensn 控制生成内容的数量和长度,帮助管理生成成本。
  2. 生成行为控制

    • frequency_penaltypresence_penalty 都用于影响生成结果的内容重复度和新颖性。
    • logit_bias 是用于调整特定 token 出现概率的高级控制工具。
    • temperaturetop_p 通过不同的方式控制生成结果的随机性,建议选其一进行调整。
  3. 高级功能

    • logprobstop_logprobs 用于返回每个 token 的概率信息,适合对模型输出进行更细粒度分析。
    • stream 启用后会实时返回生成的结果,适用于需要逐步展示内容的场景。
    • tools 允许模型调用外部工具(如函数),适用于扩展模型的功能。
  4. 服务和用户相关参数

    • service_tier 控制服务的延迟和稳定性,适合高性能要求的付费用户。
    • user 用于标识最终用户,有助于监控使用行为,防止滥用。

4.借助Messages参数构建多轮对话机器人

  • 构建多轮对话机器人
import re
from IPython.display import display, Code, Markdown
from IPython.display import display, Markdown

def chat_with_DeepSeek(client, messages):
"""
使用 DeepSeek 模型进行多轮对话。

参数:
client: 实例化的 OpenAI 客户端。
messages (list): 对话上下文消息列表。

返回:
str: 模型生成的回复文本。
"""
response = client.chat.completions.create(
model="deepseek-chat",
messages=messages
)
return response.choices[0].message.content

def multi_round_chat(client):
"""
多轮对话机器人示例函数,支持纯文本对话(不处理 URL)。
用户输入 'exit' 时退出对话。
"""
# 初始化消息列表,加入系统消息
messages = [{"role": "system", "content": "你是一名助人为乐的助手。"}]

while True:
user_input = input("User: ").strip()
if user_input.lower() == 'exit':
print("对话结束。")
break

# 直接构造用户消息
messages.append({"role": "user", "content": user_input})

# 调用 DeepSeek 模型获取回复
assistant_reply = chat_with_DeepSeek(client, messages)
display(Markdown(f"Assistant: {assistant_reply}"))

# 添加助手回复到消息列表中
messages.append({"role": "assistant", "content": assistant_reply})
multi_round_chat(client)
  • 对比第一代DeepSeek-V3模型问答效果:
# 调用多轮对话机器人函数
multi_round_chat()

二、DeepSeek-V3 Function calling功能详解

1.Function calling技术概念介绍

  我们都知道,能调用外部工具,是大模型进化为智能体Agent的关键,如果不能使用外部工具,大模型就只能是个简单的聊天机器人,甚至连查询天气都做不到。由于底层技术限制啊,大模型本身是无法和外部工具直接通信的,因此Function calling的思路,就是创建一个外部函数(function)作为中介,一边传递大模型的请求,另一边调用外部工具,最终让大模型能够间接的调用外部工具。

image-20250318202017508

例如,当我们要查询当前天气时,让大模型调用外部工具的function calling的过程就如图所示:

image-20250318202029130

而完整的一次Function calling执行流程如下:

202412191720637

需要注意的是,对于大模型来说,Function calling的本质,是当模型在特殊情况下的一种特殊响应形式: image-20250327181953725

【选学】2.外部工具OpenWeather注册及API key获取方法

2.1 OpenWeather API获取流程

  OpenWeather是一家提供全球范围内的气象数据服务的公司,该公司的服务包括实时天气信息、天气预报、历史天气数据以及各种气象相关的报告等,并且OpenWeather开放了一定使用限度内完全免费的API,即我们可以在代码环境中通过调用OpenWeather API来进行实时天气查询、天气预报等功能,这意味着开发者可以将OpenWeather的天气预报功能加入到他们自己的应用或网站中。

  为了能够调用OpenWeather服务,和OpenAI的API使用过程类似,我们首先需要先注册OpenWeather账号,并获取OpenWeather API Key。这里需要注意的是,对于大多数在线服务的API来说,都需要通过API key来进行身份验证,尽管OpenWeather相对更加Open,有非常多的免费使用的次数,但身份验证仍然是必要的防止API被滥用的有效手段。OpenWeather API key获取流程如下:

  • Step 1.登录OpenWeather官网并点击Sign—>create account完成注册。该网站无需魔法即可直接登录,可以使用国内邮箱或者QQ邮箱均可进行注册,官网地址为:https://openweathermap.org/
e9a6286c483ccf21ab96af1972a918b 577e19b46f4c124b50a0455ccc132e9
  • Step 2.获取API-key:注册完成后,即可在API keys页面查看当前账户的API key:
f44ba05a810500a61516caa28a4fcb4 e497a7ebb4f8d50ff3b6e362e4b569a

一般来说完成注册后,就会有一个已经激活的API-key。和OpenAI一样,OpenWeather的API key也创建多个。

  • Step 3.将其设置为环境变量:和OpenAI API key类似,为了方便后续调用,我们也可以直接将OpenWeather API key设置为环境变量,变量名为OPENWEATHER_API_KEY。具体设置环境变量的方法参考Ch.1中OpenAI APkey设置环境变量流程,此处不再赘述。
aa0f15de151921727c20918fccc8de0

设置完了环境变量之后,接下来即可按照如下方式创建OpenWeather API key变量:

open_weather_key = "YOUR_KEY"

2.2 利用OpenWeather API获取实时天气信息

  接下来我们通过一个简单的示例,来介绍如何通过OpenWeather API获取实时天气信息:

import requests
import json
# Step 1.构建请求
url = "https://api.openweathermap.org/data/2.5/weather"

# Step 2.设置查询参数
params = {
"q": "Beijing", # 查询北京实时天气
"appid": open_weather_key, # 输入API key
"units": "metric", # 使用摄氏度而不是华氏度
"lang":"zh_cn" # 输出语言为简体中文
}

# Step 3.发送GET请求
response = requests.get(url, params=params)

# Step 4.解析响应
data = response.json()

这里需要注意的是,城市名必须输入英文名,否则无法正确识别。接下来查看返回结果。首先我们先查看response结果:

response
type(response)

在未解析之前,我们只能查看到基本请求结果状态,这里的200代表成功相应,即本次发送请求获得了对应的响应,且响应内容包含在response中。考虑到默认情况下返回结果是JSON格式,因此后续代码使用了response.json()对其进行解析。解析内容如下:

data
def get_weather(loc):
"""
查询即时天气函数
:param loc: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing';
:return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
"""
# Step 1.构建请求
url = "https://api.openweathermap.org/data/2.5/weather"

# Step 2.设置查询参数
params = {
"q": loc,
"appid": open_weather_key, # 输入API key
"units": "metric", # 使用摄氏度而不是华氏度
"lang":"zh_cn" # 输出语言为简体中文
}

# Step 3.发送GET请求
response = requests.get(url, params=params)

# Step 4.解析响应
data = response.json()
return json.dumps(data)

3.Function calling完整执行流程

  在准备好外部函数及函数库之后,接下来非常重要的一步就是需要将外部函数的信息以某种形式传输给Chat模型。此时就需要使用到ChatCompletion.create函数的functions参数,类似于messages参数是用于向模型传输消息,functions参数专门用于向模型传递当前可以调用的外部函数信息。并且,从参数的具体形式来看,functions参数和messages参数也是非常类似的——都是包含多个字典的list。对于messages来说,每个字典都是一条信息,而对于functions参数来说,每个字典都是一个函数。在大语言模型实际进行问答时,会根据functions参数提供的信息对各函数进行检索。

  很明显,functions参数对于Chat模型的Function calling功能的实现至关重要。接下来我们详细解释functions中每个用于描述函数的字典编写方法。总的来说,每个字典都有三个参数(三组键值对),各参数(Key)名称及解释如下:

  • name:代表函数函数名称字的符串,必选参数,按照要求函数名称必须是 a-z、A-Z、0-9,或包含下划线和破折号,最大长度为 64。需要注意的是,name必须输入函数名称,而后续模型将根据函数名称在外部函数库中进行函数筛选;
  • description:用于描述函数功能的字符串,虽然是可选参数,但该参数传递的信息实际上是Chat模型对函数功能识别的核心依据。即Chat函数实际上是通过每个函数的description来判断当前函数的实际功能的,若要实现多个备选函数的智能挑选,则需要严谨详细的描述函数功能;(需要注意的是,在某些情况下,我们会通过其他函数标注本次对话特指的函数,此时模型就不会执行这个根据描述信息进行函数挑选的过程,此时是可以不设置description的。)
  • parameters:函数参数,必选参数,要求遵照JSON Schema格式进行输入,JSON Schema是一种特殊的JSON对象,专门用于验证JSON数据格式是否满足要求。

  例如,对于get_weather函数,我们需要创建如下字典来对其进行完整描述:

tools = [
{
"type": "function",
"function":{
'name': 'get_weather',
'description': '查询即时天气函数,根据输入的城市名称,查询对应城市的实时天气,一次只能输入一个城市名称',
'parameters': {
'type': 'object',
'properties': {
'loc': {
'description': "城市名称,注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing'",
'type': 'string'
}
},
'required': ['loc']
}
}
}
]

同时还需要封装外部函数库,用于关联外部函数名称和外部函数对象

available_functions = {
"get_weather": get_weather,
}

3.1 First response

  在进行了一系列基础准备工作之后,接下来我们尝试在Chat模型对话执行Function calling功能。这里我们创建如下messages:

# 实例化客户端
client = OpenAI(api_key=ds_api_key,
base_url="https://api.deepseek.com")
messages=[
{"role": "user", "content": "请帮我查询北京地区今日天气情况"}
]

首先我们测试如果只输入这个信息而不输入外部函数库的时候,模型能否知道如何查询天气:

response = client.chat.completions.create(
model="deepseek-chat",
messages=messages
)
response
response.choices[0].message.content
response.choices[0].finish_reason

很明显,模型无法进行回答。接下来开启Function calling功能:

response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "user", "content": "请帮我查询北京地区今日天气情况"}
],
tools=tools,
)

观察此时response结果:

response

此时模型回复结果为空:

response.choices[0].message.content

而模型停止输出的原因是发起了tool_calls

response.choices[0].finish_reason

而此时模型tool_calls的全部信息都保存在message.tool_calls中:

response.choices[0].message.tool_calls

该对象是一个列表,如果此时只有一次工具调用,则只会有一个ChatCompletionMessageToolCall对象。

response_message = response.choices[0].message
response_message

能够发现,此时返回的message中content为空,而增了一个"tool_calls"的list,该list就包含了当前调用外部函数的全部信息:

response_message.tool_calls
response_message.tool_calls[0]

对于当前CompletionMessageToolCall对象,id为外部函数调用发起请求id,function则表示调用外部函数基本信息,而type则代表了当前当前调用外部函数类型,function代表调用自定义的外部函数。

response_message.tool_calls[0].id
response_message.tool_calls[0].function

我们可以在此基础上分别提取调用外部函数名称信息和参数信息,分别保存为function_name和function_args对象:

# 完成对话需要调用的函数名称
function_name = response_message.tool_calls[0].function.name
function_name
# 具体的函数对象
fuction_to_call = available_functions[function_name]
fuction_to_call
response_message.tool_calls[0].function.arguments
# 执行该函数所需要的参数
function_args = json.loads(response_message.tool_calls[0].function.arguments)
function_args

需要注意的是,外部函数的计算过程仍然是在本地执行,即Chat模型并不会将代码读取到服务器上再进行在线计算,因此接下来我们需要根据模型返回的函数和函数参数,在本地完成函数计算,然后再将计算过程和结果保存为message并追加到messages后面,并第二次调用Chat模型分析函数的计算结果,并最终根据函数计算结果输出用户问题的答案。

202412191720637

3.2 Second response

  这里我们只需要借助**方法,直接将function_args对象传入fuction_to_call中,即可一次性传输全部参数,**方法的功能可以参考如下示例:

def function_to_call_test(a, b, c):
return a + b + c

function_args_test = {'a': 1, 'b': 2, 'c': 3}

result = function_to_call_test(**function_args_test)

print(result)

**方法其实是一种较为特殊、但同时也非常便捷的参数传递方法吗,该方法会将字典中的每个key对应的value传输到同名参数位中。接下来我们将function_args对象传入fuction_to_call中并完成计算:

function_response = fuction_to_call(**function_args)
function_response

能够发现,模型已经顺利完成计算。接下来我们在messages对象中追加两条消息,第一条消息是第一次模型返回的结果(即调用模型的assistant message),第二条消息则是外部函数计算结果,该条消息的role为function,且name为函数名称。这也是我们首次接触function message,和user、system、assistant message不同,function message必须要输入关键词name,且function message的内容源于外部函数执行的计算结果,并且需要手动进行输入。具体添加过程如下:

messages

然后使用如下方法,将第一轮响应结果转化为message格式:

response_message.model_dump()
# 追加第一次模型返回结果消息
messages.append(response_message.model_dump())
messages
function_response
# 追加function返回消息
messages.append({
"role": "tool",
"content": function_response,
"tool_call_id":response_message.tool_calls[0].id
})
messages

接下来,再次调用Chat模型来围绕messages进行回答。需要注意的是,此时我们不再需要向模型重复提问,只需要简单的将我们已经准备好的messages传入Chat模型即可:

second_response = client.chat.completions.create(
model="deepseek-chat",
messages=messages,
tools=tools)
second_response.choices[0].message

能够发现,模型最终做出了准确回答。并且此时finish_reason为stop

second_response.choices[0].finish_reason
202412191720637

3.3 完整函数封装

def run_conv(messages,
api_key,
tools=None,
functions_list=None,
model="deepseek-chat"):
"""
能够自动执行外部函数调用的Chat对话模型
:param messages: 必要参数,输入到Chat模型的messages参数对象
:param api_key: 必要参数,调用模型的API-KEY
:param tools: 可选参数,默认为None,可以设置为包含全部外部函数的列表对象
:param model: Chat模型,可选参数,默认模型为deepseek-chat
:return:Chat模型输出结果
"""
user_messages = messages

client = OpenAI(api_key=api_key,
base_url="https://api.deepseek.com")

# 如果没有外部函数库,则执行普通的对话任务
if tools == None:
response = client.chat.completions.create(
model=model,
messages=user_messages
)
final_response = response.choices[0].message.content

# 若存在外部函数库,则需要灵活选取外部函数并进行回答
else:
# 创建外部函数库字典
available_functions = {func.__name__: func for func in functions_list}

# 创建包含用户问题的message
messages = user_messages

# first response
response = client.chat.completions.create(
model=model,
messages=user_messages,
tools=tools,
)
response_message = response.choices[0].message

# 获取函数名
function_name = response_message.tool_calls[0].function.name
# 获取函数对象
fuction_to_call = available_functions[function_name]
# 获取函数参数
function_args = json.loads(response_message.tool_calls[0].function.arguments)

# 将函数参数输入到函数中,获取函数计算结果
function_response = fuction_to_call(**function_args)

# messages中拼接first response消息
user_messages.append(response_message.model_dump())

# messages中拼接外部函数输出结果
user_messages.append(
{
"role": "tool",
"content": function_response,
"tool_call_id":response_message.tool_calls[0].id
}
)

# 第二次调用模型
second_response = client.chat.completions.create(
model=model,
messages=user_messages)

# 获取最终结果
final_response = second_response.choices[0].message.content
return display(Markdown(f"Assistant: {final_response}"))
messages = [{"role": "user", "content": "请问什么是机器学习?"}]
run_conv(messages=messages,
api_key = ds_api_key)
messages = [{"role": "user", "content": "请问北京今天天气如何?"}]
run_conv(messages=messages,
api_key = ds_api_key,
tools=tools,
functions_list=[get_weather])

二、更多外部工具调用流程

1.NL2Python工具

def python_inter(py_code):
"""
运行用户提供的 Python 代码,并返回执行结果。

:param py_code: 字符串形式的 Python 代码
:return: 代码运行的最终结果
"""
g = globals()

try:
# 若是表达式,直接运行并返回
result = eval(py_code, g)
return json.dumps(str(result), ensure_ascii=False)

except Exception:
global_vars_before = set(g.keys())
try:
exec(py_code, g)
except Exception as e:
return json.dumps(f"代码执行时报错: {e}", ensure_ascii=False)

global_vars_after = set(g.keys())
new_vars = global_vars_after - global_vars_before

if new_vars:
# 只返回可序列化的变量值
safe_result = {}
for var in new_vars:
try:
json.dumps(g[var]) # 尝试序列化,确保可以转换为 JSON
safe_result[var] = g[var]
except (TypeError, OverflowError):
safe_result[var] = str(g[var]) # 如果不能序列化,则转换为字符串

return json.dumps(safe_result, ensure_ascii=False)

else:
return json.dumps("已经顺利执行代码", ensure_ascii=False)
tools = [
{
"type": "function",
"function":{
'name': 'python_inter',
'description': '运行用户提供的 Python 代码,并返回执行结果。',
'parameters': {
'type': 'object',
'properties': {
'py_code': {
'description': "字符串形式的 Python 代码",
'type': 'string'
}
},
'required': ['py_code']
}
}
}
]
messages = [{"role": "user", "content": "请帮我用Python代码模拟一组数据,来绘制核密度分布图。"}]
run_conv(messages=messages,
api_key = ds_api_key,
tools=tools,
functions_list=[python_inter])

2.NL2SQL工具

import pymysql
def sql_inter(sql_query):
"""
查询本地MySQL数据库,通过运行一段SQL代码来进行数据库查询。\
:param sql_query: 字符串形式的SQL查询语句,用于执行对MySQL中school数据库中各张表进行查询,并获得各表中的各类相关信息
:return:sql_query在MySQL中的运行结果。
"""

connection = pymysql.connect(
host='localhost', # 数据库地址
user='root', # 数据库用户名
passwd='123', # 数据库密码
db='telco_db', # 数据库名
charset='utf8' # 字符集选择utf8
)

try:
with connection.cursor() as cursor:
# SQL查询语句
sql = sql_query
cursor.execute(sql)

# 获取查询结果
results = cursor.fetchall()

finally:
connection.close()


return json.dumps(results)
tools = [
{
"type": "function",
"function":{
'name': 'sql_inter',
'description': '查询本地MySQL数据库,通过运行一段SQL代码来进行数据库查询。',
'parameters': {
'type': 'object',
'properties': {
'sql_query': {
'description': "字符串形式的SQL查询语句,用于执行对MySQL中school数据库中各张表进行查询,并获得各表中的各类相关信息",
'type': 'string'
}
},
'required': ['sql_query']
}
}
}
]
messages = [{"role": "user", "content": "请帮我查询当前数据库中,总共有几张表。"}]
run_conv(messages=messages,
api_key = ds_api_key,
tools=tools,
functions_list=[sql_inter])
image-20250327191505886