Skip to content

fix(claude): read text blocks after leading ThinkingBlock - #2734

Open
mdshzb04 wants to merge 1 commit into
Graphify-Labs:v8from
mdshzb04:fix/claude-thinking-block-response-text
Open

fix(claude): read text blocks after leading ThinkingBlock#2734
mdshzb04 wants to merge 1 commit into
Graphify-Labs:v8from
mdshzb04:fix/claude-thinking-block-response-text

Conversation

@mdshzb04

Copy link
Copy Markdown
Contributor

Summary

graphify extract --backend claude and community labeling both read resp.content[0].text. On current Claude models, the first block is often a ThinkingBlock, not the answer — so extraction fails with ThinkingBlock object has no attribute text.

What changed

Added _anthropic_response_text() to pick the first text block instead of assuming index 0. Wired it into _call_claude and the claude branch of _call_llm. Added regression tests mirroring the existing Bedrock reasoning-block coverage.

Why

Fixes #2697. I kept hitting chunk failures on semantic extraction where every error was the ThinkingBlock attribute error, not the actual API problem.

Test plan

  • pytest tests/test_image_vision.py -k anthropic_response_text
  • pytest tests/test_image_vision.py::test_call_claude_parses_thinking_model_response
  • pytest tests/test_llm_backends.py::test_call_llm_claude_client_built_with_timeout_and_retries

Anthropic models with extended thinking return a ThinkingBlock before the
TextBlock. Indexing content[0] crashed semantic extraction and community
labeling. Select the first text block instead.

Fixes Graphify-Labs#2697.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

This PR adds a helper _anthropic_response_text in graphify/llm.py that scans Anthropic response content blocks and returns the first block carrying non-empty text, rather than assuming text lives at content[0]. It updates the two Anthropic call sites (_call_claude and the Claude branch of _call_llm) to use this helper, motivated by extended-thinking models emitting a leading thinking block. The PR also adds unit tests in tests/test_image_vision.py covering the new helper (single text block, leading thinking block, legacy blocks without a type, and default fallback) and an end-to-end _call_claude test simulating a thinking-model response. Note: many of the "changed symbols" listed (e.g. various rationale_*, image/bedrock helpers, temperature/tokenizer functions) don't appear in the diff, so the actual code surface touched is limited to the additions and two call-site edits shown above.

No blocking issues surfaced.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 692 functions depend on the 208 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: _call_llm() — 11 callers, 18 callees
  • worse: _build_image_refs() — 15 callers, 3 callees
  • worse: _call_claude() — 3 callers, 8 callees

Verification — 692 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 443 function(s) in the blast radius were not formally verified this run

Formal verification

Verification did not run: Verification did not run for \_call\_claude.

The verification could not execute (an environment/toolchain issue, not a statement about the code).

Guarantee: No guarantee, the check itself did not complete.

Note: Detail: harness produced no verdict (rc=124): timeout after 30s

Could not verify: Could not verify \_call\_llm.

The verifier did not have enough to check \_call\_llm, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 23 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly TypeError — names the real obstacle, not a sampling gap)

· 3 more finding(s) on lines outside this diff (see the check run).

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.

graphify extract --backend claude crashes on 'ThinkingBlock' object has no attribute 'text'

1 participant