X Tutup
Skip to content

feat(provider): Integrate OpenAI Responses API with native web search and code interpreter support.#5953

Draft
outlook84 wants to merge 2 commits intoAstrBotDevs:masterfrom
outlook84:fix/openai-responses-streaming-tools
Draft

feat(provider): Integrate OpenAI Responses API with native web search and code interpreter support.#5953
outlook84 wants to merge 2 commits intoAstrBotDevs:masterfrom
outlook84:fix/openai-responses-streaming-tools

Conversation

@outlook84
Copy link

@outlook84 outlook84 commented Mar 9, 2026

支持 OpenAI 新版 Responses API 和网页搜索/代码执行器原生工具。

Modifications / 改动点

核心改动文件有 5 个:

  • astrbot/core/provider/sources/openai_source.py
  • astrbot/core/config/default.py
  • dashboard/src/i18n/locales/zh-CN/features/config-metadata.json
  • dashboard/src/i18n/locales/en-US/features/config-metadata.json
  • tests/test_openai_source.py

它实现的功能可以概括成三块:

  1. OpenAI Provider 增加 Responses API 支持
    在 openai_source.py 里新增了 use_responses_api 开关,并在请求路径上区分:

    • 传统 /v1/chat/completions
    • 新的 /v1/responses
  2. 支持 OpenAI 原生工具
    增加了两个能力开关:

    • oa_native_web_search
    • oa_native_code_interpreter

    启用后会强制走 Responses API,并使用 OpenAI 原生工具,而不是 AstrBot 原本的函数工具链。

  3. 配置项和测试补齐

    • 在 default.py 给 provider 模板加了这几个新配置项
    • 在中英文 config-metadata.json / config-metadata.json 补了 WebUI 文案
    • 在 test_openai_source.py 增加了对应行为测试
  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

firefox_9SveKJwOYr firefox_7ELCEqPEOK

Checklist / 检查清单

  • 😊 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。/ If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
  • 👀 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。/ My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
  • 🤓 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到了 requirements.txtpyproject.toml 文件相应位置。/ I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
  • 😮 我的更改没有引入恶意代码。/ My changes do not introduce malicious code.

Summary by Sourcery

在基于 OpenAI 的 provider 栈中新增对 Responses API 的支持,并将其接入现有的查询/流式处理管线,包括在聊天消息格式与 Responses 输入/输出之间进行转换。

新功能:

  • 引入一个可配置开关,使 OpenAI Responses API 能与现有的 chat completions 端点并行使用。
  • 增加对 OpenAI 原生 Web 搜索和代码解释器工具的支持,通过 provider 配置开关启用,并映射到 Responses 的 tools 接口中。

增强内容:

  • 为兼容 OpenAI 的后端扩展 provider 模板,增加用于选择使用 Responses API 和原生工具的新标志位。
  • 改进 token 使用量统计,通过处理 Responses API 的使用字段,并区分缓存与非缓存的输入 tokens。

测试:

  • 新增单元测试,覆盖 Responses 负载构造、原生工具优先于函数工具的策略、Responses 补全结果解析、无效工具参数的错误处理,以及流式分片行为。
Original summary in English

Summary by Sourcery

Add Responses API support to the OpenAI-based provider stack and wire it into the existing query/streaming pipeline, including conversion between chat-style messages and Responses inputs/outputs.

New Features:

  • Introduce a configurable switch to use the OpenAI Responses API alongside the existing chat completions endpoint.
  • Add support for OpenAI native web search and code interpreter tools, enabled via provider configuration flags and mapped into the Responses tools interface.

Enhancements:

  • Extend provider templates for OpenAI-compatible backends with new flags for selecting Responses API and native tool usage.
  • Improve token usage tracking by handling Responses API usage fields and distinguishing cached vs non-cached input tokens.

Tests:

  • Add unit tests covering Responses payload construction, native tool precedence over function tools, Responses completion parsing, error handling for invalid tool arguments, and streaming chunk behavior.

@auto-assign auto-assign bot requested review from LIghtJUNction and anka-afk March 9, 2026 13:33
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Mar 9, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the OpenAI provider by integrating the latest Responses API, which unlocks powerful native tools like web search and code interpreter. The changes include core logic for API interaction, message conversion, and tool handling, alongside necessary configuration updates and UI localizations. This enhancement allows users to tap into advanced OpenAI capabilities directly, offering more robust and integrated functionality.

