Skip to content

feat: add reasoningEffort field support in OpenAIChatFormatter#444

Merged
AlbumenJ merged 1 commit intoagentscope-ai:mainfrom
JGoP-L:feat/support-reasoning_effort-parameter-for-OpenAI-models
Jan 5, 2026
Merged

feat: add reasoningEffort field support in OpenAIChatFormatter#444
AlbumenJ merged 1 commit intoagentscope-ai:mainfrom
JGoP-L:feat/support-reasoning_effort-parameter-for-OpenAI-models

Conversation

@JGoP-L
Copy link
Contributor

@JGoP-L JGoP-L commented Jan 5, 2026

AgentScope-Java Version

0.9.0-SNAPSHOT

Description

Background

Issue #98 requested support for OpenAI's thinking block/reasoning mode. While the response parsing was already implemented, the request building was missing direct handling of the reasoningEffort field from GenerateOptions.

Changes

  • Added direct reasoningEffort parameter handling in OpenAIChatFormatter.applyOptions()
  • Added 3 unit tests to verify the new functionality:
    • testApplyReasoningEffortFromField - test direct field usage
    • testApplyReasoningEffortWithDefault - test with default options
    • testApplyReasoningEffortFromDefaultOnly - test default-only scenario

How to Test

# Run unit tests
mvn test -Dtest=OpenAIChatFormatterTest

# Test with real API (requires OPENROUTER_API_KEY)
curl https://openrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -d '{"model":"openai/o3-mini","reasoning_effort":"low","messages":[{"role":"user","content":"2+2=?"}],"max_tokens":500}'

Checklist

- Code has been formatted with mvn spotless:apply
- All tests are passing (mvn test)
- Javadoc comments are complete and follow project conventions
- Related documentation has been updated (e.g. links, examples, etc.)
- Code is ready for review

Closes #98

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds direct field support for the reasoningEffort parameter in OpenAIChatFormatter, completing the implementation for OpenAI's thinking block/reasoning mode (Issue #98). While the response parsing was already implemented, this change adds the ability to set reasoningEffort directly through GenerateOptions.builder().reasoningEffort("high") instead of only through additionalBodyParam().

Key Changes:

  • Added direct reasoningEffort field handling in OpenAIChatFormatter.applyOptions() using the same pattern as other generation parameters
  • Added 3 comprehensive unit tests covering direct field usage, default options merging, and default-only scenarios
  • Implementation follows the existing code patterns and integrates seamlessly with the existing additionalBodyParam mechanism

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
OpenAIChatFormatter.java Added 6 lines of code to extract and apply the reasoningEffort field from GenerateOptions using the standard getOptionOrDefault() pattern
OpenAIChatFormatterTest.java Added 3 new unit tests to verify the new functionality works correctly with direct field usage, default options, and null options scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +397 to +435
@Test
@DisplayName("Should apply reasoningEffort from GenerateOptions field")
void testApplyReasoningEffortFromField() {
OpenAIRequest request = OpenAIRequest.builder().model("o1").messages(List.of()).build();

GenerateOptions options = GenerateOptions.builder().reasoningEffort("high").build();

formatter.applyOptions(request, options, null);

assertEquals("high", request.getReasoningEffort());
}

@Test
@DisplayName("Should apply reasoningEffort with default options")
void testApplyReasoningEffortWithDefault() {
OpenAIRequest request = OpenAIRequest.builder().model("o1").messages(List.of()).build();

GenerateOptions defaultOptions =
GenerateOptions.builder().reasoningEffort("low").build();
GenerateOptions options = GenerateOptions.builder().reasoningEffort("high").build();

formatter.applyOptions(request, options, defaultOptions);

// Options should override defaultOptions
assertEquals("high", request.getReasoningEffort());
}

@Test
@DisplayName("Should apply reasoningEffort from default when options is null")
void testApplyReasoningEffortFromDefaultOnly() {
OpenAIRequest request = OpenAIRequest.builder().model("o1").messages(List.of()).build();

GenerateOptions defaultOptions =
GenerateOptions.builder().reasoningEffort("medium").build();

formatter.applyOptions(request, null, defaultOptions);

assertEquals("medium", request.getReasoningEffort());
}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Consider adding a test case that validates the behavior when both the direct reasoningEffort field and the additionalBodyParam("reasoning_effort", ...) are set. Based on the implementation in OpenAIChatFormatter.applyOptions(), the additionalBodyParam is applied after the direct field (lines 120-122 with comment "must be last to allow overriding"), which means it will override the direct field value. This behavior should be explicitly tested to ensure it's intentional and to document this precedence for future maintainers.

Copilot uses AI. Check for mistakes.
@@ -73,6 +73,12 @@ public void applyOptions(
if (temperature != null) {
request.setTemperature(temperature);
}
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Add a blank line before the "Apply reasoning effort" comment to maintain consistency with the formatting of other parameter applications in this method. All other parameter sections (temperature, top_p, frequency penalty, etc.) have a blank line separating them from the previous section.

Suggested change
}
}

Copilot uses AI. Check for mistakes.
@codecov
Copy link

codecov bot commented Jan 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@AlbumenJ AlbumenJ merged commit 13f042b into agentscope-ai:main Jan 5, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants