Skip to content

fix(py/plugins/openai): map max_tokens for reasoning models - #6324

Open
0x90000 wants to merge 3 commits into
genkit-ai:mainfrom
0x90000:fix/openai-max-completion-tokens-6320
Open

0x90000 wants to merge 3 commits into
genkit-ai:mainfrom
0x90000:fix/openai-max-completion-tokens-6320

Conversation

@0x90000

@0x90000 0x90000 commented Sep 9, 2026

Copy link
Copy Markdown

Summary

Fixes #6320.

OpenAIConfig(max_tokens=...) was forwarded as max_tokens for reasoning models, which OpenAI rejects. This maps the deprecated option to max_completion_tokens for reasoning-model IDs (o1, o3, o4, gpt-5*, and gpt-6*) while preserving max_tokens for legacy models.

When both options are supplied, the explicit max_completion_tokens value wins so mutually exclusive fields are not sent together.

Tests

  • Added async regression coverage for reasoning models, legacy models, and explicit precedence.
  • ruff check and ruff format --check pass on changed files.
  • Python compilation passes.
  • The focused test file runs 49 passing tests in an isolated dependency environment; one unrelated existing usage assertion fails against the installed OpenAI SDK because image_tokens is omitted from its PromptTokensDetails model.
  • The full workspace environment cannot be resolved on Windows because dotpromptz-handlebars currently publishes no Windows wheel.

Google CLA requirements in CONTRIBUTING.md noted.

@google-cla

google-cla Bot commented Sep 9, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces logic to map the deprecated "max_tokens" parameter to "max_completion_tokens" for OpenAI reasoning models or when "reasoning_effort" is specified, while preserving "max_tokens" for legacy models. It also adds corresponding unit tests. The review feedback suggests making the reasoning model detection heuristic more robust to handle fine-tuned models (prefixed with "ft:") and custom deployment names, and updating the tests to cover these scenarios.

Comment thread py/packages/genkit-openai/src/genkit_openai/models/model.py Outdated
Comment thread py/packages/genkit-openai/tests/openai_model_test.py
@0x90000

0x90000 commented Sep 9, 2026

Copy link
Copy Markdown
Author

Addressed the Gemini review feedback in commit 1a26dcf. Reasoning-model detection now handles fine-tuned IDs (ft: prefix) , with regression coverage for both cases.

@0x90000

0x90000 commented Sep 14, 2026

Copy link
Copy Markdown
Author

Formatting-only follow-up pushed in commit a29a5e54ae.

The failed Python Checks job was isolated to ruff format --check --preview reporting model.py as unformatted. I applied the exact Ruff preview formatting and verified locally:

  • ruff check on the changed source and tests: pass
  • ruff format --check --preview: pass
  • Git author: Letian Liu <cracktt@gmail.com>

The latest push triggered the PR workflows; CLA, Actions scan, and labeler have passed. The remaining PR workflows currently show action_required, which requires maintainer approval for the fork workflow run.

# both knobs are supplied so the request remains valid.
if config.max_completion_tokens is not None:
continue
if _uses_max_completion_tokens(model) or config.reasoning_effort is not None:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The reasoning_effort branch is not covered. Can we add one case with a model id the heuristic does not match (say 'my-deployment') and reasoning_effort set, asserting max_completion_tokens goes out?

continue
value = getattr(config, name)
if value is not None:
if name == 'max_tokens':

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: This docstring still says everything else goes out under its field name. Can we add a line that max_tokens becomes max_completion_tokens for reasoning models?

@pytest.mark.asyncio
async def test_get_openai_config_uses_max_completion_tokens_for_reasoning_models() -> None:
"""Reasoning models reject the deprecated max_tokens request field."""
for model_name in ('gpt-6-astra', 'ft:o1-mini:my-org:custom', 'my-o1-mini-deployment'):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: This file already uses pytest.mark.parametrize; can we use it here so each id shows up as its own case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[py/plugins/openai] max_tokens is sent verbatim and rejected by reasoning models

2 participants