当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > OpenAI Responses API 怎样让模型调用自定义函数

OpenAI Responses API 怎样让模型调用自定义函数

来源:17golang原创 2026-10-27 02:48:15 0浏览 收藏

我们拿开发时经常用到的「查询项目发布状态」场景做演示,你可以直接把自定义的函数作为工具声明传给OpenAI Responses API,就能让模型自动判断什么时候需要调用工具、传什么参数,不需要自己手动处理多轮上下文的来回拼接,上手门槛很低。

直接把自定义函数的名称、参数结构、功能说明按规范格式放到tools请求字段里,调用API后模型会自行判断是否触发函数,拿到返回结果后再整理成自然语言回复用户。

让 OpenAI Responses API 调用自定义函数,关键不是把函数代码发给模型,而是把“函数契约”放进 tools,再由你的应用接住模型返回的 function_call、执行本地函数,最后提交对应的 function_call_output。这是一条明确的往返链路:模型决定调用什么,你的服务决定是否真的执行。

官方文档:https://developers.openai.com/api/docs/guides/tools

最小闭环可以概括为:定义一个 type: "function" 工具,读取 response.output 中的 function_call,用它的 call_id 回传执行结果,再请求一次 Responses API。模型不会直接访问你的数据库或业务函数。

先写一个最小可用的函数工具

下面用 get_project_status 作为示例:模型只负责根据用户问题填出项目名,真正的状态查询由应用里的 getProjectStatus 完成。Responses API 的函数工具可以直接写成 type、name、description、parameters 和 strict 这些字段。

const tools = [
  {
    type: "function",
    name: "get_project_status",
    description: "查询指定项目当前的发布状态。",
    parameters: {
      type: "object",
      properties: {
        project: {
          type: "string",
          description: "项目标识,例如 billing-api"
        }
      },
      required: ["project"],
      additionalProperties: false
    },
    // strict 让模型生成的参数遵守上面的 JSON Schema。
    strict: true
  }
];

这里的 description 要写成模型能理解的业务边界,参数名也要保持稳定。开启严格模式时,对象需要显式设置 additionalProperties: false,并把属性列入 required;如果某个业务字段可以缺省,可以把它声明为允许 null,而不是遗漏必填声明。

自定义函数工具从名称、描述和 JSON Schema 形成可调用契约的静态说明图
图1:工具契约说明图,展示 function 工具的名称、参数 Schema、strict 约束与模型可调用入口;这是原创静态说明图,不是运行截图。

把工具交给 Responses API

工具定义完成后,在第一次请求里把它放到 tools。默认情况下,模型会自己判断是否需要调用工具;如果一次业务只允许一个本地动作,可以同时设置 parallel_tool_calls: false,让这一轮最多出现一个函数调用。

import OpenAI from "openai";

const client = new OpenAI();

const response = await client.responses.create({
  model: "gpt-6-astra",
  input: "请告诉我 billing-api 当前是否可以发布。",
  tools,
  // 关闭并行调用,便于这个单动作示例按一个函数处理。
  parallel_tool_calls: false
});

console.log(response.output);

如果希望强制模型调用某一个工具,可以进一步使用 tool_choice;但一般的业务问答先使用默认的自动选择更自然。工具数量较多时,也要让每个函数的描述互相区分,避免模型面对多个相似入口时难以选择。

识别 function_call 并执行本地函数

响应的 output 不是一段固定文本数组,其中可能出现类型为 function_call 的项目。这个项目包含函数名、JSON 编码的 arguments 和后续回传必须使用的 call_id。应用先解析参数,再按函数名路由到白名单实现。

function getProjectStatus(project) {
  // 真实项目中可在这里访问受控的数据库或内部服务。
  const known = {
    "billing-api": { state: "ready", blockers: 0 },
    "search-api": { state: "blocked", blockers: 2 }
  };
  return known[project] ?? { state: "unknown", blockers: null };
}

function callFunction(name, args) {
  // 只允许显式列出的函数名,避免把任意输入当作可执行入口。
  if (name === "get_project_status") {
    return getProjectStatus(args.project);
  }
  throw new Error(`未知函数:${name}`);
}

const functionCalls = response.output.filter(
  (item) => item.type === "function_call"
);

for (const toolCall of functionCalls) {
  const args = JSON.parse(toolCall.arguments);
  const result = callFunction(toolCall.name, args);
  console.log(toolCall.call_id, result);
}

