掌握OpenAI Assistant函数调用:正确提交工具输出的Python指南


掌握openai assistant函数调用:正确提交工具输出的python指南

本文详细阐述了在OpenAI Assistant API中处理函数调用并正确提交工具输出的方法。针对常见的`BadRequestError`问题,文章深入分析了错误原因,并提供了使用`client.beta.threads.runs.submit_tool_outputs`的正确解决方案。通过完整的Python代码示例和注意事项,旨在帮助开发者高效、准确地实现Assistant的函数调用功能,确保API交互的顺畅与可靠。

理解OpenAI Assistant的函数调用机制

OpenAI Assistant API提供了一个强大的功能,允许助手在对话过程中调用外部工具或函数来获取信息或执行操作。当助手需要调用某个函数时,它会将对话状态从“in_progress”转换为“requires_action”,并在run.required_action.submit_tool_outputs.tool_calls中提供需要调用的函数信息,包括函数名和参数。开发者的任务是执行这些函数,并将结果反馈给助手,以便其继续生成响应。

常见的错误与原因分析

许多开发者在首次尝试向Assistant提交函数执行结果时,可能会遇到类似于以下代码片段所示的错误:

# 错误的尝试
message = client.beta.threads.messages.create(
    thread_id=thread.id,
    role="tool", # 错误:此角色不适用于创建新消息来提交工具输出
    content=ret,
)

当尝试使用client.beta.threads.messages.create方法并指定role="tool"来提交函数执行结果时,API会返回openai.BadRequestError: Error code: 400 - {'error': {'message': "1 validation error for Request\nbody -> role\n value is not a valid enumeration member; permitted: 'user' (type=type_error.enum; enum_values=[])", ...}}。

这个错误清晰地表明,client.beta.threads.messages.create方法中的role参数仅接受"user"(用户消息)或"assistant"(助手消息)。它并不是用来提交工具函数执行结果的接口。工具函数的结果需要通过专门的机制来通知Assistant,而不是作为普通对话消息的一部分。

正确的函数结果提交方法

OpenAI Assistant API为提交工具函数执行结果提供了专用的方法:client.beta.threads.runs.submit_tool_outputs。这个方法允许你将一个或多个工具调用的输出结果与特定的运行(Run)关联起来,从而让Assistant能够获取这些结果并继续处理。

腾讯AI 开放平台 腾讯AI 开放平台

腾讯AI开放平台

腾讯AI 开放平台 381 查看详情 腾讯AI 开放平台

其基本用法如下:

run = client.beta.threads.runs.submit_tool_outputs(
  thread_id=thread.id,
  run_id=run.id,
  tool_outputs=[
      {
        "tool_call_id": tool_call_id,
        "output": "your_function_output_string_here",
      },
      # 如果有多个工具调用,可以在这里添加更多字典
    ]
)
  • thread_id: 当前会话的线程ID。
  • run_id: 当前处于requires_action状态的运行ID。
  • tool_outputs: 一个列表,包含所有需要提交的工具输出。每个输出是一个字典,必须包含:
    • tool_call_id: 助手在run.required_action.submit_tool_outputs.tool_calls中提供的具体工具调用的ID。这个ID用于将输出与助手请求的特定函数调用进行匹配。
    • output: 对应工具函数执行后的结果字符串。

完整的示例代码

下面是一个完整的Python示例,演示了如何正确地处理Assistant的函数调用并提交结果:

from openai import OpenAI
import time
import os
import json # 导入json库,用于处理函数参数

# 初始化OpenAI客户端
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) # 建议从环境变量获取API_KEY

# 假设你已经创建并配置了一个Assistant,其ID存储在环境变量中
# 并添加了名为 'funnyfunc' 的工具
# 例如:assistant = client.beta.assistants.create(
#     name="Function Caller Assistant",
#     instructions="You are a helpful assistant that can call the funnyfunc.",
#     model="gpt-4-turbo",
#     tools=[{"type": "function", "function": {"name": "funnyfunc", "description": "Returns a funny value."}}]
# )
# 然后将 assistant.id 存储到环境变量 ALEXA_ASSISTANT_ID_OPENAI 中

assistant_id = os.environ.get("ALEXA_ASSISTANT_ID_OPENAI")
if not assistant_id:
    raise ValueError("请设置环境变量 ALEXA_ASSISTANT_ID_OPENAI 为您的Assistant ID")

# 创建一个新的线程
thread = client.beta.threads.create()