Highlights

  • OpenAI Responses API Integration: Implemented support for OpenAI's new Responses API, allowing the system to utilize the /v1/responses endpoint instead of /v1/chat/completions when enabled.
  • Native Web Search and Code Interpreter Support: Added functionality to leverage OpenAI's native web search and code interpreter tools, which are exclusively available through the Responses API. Enabling these tools will override AstrBot's custom function toolchain.
  • New Configuration Options: Introduced new boolean configuration parameters (use_responses_api, oa_native_web_search, oa_native_code_interpreter) across various chat provider templates to control the new features.
  • User Interface Updates: Updated the English and Chinese UI metadata to include descriptions and hints for the newly added configuration options, ensuring clarity for users.
  • Comprehensive Testing: Added new unit tests to validate the correct construction of Responses API payloads, the behavior of native tools, and the parsing of Responses API completions, including streaming responses.
Changelog
  • astrbot/core/config/default.py
    • Added 'use_responses_api', 'oa_native_web_search', and 'oa_native_code_interpreter' boolean fields to all chat provider templates, defaulting to False.
    • Updated the configuration metadata structure to include descriptions and hints for the new fields.
  • astrbot/core/provider/sources/openai_source.py
    • Imported new types from openai.types.responses for Responses API handling.
    • Added a static helper method _as_bool to robustly convert various input types to boolean.
    • Modified the __init__ method to store responses_default_params and initialize use_responses_api based on provider configuration.
    • Implemented _get_openai_native_tools, _openai_native_tools_enabled, and _should_use_responses_api methods to manage native tool activation and Responses API usage.
    • Updated _query and _query_stream methods to conditionally call _query_responses or _query_stream_responses based on configuration.
    • Refactored parameter handling in _query and _query_stream to use chat_default_params for traditional chat completions.
    • Added _convert_openai_tools_to_responses to transform AstrBot's tool format to OpenAI Responses API format.
    • Implemented _normalize_message_content_to_list and _convert_message_parts_to_responses_content for robust message content conversion.
    • Developed _convert_openai_messages_to_responses_input to map OpenAI chat messages to the Responses API input format, handling various roles and content types.
    • Created _build_responses_payload to construct the request payload for the Responses API, including native tools and custom extra body parameters.
    • Added _query_responses for non-streaming Responses API calls and _query_stream_responses for streaming Responses API calls, handling events and final response parsing.
    • Implemented _extract_responses_usage to parse token usage from Responses API responses.
    • Developed _parse_responses_completion to extract text, reasoning, and tool calls from the Responses API response object.
  • dashboard/src/i18n/locales/en-US/features/config-metadata.json
    • Added English descriptions and hints for 'use_responses_api', 'oa_native_web_search', and 'oa_native_code_interpreter' in the configuration metadata.
  • dashboard/src/i18n/locales/zh-CN/features/config-metadata.json
    • Added Chinese descriptions and hints for 'use_responses_api', 'oa_native_web_search', and 'oa_native_code_interpreter' in the configuration metadata.
  • tests/test_openai_source.py
    • Imported OpenAIResponse from openai.types.responses for testing.
    • Added test_build_responses_payload_converts_messages_and_tools to verify correct payload construction for the Responses API, including message and tool conversion.
    • Added test_native_tools_force_responses_mode_and_override_function_tools to confirm native tools enable Responses API mode and take precedence over AstrBot's function tools.
    • Added test_parse_responses_completion_extracts_text_reasoning_and_tool_calls to test parsing of text, reasoning, and tool calls from a Responses API completion.
    • Added test_parse_responses_completion_raises_on_invalid_tool_arguments to ensure an exception is raised for malformed tool arguments in Responses API.
    • Added test_query_stream_responses_yields_distinct_text_and_reasoning_chunks to verify correct handling and yielding of streaming text and reasoning chunks from the Responses API.
Activity
  • The pull request was created by outlook84 to integrate OpenAI's Responses API and native tools.
  • Screenshots were provided by the author to demonstrate the new functionality and UI changes.
  • The author confirmed that this is not a breaking change.
  • The author verified that the changes are well-tested and provided evidence.
  • The author confirmed that no new dependencies were introduced, or if so, they were properly added.
  • The author confirmed that no malicious code was introduced.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dosubot dosubot bot added the area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. label Mar 9, 2026
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="astrbot/core/provider/sources/openai_source.py" line_range="691-692" />
<code_context>
             output=completion_tokens,
         )

+    def _extract_responses_usage(self, usage: ResponseUsage) -> TokenUsage:
+        cached = usage.input_tokens_details.cached_tokens or 0
+        input_tokens = usage.input_tokens or 0
+        output_tokens = usage.output_tokens or 0
</code_context>
<issue_to_address>
**issue (bug_risk):** 当提取 Responses API 的 token 使用情况时,如果 `usage.input_tokens_details` 为 None,可能会引发 AttributeError。

在 `_extract_responses_usage` 中,`cached = usage.input_tokens_details.cached_tokens or 0` 假设 `input_tokens_details` 一定有值。但某些 Responses API 的负载中,`input_tokens_details` 可能为 `None` 或被省略,这会导致 AttributeError。建议在访问前进行保护,例如:

