一、Code Interpreter工具概述
Code Interpreter(代码解释器)是OpenAI官方提供的内置工具,它能够把用户的需求转换到Python代码的沙盒环境中运行,在数学计算、文本分析以及数据分析等场景发挥重要作用,常被用于处理表格数据,如进行数学分析、绘制图表等任务。
二、使用Code Interpreter的费用及注意事项
使用该工具时,每次会话会收取0.03美元的费用,每个会话的有效时长为一小时。在同一线程中与代码解释器交互,一小时内仅需支付一次费用;若在不同线程中同时调用代码解释器,会创建多个会话,从而产生多次收费。所以在使用过程中,要避免频繁创建新线程,以防止费用增加。
三、Code Interpreter工具的实践应用
- 初始化OpenAI客户端
from openai import OpenAI
# 从openai库中导入OpenAI类,用于创建OpenAI客户端实例
client = OpenAI()
# 创建OpenAI客户端实例,后续通过该实例调用OpenAI的相关API
- 启用代码解释器
assistant = client.assistants.create(
name="Data Engineer", # 将助手命名为“数据分析师”,方便识别和管理
instructions="You're a weather data analyst. When asked for data information, write and run code to answer the question", # 设定助手的任务,明确其作为气象数据分析师,在被询问数据信息时,需编写并运行代码来回答问题
tools=[
{"type": "code_interpreter"}
],
# 在tools参数中指定使用代码解释器工具,使助手具备执行代码的能力
model="gpt-4o-mini-2024-07-18"
# 选择使用的模型为gpt-4o-mini-2024-07-18,不同模型在性能和功能上可能存在差异
)
若希望增强代码解释器的使用概率,可以在instructions
中明确提示,例如“编写代码来解决这个问题”,这样能引导GPT模型更倾向于使用代码解释器来执行任务。
3. 创建线程
thread = client.threads.create()
# 创建一个新的线程,每个线程开启新的Code Interpreter会产生新的计费,所以要谨慎创建
thread_id = thread.id
# 获取新创建线程的ID,后续在与线程相关的操作中会用到该ID
- 传递文件给代码解释器
file = client.files.create(
file=open("./data/weather_data_complex.csv", "rb"),
# 以二进制读取模式打开本地的天气数据文件weather_data_complex.csv,准备上传到OpenAI服务器
purpose='assistants'
# 指定文件用途为assistants,表明该文件用于辅助助手完成任务
)
file_id = file.id
# 获取上传文件的ID,这个ID在后续让代码解释器基于该文件进行分析时会用到
若要让代码解释器基于上传的文件进行分析,可使用assist.update
方法更新Assistant对象,传递文件ID:
assistant = client.assistants.update(
assistant_id=assistant.id,
# 指定要更新的助手ID,确保更新的是正确的Assistant对象
tool_resources={
"code_interpreter": {
"file_ids": [file_id]
}
}
# 在tool_resources参数中,为code_interpreter指定要处理的文件ID列表,这里只包含刚上传的文件ID
)
- 创建消息并执行Run状态
构建新消息并追加到现有线程中,提出数据分析需求,如分析城市实时天气数据并绘制折线图:
thread_message = client.threads.messages.create(
thread_id=thread.id,
# 指定消息所属的线程ID,确保消息被添加到正确的线程中
role="user",
# 设定消息的角色为“user”,表示这是用户发出的消息
content="请帮我分析各个城市的实时天气数据,并绘制折线图"
# 消息的内容,即用户的需求,要求助手分析城市实时天气数据并绘制折线图
)
接着创建Run状态,让Assistant对象处理用户请求:
run = client.threads.runs.create(
thread_id=thread.id,
# 指定线程ID,让助手在该线程中执行任务
assistant_id=assistant.id
# 指定执行任务的助手ID
)
Run开始运行后会进入queued
排队状态,需要等待一段时间才能完成。可通过client.threads.messages.list
方法获取最终结果:
messages = client.threads.messages.list(
thread_id=thread.id
# 指定要获取消息的线程ID,获取该线程中的所有消息
)
last_message = messages.data[0]
# 从获取到的消息列表中,取第一个消息(通常是助手的回复,因为这里只创建了一条用户消息,助手的回复是列表中的第一条)
- 处理代码解释器的输出:代码解释器除生成文本外,还可输出文件,包括图片类型和数据文件(如
.csv
文件)。
- 下载图片文件:若生成的是图片文件,可从最终消息响应的
file_id
字段获取图片的文件ID,通过以下代码下载:
file_id = last_message.content[0].image_file.file_id
# 从消息内容的第一个元素(假设是包含图片文件信息的对象)中获取图片的文件ID
image_data = client.files.content(file_id=file_id)
# 使用client.files.content方法,根据文件ID获取图片文件的内容
image_data_bytes = image_data.read()
# 读取图片文件内容为字节流
with open("./my-image.png", "wb") as file:
# 以二进制写入模式打开本地文件my-image.png
file.write(image_data_bytes)
# 将图片字节流写入该文件,实现图片下载到本地
- 下载数据文件:当代码解释器生成数据文件(如
.csv
文件)并返回文件路径注释时,需提取注释中的文件ID进行下载。示例代码如下:
file_id = last_message.content[0].text.annotations[0].file_path.file_id
# 从消息文本的注释中,获取生成的.csv文件的文件ID
file_data = client.files.content(file_id)
# 使用client.files.content方法,根据文件ID获取数据文件的内容
file_data_bytes = file_data.read()
# 读取文件内容为字节流
with open("./sorted_cities_by_temperature.csv", "wb") as file:
# 以二进制写入模式打开本地文件sorted_cities_by_temperature.csv
file.write(file_data_bytes)
# 将文件字节流写入该文件,实现.csv文件下载到本地
四、总结
Code Interpreter工具在数据分析等领域有着重要的应用价值。在使用过程中,务必注意其收费机制,避免因频繁创建新线程而增加费用。熟练掌握文件处理和结果下载的方法,能够帮助我们在实际应用中更高效地利用该工具进行数据处理和分析工作。
# 导入OpenAI库
from openai import OpenAI
# 创建OpenAI客户端实例
client = OpenAI()
# 创建一个Assistant对象
# name参数为助手名称,设定为Data Engineer(数据分析师)
# instructions描述助手的任务,这里设定为气象数据分析师,要求编写并运行代码回答数据相关问题
# tools列表中指定使用code_interpreter工具
# model选择gpt-4o-mini-2024-07-18模型
assistant = client.beta.assistants.create(
name="Data Engineer",
instructions="You're a weather data analyst. When asked for data information, write and run code to answer the question",
tools=[
{"type": "code_interpreter"}
],
model="gpt-4o-mini-2024-07-18"
)
# 创建一个线程
# 每个线程会开启新的Code interpreter,注意避免频繁创建导致费用增加
thread = client.beta.threads.create()
# 获取线程的ID
thread_id = thread.id
# 上传文件到OpenAI服务器
# open函数以二进制读取模式打开本地的天气数据文件weather_data_complex.csv
# purpose参数指定文件用途为assistants
file = client.files.create(
file=open("./data/weather_data_complex.csv", "rb"),
purpose='assistants'
)
# 获取上传文件的ID
file_id = file.id
# 更新Assistant对象
# assistant_id指定要更新的助手ID
# tool_resources参数中设置code_interpreter的file_ids为刚上传文件的ID,让助手基于该文件进行分析
assistant = client.beta.assistants.update(
assistant_id=assistant.id,
tool_resources={
"code_interpreter": {
"file_ids": [file_id]
}
}
)
# 在当前线程中创建一条消息
# thread_id指定消息所属线程的ID
# role设定消息角色为user(用户)
# content为用户的问题,要求分析城市实时天气数据并绘制折线图
thread_message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="请帮我分析各个城市的实时天气数据,并绘制折线图"
)
# 在当前线程中创建一个Run
# thread_id指定线程ID
# assistant_id指定助手ID,让助手在该线程中执行任务
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id
)
# 获取线程中的消息列表
# thread_id指定要获取消息的线程ID
messages = client.beta.threads.messages.list(
thread_id=thread.id
)
# 获取最新的消息(通常是助手的回复)
last_message = messages.data[0]
# 从消息内容中获取生成的图片文件的file_id
# 假设消息内容的第一个元素是包含图片文件信息的对象
file_id = last_message.content[0].image_file.file_id
# 获取图片文件的内容
image_data = client.files.content(file_id=file_id)
# 读取图片文件内容为字节流
image_data_bytes = image_data.read()
# 以二进制写入模式打开本地文件my-image.png
# 将图片字节流写入该文件,实现图片下载
with open("./my-image.png", "wb") as file:
file.write(image_data_bytes)
# 再次上传文件(可能是为了新的任务)
file = client.files.create(
file=open("./data/weather_data_complex.csv", "rb"),
purpose='assistants'
)
file_id = file.id
# 在当前线程中创建一条新消息
# thread_id指定线程ID
# role设定为user
# content要求根据平均温度对城市进行排序并生成新的.csv文件供下载
# attachments中指定文件ID和使用的工具为code_interpreter
thread_message = client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="根据平均温度对城市进行排序,并生成一个新的.csv文件供我下载",
attachments=[
{
"file_id": file_id,
"tools": [
{"type": "code_interpreter"}
]
}
]
)
# 创建一个新的Run来处理新的任务
# thread_id指定线程ID
# assistant_id指定助手ID
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id
)
# 获取线程中的消息列表(等待任务完成后获取结果)
messages = client.beta.threads.messages.list(
thread_id=thread.id
)
last_message = messages.data[0]
# 从消息文本的注释中获取生成的.csv文件的file_id
file_id = last_message.content[0].text.annotations[0].file_path.file_id
# 获取.csv文件的内容
file_data = client.files.content(file_id)
# 读取文件内容为字节流
file_data_bytes = file_data.read()
# 以二进制写入模式打开本地文件sorted_cities_by_temperature.csv
# 将文件字节流写入该文件,实现.csv文件下载
with open("./sorted_cities_by_temperature.csv", "wb") as file:
file.write(file_data_bytes)