不要用 response.output_text 代替这一步,因为模型此时可能还没有最终回答。也不要根据函数名拼接任意方法调用;把可执行函数放进明确的路由表,未知名称和参数解析失败都应该进入应用自己的错误处理。

Responses API 返回 function_call、应用执行函数并按 call_id 回传结果的闭环关系图
图2:调用闭环说明图,展示模型请求、function_call、应用执行和 function_call_output 的往返关系;这是原创静态说明图,不是运行截图。

用原始 call_id 回传 function_call_output

执行结果需要作为新的输入项回传给下一次 Responses 请求。先把上一轮的 response.output 转成可继续使用的输入项,再追加一个与当前调用对应的 function_call_output。其中 call_id 必须来自原始函数调用,不能自己生成一个看似相近的编号。

import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";

const input = [
  { role: "user", content: "请告诉我 billing-api 当前是否可以发布。" }
];

// 保留模型这轮产生的完整 output,供下一次请求理解调用上下文。
input.push(...toResponseInputItems(response.output));

for (const toolCall of functionCalls) {
  let output;
  try {
    const args = JSON.parse(toolCall.arguments);
    output = JSON.stringify(callFunction(toolCall.name, args));
  } catch (error) {
    // 把可读错误作为工具结果交回模型,而不是让调用链静默中断。
    output = JSON.stringify({
      state: "error",
      message: error instanceof Error ? error.message : "函数执行失败"
    });
  }

  input.push({
    type: "function_call_output",
    call_id: toolCall.call_id,
    output
  });
}

const finalResponse = await client.responses.create({
  model: "gpt-6-astra",
  input,
  tools,
  parallel_tool_calls: false
});

console.log(finalResponse.output_text);

这次请求得到的 output_text 才是面向用户的最终回答。函数返回值最好是结构稳定、字段含义明确的 JSON 字符串;如果业务失败,也可以把失败状态作为工具结果交回模型,让它据此向用户解释,而不是把内部堆栈直接写进输出。

三个容易让调用链失效的边界

现象优先检查处理方向
模型没有调用函数用户任务是否真的需要该工具,工具描述是否清晰先保持默认自动选择;需要强制动作时再配置 tool_choice
请求因 Schema 被拒绝strict、required 和 additionalProperties 是否匹配补齐对象字段约束,可选值用允许 null 表达
回传后没有最终文本call_id 是否原样对应,是否把函数结果追加为新输入保留完整 output item,再提交 function_call_output
一轮出现多个调用是否允许并行函数调用单动作流程设置 parallel_tool_calls: false,批量任务再设计并行处理

最后要把“模型选择函数”和“应用授权执行”分开。模型输出的是建议调用及其参数,真正的权限校验、数据访问、超时、幂等和审计仍然属于你的应用。函数调用做得越接近真实业务,越应该在本地路由层再次检查参数,而不是只依赖模型给出的 JSON。

常见问题

模型会直接运行我写的 JavaScript 函数吗?

不会。模型只能输出符合工具契约的 function_call;你的应用要自行解析参数、调用本地函数,并把结果作为 function_call_output 发回。

为什么一定要保存 call_id?

它把函数结果和当前响应里的具体调用关联起来。尤其在允许并行调用时,不能只按函数名匹配结果,必须为每一个调用使用对应的 call_id。

strict=true 是否代表业务参数一定安全?

不是。严格模式主要约束输出参数符合 Schema;权限、资源范围、字段值合法性和业务副作用仍要由你的服务校验。

这条实现路径可以压缩成一句话:用 tools 声明契约,读取 function_call,由应用白名单路由并执行函数,再用原始 call_id 发送 function_call_output,最后读取新的 output_text。如果把并行策略、Schema 约束和业务授权都放在应用边界内,Responses API 的自定义函数调用就会变成一条可控的工程流程。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL JSON_TABLE 数值与日期字段的类型转换和截断边界MySQL JSON_TABLE 数值与日期字段的类型转换和截断边界
上一篇
MySQL JSON_TABLE 数值与日期字段的类型转换和截断边界
MySQL GET_LOCK 怎样实现同一任务的单实例执行
下一篇
MySQL GET_LOCK 怎样实现同一任务的单实例执行
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    720次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    728次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    804次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    767次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    604次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码