```python
details = getattr(usage, "input_tokens_details", None) or {}
cached = getattr(details, "cached_tokens", 0) or 0
```

或者在读取 `cached_tokens` 之前显式判断是否为 `None`。
</issue_to_address>

Sourcery 对开源项目免费 —— 如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈改进评审质量。
Original comment in English

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="astrbot/core/provider/sources/openai_source.py" line_range="691-692" />
<code_context>
             output=completion_tokens,
         )

+    def _extract_responses_usage(self, usage: ResponseUsage) -> TokenUsage:
+        cached = usage.input_tokens_details.cached_tokens or 0
+        input_tokens = usage.input_tokens or 0
+        output_tokens = usage.output_tokens or 0
</code_context>
<issue_to_address>
**issue (bug_risk):** Potential AttributeError if usage.input_tokens_details is None when extracting Responses API token usage.

In `_extract_responses_usage`, `cached = usage.input_tokens_details.cached_tokens or 0` assumes `input_tokens_details` is always set. Some Responses API payloads may have `input_tokens_details` as `None` or omit it, which would raise an AttributeError. Consider guarding the access, e.g.:

```python
details = getattr(usage, "input_tokens_details", None) or {}
cached = getattr(details, "cached_tokens", 0) or 0
```

or equivalently check for `None` before reading `cached_tokens`.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

本次 PR 集成了 OpenAI 最新的 Responses API,并增加了对原生网页搜索和代码解释器工具的支持。openai_source.py 中的核心逻辑改动结构清晰,妥善地处理了新的 API 端点、消息格式以及流式和非流式请求。新功能也同步更新到了配置和 UI 中。新增的测试用例很全面,覆盖了多种场景。

我有几点建议可以提高代码的可维护性和一致性。具体来说,我指出了默认配置文件中的代码重复问题,一个改进响应解析逻辑中类型检查的方法,以及新测试代码中的一个风格问题。

总体而言,这是一次很棒的功能增强。

Comment on lines +1084 to +1086
"use_responses_api": False,
"oa_native_web_search": False,
"oa_native_code_interpreter": False,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

这三个新的配置项在此文件中为几乎所有 OpenAI 兼容的 provider 重复添加(约20次),导致了严重的代码重复,使未来的修改变得困难。为了提高可维护性,建议将这些选项定义在一个公共字典中,然后合并到每个 provider 的配置中。这将集中管理默认值,使配置更易于维护。例如:

OPENAI_COMPATIBLE_DEFAULTS = {
    "use_responses_api": False,
    "oa_native_web_search": False,
    "oa_native_code_interpreter": False,
}

# 在定义 provider 配置时
"OpenAI": {
    ...,
    **OPENAI_COMPATIBLE_DEFAULTS,
    "custom_headers": {},
},

此建议适用于此文件中所有类似的代码块。

Comment on lines +901 to +916
else:
item_type = getattr(item, "type", "")
if item_type == "function_call" and tools is not None:
try:
args = json.loads(item.arguments)
except json.JSONDecodeError:
logger.error(
"Responses API function_call arguments is not valid JSON: %s",
item.arguments,
)
raise Exception(
f"Responses API function_call arguments is not valid JSON: {item.arguments}"
)
tool_args.append(args)
tool_names.append(item.name)
tool_ids.append(item.call_id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

为了与其他响应项类型(如 ResponseOutputMessage)的处理方式保持一致,并增强类型安全性,建议使用 isinstance 来检查 FunctionCall 类型。

这需要在文件顶部添加以下导入:

from openai.types.responses.function_call import FunctionCall
            elif isinstance(item, FunctionCall) and tools is not None:
                try:
                    args = json.loads(item.arguments)
                except json.JSONDecodeError:
                    logger.error(
                        "Responses API function_call arguments is not valid JSON: %s",
                        item.arguments,
                    )
                    raise Exception(
                        f"Responses API function_call arguments is not valid JSON: {item.arguments}"
                    )
                tool_args.append(args)
                tool_names.append(item.name)
                tool_ids.append(item.call_id)

Comment on lines +267 to +269
import asyncio

asyncio.run(provider.terminate())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

根据 PEP 8 风格指南,导入语句应放在文件的顶部。在 finally 块中导入 asyncio 是不常规的做法,并且会使模块的依赖关系不够清晰。请将 import asyncio 移动到文件的顶部。此评论同样适用于 test_native_tools_force_responses_mode_and_override_function_tools 测试函数中的导入。

Suggested change
import asyncio
asyncio.run(provider.terminate())
asyncio.run(provider.terminate())
References
  1. According to PEP 8, import statements should be placed at the top of the file, after any module docstrings and before any module-level global variables and constants. (link)

@outlook84
Copy link
Author

代码执行器输出渲染效果不行,明天修一下。

@outlook84 outlook84 marked this pull request as draft March 9, 2026 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

X Tutup