# 辅助函数:等待Run完成
def wait_on_run(run_obj, thread_obj):
    """
    等待Run对象完成执行,并返回最新的Run状态。
    """
    while run_obj.status in ["queued", "in_progress", "cancelling"]:
        time.sleep(0.5) # 适当增加等待时间以减少API调用频率
        run_obj = client.beta.threads.runs.retrieve(
            thread_id=thread_obj.id,
            run_id=run_obj.id,
        )
    return run_obj

# 模拟自定义函数
def funnyfunc():
    """一个简单的模拟函数,返回一个字符串。"""
    print("Executing funnyfunc...")
    return "The funniest number is five!"

# 核心函数:向Assistant提问并处理函数调用
def ask_question_and_handle_tools(question_content):
    """
    向Assistant提问,并处理可能的函数调用。
    """
    # 1. 向线程添加用户消息
    client.beta.threads.messages.create(
        thread_id=thread.id,
        role="user",
        content=question_content,
    )

    # 2. 创建并运行Assistant
    run = client.beta.threads.runs.create(
        thread_id=thread.id,
        assistant_id=assistant_id,
    )

    # 3. 等待Run完成或需要动作
    run = wait_on_run(run, thread)

    # 4. 循环处理 'requires_action' 状态
    while run.status == 'requires_action':
        if run.required_action.type == 'submit_tool_outputs':
            tool_outputs_to_submit = []
            for tool_call in run.required_action.submit_tool_outputs.tool_calls:
                function_name = tool_call.function.name
                tool_call_id = tool_call.id

                # 假设我们只处理 'funnyfunc'
                if function_name == 'funnyfunc':
                    # 在实际应用中,这里会解析 tool_call.function.arguments 并传递给实际函数
                    # 例如:args = json.loads(tool_call.function.arguments)
                    # result = funnyfunc(**args)
                    result = funnyfunc() # 调用模拟函数
                    tool_outputs_to_submit.append({
                        "tool_call_id": tool_call_id,
                        "output": result,
                    })
                else:
                    # 对于未实现的函数,可以返回一个错误或默认值
                    print(f"Warning: Unimplemented function called: {function_name}")
                    tool_outputs_to_submit.append({
                        "tool_call_id": tool_call_id,
                        "output": f"Error: Function '{function_name}' not implemented.",
                    })

            # 提交工具输出
            run = client.beta.threads.runs.submit_tool_outputs(
                thread_id=thread.id,
                run_id=run.id,
                tool_outputs=tool_outputs_to_submit
            )

            # 提交后,需要再次等待Run完成
            run = wait_on_run(run, thread)
        else:
            raise NotImplementedError(f"Unhandled required action type: {run.required_action.type}")

    # 5. Run完成后,获取Assistant的响应
    if run.status == 'completed':
        messages = client.beta.threads.messages.list(
            thread_id=thread.id,
            order="desc", # 获取最新消息
            limit=1 # 只获取一条
        )
        # 查找最新的Assistant消息
        for message in messages.data:
            if message.role == "assistant":
                for content_block in message.content:
                    if content_block.type == "text":
                        return content_block.text.value
        return "No assistant response found."
    else:
        return f"Run finished with status: {run.status}"

# 提问并打印结果
response = ask_question_and_handle_tools("What is funnyfunc() equal to right now?")
print("\nAssistant's final response:")
print(response)

运行前请确保:

  1. 你已设置 OPENAI_API_KEY 环境变量。
  2. 你已创建了一个OpenAI Assistant,并为其添加了名为 funnyfunc 的Function Tool。
  3. 将你的Assistant ID赋值给 ALEXA_ASSISTANT_ID_OPENAI 环境变量。

注意事项

  1. 错误处理与重试机制:在生产环境中,wait_on_run函数应包含更健壮的错误处理和指数退避重试机制,以应对API调用失败或暂时*务问题。
  2. 多工具调用:如果Assistant在一个requires_action状态下请求调用多个工具,run.required_action.submit_tool_outputs.tool_calls将是一个列表。你的代码需要遍历这个列表,为每个工具调用执行相应的函数,并收集所有结果,然后一次性通过submit_tool_outputs提交。
  3. 函数参数解析:当Assistant调用函数时,tool_call.function.arguments会包含函数参数的JSON字符串。你需要使用json.loads()来解析这些参数,并将其传递给你的实际函数。
  4. 状态管理:Assistant API是异步的。每次提交工具输出后,都需要再次等待Run完成或进入下一个requires_action状态。
  5. API版本:请确保你的openai Python库是最新版本,以兼容OpenAI Assistant API的最新功能和行为。

