Skip to content

fix(workflow-operator): read chat-provider responses for the image question-answering tasks - #7920

Open
PG1204 wants to merge 1 commit into
apache:mainfrom
PG1204:fix/hf-image-chat-response-parse
Open

fix(workflow-operator): read chat-provider responses for the image question-answering tasks#7920
PG1204 wants to merge 1 commit into
apache:mainfrom
PG1204:fix/hf-image-chat-response-parse

Conversation

@PG1204

@PG1204 PG1204 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

When the operator falls back from hf-inference to a third-party chat-completions provider, the reply comes back as {"choices": [{"message": {"content": ...}}]}. Three image tasks in ImageTaskCodegen.parsePython could not read that shape, so a correct answer was written to the result column as a raw JSON envelope:

  • visual-question-answering and document-question-answering returned body.get("answer", json.dumps(body)), and a chat response has no answer key.
  • zero-shot-image-classification shared the image-only branch, which always returnsjson.dumps(body).

Both now read choices[0]["message"]["content"] when the body carries choices, keeping the native hf-inference shape as the primary path. zero-shot-image-classification gets its own branch, placed ahead of the image-only tasks because the generated if/elif chain is first-match-wins. This is the same idiom image-to-text and image-text-to-text already use in this file, and the one applied to the text tasks in #7798.

image-classification, object-detection and image-segmentation are left as they are: they have no question to answer, so a free-text chat reply is not meaningful structured output for them.

This is Part A of #7906 and covers the response side only. The request side which is carrying candidate_labels into the chat message for zero-shot-image-classification, follows in Part B.

Any related issues?

Addresses #7906

How was this PR tested?

133 tests pass in the WorkflowOperator Hugging Face suites, PythonCodeRawInvalidTextSpec py-compiles the generated Python for all 117 operators, and scalafmtCheck is clean for main and test sources. Two tests were added to ImageTaskCodegenSpec: one asserts the visual/document question-answering branch reads choices ahead of the native answer lookup, the other asserts the new zero-shot-image-classification branch exists and precedes the image-only branch.

The emitted Python was also exercised directly: the three fixed tasks return the chat content, native hf-inference responses parse exactly as before, non-dict and answer-less bodies still fall through to json.dumps, and the untouched branches (image-classification, object-detection, image-segmentation, image-to-text, image-text-to-text) are unchanged.

Was this PR authored or co-authored using generative AI tooling?

Yes, this PR was co-authored with Claude in compliance with ASF policy.

@github-actions

Copy link
Copy Markdown
Contributor

Backport auto-label report

This fix: PR was checked against each actively-supported release branch. release/* labels drive the post-merge backport, so add or remove one to change where this fix lands.

Release branch Analysis
⚠️ release/v1.2 Not labeled automatically — none of the files this PR modifies exist on this branch (common/workflow-operator/src/main/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegen.scala, common/workflow-operator/src/test/scala/org/apache/texera/amber/operator/huggingFace/codegen/ImageTaskCodegenSpec.scala). The fix may target code that isn't on this release, or the files were moved/renamed after the branch was cut. Please check and add release/v1.2 by hand if this fix should be backported here.

Auto-label run.

@github-actions

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • No candidates found from git blame history.

@codecov-commenter

codecov-commenter commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.46%. Comparing base (7738b6c) to head (0122bdc).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #7920      +/-   ##
============================================
+ Coverage     92.43%   92.46%   +0.03%     
- Complexity     4590     4605      +15     
============================================
  Files          1173     1173              
  Lines         47347    47355       +8     
  Branches       5306     5302       -4     
============================================
+ Hits          43764    43787      +23     
+ Misses         1995     1992       -3     
+ Partials       1588     1576      -12     
Flag Coverage Δ *Carryforward flag
access-control-service 81.00% <ø> (ø)
agent-service 98.62% <ø> (ø) Carriedforward from 7738b6c
amber 89.12% <ø> (+0.09%) ⬆️
computing-unit-managing-service 73.67% <ø> (ø)
config-service 86.73% <ø> (ø)
file-service 82.59% <ø> (ø)
frontend 94.30% <ø> (ø) Carriedforward from 7738b6c
notebook-migration-service 79.13% <ø> (ø)
pyamber 97.57% <ø> (ø) Carriedforward from 7738b6c
workflow-compiling-service 77.19% <ø> (ø)

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 2 better · 🔴 1 worse · ⚪ 12 noise (<±5%) · 0 without baseline

Compared against main 84e2d7d benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
🔴 bs=10 sw=10 sl=64 428 0.261 22,685/29,605/29,605 us 🟢 -12.7% / 🔴 +110.5%
bs=100 sw=10 sl=64 957 0.584 104,898/122,463/122,463 us ⚪ within ±5% / 🔴 +26.9%
bs=1000 sw=10 sl=64 1,106 0.675 899,427/1,002,962/1,002,962 us ⚪ within ±5% / 🔴 +7.8%
Baseline details

Latest main 84e2d7d from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 428 tuples/sec 443 tuples/sec 863.81 tuples/sec -3.4% -50.5%
bs=10 sw=10 sl=64 MB/s 0.261 MB/s 0.27 MB/s 0.527 MB/s -3.3% -50.5%
bs=10 sw=10 sl=64 p50 22,685 us 21,558 us 11,488 us +5.2% +97.5%
bs=10 sw=10 sl=64 p95 29,605 us 33,931 us 14,067 us -12.7% +110.5%
bs=10 sw=10 sl=64 p99 29,605 us 33,931 us 17,591 us -12.7% +68.3%
bs=100 sw=10 sl=64 throughput 957 tuples/sec 948 tuples/sec 1,127 tuples/sec +0.9% -15.1%
bs=100 sw=10 sl=64 MB/s 0.584 MB/s 0.578 MB/s 0.688 MB/s +1.0% -15.1%
bs=100 sw=10 sl=64 p50 104,898 us 103,445 us 89,893 us +1.4% +16.7%
bs=100 sw=10 sl=64 p95 122,463 us 127,292 us 96,506 us -3.8% +26.9%
bs=100 sw=10 sl=64 p99 122,463 us 127,292 us 104,915 us -3.8% +16.7%
bs=1000 sw=10 sl=64 throughput 1,106 tuples/sec 1,102 tuples/sec 1,156 tuples/sec +0.4% -4.3%
bs=1000 sw=10 sl=64 MB/s 0.675 MB/s 0.673 MB/s 0.705 MB/s +0.3% -4.3%
bs=1000 sw=10 sl=64 p50 899,427 us 907,952 us 886,448 us -0.9% +1.5%
bs=1000 sw=10 sl=64 p95 1,002,962 us 964,714 us 930,093 us +4.0% +7.8%
bs=1000 sw=10 sl=64 p99 1,002,962 us 964,714 us 963,104 us +4.0% +4.1%
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,467.22,200,128000,428,0.261,22684.89,29605.43,29605.43
1,100,10,64,20,2089.66,2000,1280000,957,0.584,104898.01,122463.19,122463.19
2,1000,10,64,20,18090.76,20000,12800000,1106,0.675,899427.35,1002962.15,1002962.15

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants