[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-openai--openai-go":3,"tool-openai--openai-go":64},[4,17,25,39,48,56],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":16},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",140436,2,"2026-04-05T23:32:43",[13,14,15],"开发框架","Agent","语言模型","ready",{"id":18,"name":19,"github_repo":20,"description_zh":21,"stars":22,"difficulty_score":10,"last_commit_at":23,"category_tags":24,"status":16},3704,"NextChat","ChatGPTNextWeb\u002FNextChat","NextChat 是一款轻量且极速的 AI 助手，旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性，以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发，NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。\n\n这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言，它也提供了便捷的自托管方案，支持一键部署到 Vercel 或 Zeabur 等平台。\n\nNextChat 的核心亮点在于其广泛的模型兼容性，原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型，让用户在一个界面即可自由切换不同 AI 能力。此外，它还率先支持 MCP（Model Context Protocol）协议，增强了上下文处理能力。针对企业用户，NextChat 提供专业版解决方案，具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能，满足公司对数据隐私和个性化管理的高标准要求。",87618,"2026-04-05T07:20:52",[13,15],{"id":26,"name":27,"github_repo":28,"description_zh":29,"stars":30,"difficulty_score":10,"last_commit_at":31,"category_tags":32,"status":16},2268,"ML-For-Beginners","microsoft\u002FML-For-Beginners","ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程，旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周，包含 26 节精炼课程和 52 道配套测验，内容涵盖从基础概念到实际应用的完整流程，有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。\n\n无论是希望转型的开发者、需要补充算法背景的研究人员，还是对人工智能充满好奇的普通爱好者，都能从中受益。课程不仅提供了清晰的理论讲解，还强调动手实践，让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持，通过自动化机制提供了包括简体中文在内的 50 多种语言版本，极大地降低了全球不同背景用户的学习门槛。此外，项目采用开源协作模式，社区活跃且内容持续更新，确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路，ML-For-Beginners 将是理想的起点。",84991,"2026-04-05T10:45:23",[33,34,35,36,14,37,15,13,38],"图像","数据工具","视频","插件","其他","音频",{"id":40,"name":41,"github_repo":42,"description_zh":43,"stars":44,"difficulty_score":45,"last_commit_at":46,"category_tags":47,"status":16},3128,"ragflow","infiniflow\u002Fragflow","RAGFlow 是一款领先的开源检索增强生成（RAG）引擎，旨在为大语言模型构建更精准、可靠的上下文层。它巧妙地将前沿的 RAG 技术与智能体（Agent）能力相结合，不仅支持从各类文档中高效提取知识，还能让模型基于这些知识进行逻辑推理和任务执行。\n\n在大模型应用中，幻觉问题和知识滞后是常见痛点。RAGFlow 通过深度解析复杂文档结构（如表格、图表及混合排版），显著提升了信息检索的准确度，从而有效减少模型“胡编乱造”的现象，确保回答既有据可依又具备时效性。其内置的智能体机制更进一步，使系统不仅能回答问题，还能自主规划步骤解决复杂问题。\n\n这款工具特别适合开发者、企业技术团队以及 AI 研究人员使用。无论是希望快速搭建私有知识库问答系统，还是致力于探索大模型在垂直领域落地的创新者，都能从中受益。RAGFlow 提供了可视化的工作流编排界面和灵活的 API 接口，既降低了非算法背景用户的上手门槛，也满足了专业开发者对系统深度定制的需求。作为基于 Apache 2.0 协议开源的项目，它正成为连接通用大模型与行业专有知识之间的重要桥梁。",77062,3,"2026-04-04T04:44:48",[14,33,13,15,37],{"id":49,"name":50,"github_repo":51,"description_zh":52,"stars":53,"difficulty_score":45,"last_commit_at":54,"category_tags":55,"status":16},519,"PaddleOCR","PaddlePaddle\u002FPaddleOCR","PaddleOCR 是一款基于百度飞桨框架开发的高性能开源光学字符识别工具包。它的核心能力是将图片、PDF 等文档中的文字提取出来，转换成计算机可读取的结构化数据，让机器真正“看懂”图文内容。\n\n面对海量纸质或电子文档，PaddleOCR 解决了人工录入效率低、数字化成本高的问题。尤其在人工智能领域，它扮演着连接图像与大型语言模型（LLM）的桥梁角色，能将视觉信息直接转化为文本输入，助力智能问答、文档分析等应用场景落地。\n\nPaddleOCR 适合开发者、算法研究人员以及有文档自动化需求的普通用户。其技术优势十分明显：不仅支持全球 100 多种语言的识别，还能在 Windows、Linux、macOS 等多个系统上运行，并灵活适配 CPU、GPU、NPU 等各类硬件。作为一个轻量级且社区活跃的开源项目，PaddleOCR 既能满足快速集成的需求，也能支撑前沿的视觉语言研究，是处理文字识别任务的理想选择。",74939,"2026-04-05T23:16:38",[15,33,13,37],{"id":57,"name":58,"github_repo":59,"description_zh":60,"stars":61,"difficulty_score":45,"last_commit_at":62,"category_tags":63,"status":16},2181,"OpenHands","OpenHands\u002FOpenHands","OpenHands 是一个专注于 AI 驱动开发的开源平台，旨在让智能体（Agent）像人类开发者一样理解、编写和调试代码。它解决了传统编程中重复性劳动多、环境配置复杂以及人机协作效率低等痛点，通过自动化流程显著提升开发速度。\n\n无论是希望提升编码效率的软件工程师、探索智能体技术的研究人员，还是需要快速原型验证的技术团队，都能从中受益。OpenHands 提供了灵活多样的使用方式：既可以通过命令行（CLI）或本地图形界面在个人电脑上轻松上手，体验类似 Devin 的流畅交互；也能利用其强大的 Python SDK 自定义智能体逻辑，甚至在云端大规模部署上千个智能体并行工作。\n\n其核心技术亮点在于模块化的软件智能体 SDK，这不仅构成了平台的引擎，还支持高度可组合的开发模式。此外，OpenHands 在 SWE-bench 基准测试中取得了 77.6% 的优异成绩，证明了其解决真实世界软件工程问题的能力。平台还具备完善的企业级功能，支持与 Slack、Jira 等工具集成，并提供细粒度的权限管理，适合从个人开发者到大型企业的各类用户场景。",70626,"2026-04-05T22:51:36",[15,14,13,36],{"id":65,"github_repo":66,"name":67,"description_en":68,"description_zh":69,"ai_summary_zh":69,"readme_en":70,"readme_zh":71,"quickstart_zh":72,"use_case_zh":73,"hero_image_url":74,"owner_login":75,"owner_name":76,"owner_avatar_url":77,"owner_bio":78,"owner_company":79,"owner_location":79,"owner_email":79,"owner_twitter":79,"owner_website":80,"owner_url":81,"languages":82,"stars":95,"forks":96,"last_commit_at":97,"license":98,"difficulty_score":10,"env_os":78,"env_gpu":99,"env_ram":99,"env_deps":100,"category_tags":103,"github_topics":79,"view_count":104,"oss_zip_url":79,"oss_zip_packed_at":79,"status":16,"created_at":105,"updated_at":106,"faqs":107,"releases":137},186,"openai\u002Fopenai-go","openai-go","The official Go library for the OpenAI API","openai-go 是 OpenAI 官方推出的 Go 语言 SDK，让开发者能轻松调用 OpenAI 的强大 AI 能力，比如生成文本、对话交互、多轮问答等。它封装了复杂的 HTTP 请求和数据结构，让你只需几行代码就能接入 GPT 等模型，省去手动拼接 API 请求的麻烦。\n\n它主要解决的是 Go 开发者在项目中集成 AI 功能时“从零造轮子”的痛点——无需自己处理认证、参数序列化或错误重试，直接使用清晰的接口即可完成复杂任务。无论是构建聊天机器人、智能客服，还是自动化内容生成，都能快速落地。\n\n适合熟悉 Go 语言的后端工程师、全栈开发者或技术型创业者使用，尤其推荐正在用 Go 构建服务并希望加入 AI 能力的团队。普通用户或非技术人员不建议直接使用。\n\n技术亮点包括：支持流式响应（实时获取生成结果）、会话状态管理（自动维护上下文）、多轮对话追踪，以及类型安全的参数构造。要求 Go 1.22 或更高版本，安装简单，文档齐全，是目前 Go 生态中最权威的 OpenAI 接入方案。","# OpenAI Go API Library\n\n\u003C!-- x-release-please-start-version -->\n\n\u003Ca href=\"https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fv3\">\u003Cimg src=\"https:\u002F\u002Fpkg.go.dev\u002Fbadge\u002Fgithub.com\u002Fopenai\u002Fopenai-go.svg\" alt=\"Go Reference\">\u003C\u002Fa>\n\n\u003C!-- x-release-please-end -->\n\nThe OpenAI Go library provides convenient access to the [OpenAI REST API](https:\u002F\u002Fplatform.openai.com\u002Fdocs)\nfrom applications written in Go.\n\n> [!WARNING]\n> The latest version of this package has small and limited breaking changes.\n> See the [changelog](CHANGELOG.md) for details.\n\n## Installation\n\n\u003C!-- x-release-please-start-version -->\n\n```go\nimport (\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\" \u002F\u002F imported as openai\n)\n```\n\n\u003C!-- x-release-please-end -->\n\nOr to pin the version:\n\n\u003C!-- x-release-please-start-version -->\n\n```sh\ngo get -u 'github.com\u002Fopenai\u002Fopenai-go\u002Fv3@v3.30.0'\n```\n\n\u003C!-- x-release-please-end -->\n\n## Requirements\n\nThis library requires Go 1.22+.\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\nThe primary API for interacting with OpenAI models is the [Responses API](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fresponses). You can generate text from the model with the code below.\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Foption\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Fresponses\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient := openai.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"), \u002F\u002F defaults to os.LookupEnv(\"OPENAI_API_KEY\")\n\t)\n\n\tquestion := \"Write me a haiku about computers\"\n\n\tresp, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\t\tInput: responses.ResponseNewParamsInputUnion{OfString: openai.String(question)},\n\t\tModel: openai.ChatModelGPT5_2,\n\t})\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tprintln(resp.OutputText())\n}\n```\n\n\u003Cdetails>\n\u003Csummary>Multi-turn Responses\u003C\u002Fsummary>\n\n```go\nresponse, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"What is the capital of France?\"),\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"First response:\", response.OutputText())\n\n\u002F\u002F Use PreviousResponseID to continue the conversation\nresponse, err = client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel:              openai.ChatModelGPT5_2,\n\tPreviousResponseID: openai.String(response.ID),\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"And what is the population of that city?\"),\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"Second response:\", response.OutputText())\n```\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Conversations\u003C\u002Fsummary>\n\n```go\nconv, err := client.Conversations.New(ctx, conversations.ConversationNewParams{})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"Created conversation:\", conv.ID)\n\nresponse, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"Hello! Remember that my favorite color is blue.\"),\n\t},\n\tConversation: responses.ResponseNewParamsConversationUnion{\n\t\tOfConversationObject: &responses.ResponseConversationParam{\n\t\t\tID: conv.ID,\n\t\t},\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"First response:\", response.OutputText())\n\n\u002F\u002F Continue the conversation\nresponse, err = client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"What is my favorite color?\"),\n\t},\n\tConversation: responses.ResponseNewParamsConversationUnion{\n\t\tOfConversationObject: &responses.ResponseConversationParam{\n\t\t\tID: conv.ID,\n\t\t},\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"Second response:\", response.OutputText())\n\nitems, err := client.Conversations.Items.List(ctx, conv.ID, conversations.ItemListParams{})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"Conversation has\", len(items.Data), \"items\")\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Streaming responses\u003C\u002Fsummary>\n\n```go\nctx := context.Background()\n\nstream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"Write a haiku about programming\"),\n\t},\n})\n\nfor stream.Next() {\n\tevent := stream.Current()\n\tprint(event.Delta)\n}\n\nif stream.Err() != nil {\n\tpanic(stream.Err())\n}\n```\n\n> See the [full streaming example](.\u002Fexamples\u002Fresponses-streaming\u002Fmain.go)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Tool calling\u003C\u002Fsummary>\n\n```go\nctx := context.Background()\n\nparams := responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"What is the weather in New York City?\"),\n\t},\n\tTools: []responses.ToolUnionParam{{\n\t\tOfFunction: &responses.FunctionToolParam{\n\t\t\tName:        \"get_weather\",\n\t\t\tDescription: openai.String(\"Get weather at the given location\"),\n\t\t\tParameters: map[string]any{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": map[string]any{\n\t\t\t\t\t\"location\": map[string]string{\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"required\": []string{\"location\"},\n\t\t\t},\n\t\t},\n\t}},\n}\n\nresponse, _ := client.Responses.New(ctx, params)\n\n\u002F\u002F Check for function calls in the response output\nfor _, item := range response.Output {\n\tif item.Type == \"function_call\" {\n\t\ttoolCall := item.AsFunctionCall()\n\t\tif toolCall.Name == \"get_weather\" {\n\t\t\t\u002F\u002F Extract arguments and call your function\n\t\t\tvar args map[string]any\n\t\t\tjson.Unmarshal([]byte(toolCall.Arguments), &args)\n\t\t\tlocation := args[\"location\"].(string)\n\n\t\t\t\u002F\u002F Simulate getting weather data\n\t\t\tweatherData := getWeather(location)\n\t\t\tfmt.Printf(\"Weather in %s: %s\\n\", location, weatherData)\n\n\t\t\t\u002F\u002F Continue conversation with function result\n\t\t\tresponse, _ = client.Responses.New(ctx, responses.ResponseNewParams{\n\t\t\t\tModel:              openai.ChatModelGPT5_2,\n\t\t\t\tPreviousResponseID: openai.String(response.ID),\n\t\t\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\t\t\tOfInputItemList: []responses.ResponseInputItemUnionParam{{\n\t\t\t\t\t\tOfFunctionCallOutput: &responses.ResponseInputItemFunctionCallOutputParam{\n\t\t\t\t\t\t\tCallID: toolCall.CallID,\n\t\t\t\t\t\t\tOutput: responses.ResponseInputItemFunctionCallOutputOutputUnionParam{\n\t\t\t\t\t\t\t\tOfString: openai.String(weatherData),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t}},\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Structured outputs\u003C\u002Fsummary>\n\n```go\nimport (\n\t\"encoding\u002Fjson\"\n\t\"github.com\u002Finvopop\u002Fjsonschema\"\n\t\u002F\u002F ...\n)\n\n\u002F\u002F A struct that will be converted to a Structured Outputs response schema\ntype HistoricalComputer struct {\n\tOrigin       Origin   `json:\"origin\" jsonschema_description:\"The origin of the computer\"`\n\tName         string   `json:\"full_name\" jsonschema_description:\"The name of the device model\"`\n\tLegacy       string   `json:\"legacy\" jsonschema:\"enum=positive,enum=neutral,enum=negative\" jsonschema_description:\"Its influence on the field of computing\"`\n\tNotableFacts []string `json:\"notable_facts\" jsonschema_description:\"A few key facts about the computer\"`\n}\n\ntype Origin struct {\n\tYearBuilt    int64  `json:\"year_of_construction\" jsonschema_description:\"The year it was made\"`\n\tOrganization string `json:\"organization\" jsonschema_description:\"The organization that was in charge of its development\"`\n}\n\n\u002F\u002F Structured Outputs uses a subset of JSON schema\n\u002F\u002F These flags are necessary to comply with the subset\nfunc GenerateSchema[T any]() map[string]any {\n\treflector := jsonschema.Reflector{\n\t\tAllowAdditionalProperties: false,\n\t\tDoNotReference:            true,\n\t}\n\tvar v T\n\tschema := reflector.Reflect(v)\n\n\tdata, _ := json.Marshal(schema)\n\tvar result map[string]any\n\tjson.Unmarshal(data, &result)\n\treturn result\n}\n\n\u002F\u002F Generate the JSON schema at initialization time\nvar HistoricalComputerSchema = GenerateSchema[HistoricalComputer]()\n\nfunc main() {\n\tclient := openai.NewClient()\n\tctx := context.Background()\n\n\tresponse, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"What computer ran the first neural network?\"),\n\t\t},\n\t\tText: responses.ResponseTextConfigParam{\n\t\t\tFormat: responses.ResponseFormatTextConfigParamOfJSONSchema(\n\t\t\t\t\"historical_computer\",\n\t\t\t\tHistoricalComputerSchema,\n\t\t\t),\n\t\t},\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t\u002F\u002F extract into a well-typed struct\n\tvar historicalComputer HistoricalComputer\n\t_ = json.Unmarshal([]byte(response.OutputText()), &historicalComputer)\n\n\thistoricalComputer.Name\n\thistoricalComputer.Origin.YearBuilt\n\thistoricalComputer.Origin.Organization\n\tfor i, fact := range historicalComputer.NotableFacts {\n\t\t\u002F\u002F ...\n\t}\n}\n```\n\n> See the [full structured outputs example](.\u002Fexamples\u002Fresponses-structured-outputs\u002Fmain.go)\n\n\u003C\u002Fdetails>\n\n### Chat Completions API\n\nThe previous standard (supported indefinitely) for generating text is the [Chat Completions API](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fchat). You can use that API to generate text from the model with the code below.\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n)\n\nfunc main() {\n\tclient := openai.NewClient()\n\n\tchatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{\n\t\tMessages: []openai.ChatCompletionMessageParamUnion{\n\t\t\topenai.DeveloperMessage(\"You are a coding assistant that talks like a pirate.\"),\n\t\t\topenai.UserMessage(\"How do I check if a slice is empty in Go?\"),\n\t\t},\n\t\tModel: openai.ChatModelGPT5_2,\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tprintln(chatCompletion.Choices[0].Message.Content)\n}\n```\n\n### Request fields\n\nThe openai library uses the [`omitzero`](https:\u002F\u002Ftip.golang.org\u002Fdoc\u002Fgo1.24#encodingjsonpkgencodingjson)\nsemantics from the Go 1.24+ `encoding\u002Fjson` release for request fields.\n\nRequired primitive fields (`int64`, `string`, etc.) feature the tag \u003Ccode>\\`json:\"...,required\"\\`\u003C\u002Fcode>. These\nfields are always serialized, even their zero values.\n\nOptional primitive types are wrapped in a `param.Opt[T]`. These fields can be set with the provided constructors, `openai.String(string)`, `openai.Int(int64)`, etc.\n\nAny `param.Opt[T]`, map, slice, struct or string enum uses the\ntag \u003Ccode>\\`json:\"...,omitzero\"\\`\u003C\u002Fcode>. Its zero value is considered omitted.\n\nThe `param.IsOmitted(any)` function can confirm the presence of any `omitzero` field.\n\n```go\np := openai.ExampleParams{\n\tID:   \"id_xxx\",             \u002F\u002F required property\n\tName: openai.String(\"...\"), \u002F\u002F optional property\n\n\tPoint: openai.Point{\n\t\tX: 0,             \u002F\u002F required field will serialize as 0\n\t\tY: openai.Int(1), \u002F\u002F optional field will serialize as 1\n\t\t\u002F\u002F ... omitted non-required fields will not be serialized\n\t},\n\n\tOrigin: openai.Origin{}, \u002F\u002F the zero value of [Origin] is considered omitted\n}\n```\n\nTo send `null` instead of a `param.Opt[T]`, use `param.Null[T]()`.\nTo send `null` instead of a struct `T`, use `param.NullStruct[T]()`.\n\n```go\np.Name = param.Null[string]()       \u002F\u002F 'null' instead of string\np.Point = param.NullStruct[Point]() \u002F\u002F 'null' instead of struct\n\nparam.IsNull(p.Name)  \u002F\u002F true\nparam.IsNull(p.Point) \u002F\u002F true\n```\n\nRequest structs contain a `.SetExtraFields(map[string]any)` method which can send non-conforming\nfields in the request body. Extra fields overwrite any struct fields with a matching\nkey. For security reasons, only use `SetExtraFields` with trusted data.\n\nTo send a custom value instead of a struct, use `param.Override[T](value)`.\n\n```go\n\u002F\u002F In cases where the API specifies a given type,\n\u002F\u002F but you want to send something else, use [SetExtraFields]:\np.SetExtraFields(map[string]any{\n\t\"x\": 0.01, \u002F\u002F send \"x\" as a float instead of int\n})\n\n\u002F\u002F Send a number instead of an object\ncustom := param.Override[openai.FooParams](12)\n```\n\n### Request unions\n\nUnions are represented as a struct with fields prefixed by \"Of\" for each of its variants,\nonly one field can be non-zero. The non-zero field will be serialized.\n\nSub-properties of the union can be accessed via methods on the union struct.\nThese methods return a mutable pointer to the underlying data, if present.\n\n```go\n\u002F\u002F Only one field can be non-zero, use param.IsOmitted() to check if a field is set\ntype AnimalUnionParam struct {\n\tOfCat *Cat `json:\",omitzero,inline`\n\tOfDog *Dog `json:\",omitzero,inline`\n}\n\nanimal := AnimalUnionParam{\n\tOfCat: &Cat{\n\t\tName: \"Whiskers\",\n\t\tOwner: PersonParam{\n\t\t\tAddress: AddressParam{Street: \"3333 Coyote Hill Rd\", Zip: 0},\n\t\t},\n\t},\n}\n\n\u002F\u002F Mutating a field\nif address := animal.GetOwner().GetAddress(); address != nil {\n\taddress.ZipCode = 94304\n}\n```\n\n### Response objects\n\nAll fields in response structs are ordinary value types (not pointers or wrappers).\nResponse structs also include a special `JSON` field containing metadata about\neach property.\n\n```go\ntype Animal struct {\n\tName   string `json:\"name,nullable\"`\n\tOwners int    `json:\"owners\"`\n\tAge    int    `json:\"age\"`\n\tJSON   struct {\n\t\tName        respjson.Field\n\t\tOwner       respjson.Field\n\t\tAge         respjson.Field\n\t\tExtraFields map[string]respjson.Field\n\t} `json:\"-\"`\n}\n```\n\nTo handle optional data, use the `.Valid()` method on the JSON field.\n`.Valid()` returns true if a field is not `null`, not present, or couldn't be marshaled.\n\nIf `.Valid()` is false, the corresponding field will simply be its zero value.\n\n```go\nraw := `{\"owners\": 1, \"name\": null}`\n\nvar res Animal\njson.Unmarshal([]byte(raw), &res)\n\n\u002F\u002F Accessing regular fields\n\nres.Owners \u002F\u002F 1\nres.Name   \u002F\u002F \"\"\nres.Age    \u002F\u002F 0\n\n\u002F\u002F Optional field checks\n\nres.JSON.Owners.Valid() \u002F\u002F true\nres.JSON.Name.Valid()   \u002F\u002F false\nres.JSON.Age.Valid()    \u002F\u002F false\n\n\u002F\u002F Raw JSON values\n\nres.JSON.Owners.Raw()                  \u002F\u002F \"1\"\nres.JSON.Name.Raw() == \"null\"          \u002F\u002F true\nres.JSON.Name.Raw() == respjson.Null   \u002F\u002F true\nres.JSON.Age.Raw() == \"\"               \u002F\u002F true\nres.JSON.Age.Raw() == respjson.Omitted \u002F\u002F true\n```\n\nThese `.JSON` structs also include an `ExtraFields` map containing\nany properties in the json response that were not specified\nin the struct. This can be useful for API features not yet\npresent in the SDK.\n\n```go\nbody := res.JSON.ExtraFields[\"my_unexpected_field\"].Raw()\n```\n\n### Response Unions\n\nIn responses, unions are represented by a flattened struct containing all possible fields from each of the\nobject variants.\nTo convert it to a variant use the `.AsFooVariant()` method or the `.AsAny()` method if present.\n\nIf a response value union contains primitive values, primitive fields will be alongside\nthe properties but prefixed with `Of` and feature the tag `json:\"...,inline\"`.\n\n```go\ntype AnimalUnion struct {\n\t\u002F\u002F From variants [Dog], [Cat]\n\tOwner Person `json:\"owner\"`\n\t\u002F\u002F From variant [Dog]\n\tDogBreed string `json:\"dog_breed\"`\n\t\u002F\u002F From variant [Cat]\n\tCatBreed string `json:\"cat_breed\"`\n\t\u002F\u002F ...\n\n\tJSON struct {\n\t\tOwner respjson.Field\n\t\t\u002F\u002F ...\n\t} `json:\"-\"`\n}\n\n\u002F\u002F If animal variant\nif animal.Owner.Address.ZipCode == \"\" {\n\tpanic(\"missing zip code\")\n}\n\n\u002F\u002F Switch on the variant\nswitch variant := animal.AsAny().(type) {\ncase Dog:\ncase Cat:\ndefault:\n\tpanic(\"unexpected type\")\n}\n```\n\n### RequestOptions\n\nThis library uses the functional options pattern. Functions defined in the\n`option` package return a `RequestOption`, which is a closure that mutates a\n`RequestConfig`. These options can be supplied to the client or at individual\nrequests. For example:\n\n```go\nclient := openai.NewClient(\n\t\u002F\u002F Adds a header to every request made by the client\n\toption.WithHeader(\"X-Some-Header\", \"custom_header_info\"),\n)\n\nclient.Responses.New(context.TODO(), responses.ResponseNewParams{...},\n\t\u002F\u002F Override the header\n\toption.WithHeader(\"X-Some-Header\", \"some_other_custom_header_info\"),\n\t\u002F\u002F Add an undocumented field to the request body, using sjson syntax\n\toption.WithJSONSet(\"some.json.path\", map[string]string{\"my\": \"object\"}),\n)\n```\n\nThe request option `option.WithDebugLog(nil)` may be helpful while debugging.\n\nSee the [full list of request options](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Foption).\n\n### Pagination\n\nThis library provides some conveniences for working with paginated list endpoints.\n\nYou can use `.ListAutoPaging()` methods to iterate through items across all pages:\n\n```go\niter := client.FineTuning.Jobs.ListAutoPaging(context.TODO(), openai.FineTuningJobListParams{\n\tLimit: openai.Int(20),\n})\n\u002F\u002F Automatically fetches more pages as needed.\nfor iter.Next() {\n\tfineTuningJob := iter.Current()\n\tfmt.Printf(\"%+v\\n\", fineTuningJob)\n}\nif err := iter.Err(); err != nil {\n\tpanic(err.Error())\n}\n```\n\nOr you can use simple `.List()` methods to fetch a single page and receive a standard response object\nwith additional helper methods like `.GetNextPage()`, e.g.:\n\n```go\npage, err := client.FineTuning.Jobs.List(context.TODO(), openai.FineTuningJobListParams{\n\tLimit: openai.Int(20),\n})\nfor page != nil {\n\tfor _, job := range page.Data {\n\t\tfmt.Printf(\"%+v\\n\", job)\n\t}\n\tpage, err = page.GetNextPage()\n}\nif err != nil {\n\tpanic(err.Error())\n}\n```\n\n### Errors\n\nWhen the API returns a non-success status code, we return an error with type\n`*openai.Error`. This contains the `StatusCode`, `*http.Request`, and\n`*http.Response` values of the request, as well as the JSON of the error body\n(much like other response objects in the SDK).\n\nTo handle errors, we recommend that you use the `errors.As` pattern:\n\n```go\n_, err := client.FineTuning.Jobs.New(context.TODO(), openai.FineTuningJobNewParams{\n\tModel:        openai.FineTuningJobNewParamsModel(\"gpt-4o\"),\n\tTrainingFile: \"file-abc123\",\n})\nif err != nil {\n\tvar apierr *openai.Error\n\tif errors.As(err, &apierr) {\n\t\tprintln(string(apierr.DumpRequest(true)))  \u002F\u002F Prints the serialized HTTP request\n\t\tprintln(string(apierr.DumpResponse(true))) \u002F\u002F Prints the serialized HTTP response\n\t}\n\tpanic(err.Error()) \u002F\u002F GET \"\u002Ffine_tuning\u002Fjobs\": 400 Bad Request { ... }\n}\n```\n\nWhen other errors occur, they are returned unwrapped; for example,\nif HTTP transport fails, you might receive `*url.Error` wrapping `*net.OpError`.\n\n### Timeouts\n\nRequests do not time out by default; use context to configure a timeout for a request lifecycle.\n\nNote that if a request is [retried](#retries), the context timeout does not start over.\nTo set a per-retry timeout, use `option.WithRequestTimeout()`.\n\n```go\n\u002F\u002F This sets the timeout for the request, including all the retries.\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\nclient.Responses.New(\n\tctx,\n\tresponses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"How can I list all files in a directory using Python?\"),\n\t\t},\n\t},\n\t\u002F\u002F This sets the per-retry timeout\n\toption.WithRequestTimeout(20*time.Second),\n)\n```\n\n### File uploads\n\nRequest parameters that correspond to file uploads in multipart requests are typed as\n`io.Reader`. The contents of the `io.Reader` will by default be sent as a multipart form\npart with the file name of \"anonymous_file\" and content-type of \"application\u002Foctet-stream\".\n\nThe file name and content-type can be customized by implementing `Name() string` or `ContentType()\nstring` on the run-time type of `io.Reader`. Note that `os.File` implements `Name() string`, so a\nfile returned by `os.Open` will be sent with the file name on disk.\n\nWe also provide a helper `openai.File(reader io.Reader, filename string, contentType string)`\nwhich can be used to wrap any `io.Reader` with the appropriate file name and content type.\n\n```go\n\u002F\u002F A file from the file system\nfile, err := os.Open(\"input.jsonl\")\nopenai.FileNewParams{\n\tFile:    file,\n\tPurpose: openai.FilePurposeFineTune,\n}\n\n\u002F\u002F A file from a string\nopenai.FileNewParams{\n\tFile:    strings.NewReader(\"my file contents\"),\n\tPurpose: openai.FilePurposeFineTune,\n}\n\n\u002F\u002F With a custom filename and contentType\nopenai.FileNewParams{\n\tFile:    openai.File(strings.NewReader(`{\"hello\": \"foo\"}`), \"file.go\", \"application\u002Fjson\"),\n\tPurpose: openai.FilePurposeFineTune,\n}\n```\n\n## Webhook Verification\n\nVerifying webhook signatures is _optional but encouraged_.\n\nFor more information about webhooks, see [the API docs](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Fwebhooks).\n\n### Parsing webhook payloads\n\nFor most use cases, you will likely want to verify the webhook and parse the payload at the same time. To achieve this, we provide the method `client.Webhooks.Unwrap()`, which parses a webhook request and verifies that it was sent by OpenAI. This method will return an error if the signature is invalid.\n\nNote that the `body` parameter should be the raw JSON bytes sent from the server (do not parse it first). The `Unwrap()` method will parse this JSON for you into an event object after verifying the webhook was sent from OpenAI.\n\n```go\npackage main\n\nimport (\n\t\"io\"\n\t\"log\"\n\t\"net\u002Fhttp\"\n\t\"os\"\n\n\t\"github.com\u002Fgin-gonic\u002Fgin\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Foption\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Fwebhooks\"\n)\n\nfunc main() {\n\tclient := openai.NewClient(\n\t\toption.WithWebhookSecret(os.Getenv(\"OPENAI_WEBHOOK_SECRET\")), \u002F\u002F env var used by default; explicit here.\n\t)\n\n\tr := gin.Default()\n\n\tr.POST(\"\u002Fwebhook\", func(c *gin.Context) {\n\t\tbody, err := io.ReadAll(c.Request.Body)\n\t\tif err != nil {\n\t\t\tc.JSON(http.StatusInternalServerError, gin.H{\"error\": \"Error reading request body\"})\n\t\t\treturn\n\t\t}\n\t\tdefer c.Request.Body.Close()\n\n\t\twebhookEvent, err := client.Webhooks.Unwrap(body, c.Request.Header)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Invalid webhook signature: %v\", err)\n\t\t\tc.JSON(http.StatusBadRequest, gin.H{\"error\": \"invalid signature\"})\n\t\t\treturn\n\t\t}\n\n\t\tswitch event := webhookEvent.AsAny().(type) {\n\t\tcase webhooks.ResponseCompletedWebhookEvent:\n\t\t\tlog.Printf(\"Response completed: %+v\", event.Data)\n\t\tcase webhooks.ResponseFailedWebhookEvent:\n\t\t\tlog.Printf(\"Response failed: %+v\", event.Data)\n\t\tdefault:\n\t\t\tlog.Printf(\"Unhandled event type: %T\", event)\n\t\t}\n\n\t\tc.JSON(http.StatusOK, gin.H{\"message\": \"ok\"})\n\t})\n\n\tr.Run(\":8000\")\n}\n```\n\n### Verifying webhook payloads directly\n\nIn some cases, you may want to verify the webhook separately from parsing the payload. If you prefer to handle these steps separately, we provide the method `client.Webhooks.VerifySignature()` to _only verify_ the signature of a webhook request. Like `Unwrap()`, this method will return an error if the signature is invalid.\n\nNote that the `body` parameter should be the raw JSON bytes sent from the server (do not parse it first). You will then need to parse the body after verifying the signature.\n\n```go\npackage main\n\nimport (\n\t\"encoding\u002Fjson\"\n\t\"io\"\n\t\"log\"\n\t\"net\u002Fhttp\"\n\t\"os\"\n\n\t\"github.com\u002Fgin-gonic\u002Fgin\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Foption\"\n)\n\nfunc main() {\n\tclient := openai.NewClient(\n\t\toption.WithWebhookSecret(os.Getenv(\"OPENAI_WEBHOOK_SECRET\")), \u002F\u002F env var used by default; explicit here.\n\t)\n\n\tr := gin.Default()\n\n\tr.POST(\"\u002Fwebhook\", func(c *gin.Context) {\n\t\tbody, err := io.ReadAll(c.Request.Body)\n\t\tif err != nil {\n\t\t\tc.JSON(http.StatusInternalServerError, gin.H{\"error\": \"Error reading request body\"})\n\t\t\treturn\n\t\t}\n\t\tdefer c.Request.Body.Close()\n\n\t\terr = client.Webhooks.VerifySignature(body, c.Request.Header)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Invalid webhook signature: %v\", err)\n\t\t\tc.JSON(http.StatusBadRequest, gin.H{\"error\": \"invalid signature\"})\n\t\t\treturn\n\t\t}\n\n\t\tc.JSON(http.StatusOK, gin.H{\"message\": \"ok\"})\n\t})\n\n\tr.Run(\":8000\")\n}\n```\n\n### Retries\n\nCertain errors will be automatically retried 2 times by default, with a short exponential backoff.\nWe retry by default all connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit,\nand >=500 Internal errors.\n\nYou can use the `WithMaxRetries` option to configure or disable this:\n\n```go\n\u002F\u002F Configure the default for all requests:\nclient := openai.NewClient(\n\toption.WithMaxRetries(0), \u002F\u002F default is 2\n)\n\n\u002F\u002F Override per-request:\nclient.Responses.New(\n\tcontext.TODO(),\n\tresponses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"How can I get the name of the current day in JavaScript?\"),\n\t\t},\n\t},\n\toption.WithMaxRetries(5),\n)\n```\n\n### Accessing raw response data (e.g. response headers)\n\nYou can access the raw HTTP response data by using the `option.WithResponseInto()` request option. This is useful when\nyou need to examine response headers, status codes, or other details.\n\n```go\n\u002F\u002F Create a variable to store the HTTP response\nvar httpResp *http.Response\nresponse, err := client.Responses.New(\n\tcontext.TODO(),\n\tresponses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"Say this is a test\"),\n\t\t},\n\t},\n\toption.WithResponseInto(&httpResp),\n)\nif err != nil {\n\t\u002F\u002F handle error\n}\nfmt.Printf(\"%+v\\n\", response)\n\nfmt.Printf(\"Status Code: %d\\n\", httpResp.StatusCode)\nfmt.Printf(\"Headers: %+#v\\n\", httpResp.Header)\n```\n\n### Making custom\u002Fundocumented requests\n\nThis library is typed for convenient access to the documented API. If you need to access undocumented\nendpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can use `client.Get`, `client.Post`, and other HTTP verbs.\n`RequestOptions` on the client, such as retries, will be respected when making these requests.\n\n```go\nvar (\n    \u002F\u002F params can be an io.Reader, a []byte, an encoding\u002Fjson serializable object,\n    \u002F\u002F or a \"…Params\" struct defined in this library.\n    params map[string]any\n\n    \u002F\u002F result can be an []byte, *http.Response, a encoding\u002Fjson deserializable object,\n    \u002F\u002F or a model defined in this library.\n    result *http.Response\n)\nerr := client.Post(context.Background(), \"\u002Funspecified\", params, &result)\nif err != nil {\n    …\n}\n```\n\n#### Undocumented request params\n\nTo make requests using undocumented parameters, you may use either the `option.WithQuerySet()`\nor the `option.WithJSONSet()` methods.\n\n```go\nparams := FooNewParams{\n    ID:   \"id_xxxx\",\n    Data: FooNewParamsData{\n        FirstName: openai.String(\"John\"),\n    },\n}\nclient.Foo.New(context.Background(), params, option.WithJSONSet(\"data.last_name\", \"Doe\"))\n```\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you may either access the raw JSON of the response as a string\nwith `result.JSON.RawJSON()`, or get the raw JSON of a particular field on the result with\n`result.JSON.Foo.Raw()`.\n\nAny fields that are not present on the response struct will be saved and can be accessed by `result.JSON.ExtraFields()` which returns the extra fields as a `map[string]Field`.\n\n### Middleware\n\nWe provide `option.WithMiddleware` which applies the given\nmiddleware to requests.\n\n```go\nfunc Logger(req *http.Request, next option.MiddlewareNext) (res *http.Response, err error) {\n\t\u002F\u002F Before the request\n\tstart := time.Now()\n\tLogReq(req)\n\n\t\u002F\u002F Forward the request to the next handler\n\tres, err = next(req)\n\n\t\u002F\u002F Handle stuff after the request\n\tend := time.Now()\n\tLogRes(res, err, start - end)\n\n    return res, err\n}\n\nclient := openai.NewClient(\n\toption.WithMiddleware(Logger),\n)\n```\n\nWhen multiple middlewares are provided as variadic arguments, the middlewares\nare applied left to right. If `option.WithMiddleware` is given\nmultiple times, for example first in the client then the method, the\nmiddleware in the client will run first and the middleware given in the method\nwill run next.\n\nYou may also replace the default `http.Client` with\n`option.WithHTTPClient(client)`. Only one http client is\naccepted (this overwrites any previous client) and receives requests after any\nmiddleware has been applied.\n\n## Microsoft Azure OpenAI\n\nTo use this library with [Azure OpenAI]https:\u002F\u002Flearn.microsoft.com\u002Fazure\u002Fai-services\u002Fopenai\u002Foverview),\nuse the option.RequestOption functions in the `azure` package.\n\n```go\npackage main\n\nimport (\n\t\"github.com\u002FAzure\u002Fazure-sdk-for-go\u002Fsdk\u002Fazidentity\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Fazure\"\n)\n\nfunc main() {\n\tconst azureOpenAIEndpoint = \"https:\u002F\u002F\u003Cazure-openai-resource>.openai.azure.com\"\n\n\t\u002F\u002F The latest API versions, including previews, can be found here:\n\t\u002F\u002F https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fai-services\u002Fopenai\u002Freference#rest-api-versionng\n\tconst azureOpenAIAPIVersion = \"2024-06-01\"\n\n\ttokenCredential, err := azidentity.NewDefaultAzureCredential(nil)\n\n\tif err != nil {\n\t\tfmt.Printf(\"Failed to create the DefaultAzureCredential: %s\", err)\n\t\tos.Exit(1)\n\t}\n\n\tclient := openai.NewClient(\n\t\tazure.WithEndpoint(azureOpenAIEndpoint, azureOpenAIAPIVersion),\n\n\t\t\u002F\u002F Choose between authenticating using a TokenCredential or an API Key\n\t\tazure.WithTokenCredential(tokenCredential),\n\t\t\u002F\u002F or azure.WithAPIKey(azureOpenAIAPIKey),\n\t)\n}\n```\n\n## Semantic versioning\n\nThis package generally follows [SemVer](https:\u002F\u002Fsemver.org\u002Fspec\u002Fv2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n2. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https:\u002F\u002Fwww.github.com\u002Fopenai\u002Fopenai-go\u002Fissues) with questions, bugs, or suggestions.\n\n## Contributing\n\nSee [the contributing documentation](.\u002FCONTRIBUTING.md).\n","# OpenAI Go API 库\n\n\u003C!-- x-release-please-start-version -->\n\n\u003Ca href=\"https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fv3\">\u003Cimg src=\"https:\u002F\u002Fpkg.go.dev\u002Fbadge\u002Fgithub.com\u002Fopenai\u002Fopenai-go.svg\" alt=\"Go 参考文档\">\u003C\u002Fa>\n\n\u003C!-- x-release-please-end -->\n\nOpenAI Go 库为使用 Go 语言编写的应用程序提供了便捷访问 [OpenAI REST API](https:\u002F\u002Fplatform.openai.com\u002Fdocs) 的能力。\n\n> [!WARNING]\n> 此包的最新版本包含少量且有限的破坏性变更。\n> 详情请参阅 [变更日志](CHANGELOG.md)。\n\n## 安装\n\n\u003C!-- x-release-please-start-version -->\n\n```go\nimport (\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\" \u002F\u002F 导入后别名为 openai\n)\n```\n\n\u003C!-- x-release-please-end -->\n\n或指定固定版本：\n\n\u003C!-- x-release-please-start-version -->\n\n```sh\ngo get -u 'github.com\u002Fopenai\u002Fopenai-go\u002Fv3@v3.30.0'\n```\n\n\u003C!-- x-release-please-end -->\n\n## 要求\n\n本库要求 Go 1.22 或更高版本。\n\n## 使用方法\n\n本库完整的 API 文档请参见 [api.md](api.md)。\n\n与 OpenAI 模型交互的主要接口是 [Responses API](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fresponses)。你可以使用以下代码从模型生成文本。\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Foption\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Fresponses\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient := openai.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"), \u002F\u002F 默认从 os.LookupEnv(\"OPENAI_API_KEY\") 获取\n\t)\n\n\tquestion := \"写一首关于计算机的俳句\"\n\n\tresp, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\t\tInput: responses.ResponseNewParamsInputUnion{OfString: openai.String(question)},\n\t\tModel: openai.ChatModelGPT5_2,\n\t})\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tprintln(resp.OutputText())\n}\n```\n\n\u003Cdetails>\n\u003Csummary>多轮对话响应\u003C\u002Fsummary>\n\n```go\nresponse, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"法国的首都是哪里？\"),\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"第一轮响应：\", response.OutputText())\n\n\u002F\u002F 使用 PreviousResponseID 继续对话\nresponse, err = client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel:              openai.ChatModelGPT5_2,\n\tPreviousResponseID: openai.String(response.ID),\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"那座城市的人口是多少？\"),\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"第二轮响应：\", response.OutputText())\n```\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>会话（Conversations）\u003C\u002Fsummary>\n\n```go\nconv, err := client.Conversations.New(ctx, conversations.ConversationNewParams{})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"已创建会话：\", conv.ID)\n\nresponse, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"你好！记住我最喜欢的颜色是蓝色。\"),\n\t},\n\tConversation: responses.ResponseNewParamsConversationUnion{\n\t\tOfConversationObject: &responses.ResponseConversationParam{\n\t\t\tID: conv.ID,\n\t\t},\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"第一轮响应：\", response.OutputText())\n\n\u002F\u002F 继续会话\nresponse, err = client.Responses.New(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"我最喜欢的颜色是什么？\"),\n\t},\n\tConversation: responses.ResponseNewParamsConversationUnion{\n\t\tOfConversationObject: &responses.ResponseConversationParam{\n\t\t\tID: conv.ID,\n\t\t},\n\t},\n})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"第二轮响应：\", response.OutputText())\n\nitems, err := client.Conversations.Items.List(ctx, conv.ID, conversations.ItemListParams{})\nif err != nil {\n\tpanic(err)\n}\nfmt.Println(\"会话包含\", len(items.Data), \"条记录\")\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>流式响应\u003C\u002Fsummary>\n\n```go\nctx := context.Background()\n\nstream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"写一首关于编程的俳句\"),\n\t},\n})\n\nfor stream.Next() {\n\tevent := stream.Current()\n\tprint(event.Delta)\n}\n\nif stream.Err() != nil {\n\tpanic(stream.Err())\n}\n```\n\n> 查看[完整流式示例](.\u002Fexamples\u002Fresponses-streaming\u002Fmain.go)\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>工具调用（Tool calling）\u003C\u002Fsummary>\n\n```go\nctx := context.Background()\n\nparams := responses.ResponseNewParams{\n\tModel: openai.ChatModelGPT5_2,\n\tInput: responses.ResponseNewParamsInputUnion{\n\t\tOfString: openai.String(\"纽约市的天气如何？\"),\n\t},\n\tTools: []responses.ToolUnionParam{{\n\t\tOfFunction: &responses.FunctionToolParam{\n\t\t\tName:        \"get_weather\",\n\t\t\tDescription: openai.String(\"获取指定位置的天气\"),\n\t\t\tParameters: map[string]any{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": map[string]any{\n\t\t\t\t\t\"location\": map[string]string{\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"required\": []string{\"location\"},\n\t\t\t},\n\t\t},\n\t}},\n}\n\nresponse, _ := client.Responses.New(ctx, params)\n\n\u002F\u002F 检查响应输出中的函数调用\nfor _, item := range response.Output {\n\tif item.Type == \"function_call\" {\n\t\ttoolCall := item.AsFunctionCall()\n\t\tif toolCall.Name == \"get_weather\" {\n\t\t\t\u002F\u002F 提取参数并调用你的函数\n\t\t\tvar args map[string]any\n\t\t\tjson.Unmarshal([]byte(toolCall.Arguments), &args)\n\t\t\tlocation := args[\"location\"].(string)\n\n\t\t\t\u002F\u002F 模拟获取天气数据\n\t\t\tweatherData := getWeather(location)\n\t\t\tfmt.Printf(\"地点 %s 的天气：%s\\n\", location, weatherData)\n\n\t\t\t\u002F\u002F 使用函数结果继续对话\n\t\t\tresponse, _ = client.Responses.New(ctx, responses.ResponseNewParams{\n\t\t\t\tModel:              openai.ChatModelGPT5_2,\n\t\t\t\tPreviousResponseID: openai.String(response.ID),\n\t\t\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\t\t\tOfInputItemList: []responses.ResponseInputItemUnionParam{{\n\t\t\t\t\t\tOfFunctionCallOutput: &responses.ResponseInputItemFunctionCallOutputParam{\n\t\t\t\t\t\t\tCallID: toolCall.CallID,\n\t\t\t\t\t\t\tOutput: responses.ResponseInputItemFunctionCallOutputOutputUnionParam{\n\t\t\t\t\t\t\t\tOfString: openai.String(weatherData),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t}},\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t}\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>结构化输出（Structured outputs）\u003C\u002Fsummary>\n\n```go\nimport (\n\t\"encoding\u002Fjson\"\n\t\"github.com\u002Finvopop\u002Fjsonschema\"\n\t\u002F\u002F ...\n)\n\n```go\n\u002F\u002F 一个将被转换为结构化输出（Structured Outputs）响应模式的结构体\ntype HistoricalComputer struct {\n\tOrigin       Origin   `json:\"origin\" jsonschema_description:\"计算机的起源\"`\n\tName         string   `json:\"full_name\" jsonschema_description:\"设备型号的名称\"`\n\tLegacy       string   `json:\"legacy\" jsonschema:\"enum=positive,enum=neutral,enum=negative\" jsonschema_description:\"其对计算领域的影响\"`\n\tNotableFacts []string `json:\"notable_facts\" jsonschema_description:\"关于该计算机的一些关键事实\"`\n}\n\ntype Origin struct {\n\tYearBuilt    int64  `json:\"year_of_construction\" jsonschema_description:\"制造年份\"`\n\tOrganization string `json:\"organization\" jsonschema_description:\"负责其开发的组织\"`\n}\n\n\u002F\u002F 结构化输出使用 JSON 模式的一个子集\n\u002F\u002F 这些标志是符合该子集所必需的\nfunc GenerateSchema[T any]() map[string]any {\n\treflector := jsonschema.Reflector{\n\t\tAllowAdditionalProperties: false,\n\t\tDoNotReference:            true,\n\t}\n\tvar v T\n\tschema := reflector.Reflect(v)\n\n\tdata, _ := json.Marshal(schema)\n\tvar result map[string]any\n\tjson.Unmarshal(data, &result)\n\treturn result\n}\n\n\u002F\u002F 在初始化时生成 JSON 模式\nvar HistoricalComputerSchema = GenerateSchema[HistoricalComputer]()\n\nfunc main() {\n\tclient := openai.NewClient()\n\tctx := context.Background()\n\n\tresponse, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"什么计算机运行了第一个神经网络？\"),\n\t\t},\n\t\tText: responses.ResponseTextConfigParam{\n\t\t\tFormat: responses.ResponseFormatTextConfigParamOfJSONSchema(\n\t\t\t\t\"historical_computer\",\n\t\t\t\tHistoricalComputerSchema,\n\t\t\t),\n\t\t},\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t\u002F\u002F 提取到一个类型安全的结构体中\n\tvar historicalComputer HistoricalComputer\n\t_ = json.Unmarshal([]byte(response.OutputText()), &historicalComputer)\n\n\thistoricalComputer.Name\n\thistoricalComputer.Origin.YearBuilt\n\thistoricalComputer.Origin.Organization\n\tfor i, fact := range historicalComputer.NotableFacts {\n\t\t\u002F\u002F ...\n\t}\n}\n```\n\n> 查看 [完整的结构化输出示例](.\u002Fexamples\u002Fresponses-structured-outputs\u002Fmain.go)\n\n\u003C\u002Fdetails>\n\n\n\n### 聊天补全 API\n\n此前的标准（将无限期支持）文本生成接口是 [聊天补全 API](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fchat)。你可以使用以下代码通过该 API 从模型生成文本。\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n)\n\nfunc main() {\n\tclient := openai.NewClient()\n\n\tchatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{\n\t\tMessages: []openai.ChatCompletionMessageParamUnion{\n\t\t\topenai.DeveloperMessage(\"你是一个说话像海盗的编程助手。\"),\n\t\t\topenai.UserMessage(\"我如何在 Go 中检查切片是否为空？\"),\n\t\t},\n\t\tModel: openai.ChatModelGPT5_2,\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tprintln(chatCompletion.Choices[0].Message.Content)\n}\n```\n\n### 请求字段\n\nopenai 库对请求字段使用 Go 1.24+ `encoding\u002Fjson` 发布版中的 [`omitzero`](https:\u002F\u002Ftip.golang.org\u002Fdoc\u002Fgo1.24#encodingjsonpkgencodingjson) 语义。\n\n必需的基本类型字段（`int64`、`string` 等）带有标签 \u003Ccode>\\`json:\"...,required\"\\`\u003C\u002Fcode>。这些字段即使为零值也会始终序列化。\n\n可选的基本类型被包装在 `param.Opt[T]` 中。这些字段可通过提供的构造函数设置，如 `openai.String(string)`、`openai.Int(int64)` 等。\n\n任何 `param.Opt[T]`、map、slice、struct 或字符串枚举均使用标签 \u003Ccode>\\`json:\"...,omitzero\"\\`\u003C\u002Fcode>。其零值被视为省略。\n\n`param.IsOmitted(any)` 函数可用于确认任意 `omitzero` 字段是否存在。\n\n```go\np := openai.ExampleParams{\n\tID:   \"id_xxx\",             \u002F\u002F 必需属性\n\tName: openai.String(\"...\"), \u002F\u002F 可选属性\n\n\tPoint: openai.Point{\n\t\tX: 0,             \u002F\u002F 必需字段，序列化为 0\n\t\tY: openai.Int(1), \u002F\u002F 可选字段，序列化为 1\n\t\t\u002F\u002F ... 省略的非必需字段不会被序列化\n\t},\n\n\tOrigin: openai.Origin{}, \u002F\u002F [Origin] 的零值被视为省略\n}\n```\n\n若要发送 `null` 而非 `param.Opt[T]`，请使用 `param.Null[T]()`。\n若要发送 `null` 而非结构体 `T`，请使用 `param.NullStruct[T]()`。\n\n```go\np.Name = param.Null[string]()       \u002F\u002F 发送 'null' 而非字符串\np.Point = param.NullStruct[Point]() \u002F\u002F 发送 'null' 而非结构体\n\nparam.IsNull(p.Name)  \u002F\u002F true\nparam.IsNull(p.Point) \u002F\u002F true\n```\n\n请求结构体包含 `.SetExtraFields(map[string]any)` 方法，可用于在请求体中发送不符合规范的字段。额外字段会覆盖具有相同键的结构体字段。出于安全考虑，请仅对可信数据使用 `SetExtraFields`。\n\n若要发送自定义值而非结构体，请使用 `param.Override[T](value)`。\n\n```go\n\u002F\u002F 当 API 指定某种类型，但你想发送其他内容时，使用 [SetExtraFields]：\np.SetExtraFields(map[string]any{\n\t\"x\": 0.01, \u002F\u002F 将 \"x\" 作为浮点数发送，而非整数\n})\n\n\u002F\u002F 发送数字而非对象\ncustom := param.Override[openai.FooParams](12)\n```\n\n### 请求联合类型（Unions）\n\n联合类型表示为一个结构体，其每个变体字段前缀为 \"Of\"，\n仅允许一个字段非零。非零字段将被序列化。\n\n联合类型的子属性可通过联合结构体上的方法访问。\n这些方法返回指向底层数据的可变指针（如果存在）。\n\n```go\n\u002F\u002F 仅允许一个字段非零，使用 param.IsOmitted() 检查字段是否已设置\ntype AnimalUnionParam struct {\n\tOfCat *Cat `json:\",omitzero,inline`\n\tOfDog *Dog `json:\",omitzero,inline`\n}\n\nanimal := AnimalUnionParam{\n\tOfCat: &Cat{\n\t\tName: \"Whiskers\",\n\t\tOwner: PersonParam{\n\t\t\tAddress: AddressParam{Street: \"3333 Coyote Hill Rd\", Zip: 0},\n\t\t},\n\t},\n}\n\n\u002F\u002F 修改字段\nif address := animal.GetOwner().GetAddress(); address != nil {\n\taddress.ZipCode = 94304\n}\n```\n\n### 响应对象（Response objects）\n\n响应结构体中的所有字段均为普通值类型（非指针或包装器）。  \n响应结构体还包含一个特殊的 `JSON` 字段，用于存储每个属性的元数据。\n\n```go\ntype Animal struct {\n\tName   string `json:\"name,nullable\"`\n\tOwners int    `json:\"owners\"`\n\tAge    int    `json:\"age\"`\n\tJSON   struct {\n\t\tName        respjson.Field\n\t\tOwner       respjson.Field\n\t\tAge         respjson.Field\n\t\tExtraFields map[string]respjson.Field\n\t} `json:\"-\"`\n}\n```\n\n要处理可选数据，请使用 JSON 字段上的 `.Valid()` 方法。  \n`.Valid()` 在字段不为 `null`、不存在或无法被序列化时返回 true。\n\n若 `.Valid()` 为 false，则对应字段将为其零值。\n\n```go\nraw := `{\"owners\": 1, \"name\": null}`\n\nvar res Animal\njson.Unmarshal([]byte(raw), &res)\n\n\u002F\u002F 访问常规字段\n\nres.Owners \u002F\u002F 1\nres.Name   \u002F\u002F \"\"\nres.Age    \u002F\u002F 0\n\n\u002F\u002F 可选字段检查\n\nres.JSON.Owners.Valid() \u002F\u002F true\nres.JSON.Name.Valid()   \u002F\u002F false\nres.JSON.Age.Valid()    \u002F\u002F false\n\n\u002F\u002F 原始 JSON 值\n\nres.JSON.Owners.Raw()                  \u002F\u002F \"1\"\nres.JSON.Name.Raw() == \"null\"          \u002F\u002F true\nres.JSON.Name.Raw() == respjson.Null   \u002F\u002F true\nres.JSON.Age.Raw() == \"\"               \u002F\u002F true\nres.JSON.Age.Raw() == respjson.Omitted \u002F\u002F true\n```\n\n这些 `.JSON` 结构体还包含一个 `ExtraFields` 映射，其中包含 JSON 响应中未在结构体中定义的任何属性。  \n这对于 SDK 尚未支持的 API 功能非常有用。\n\n```go\nbody := res.JSON.ExtraFields[\"my_unexpected_field\"].Raw()\n```\n\n### 响应联合类型（Response Unions）\n\n在响应中，联合类型（union）由一个扁平化的结构体表示，该结构体包含每个对象变体的所有可能字段。  \n要将其转换为具体变体，请使用 `.AsFooVariant()` 方法；如果存在，也可使用 `.AsAny()` 方法。\n\n如果响应值联合类型包含基本类型（primitive values），则基本类型字段将与属性并列，但会以 `Of` 为前缀，并带有标签 `json:\"...,inline\"`。\n\n```go\ntype AnimalUnion struct {\n\t\u002F\u002F 来自变体 [Dog], [Cat]\n\tOwner Person `json:\"owner\"`\n\t\u002F\u002F 来自变体 [Dog]\n\tDogBreed string `json:\"dog_breed\"`\n\t\u002F\u002F 来自变体 [Cat]\n\tCatBreed string `json:\"cat_breed\"`\n\t\u002F\u002F ...\n\n\tJSON struct {\n\t\tOwner respjson.Field\n\t\t\u002F\u002F ...\n\t} `json:\"-\"`\n}\n\n\u002F\u002F 如果是 animal 变体\nif animal.Owner.Address.ZipCode == \"\" {\n\tpanic(\"missing zip code\")\n}\n\n\u002F\u002F 根据变体进行切换\nswitch variant := animal.AsAny().(type) {\ncase Dog:\ncase Cat:\ndefault:\n\tpanic(\"unexpected type\")\n}\n```\n\n### 请求选项（RequestOptions）\n\n本库使用函数式选项模式（functional options pattern）。  \n`option` 包中定义的函数返回一个 `RequestOption`，它是一个修改 `RequestConfig` 的闭包。  \n这些选项可以提供给客户端，也可以在单个请求中指定。例如：\n\n```go\nclient := openai.NewClient(\n\t\u002F\u002F 为客户端发起的每个请求添加一个头部\n\toption.WithHeader(\"X-Some-Header\", \"custom_header_info\"),\n)\n\nclient.Responses.New(context.TODO(), responses.ResponseNewParams{...},\n\t\u002F\u002F 覆盖头部\n\toption.WithHeader(\"X-Some-Header\", \"some_other_custom_header_info\"),\n\t\u002F\u002F 使用 sjson 语法向请求体添加未文档化的字段\n\toption.WithJSONSet(\"some.json.path\", map[string]string{\"my\": \"object\"}),\n)\n```\n\n调试时，请求选项 `option.WithDebugLog(nil)` 可能会有帮助。\n\n请参阅[完整的请求选项列表](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Foption)。\n\n### 分页（Pagination）\n\n本库为处理分页列表端点提供了一些便利功能。\n\n你可以使用 `.ListAutoPaging()` 方法遍历所有页面中的项目：\n\n```go\niter := client.FineTuning.Jobs.ListAutoPaging(context.TODO(), openai.FineTuningJobListParams{\n\tLimit: openai.Int(20),\n})\n\u002F\u002F 根据需要自动获取更多页面。\nfor iter.Next() {\n\tfineTuningJob := iter.Current()\n\tfmt.Printf(\"%+v\\n\", fineTuningJob)\n}\nif err := iter.Err(); err != nil {\n\tpanic(err.Error())\n}\n```\n\n或者，你也可以使用简单的 `.List()` 方法获取单个页面，并接收一个标准响应对象，该对象包含如 `.GetNextPage()` 等辅助方法，例如：\n\n```go\npage, err := client.FineTuning.Jobs.List(context.TODO(), openai.FineTuningJobListParams{\n\tLimit: openai.Int(20),\n})\nfor page != nil {\n\tfor _, job := range page.Data {\n\t\tfmt.Printf(\"%+v\\n\", job)\n\t}\n\tpage, err = page.GetNextPage()\n}\nif err != nil {\n\tpanic(err.Error())\n}\n```\n\n### 错误（Errors）\n\n当 API 返回非成功状态码时，我们会返回一个类型为 `*openai.Error` 的错误。  \n该错误包含请求的 `StatusCode`、`*http.Request` 和 `*http.Response` 值，以及错误体的 JSON 数据（类似于 SDK 中的其他响应对象）。\n\n我们建议你使用 `errors.As` 模式来处理错误：\n\n```go\n_, err := client.FineTuning.Jobs.New(context.TODO(), openai.FineTuningJobNewParams{\n\tModel:        openai.FineTuningJobNewParamsModel(\"gpt-4o\"),\n\tTrainingFile: \"file-abc123\",\n})\nif err != nil {\n\tvar apierr *openai.Error\n\tif errors.As(err, &apierr) {\n\t\tprintln(string(apierr.DumpRequest(true)))  \u002F\u002F 打印序列化的 HTTP 请求\n\t\tprintln(string(apierr.DumpResponse(true))) \u002F\u002F 打印序列化的 HTTP 响应\n\t}\n\tpanic(err.Error()) \u002F\u002F GET \"\u002Ffine_tuning\u002Fjobs\": 400 Bad Request { ... }\n}\n```\n\n当发生其他错误时，它们将以未包装形式返回；例如，  \n如果 HTTP 传输失败，你可能会收到一个包装了 `*net.OpError` 的 `*url.Error`。\n\n### 超时（Timeouts）\n\n默认情况下，请求不会超时；请使用 context 配置请求生命周期的超时时间。\n\n注意：如果请求被[重试](#retries)，context 超时不会重新计时。  \n要设置每次重试的超时时间，请使用 `option.WithRequestTimeout()`。\n\n```go\n\u002F\u002F 此处设置的是整个请求（包括所有重试）的超时时间。\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)\ndefer cancel()\nclient.Responses.New(\n\tctx,\n\tresponses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"How can I list all files in a directory using Python?\"),\n\t\t},\n\t},\n\t\u002F\u002F 此处设置的是每次重试的超时时间\n\toption.WithRequestTimeout(20*time.Second),\n)\n```\n\n### 文件上传\n\n在 multipart 请求中，对应文件上传的请求参数类型为 `io.Reader`。默认情况下，`io.Reader` 的内容将以文件名为 \"anonymous_file\"、内容类型（content-type）为 \"application\u002Foctet-stream\" 的 multipart 表单部分发送。\n\n可以通过在 `io.Reader` 的运行时类型上实现 `Name() string` 或 `ContentType() string` 方法来自定义文件名和内容类型。注意：`os.File` 已实现 `Name() string`，因此通过 `os.Open` 返回的文件将使用磁盘上的实际文件名发送。\n\n我们还提供了一个辅助函数 `openai.File(reader io.Reader, filename string, contentType string)`，可用于为任意 `io.Reader` 包装指定的文件名和内容类型。\n\n```go\n\u002F\u002F 来自文件系统的文件\nfile, err := os.Open(\"input.jsonl\")\nopenai.FileNewParams{\n\tFile:    file,\n\tPurpose: openai.FilePurposeFineTune,\n}\n\n\u002F\u002F 来自字符串的文件\nopenai.FileNewParams{\n\tFile:    strings.NewReader(\"my file contents\"),\n\tPurpose: openai.FilePurposeFineTune,\n}\n\n\u002F\u002F 自定义文件名和 contentType\nopenai.FileNewParams{\n\tFile:    openai.File(strings.NewReader(`{\"hello\": \"foo\"}`), \"file.go\", \"application\u002Fjson\"),\n\tPurpose: openai.FilePurposeFineTune,\n}\n```\n\n## Webhook 验证\n\n验证 webhook 签名是_可选但推荐的_。\n\n有关 webhook 的更多信息，请参阅 [API 文档](https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fguides\u002Fwebhooks)。\n\n### 解析 webhook 负载\n\n在大多数使用场景中，你可能希望同时验证 webhook 并解析其负载。为此，我们提供了方法 `client.Webhooks.Unwrap()`，该方法会解析 webhook 请求并验证其确实由 OpenAI 发送。如果签名无效，此方法将返回错误。\n\n请注意，`body` 参数应为服务器发送的原始 JSON 字节（不要先解析它）。`Unwrap()` 方法将在确认 webhook 来自 OpenAI 后，为你将此 JSON 解析为事件对象。\n\n```go\npackage main\n\nimport (\n\t\"io\"\n\t\"log\"\n\t\"net\u002Fhttp\"\n\t\"os\"\n\n\t\"github.com\u002Fgin-gonic\u002Fgin\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Foption\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Fwebhooks\"\n)\n\nfunc main() {\n\tclient := openai.NewClient(\n\t\toption.WithWebhookSecret(os.Getenv(\"OPENAI_WEBHOOK_SECRET\")), \u002F\u002F 默认使用环境变量；此处显式指定。\n\t)\n\n\tr := gin.Default()\n\n\tr.POST(\"\u002Fwebhook\", func(c *gin.Context) {\n\t\tbody, err := io.ReadAll(c.Request.Body)\n\t\tif err != nil {\n\t\t\tc.JSON(http.StatusInternalServerError, gin.H{\"error\": \"读取请求体失败\"})\n\t\t\treturn\n\t\t}\n\t\tdefer c.Request.Body.Close()\n\n\t\twebhookEvent, err := client.Webhooks.Unwrap(body, c.Request.Header)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"无效的 webhook 签名: %v\", err)\n\t\t\tc.JSON(http.StatusBadRequest, gin.H{\"error\": \"签名无效\"})\n\t\t\treturn\n\t\t}\n\n\t\tswitch event := webhookEvent.AsAny().(type) {\n\t\tcase webhooks.ResponseCompletedWebhookEvent:\n\t\t\tlog.Printf(\"响应完成: %+v\", event.Data)\n\t\tcase webhooks.ResponseFailedWebhookEvent:\n\t\t\tlog.Printf(\"响应失败: %+v\", event.Data)\n\t\tdefault:\n\t\t\tlog.Printf(\"未处理的事件类型: %T\", event)\n\t\t}\n\n\t\tc.JSON(http.StatusOK, gin.H{\"message\": \"ok\"})\n\t})\n\n\tr.Run(\":8000\")\n}\n```\n\n### 直接验证 webhook 负载\n\n在某些情况下，你可能希望在解析负载之前单独验证 webhook。如果你倾向于分别处理这两个步骤，我们提供了 `client.Webhooks.VerifySignature()` 方法，仅用于验证 webhook 请求的签名。与 `Unwrap()` 类似，如果签名无效，此方法将返回错误。\n\n请注意，`body` 参数应为服务器发送的原始 JSON 字节（不要先解析它）。你需要在验证签名后再自行解析 body。\n\n```go\npackage main\n\nimport (\n\t\"encoding\u002Fjson\"\n\t\"io\"\n\t\"log\"\n\t\"net\u002Fhttp\"\n\t\"os\"\n\n\t\"github.com\u002Fgin-gonic\u002Fgin\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Foption\"\n)\n\nfunc main() {\n\tclient := openai.NewClient(\n\t\toption.WithWebhookSecret(os.Getenv(\"OPENAI_WEBHOOK_SECRET\")), \u002F\u002F 默认使用环境变量；此处显式指定。\n\t)\n\n\tr := gin.Default()\n\n\tr.POST(\"\u002Fwebhook\", func(c *gin.Context) {\n\t\tbody, err := io.ReadAll(c.Request.Body)\n\t\tif err != nil {\n\t\t\tc.JSON(http.StatusInternalServerError, gin.H{\"error\": \"读取请求体失败\"})\n\t\t\treturn\n\t\t}\n\t\tdefer c.Request.Body.Close()\n\n\t\terr = client.Webhooks.VerifySignature(body, c.Request.Header)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"无效的 webhook 签名: %v\", err)\n\t\t\tc.JSON(http.StatusBadRequest, gin.H{\"error\": \"签名无效\"})\n\t\t\treturn\n\t\t}\n\n\t\tc.JSON(http.StatusOK, gin.H{\"message\": \"ok\"})\n\t})\n\n\tr.Run(\":8000\")\n}\n```\n\n### 重试机制\n\n默认情况下，某些错误会自动重试 2 次，并采用短指数退避策略。\n默认重试所有连接错误、408 请求超时、409 冲突、429 速率限制以及 >=500 的内部错误。\n\n你可以使用 `WithMaxRetries` 选项来配置或禁用此行为：\n\n```go\n\u002F\u002F 为所有请求配置默认值：\nclient := openai.NewClient(\n\toption.WithMaxRetries(0), \u002F\u002F 默认值为 2\n)\n\n\u002F\u002F 为单个请求覆盖设置：\nclient.Responses.New(\n\tcontext.TODO(),\n\tresponses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"如何在 JavaScript 中获取当前星期几的名称？\"),\n\t\t},\n\t},\n\toption.WithMaxRetries(5),\n)\n```\n\n### 访问原始响应数据（如响应头）\n\n你可以使用 `option.WithResponseInto()` 请求选项访问原始 HTTP 响应数据。当你需要检查响应头、状态码或其他详细信息时，这非常有用。\n\n```go\n\u002F\u002F 创建一个变量用于存储 HTTP 响应\nvar httpResp *http.Response\nresponse, err := client.Responses.New(\n\tcontext.TODO(),\n\tresponses.ResponseNewParams{\n\t\tModel: openai.ChatModelGPT5_2,\n\t\tInput: responses.ResponseNewParamsInputUnion{\n\t\t\tOfString: openai.String(\"说这是一次测试\"),\n\t\t},\n\t},\n\toption.WithResponseInto(&httpResp),\n)\nif err != nil {\n\t\u002F\u002F 处理错误\n}\nfmt.Printf(\"%+v\\n\", response)\n\nfmt.Printf(\"状态码: %d\\n\", httpResp.StatusCode)\nfmt.Printf(\"响应头: %+#v\\n\", httpResp.Header)\n```\n\n### 发起自定义\u002F未文档化的请求\n\n本库为方便访问已文档化的 API 而进行了类型标注。若您需要访问未文档化的端点（endpoints）、参数（params）或响应属性（response properties），仍可使用本库。\n\n#### 未文档化的端点\n\n要向未文档化的端点发起请求，您可以使用 `client.Get`、`client.Post` 及其他 HTTP 动词方法。客户端上的 `RequestOptions`（如重试机制）在发起此类请求时仍将生效。\n\n```go\nvar (\n    \u002F\u002F params 可以是 io.Reader、[]byte、可被 encoding\u002Fjson 序列化的对象，\n    \u002F\u002F 或本库中定义的“…Params”结构体。\n    params map[string]any\n\n    \u002F\u002F result 可以是 []byte、*http.Response、可被 encoding\u002Fjson 反序列化的对象，\n    \u002F\u002F 或本库中定义的模型。\n    result *http.Response\n)\nerr := client.Post(context.Background(), \"\u002Funspecified\", params, &result)\nif err != nil {\n    …\n}\n```\n\n#### 未文档化的请求参数\n\n若需使用未文档化的参数发起请求，您可以使用 `option.WithQuerySet()` 或 `option.WithJSONSet()` 方法。\n\n```go\nparams := FooNewParams{\n    ID:   \"id_xxxx\",\n    Data: FooNewParamsData{\n        FirstName: openai.String(\"John\"),\n    },\n}\nclient.Foo.New(context.Background(), params, option.WithJSONSet(\"data.last_name\", \"Doe\"))\n```\n\n#### 未文档化的响应属性\n\n要访问未文档化的响应属性，您可以通过 `result.JSON.RawJSON()` 获取响应的原始 JSON 字符串，或通过 `result.JSON.Foo.Raw()` 获取结果中特定字段的原始 JSON。\n\n任何未在响应结构体中声明的字段都会被保存，并可通过 `result.JSON.ExtraFields()` 访问，该方法返回一个 `map[string]Field` 类型的额外字段集合。\n\n### 中间件（Middleware）\n\n我们提供 `option.WithMiddleware`，用于将指定的中间件应用于请求。\n\n```go\nfunc Logger(req *http.Request, next option.MiddlewareNext) (res *http.Response, err error) {\n\t\u002F\u002F 请求前处理\n\tstart := time.Now()\n\tLogReq(req)\n\n\t\u002F\u002F 将请求转发给下一个处理器\n\tres, err = next(req)\n\n\t\u002F\u002F 请求后处理\n\tend := time.Now()\n\tLogRes(res, err, start - end)\n\n    return res, err\n}\n\nclient := openai.NewClient(\n\toption.WithMiddleware(Logger),\n)\n```\n\n当以变长参数形式提供多个中间件时，中间件将从左到右依次应用。如果多次调用 `option.WithMiddleware`（例如先在客户端设置，再在方法中设置），则客户端设置的中间件会先执行，方法中设置的中间件随后执行。\n\n您也可以使用 `option.WithHTTPClient(client)` 替换默认的 `http.Client`。仅接受一个 HTTP 客户端（这会覆盖之前设置的客户端），且该客户端将在所有中间件处理完毕后接收请求。\n\n## Microsoft Azure OpenAI\n\n要在 [Azure OpenAI](https:\u002F\u002Flearn.microsoft.com\u002Fazure\u002Fai-services\u002Fopenai\u002Foverview) 上使用本库，请使用 `azure` 包中的 `option.RequestOption` 函数。\n\n```go\npackage main\n\nimport (\n\t\"github.com\u002FAzure\u002Fazure-sdk-for-go\u002Fsdk\u002Fazidentity\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Fazure\"\n)\n\nfunc main() {\n\tconst azureOpenAIEndpoint = \"https:\u002F\u002F\u003Cazure-openai-resource>.openai.azure.com\"\n\n\t\u002F\u002F 最新的 API 版本（包括预览版）可在此处找到：\n\t\u002F\u002F https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fazure\u002Fai-services\u002Fopenai\u002Freference#rest-api-versionng\n\tconst azureOpenAIAPIVersion = \"2024-06-01\"\n\n\ttokenCredential, err := azidentity.NewDefaultAzureCredential(nil)\n\n\tif err != nil {\n\t\tfmt.Printf(\"Failed to create the DefaultAzureCredential: %s\", err)\n\t\tos.Exit(1)\n\t}\n\n\tclient := openai.NewClient(\n\t\tazure.WithEndpoint(azureOpenAIEndpoint, azureOpenAIAPIVersion),\n\n\t\t\u002F\u002F 选择使用 TokenCredential 或 API Key 进行身份验证\n\t\tazure.WithTokenCredential(tokenCredential),\n\t\t\u002F\u002F 或 azure.WithAPIKey(azureOpenAIAPIKey),\n\t)\n}\n```\n\n## 语义化版本控制（Semantic versioning）\n\n本包通常遵循 [SemVer](https:\u002F\u002Fsemver.org\u002Fspec\u002Fv2.0.0.html) 规范，但某些不兼容的变更可能会作为次要版本发布：\n\n1. 对库内部实现的更改，这些部分虽技术上公开，但并非为外部使用而设计或文档化。（若您依赖此类内部实现，请提交 GitHub Issue 告知我们。）\n2. 我们认为在实践中不会影响绝大多数用户的变更。\n\n我们高度重视向后兼容性，并努力确保您能获得顺畅的升级体验。\n\n我们非常期待您的反馈；请通过 [Issue](https:\u002F\u002Fwww.github.com\u002Fopenai\u002Fopenai-go\u002Fissues) 提交问题、错误或建议。\n\n## 贡献指南\n\n详见 [贡献文档](.\u002FCONTRIBUTING.md)。","# openai-go 快速上手指南\n\n## 环境准备\n\n- **Go 版本要求**：1.22 或更高版本\n- **前置依赖**：无特殊依赖，标准库 + 本包即可\n- **API 密钥**：需在 [OpenAI 平台](https:\u002F\u002Fplatform.openai.com\u002F) 获取 API Key，或设置环境变量 `OPENAI_API_KEY`\n\n> 🇨🇳 国内开发者建议使用代理或镜像服务加速访问 OpenAI API（如通过 Cloudflare Workers、Vercel 或自建中转）\n\n## 安装步骤\n\n在项目中导入：\n\n```go\nimport (\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\" \u002F\u002F 默认别名为 openai\n)\n```\n\n或通过命令行安装指定版本：\n\n```sh\ngo get -u 'github.com\u002Fopenai\u002Fopenai-go\u002Fv3@v3.30.0'\n```\n\n## 基本使用\n\n以下是最简单的文本生成示例：\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Foption\"\n\t\"github.com\u002Fopenai\u002Fopenai-go\u002Fv3\u002Fresponses\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient := openai.NewClient(\n\t\toption.WithAPIKey(\"My API Key\"), \u002F\u002F 可省略，默认读取环境变量 OPENAI_API_KEY\n\t)\n\n\tquestion := \"写一首关于计算机的俳句\"\n\n\tresp, err := client.Responses.New(ctx, responses.ResponseNewParams{\n\t\tInput: responses.ResponseNewParamsInputUnion{OfString: openai.String(question)},\n\t\tModel: openai.ChatModelGPT5_2,\n\t})\n\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tprintln(resp.OutputText())\n}\n```\n\n运行后将输出模型生成的回答文本。","一家跨境电商公司的后端团队正在用 Go 语言开发智能客服系统，需要在用户咨询时实时调用 OpenAI 的 GPT 模型生成自然语言回复。\n\n### 没有 openai-go 时\n- 团队必须手动封装 HTTP 请求，处理认证头、JSON 序列化和错误码映射，代码冗长且容易出错。\n- 每次模型升级或 API 变更都要重新调整请求结构，缺乏类型安全，调试成本高。\n- 多轮对话需自行维护上下文 ID 和会话状态，逻辑分散在多个服务中，难以统一管理。\n- 流式响应需从零实现 SSE（Server-Sent Events）解析，增加网络层复杂度和内存开销。\n- 缺乏官方支持的 SDK，遇到问题只能查阅原始 API 文档，排查效率低，新人上手慢。\n\n### 使用 openai-go 后\n- 直接调用 `client.Responses.New()` 方法即可发起请求，内置 API Key 管理和结构体参数校验，代码简洁可靠。\n- 所有参数和返回值均有强类型定义，配合 Go 1.22+ 的泛型支持，编译期就能发现接口不匹配问题。\n- 通过 `PreviousResponseID` 或 `Conversation.ID` 轻松维持对话状态，会话历史自动关联，业务逻辑清晰集中。\n- 使用内置流式响应支持，一行代码开启 `Stream: true` 即可逐字返回，降低延迟并提升用户体验。\n- 官方维护的库持续同步最新 API，附带完整示例和 changelog，团队能快速适配新功能，减少技术负债。\n\nopenai-go 让 Go 开发者以最小成本接入 OpenAI 能力，把精力从底层通信转移到真正的业务创新上。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fopenai_openai-go_a19e7d52.png","openai","OpenAI","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fopenai_1960bbf4.png","",null,"https:\u002F\u002Fopenai.com\u002F","https:\u002F\u002Fgithub.com\u002Fopenai",[83,87,91],{"name":84,"color":85,"percentage":86},"Go","#00ADD8",99.8,{"name":88,"color":89,"percentage":90},"Shell","#89e051",0.2,{"name":92,"color":93,"percentage":94},"Ruby","#701516",0,3116,290,"2026-04-05T15:14:37","Apache-2.0","未说明",{"notes":101,"python":99,"dependencies":102},"需要 Go 1.22 或更高版本，通过 go get 安装，依赖环境变量 OPENAI_API_KEY 或手动传入 API 密钥",[],[15,36],6,"2026-03-27T02:49:30.150509","2026-04-06T08:40:44.207216",[108,113,118,123,128,133],{"id":109,"question_zh":110,"answer_zh":111,"source_url":112},447,"何时会发布 beta 或稳定版本？","官方目标是在三月底前完成 beta 版本并稳定 API。从 alpha 到 beta 的重大破坏性变更不会再出现，但可能会有小调整（如辅助函数重命名、类型收窄等）。后续还会支持请求结构体实现 json.Unmarshaler。","https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fissues\u002F71",{"id":114,"question_zh":115,"answer_zh":116,"source_url":117},448,"alpha-63 版本编译报错怎么办？","请升级到 v0.1.0-alpha.65 或更高版本以解决编译错误。注意：alpha.66 可能再次出现问题，建议关注最新版本。","https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fissues\u002F265",{"id":119,"question_zh":120,"answer_zh":121,"source_url":122},449,"如何让 SDK 支持将 JSON 反序列化到请求结构体中？","该功能现已支持。所有请求结构体已实现 json.Unmarshaler 接口，可直接使用 json.Unmarshal(body, &chatRequest) 进行反序列化。","https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fissues\u002F247",{"id":124,"question_zh":125,"answer_zh":126,"source_url":127},450,"能否传入自定义 HTTP 客户端接口而非 *http.Client？","SDK 现已支持通过 option.WithHTTPClient() 传入实现了 Do() 方法的接口（即“Doer”），类似 AWS SDK 的设计。详情可参考 PR #357 的实现。","https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fissues\u002F233",{"id":129,"question_zh":130,"answer_zh":131,"source_url":132},451,"Image Edit 功能似乎有问题，mask 参数如何设为 nil？","请升级到 v1.0.0 版本修复部分问题。若仍需特定 beta 版本，可通过 commit ID 安装，例如：go get github.com\u002Fopenai\u002Fopenai-go@ecfccf0ecf93d9be8099cc0e694d41478882a598。","https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fissues\u002F385",{"id":134,"question_zh":135,"answer_zh":136,"source_url":132},452,"安装 v0.1.0-beta.11 失败提示 unknown revision 怎么办？","beta.11 尚未正式发布到 releases，建议改用 commit hash 安装指定版本，例如：go get github.com\u002Fopenai\u002Fopenai-go@ecfccf0ecf93d9be8099cc0e694d41478882a598。",[138,143,148,153,158,163,168,173,178,183,188,193,198,203,208,213,218,223,228,233],{"id":139,"version":140,"summary_zh":141,"released_at":142},109782,"v3.30.0","## 3.30.0 (2026-03-25)\n\nFull Changelog: [v3.29.0...v3.30.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.29.0...v3.30.0)\n\n### Features\n\n* **api:** add keys field to computer action types ([7abb3c4](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F7abb3c4b4d1fb3d2757dd70c5a201de4190f298a))\n\n\n### Bug Fixes\n\n* **api:** align SDK response types with expanded item schemas ([324c584](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F324c584ec31315ec18c169918e524741e74d395a))\n* **types:** generate shared enum types that are not referenced by other schemas ([e2f2920](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fe2f2920f510348ea8b7e26e6b2460f802d34998c))\n* **types:** make Type required, correct enum in ResponseInputMessageItem ([8c2c7a5](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F8c2c7a59329e95da117ffdde7b36f43e1fbdbacb))\n\n\n### Chores\n\n* **ci:** skip lint on metadata-only changes ([40cf884](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F40cf884295e1631dc637f6e3e1316e8665e5e694))\n* **client:** fix multipart serialisation of Default() fields ([06c04ae](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F06c04aeca47e7348de94573eefbfaf2e110c4573))\n* **internal:** support default value struct tag ([f1afb2a](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Ff1afb2ab20307c50da7ec421ac5cd3e5a9c33fe3))\n* **internal:** update gitignore ([bde0a0d](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fbde0a0d3e4a8b63e2ce28fae207f9546abac0722))\n* **tests:** bump steady to v0.19.4 ([a0561c3](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fa0561c3014b5d5fbeee9d7de58dad3f9be9e2d9f))\n* **tests:** bump steady to v0.19.5 ([56c5c36](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F56c5c3631cb1dec68b8cb68c1e03d62e69fe3a70))\n* **tests:** bump steady to v0.19.6 ([44ebe37](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F44ebe3744e70460f2cacd94ccf21957e30d697a1))\n* **tests:** bump steady to v0.19.7 ([1b04072](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F1b04072ef94542b2a0007e4088ef09d4f5387dcf))\n\n\n### Refactors\n\n* **tests:** switch from prism to steady ([2185358](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F21853589203e202637f9ebc7f7be5d4c73f2a471))","2026-03-25T22:09:07",{"id":144,"version":145,"summary_zh":146,"released_at":147},109783,"v3.29.0","## 3.29.0 (2026-03-17)\n\nFull Changelog: [v3.28.0...v3.29.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.28.0...v3.29.0)\n\n### Features\n\n* **api:** 5.4 nano and mini model slugs ([c4ebb48](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fc4ebb48b3314d41ae1ca8006ccf7d5b9facad61e))\n* **api:** add in and nin values to comparison filter type ([d060d44](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fd060d4473d6ca87e0427eea709f87d5edd0e7c78))\n\n\n### Chores\n\n* **internal:** tweak CI branches ([6379626](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F63796269b563770b6cbb24144edade0e57051e50))","2026-03-17T17:53:09",{"id":149,"version":150,"summary_zh":151,"released_at":152},109784,"v3.28.0","## 3.28.0 (2026-03-14)\n\nFull Changelog: [v3.27.0...v3.28.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.27.0...v3.28.0)\n\n### Features\n\n* **api:** add \u002Fv1\u002Fvideos endpoint option to batch ([7b2d67e](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F7b2d67e3d65737572d89536d16ed81a3ce39688f))\n* **api:** add defer_loading field to function tools ([6d4b683](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F6d4b6833e5b0b29a9b1d0c99062a231290e8b93f))\n* **api:** custom voices ([d00b782](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fd00b782c32db4c953b8e39edc5a77504693c70f3))\n\n### ⚠ BREAKING CHANGES\n\n* **api:** The `voice` param and resouce has changed from a `string` to a `string | {id: string}`. This is a breaking change for Go.","2026-03-14T16:11:13",{"id":154,"version":155,"summary_zh":156,"released_at":157},109785,"v3.27.0","## 3.27.0 (2026-03-13)\n\nFull Changelog: [v3.26.0...v3.27.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.26.0...v3.27.0)\n\n### Features\n\n* **api:** add video character\u002Fedit\u002Fextend, remove Azure\u002Fwebhook\u002Fpolling\u002Faccumulator ([20da043](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F20da043643286aa444450f4bf4ab6f68c5401455))\n* **api:** add video edits\u002Fextensions\u002Fcharacter, remove Azure\u002Fwebhook\u002Fpolling helpers ([fa9413f](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Ffa9413f9b7c00ec36b124c4b3714daf2b2cd978d))\n* **api:** api update ([c88c6c9](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fc88c6c9732f7b7a8cd739b8006a56d564ab59183))\n* **api:** sora api improvements: character api, video extensions\u002Fedits, higher resolution exports. ([93f6779](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F93f6779c0c2a1beb7f68b570c61aae8fda52fd1f))\n\n\n### Chores\n\n* **internal:** codegen related update ([d531232](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fd5312325255bcac5934636d320653c338bb9622e))\n* **internal:** codegen related update ([1748c11](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F1748c114b2d642b38fdacfef7823cbd4130c29c5))\n* **internal:** codegen related update ([531ece1](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F531ece1703028189ba6081a168f3a979481dcf0c))\n* **internal:** codegen related update ([ce9f435](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fce9f4357c22b533fff0d3385058dbadc033928e8))","2026-03-13T19:16:55",{"id":159,"version":160,"summary_zh":161,"released_at":162},109786,"v3.26.0","## 3.26.0 (2026-03-05)\n\nFull Changelog: [v3.25.0...v3.26.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcompare\u002Fv3.25.0...v3.26.0](https:\u002F\u002Fwww.golinks.io\u002Fcompare\u002Fv3.25.0...v3.26.0?trackSource=github))\n\n### Features\n\n* **api:** The GA ComputerTool now uses the CompuerTool class. The 'computer_use_preview' tool is moved to ComputerUsePreview ([347418b](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcommit\u002F347418be8d4fa33881d9ac30f6c7132f2f545f2b](https:\u002F\u002Fwww.golinks.io\u002Fcommit\u002F347418be8d4fa33881d9ac30f6c7132f2f545f2b?trackSource=github)))","2026-03-05T23:21:56",{"id":164,"version":165,"summary_zh":166,"released_at":167},109787,"v3.25.0","## 3.25.0 (2026-03-05)\n\nFull Changelog: [v3.24.0...v3.25.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.24.0...v3.25.0)\n\n### Features\n\n* **api:** gpt-5.4, tool search tool, and new computer tool ([101826d](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F101826dd757a0213aecb4eaa6332866657b9aa83))\n* **api:** remove Phase from input\u002Foutput messages, PromptCacheKey from responses ([961b8ca](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F961b8ca27923beca8aa08d4a8e3382c2da9d61db))\n\n\n### Bug Fixes\n\n* **api:** internal schema fixes ([fe5f7cd](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Ffe5f7cdb34d11dd18caa503716cae1512b245053))\n* **api:** manual updates ([70b02c8](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F70b02c8f63c98a17813dc6cb7f7707fb2bba81c5))\n* **api:** readd phase ([548aff8](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F548aff8ad8b96518f5549ec3bc98da71e9b7f540))\n\n\n### Chores\n\n* **internal:** codegen related update ([ab733b9](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fab733b91db39e99e292696530340333c065e04b9))\n* **internal:** codegen related update ([23d1831](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F23d1831cb5ca6f61ca8575737cec17e2f347818b))\n* **internal:** reduce warnings ([2963312](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F2963312c075fa9a30abad32b1e90813229b22129))","2026-03-05T18:22:48",{"id":169,"version":170,"summary_zh":171,"released_at":172},109788,"v3.24.0","## 3.24.0 (2026-02-24)\n\nFull Changelog: [v3.23.0...v3.24.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.23.0...v3.24.0)\n\n### Features\n\n* **api:** add phase ([72366d8](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F72366d895c78b5188a590ee7f9b572b567447b32))\n\n\n### Bug Fixes\n\n* **api:** fix phase enum ([5712ebf](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F5712ebf1f30e63d148a72c451f1df48620b14a2d))\n* **api:** phase docs ([b67dd66](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fb67dd6680110c013c1660c37dde5467e2cd50030))\n\n\n### Chores\n\n* **internal:** move custom custom `json` tags to `api` ([0735303](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F0735303849ece03c57adbb0f899d7f3a0b60bc50))\n* **internal:** refactor sse event parsing ([45dc6bb](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F45dc6bb18120330de4470739a07b13f08d7f7666))","2026-02-24T19:54:48",{"id":174,"version":175,"summary_zh":176,"released_at":177},109789,"v3.23.0","## 3.23.0 (2026-02-24)\n\nFull Changelog: [v3.22.1...v3.23.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.22.1...v3.23.0)\n\n### Features\n\n* **api:** add gpt-realtime-1.5 and gpt-audio-1.5 models to realtime session ([9076e2f](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F9076e2f2fab882d5a8ba9992096e5997902c5589))","2026-02-24T03:19:38",{"id":179,"version":180,"summary_zh":181,"released_at":182},109790,"v3.22.1","## 3.22.1 (2026-02-23)\n\nFull Changelog: [v3.22.0...v3.22.1](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.22.0...v3.22.1)\n\n### Bug Fixes\n\n* allow canceling a request while it is waiting to retry ([54672cf](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F54672cf6b2c21a0e2ac0d2a7d7bed8680eee3e44))\n\n\n### Chores\n\n* update mock server docs ([3ac84dd](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F3ac84dd90e21d9374c0141d86c07d21e0914c6b0))\n\n\n### Documentation\n\n* **api:** add batch size limit to vector store file batch parameters ([f751c40](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Ff751c40c522d6fba5c4eb244fd25f28c2317ca33))\n* **api:** clarify safety_identifier max length in chat completions and responses ([8257f9b](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F8257f9b0e4d63038f2b088a42399e3a80e9c9bb6))\n* **api:** enhance method docstrings across audio\u002Fchat\u002Fcompletion\u002Fskill\u002Fupload\u002Fvideo APIs ([38b8f63](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F38b8f63a16f9a50bb176561f7842baf976e88316))","2026-02-23T20:14:40",{"id":184,"version":185,"summary_zh":186,"released_at":187},109791,"v3.22.0","## 3.22.0 (2026-02-13)\n\nFull Changelog: [v3.21.0...v3.22.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.21.0...v3.22.0)\n\n### Features\n\n* **api:** container network_policy and skills ([8e5ea23](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F8e5ea2344580eefa186040cae3583dacf459e0b9))\n\n\n### Bug Fixes\n\n* **encoder:** correctly serialize NullStruct ([a6cb49e](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fa6cb49ef3743b1c0b58d24f8dbc5e16e1a5f5852))\n\n\n### Documentation\n\n* update comment ([bc316d7](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fbc316d7b10fa928289e0560123b0de16099edfb7))","2026-02-14T00:34:50",{"id":189,"version":190,"summary_zh":191,"released_at":192},109792,"v3.21.0","## 3.21.0 (2026-02-10)\n\nFull Changelog: [v3.20.0...v3.21.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcompare\u002Fv3.20.0...v3.21.0](https:\u002F\u002Fwww.golinks.io\u002Fcompare\u002Fv3.20.0...v3.21.0?trackSource=github))\n\n### Features\n\n* **api:** support for images in batch api ([e23aeb1](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcommit\u002Fe23aeb1b13bfd089cc73d3097c9635b687446f82](https:\u002F\u002Fwww.golinks.io\u002Fcommit\u002Fe23aeb1b13bfd089cc73d3097c9635b687446f82?trackSource=github)))","2026-02-10T19:03:30",{"id":194,"version":195,"summary_zh":196,"released_at":197},109793,"v3.20.0","## 3.20.0 (2026-02-10)\n\nFull Changelog: [v3.19.0...v3.20.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcompare\u002Fv3.19.0...v3.20.0](https:\u002F\u002Fwww.golinks.io\u002Fcompare\u002Fv3.19.0...v3.20.0?trackSource=github))\n\n### Features\n\n* **api:** skills and hosted shell ([9e191de](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcommit\u002F9e191de75f67a6a693c8b25ac9ab1b9288673993](https:\u002F\u002Fwww.golinks.io\u002Fcommit\u002F9e191de75f67a6a693c8b25ac9ab1b9288673993?trackSource=github)))","2026-02-10T18:14:43",{"id":199,"version":200,"summary_zh":201,"released_at":202},109794,"v3.19.0","## 3.19.0 (2026-02-09)\n\nFull Changelog: [v3.18.0...v3.19.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.18.0...v3.19.0)\n\n### Features\n\n* **api:** responses context_management ([199f230](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F199f23025ab098f2ac0ac9a99dee37235613c287))","2026-02-09T21:40:24",{"id":204,"version":205,"summary_zh":206,"released_at":207},109795,"v3.18.0","## 3.18.0 (2026-02-05)\n\nFull Changelog: [v3.17.0...v3.18.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.17.0...v3.18.0)\n\n### Features\n\n* **api:** add shell_call_output status field ([67a75d7](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F67a75d755e815f6d6fdf4ac48314472a94c8613f))\n* **api:** image generation actions for responses; ResponseFunctionCallArgumentsDoneEvent.name ([2c57016](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F2c57016b7c7f45072c59f193e567a55ecbda21fd))\n\n\n### Bug Fixes\n\n* **client:** undo change to web search Find action ([e340256](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fe340256509214ee386de32b993f5ec4ebba43d38))\n* **client:** update type for `find_in_page` action ([4b5d499](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F4b5d4993e82ada68276bb5560bb2cd8b457aa3da))\n\n\n### Chores\n\n* **client:** improve example values ([c86a65c](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fc86a65cefd55eb18568f4b7d2660c82dc90af4ad))\n\n\n### Documentation\n\n* split `api.md` by standalone resources ([aeed37b](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Faeed37b814d37ad3d59111b7665d48bf220cbf9e))","2026-02-05T16:27:46",{"id":209,"version":210,"summary_zh":211,"released_at":212},109796,"v3.17.0","## 3.17.0 (2026-01-27)\n\nFull Changelog: [v3.16.0...v3.17.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.16.0...v3.17.0)\n\n### Features\n\n* **api:** api update ([a456c60](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fa456c60498b33b7da048cc64bdff76c49a904117))\n* **api:** api updates ([21fd4a9](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F21fd4a9534d5ef531c6a9bc497b90c14b68ebda3))\n* **client:** add a convenient param.SetJSON helper ([1b35ece](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F1b35ece947934982609557e6acacfd3526289de1))\n* **client:** add a StreamError type to access raw events from sse streams ([fd14b30](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Ffd14b30e3cc2d14438a100be12627692e8ea045a))\n\n\n### Bug Fixes\n\n* **api:** mark assistants as deprecated ([9a8c9af](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F9a8c9af8cf988069e543487c09a0897806408d67))\n* **client:** retain streaming when user sets request body ([3a7a22e](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F3a7a22ec90c5ff44203321bbff94f9541a80601f))\n* **docs:** add missing pointer prefix to api.md return types ([dd641d9](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fdd641d924ead979b4369b952f99387880879938d))\n\n\n### Chores\n\n* **internal:** codegen related update ([74d3989](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F74d3989139a94407020f7bf43c8351c4dffe412c))\n* **internal:** update `actions\u002Fcheckout` version ([2db54a5](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F2db54a5d05e3240c415cb91320ede5704331828a))","2026-01-27T23:33:11",{"id":214,"version":215,"summary_zh":216,"released_at":217},109797,"v3.16.0","## 3.16.0 (2026-01-09)\n\nFull Changelog: [v3.15.0...v3.16.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.15.0...v3.16.0)\n\n### Features\n\n* **api:** add new Response completed_at prop ([bff6331](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fbff6331c1b428de935966f59f2465e77df08f075))\n\n\n### Bug Fixes\n\n* **client:** use the correct order of params for vector store file and batch polling ([ef32641](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fef32641b81da84c7d0524c372ee8b45cda71fe2c))\n\n\n### Chores\n\n* **internal:** codegen related update ([1e529a4](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F1e529a4b48c55a6bb611f5dcaf0ad1bfbd6f729d))\n* **internal:** use different example values for some enums ([a2836ee](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fa2836eef250be42d9e0f135c36823219129cad1e))\n\n\n### Documentation\n\n* update URL version ([dc00e14](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fdc00e14cae07daaefabeb5371daa12f90bb82dc8))","2026-01-09T22:10:12",{"id":219,"version":220,"summary_zh":221,"released_at":222},109798,"v3.15.0","## 3.15.0 (2025-12-19)\n\nFull Changelog: [v3.14.0...v3.15.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.14.0...v3.15.0)\n\n### Bug Fixes\n\n* rebuild ([8205ae7](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F8205ae7c00de1bd4a543381ba61b34f9b5676eda))\n\n\n### Chores\n\n* add float64 to valid types for RegisterFieldValidator ([e67d89d](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fe67d89d39bc14af7309df702592ae152d1dfd60b))","2025-12-19T03:28:27",{"id":224,"version":225,"summary_zh":226,"released_at":227},109799,"v3.14.0","## 3.14.0 (2025-12-16)\n\nFull Changelog: [v3.13.0...v3.14.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcompare\u002Fv3.13.0...v3.14.0](https:\u002F\u002Fwww.golinks.io\u002Fcompare\u002Fv3.13.0...v3.14.0?trackSource=github))\n\n### Features\n\n* **api:** gpt-image-1.5 ([6102f02](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-[go\u002Fcommit\u002F6102f029e7ccbffe1dcf4d53b38f7da49dfbdbaa](https:\u002F\u002Fwww.golinks.io\u002Fcommit\u002F6102f029e7ccbffe1dcf4d53b38f7da49dfbdbaa?trackSource=github)))","2025-12-16T18:16:26",{"id":229,"version":230,"summary_zh":231,"released_at":232},109800,"v3.13.0","## 3.13.0 (2025-12-15)\n\nFull Changelog: [v3.12.0...v3.13.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.12.0...v3.13.0)\n\n### Features\n\n* **api:** api update ([20b5112](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F20b51126dc55b5fa357ae848593873d46514d820))\n* **api:** fix grader input list, add dated slugs for sora-2 ([e8f0b76](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fe8f0b76c55abdcca2920372f74e08621d8a530b9))\n\n\n### Bug Fixes\n\n* **azure:** correct Azure OpenAI API URL construction and auth ([3ba3736](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F3ba3736c4b1a6138c05df5ccb64944a3dca6ea74))","2025-12-15T16:17:16",{"id":234,"version":235,"summary_zh":236,"released_at":237},109801,"v3.12.0","## 3.12.0 (2025-12-11)\n\nFull Changelog: [v3.11.0...v3.12.0](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcompare\u002Fv3.11.0...v3.12.0)\n\n### Features\n\n* **api:** gpt 5.2 ([56b5d41](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002F56b5d410cb7ee90d2c7ddd4fb8650bf1dd818855))\n* **encoder:** support bracket encoding form-data object members ([a2cbacf](https:\u002F\u002Fgithub.com\u002Fopenai\u002Fopenai-go\u002Fcommit\u002Fa2cbacff1f0189e81ec4091a33f1ec350bbabd09))","2025-12-11T18:15:40"]