总结

正确处理OpenAI Assistant的函数调用是构建智能对话系统的关键一步。核心在于理解client.beta.threads.messages.create与client.beta.threads.runs.submit_tool_outputs之间的区别。前者用于常规的对话消息,而后者则是专门用于向Assistant反馈外部工具或函数执行结果的接口。通过遵循本文提供的指南和示例代码,开发者可以有效避免常见的BadRequestError,并成功地将外部功能集成到OpenAI Assistant中,从而实现更丰富、更强大的交互体验。

以上就是掌握OpenAI Assistant函数调用:正确提交工具输出的Python指南的详细内容,更多请关注其它相关文章!


# 网站推广工作是什么  # 自然语言  # 什么用  # 重试  # 您的  # 迭代  # 单引号  # 荆州网站建设介绍  # 安阳抖音关键词搜索排名技术费用  # 是一个  # 长葛响应式网站建设  # 搜书网站怎么做推广  # seo是高手吗  # 惠州纯手工seo哪家好  # 崂山搜狗seo优化  # 深圳企业福利网站建设  # 浠水网站建设ppt  # python  # 自定义  # 多个  # 腾讯  # api调用  # 区别  # gpt-4  # gpt  # nas  # openai  # 环境变量  # ai  # 工具  # app  # json  # js 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894 】


相关推荐: 如何查询个人病历记录  知乎APP怎么查看自己被邀请的问题_知乎APP邀请回答记录查看与参与方法  51漫画网实时入口 51漫画网页版官方免费漫画入口  Win10如何查看已安装的更新补丁 Win10卸载指定更新教程【教程】  如何在mysql中使用索引提示_mysql索引提示优化方法  win11如何运行chkdsk命令 Win11检查和修复磁盘逻辑错误教程【修复】  原子笔记app误删找回教程  iPhone 13 mini如何清理Safari缓存_iPhone 13 mini浏览器缓存清理方法  word表格如何按某一列内容进行排序_Word表格按列排序方法  PHP页面重载时变量值不重置的实现方法  小米倒班助手添加日历提醒  win11资源管理器标签页怎么用 Win11文件管理器多标签高效操作【新功能】  edge浏览器怎么修改语言为中文_Edge界面语言切换教程  mysql镜像配置如何设置用户权限组_mysql镜像配置用户组与权限分级管理方法  电脑开不了机怎么办 电脑无法开机的解决方法  键盘保修需要什么_键盘售后维修流程  J*a实现任务清单管理_集合框架综合入门练手  c++如何使用std::thread::join和detach_c++线程生命周期管理  Sublime Text怎么关闭自动完成_Sublime禁用Auto Complete设置  实现可重用自定义Python Range类  悟空浏览器网页版链接 悟空浏览器网页版最新有效地址  @Team是什么?揭秘团队含义  银信通自动开通原因揭秘  《饿了么》拼好饭点外卖教程2025  C++ static关键字作用_C++静态成员变量与静态函数  《360浏览器》设置摄像头权限方法  铁路12306官网登录入口 铁路12306在线购票官方平台  Golang如何操作指针参数_Go pointer参数传递规则  b站网页版入口 哔哩哔哩官方网站直接进入  《i莞家》修改昵称方法  《腾讯相册管家》注销账号方法  解决 Vue 3 组件未定义错误:理解 createApp 与根组件的正确使用  人教版电子教材在线获取指南  excel怎么制作考勤表 excel考勤模板与函数公式讲解  支付宝网页版在线入口 支付宝官网电脑登录入口  《虎扑》取消评分记录方法  苹果官网国补入口在哪  b站如何管理订阅_b站订阅标签分类管理  《幻兽帕鲁》手游帕鲁捕捉技巧分享  Go Template中优雅处理循环最后一项:自定义函数实践  淘口令快速解析技巧  163邮箱在线登录 163邮箱网页版在线入口  Python测试中模块导入路径解析的最佳实践  背部总是隐隐作痛怎么回事 背痛如何改善  在VS Code中利用AI辅助进行代码迁移  Win10显卡驱动安装失败怎么办 Win10使用DDU彻底卸载驱动【解决】  繁花漫画使用教程  ao3入口镜像地址 ao3镜像入口可靠跳转  iSpring三分屏制作教程  《洛克王国:世界》国家队搭配攻略 

 2025-12-13

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.