Skip to content

fix: f32→f64 precision artifact in temperature causes provider 400 errors - #1418

Closed
Boomboomdunce wants to merge 1 commit into
nearai:stagingfrom
Boomboomdunce:fix/f32-precision-temperature
Closed

Boomboomdunce wants to merge 1 commit into
nearai:stagingfrom
Boomboomdunce:fix/f32-precision-temperature

Conversation

@Boomboomdunce

Copy link
Copy Markdown
Contributor

Problem

f32 as f64 preserves the binary representation, producing values like 0.699999988079071 instead of 0.7. Some OpenAI-compatible providers (e.g. Zhipu GLM-5) reject these with a 400 error ("API 调用参数有误").

Fix

Added round_f32_to_f64() helper that formats to 6 decimal places before parsing back to f64. Applied to the temperature field in build_rig_request().

Test

Regression test test_round_f32_to_f64_no_precision_artifacts verifies:

  • round_f32_to_f64(0.7_f32) == 0.7 (no artifact)
  • 0.7_f32 as f64 != 0.7 (confirms the original bug exists)

Impact

This affects all providers using RigAdapter (OpenAI, Anthropic, Ollama, Tinfoil, OpenAI-compatible). The fix is purely cosmetic for providers that tolerate the artifact, and unblocks providers that don't.

…rors

Direct f32-as-f64 preserves the binary representation, producing values
like 0.699999988079071 instead of 0.7. Some OpenAI-compatible providers
(e.g. Zhipu GLM-5) reject these with a 400 error. Add round_f32_to_f64()
that formats to 6 decimal places before parsing back to f64.
@github-actions github-actions Bot added scope: llm LLM integration size: S 10-49 changed lines risk: low Changes to docs, tests, or low-risk modules contributor: new First-time contributor labels Mar 19, 2026
@gemini-code-assist

Copy link
Copy Markdown
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 resolves a critical compatibility issue with OpenAI-compatible providers caused by floating-point precision artifacts during f32 to f64 conversion. By introducing a new helper function to correctly round and convert f32 values for parameters like temperature, it ensures that API requests are properly formatted, preventing 400 errors and improving overall provider interoperability for all RigAdapter users.

Highlights

  • Precision Fix: Addressed a floating-point precision issue where direct f32 as f64 conversion resulted in artifacts (e.g., 0.7 becoming 0.699999988079071).
  • Provider Compatibility: Resolved 400 errors encountered with certain OpenAI-compatible providers (like Zhipu GLM-5) that rejected these imprecise f64 values for parameters like temperature.
  • New Helper Function: Introduced round_f32_to_f64() which formats f32 values to 6 decimal places before parsing them back to f64, ensuring accurate representation.
  • Application: Applied the round_f32_to_f64() helper to the temperature field within the build_rig_request() function.
  • Regression Test: Included a new test, test_round_f32_to_f64_no_precision_artifacts, to verify the fix and confirm the original precision issue.
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.

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. ↩

@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 addresses an issue where converting an f32 temperature value to f64 introduces precision artifacts, causing 400 errors from some LLM providers. The fix introduces a round_f32_to_f64 helper function that rounds the value by formatting it to a string with 6 decimal places and parsing it back to an f64. This is a clever solution to the floating-point representation problem. The change is well-tested. My only suggestion is to make the parsing logic more robust by using expect() instead of unwrap_or(), to ensure any unexpected parsing failures are caught immediately rather than silently falling back to the old, problematic behavior.

Comment thread src/llm/rig_adapter.rs
/// the artifact while preserving all meaningful precision for temperature/top_p.
fn round_f32_to_f64(val: f32) -> f64 {
let s = format!("{:.6}", val);
s.parse::<f64>().unwrap_or(val as f64)

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.

medium

The use of unwrap_or with a fallback to val as f64 could silently re-introduce the precision artifact issue if s.parse::<f64>() were to fail for some unforeseen reason. Since format!("{:.6}", val) should always produce a string that can be parsed back into a float, it's safer to treat this as an infallible operation. Using .expect() would cause a panic if parsing fails, making any unexpected behavior immediately obvious during development and testing, which is preferable to silently using the incorrect value.

Suggested change
s.parse::<f64>().unwrap_or(val as f64)
s.parse::<f64>().expect("formatted f32 should always be parsable to f64")
References
  1. Prefer expect() to explicitly fail with a clear message if an operation's setup or expected outcome is not met, especially when unwrap_or() could silently lead to incorrect logic. This principle extends beyond tests to general code robustness, ensuring immediate detection of unexpected behavior.

ilblackdragon added a commit that referenced this pull request Mar 20, 2026
…ression-check]

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ilblackdragon

Copy link
Copy Markdown
Member

Thanks for the work on this, @Boomboomdunce! Great catch on the f32→f64 precision artifact. I've picked up your changes and continued them in #1450.

The new PR includes your original work plus:

  • Merge with latest staging
  • Fix for the Clippy redundant_closure lint (.map(|t| round_f32_to_f64(t)) → .map(round_f32_to_f64)) which was the sole CI blocker

You're credited as co-author on the commit. Feel free to review the new PR!

ilblackdragon added a commit that referenced this pull request Mar 20, 2026
…rors (#1450)

* fix: f32→f64 precision artifact in temperature causes provider 400 errors

Direct f32-as-f64 preserves the binary representation, producing values
like 0.699999988079071 instead of 0.7. Some OpenAI-compatible providers
(e.g. Zhipu GLM-5) reject these with a 400 error. Add round_f32_to_f64()
that formats to 6 decimal places before parsing back to f64.

* fix: address clippy redundant_closure lint (takeover #1418) [skip-regression-check]

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use numeric rounding, update doc comment, remove duplicate assertion [skip-regression-check]

Address review feedback on #1450:
- Replace format!+parse with numeric rounding to avoid allocation
- Update doc comment to only mention temperature (not top_p)
- Remove duplicate assert_eq in test

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Boomboomdunce <liweizhu0708@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
zmanian pushed a commit that referenced this pull request Mar 21, 2026
…rors (#1450)

* fix: f32→f64 precision artifact in temperature causes provider 400 errors

Direct f32-as-f64 preserves the binary representation, producing values
like 0.699999988079071 instead of 0.7. Some OpenAI-compatible providers
(e.g. Zhipu GLM-5) reject these with a 400 error. Add round_f32_to_f64()
that formats to 6 decimal places before parsing back to f64.

* fix: address clippy redundant_closure lint (takeover #1418) [skip-regression-check]

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use numeric rounding, update doc comment, remove duplicate assertion [skip-regression-check]

Address review feedback on #1450:
- Replace format!+parse with numeric rounding to avoid allocation
- Update doc comment to only mention temperature (not top_p)
- Remove duplicate assert_eq in test

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Boomboomdunce <liweizhu0708@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
zmanian pushed a commit that referenced this pull request Mar 21, 2026
…rors (#1450)

* fix: f32→f64 precision artifact in temperature causes provider 400 errors

Direct f32-as-f64 preserves the binary representation, producing values
like 0.699999988079071 instead of 0.7. Some OpenAI-compatible providers
(e.g. Zhipu GLM-5) reject these with a 400 error. Add round_f32_to_f64()
that formats to 6 decimal places before parsing back to f64.

* fix: address clippy redundant_closure lint (takeover #1418) [skip-regression-check]

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use numeric rounding, update doc comment, remove duplicate assertion [skip-regression-check]

Address review feedback on #1450:
- Replace format!+parse with numeric rounding to avoid allocation
- Update doc comment to only mention temperature (not top_p)
- Remove duplicate assert_eq in test

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Boomboomdunce <liweizhu0708@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Boomboomdunce
Boomboomdunce deleted the fix/f32-precision-temperature branch March 24, 2026 04:26
bkutasi pushed a commit to bkutasi/ironclaw that referenced this pull request Mar 28, 2026
…rors (nearai#1450)

* fix: f32→f64 precision artifact in temperature causes provider 400 errors

Direct f32-as-f64 preserves the binary representation, producing values
like 0.699999988079071 instead of 0.7. Some OpenAI-compatible providers
(e.g. Zhipu GLM-5) reject these with a 400 error. Add round_f32_to_f64()
that formats to 6 decimal places before parsing back to f64.

* fix: address clippy redundant_closure lint (takeover nearai#1418) [skip-regression-check]

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use numeric rounding, update doc comment, remove duplicate assertion [skip-regression-check]

Address review feedback on nearai#1450:
- Replace format!+parse with numeric rounding to avoid allocation
- Update doc comment to only mention temperature (not top_p)
- Remove duplicate assert_eq in test

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Boomboomdunce <liweizhu0708@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
drchirag1991 pushed a commit to drchirag1991/ironclaw that referenced this pull request Apr 8, 2026
…rors (nearai#1450)

* fix: f32→f64 precision artifact in temperature causes provider 400 errors

Direct f32-as-f64 preserves the binary representation, producing values
like 0.699999988079071 instead of 0.7. Some OpenAI-compatible providers
(e.g. Zhipu GLM-5) reject these with a 400 error. Add round_f32_to_f64()
that formats to 6 decimal places before parsing back to f64.

* fix: address clippy redundant_closure lint (takeover nearai#1418) [skip-regression-check]

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use numeric rounding, update doc comment, remove duplicate assertion [skip-regression-check]

Address review feedback on nearai#1450:
- Replace format!+parse with numeric rounding to avoid allocation
- Update doc comment to only mention temperature (not top_p)
- Remove duplicate assert_eq in test

Co-Authored-By: Boomboomdunce <liweizhu0708@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Boomboomdunce <liweizhu0708@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: new First-time contributor risk: low Changes to docs, tests, or low-risk modules scope: llm LLM integration size: S 10-49 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants