Skip to content

[FIX] Strip deprecated sampling params for Claude Opus 4.7 onwards#2103

Open
pk-zipstack wants to merge 2 commits into
mainfrom
fix/opus-sampling-params
Open

[FIX] Strip deprecated sampling params for Claude Opus 4.7 onwards#2103
pk-zipstack wants to merge 2 commits into
mainfrom
fix/opus-sampling-params

Conversation

@pk-zipstack

Copy link
Copy Markdown
Contributor

What

  • Extend the Anthropic sampling-param deprecation detector in unstract/sdk1/.../adapters/base1.py to cover every Opus release from 4.7 onwards — Opus 4.7, 4.8, 4.9 and Opus 5+ — instead of only claude-opus-4-7.
  • Replace the single regex with two anchored patterns:
    _SAMPLING_DEPRECATED_MODEL_PATTERNS = (
        re.compile(r"claude-opus-4-[789](?=$|[-:@/]|v\d)"),  # Opus 4.7, 4.8, 4.9
        re.compile(r"claude-opus-[5-9](?=$|[-:@/]|v\d)"),    # Opus 5 and later
    )
  • Trim the oversized leading comment and extend test_sampling_strip.py with 4.8 / 4.9 / Opus 5+ positives and Opus 5 boundary negatives.

Why

PR #1934 added the strip but keyed it to a single literal — claude-opus-4-7. Anthropic has since shipped Opus 4.8, which deprecates the same sampling parameters (temperature, top_p, top_k). Because claude-opus-4-8 does not match the old pattern, those calls reach the provider with temperature still set and 400:

{"type":"error","error":{"type":"invalid_request_error",
"message":"`temperature` is deprecated for this model."}}

litellm cannot fix this for us — upstream get_supported_openai_params() still reports temperature as supported for these models (open bug BerriAI/litellm#26444, unshipped), so drop_params=True is a no-op. The strip in base1.py remains the only thing preventing the 400, and it must track each new Opus id.

Reference: https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-7

How

base1.py:

  • The lone claude-opus-4-7 pattern becomes two patterns covering claude-opus-4-[789] and claude-opus-[5-9]. The existing trailing-edge lookahead ($, a -/:/@// delimiter, or v<digit>) is preserved, so:
    • Match: every encoding of 4.7/4.8/4.9 and Opus 5+ — native (claude-opus-4-8), Bedrock foundation models / cross-region profiles / ARNs (us.anthropic.claude-opus-4-8-<date>-v1:0), Vertex (vertex_ai/claude-opus-4-8@<date>), Azure deployments embedding the id, and dot/underscore variants.
    • Do not match: prefix collisions (claude-opus-4-70, claude-opus-4-7verbose), the sampling-supporting claude-opus-4-1..4-6, and Opus 5 boundary cases (claude-opus-50, claude-opus-5verbose).
  • No change to _strip_deprecated_sampling_params, the model/model_id AIP fallback, or the four adapter call sites — only the detection table widened.

test_sampling_strip.py:

  • New positives for 4.8 (representative encodings: native, anthropic/, Bedrock id + ARN, cross-region, Vertex, Azure, dotted), 4.9, and Opus 5/6.
  • New negatives locking the new boundaries: claude-opus-50, claude-opus-5verbose, claude-opus-4-1, anthropic.claude-opus-4-1-....
  • All 78 tests pass.

Known limitation

claude-opus-4-[789] covers 4.7–4.9 but not a hypothetical claude-opus-4-10. Anthropic's cadence (4-5 → 4-6 → 4-7 → 4-8) makes an Opus 5 jump far more likely than a 4-10, and Opus 5+ is already covered. Fable 5 / Mythos 5 (claude-fable-5, claude-mythos-5) also forbid these params but are out of scope here (this change is Opus-only, per the "4.7 onwards" scope); they would each need a pattern if routed through this SDK.

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

No.

  • The change only widens which model ids trigger the strip; it adds no new behavior for models already handled.
  • Models that retain temperature / top_p / top_k are unaffected — verified by negative tests for claude-opus-4-1..4-6, claude-sonnet-4-7, claude-haiku-4-5, claude-3-5-sonnet, and non-Anthropic providers (gpt-4o, gemini-2.0-flash), which all keep their sampling params.
  • The trailing-edge anchor is unchanged, so prior false-match guards (claude-opus-4-70, claude-opus-4-7verbose) still hold.
  • The _strip_deprecated_sampling_params contract, AIP model_id fallback, and adapter wiring are untouched.

🤖 Generated with Claude Code

Extend the Anthropic sampling-param deprecation detector beyond Opus 4.7
to cover every Opus release from 4.7 onwards: 4.7, 4.8, 4.9 and Opus 5+.

The previous single pattern matched only `claude-opus-4-7`, so callers on
`claude-opus-4-8` (and future Opus ids) still sent `temperature` / `top_p`
/ `top_k` and 400'd with "temperature is deprecated for this model".

Replace the lone pattern with two anchored ones — `claude-opus-4-[789]`
and `claude-opus-[5-9]` — keeping the existing trailing-edge boundary so
prefix collisions (`claude-opus-4-70`, `claude-opus-4-7verbose`) and the
sampling-supporting `claude-opus-4-1..4-6` still do not match. Extend
test_sampling_strip.py with 4.8/4.9/Opus 5+ positives and Opus 5 boundary
negatives.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c85658eb-95e9-4c59-a505-2c6f86e2b681

📥 Commits

Reviewing files that changed from the base of the PR and between 73c3e6b and 3a5f47d.

📒 Files selected for processing (1)
  • unstract/sdk1/src/unstract/sdk1/adapters/base1.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • unstract/sdk1/src/unstract/sdk1/adapters/base1.py

Summary by CodeRabbit

  • Bug Fixes

    • Improved recognition of Claude Opus models so deprecated sampling-parameter behavior is correctly applied for Opus 4.7 and later, ensuring consistent compatibility across supported deployment naming formats.
  • Tests

    • Expanded sampling-strip detection coverage with additional Claude Opus 4.8/4.9 and Opus 5+ model variants, including edge-case naming and delimiter scenarios, to prevent regressions beyond Opus 4.7.

Walkthrough

The _SAMPLING_DEPRECATED_MODEL_PATTERNS constant in base1.py is changed from a single regex matching only claude-opus-4-7 to a two-pattern tuple that covers Opus 4.7/4.8/4.9 (minor-version pattern) and Opus 5+ (major-version pattern), both with trailing-edge boundary anchoring. A docstring in the AIP ARN helper is updated to say "4.7 or later." Test fixtures are extended with additional positive (4.8, 4.9, 5+) and negative (boundary-violating 5+, and 4.1–4.6) model-id strings.

Changes

Opus 4.7+ Sampling Deprecation Detection

Layer / File(s) Summary
Expanded regex patterns and documentation
unstract/sdk1/src/unstract/sdk1/adapters/base1.py
_SAMPLING_DEPRECATED_MODEL_PATTERNS is replaced with two anchored regexes: one covering claude-opus-4-[789] and one covering claude-opus-[5-9], extending detection from only Opus 4.7 to Opus 4.7–4.9 and all Opus 5+ releases. The _looks_like_opaque_aip_arn docstring is updated to specify "4.7 or later" applicability. The _has_deprecated_sampling_params docstring example is updated to reference claude-opus-4-8 for Azure deployment guidance.
Extended test coverage for Opus 4.7+ detection
unstract/sdk1/tests/test_sampling_strip.py
Test module docstring is updated to specify coverage spans "Claude Opus 4.7+" instead of only "4.7." Positive detection fixtures are expanded with additional Opus 4.8/4.9 and Opus 5+ model identifiers across Bedrock, Vertex AI, and Azure provider encodings. Negative fixtures are expanded with boundary-violating Opus 5+ strings (e.g., claude-opus-50, claude-opus-5verbose) and Opus 4.1–4.6 examples (claude-opus-4-1) to enforce proper version-scope behavior.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: extending the deprecated sampling parameter strip to cover Claude Opus 4.7 onwards (beyond just 4.7).
Description check ✅ Passed The PR description is comprehensive and complete, covering all required template sections with detailed explanations, technical specifications, rationale, impact analysis, and testing notes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/opus-sampling-params

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR widens the Anthropic sampling-parameter deprecation guard in base1.py from a single claude-opus-4-7 literal to two anchored regex patterns covering Opus 4.7–4.9 (claude-opus-4-[789]) and every Opus 5+ release (claude-opus-[5-9]), preventing 400 errors for claude-opus-4-8 and later models that Anthropic has since shipped with the same temperature/top_p/top_k deprecation.

  • Two compile-time regex patterns replace the prior single pattern; the existing trailing-edge lookahead ($, -/:/@//, or v\\d) is preserved, so boundary guards against claude-opus-4-70 and claude-opus-50 remain intact.
  • Detection unit tests are extended with representative encodings for Opus 4.8, 4.9, and Opus 5/6 (native, Bedrock ARN, Vertex, Azure); new negatives lock claude-opus-50, claude-opus-5verbose, and claude-opus-4-1 boundaries.
  • No adapter wiring, strip contract, or model_id AIP fallback logic is changed.

Confidence Score: 5/5

Safe to merge — the change only widens which model IDs trigger an existing, well-tested strip; no adapter logic or contracts are altered.

The diff touches only pattern definitions and tests. Both new regex patterns are correctly anchored with the same trailing-edge lookahead that guards against false positives. The strip function, AIP ARN fallback, and adapter call sites are untouched. Detection is verified by 78 passing tests including boundary negatives for the new patterns.

No files require special attention.

Important Files Changed

Filename Overview
unstract/sdk1/src/unstract/sdk1/adapters/base1.py Widens the sampling-param deprecation detector from a single claude-opus-4-7 literal to two anchored patterns covering Opus 4.7–4.9 and Opus 5+; logic, adapter wiring, and strip contract are unchanged.
unstract/sdk1/tests/test_sampling_strip.py Extends detection unit tests with 4.8/4.9/Opus-5+ positives and boundary negatives; adapter-wiring helpers still hardcode 4.7 model IDs rather than exercising the new patterns end-to-end.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Adapter .validate called] --> B[_strip_deprecated_sampling_params]
    B --> C{model or model_id\nfield present?}
    C -- No --> G[Return unchanged dict]
    C -- Yes --> D[Normalize: lowercase\n. and _ to -]
    D --> E{Any pattern matches?}
    E -- Pattern 1: claude-opus-4-7/8/9 --> F[Strip temperature, top_p, top_k]
    E -- Pattern 2: claude-opus-5 thru 9 --> F
    E -- No match --> H{Opaque Bedrock AIP ARN?}
    H -- Yes --> I[Log debug breadcrumb\nReturn unchanged dict]
    H -- No --> G
    F --> J[Return copy without sampling params]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Adapter .validate called] --> B[_strip_deprecated_sampling_params]
    B --> C{model or model_id\nfield present?}
    C -- No --> G[Return unchanged dict]
    C -- Yes --> D[Normalize: lowercase\n. and _ to -]
    D --> E{Any pattern matches?}
    E -- Pattern 1: claude-opus-4-7/8/9 --> F[Strip temperature, top_p, top_k]
    E -- Pattern 2: claude-opus-5 thru 9 --> F
    E -- No match --> H{Opaque Bedrock AIP ARN?}
    H -- Yes --> I[Log debug breadcrumb\nReturn unchanged dict]
    H -- No --> G
    F --> J[Return copy without sampling params]
Loading

Reviews (2): Last reviewed commit: "[FIX] Generalize Azure deployment-name d..." | Re-trigger Greptile

…pus id

Address review feedback: the _has_deprecated_sampling_params docstring cited
`claude-opus-4-7` as the Azure AI Foundry deployment-name example, which is
stale now that the strip covers Opus 4.7 onwards. Reference the relevant
model id generally (e.g. claude-opus-4-8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

Unstract test results

Per-group results

Status Group Tier Passed Failed Errors Skipped Duration (s)
unit-connectors unit 64 12 0 3 16.7
unit-core unit 0 0 4 0 1.2
unit-platform-service unit 9 0 1 0 1.3
unit-prompt-service unit 15 0 0 0 20.0
unit-rig unit 53 0 0 0 3.3
unit-runner unit 11 0 0 0 3.0
unit-sdk1 unit 410 0 0 0 22.0
unit-tool-registry unit 0 0 1 0 1.3
unit-workers unit 0 0 0 0 17.6
TOTAL 562 12 6 3 86.3

Critical paths

⚠️ Critical paths not yet covered

  • auth-login — User can log in and obtain a session cookie. (entry: POST /api/v1/auth/login; declared coverage: no groups declared)
  • adapter-register-llm — Register and validate an LLM adapter. (entry: POST /api/v1/adapter/; declared coverage: no groups declared)
  • workflow-create-execute — Create a workflow, configure source+destination, execute, poll, fetch result. (entry: POST /api/v1/workflow/{id}/execute/; declared coverage: e2e-workflow)
  • api-deployment-run — Deploy a workflow as an API, POST a document, receive structured JSON. (entry: POST /deployment/api/{org}/{name}/; declared coverage: e2e-api-deployment)
  • prompt-studio-fetch-response — Prompt Studio: create project, add prompt, run single-pass, get response. (entry: POST /api/v1/prompt-studio/prompt-studio-tool/{id}/fetch_response/; declared coverage: e2e-prompt-studio)
  • pipeline-etl-execute — Run an ETL pipeline from source connector to destination. (entry: POST /api/v1/pipeline/{id}/execute/; declared coverage: no groups declared)
  • usage-token-tracking — Per-execution token usage is recorded and retrievable. (entry: GET /api/v1/usage/get_token_usage/; declared coverage: no groups declared)
  • workflow-execution-fan-out — Multi-file workflow execution fans out to file-processing workers and rejoins. (entry: internal: backend → rabbitmq → workers/file_processing; declared coverage: no groups declared)
  • callback-result-delivery — Async results are posted back via the callback worker. (entry: internal: workers/callback → backend /internal endpoints; declared coverage: no groups declared)
✅ Covered critical paths
  • tool-sandbox-exec — covered by unit-runner

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.

3 participants