PR 6: E05 — VLM + OCR hybrid (gpt-5.4) - #160
Conversation
|
|
||
| await fs.promises.writeFile( | ||
| path.join(ITERATION_DIR, "last-response.json"), | ||
| JSON.stringify(resultBody, null, 2), |
| elapsedMs, | ||
| rawResponseSummary, | ||
| }); | ||
| await fs.promises.writeFile(path.join(ITERATION_DIR, "last-diff.md"), md); |
| elapsedMs, | ||
| rawResponseSummary, | ||
| }); | ||
| await fs.promises.writeFile(path.join(ITERATION_DIR, "last-diff.md"), md); |
| }; | ||
| await fs.promises.writeFile( | ||
| path.join(ITERATION_DIR, "last-response.json"), | ||
| JSON.stringify(responseForDisk, null, 2), |
| ); | ||
| const outFile = path.join(outDir, "benchmark-run.json"); | ||
| fs.mkdirSync(outDir, { recursive: true }); | ||
| fs.writeFileSync(outFile, JSON.stringify(downloadResp.data, null, 2)); |
| { | ||
| model: "mistral-document-ai-2512", | ||
| document: { type: "document_url", document_url: dataUrl }, | ||
| document_annotation_format: annotationFormat, | ||
| }, |
| "experiment-02", | ||
| `mistral-azure-ocr-response-${sampleId}-smoketest.json`, | ||
| ); | ||
| await fs.promises.writeFile(outPath, JSON.stringify(data, null, 2)); |
a7d099d to
224f9ad
Compare
b17f39f to
5819a0c
Compare
224f9ad to
288dce4
Compare
…40-sample run
Two-leg hybrid extraction: Azure DI prebuilt-layout produces markdown +
bbox layout, then Azure OpenAI gpt-5.4 reads the document image alongside
the OCR markdown with a strict-mode JSON Schema response_format and a
trust-hierarchy system prompt ("prefer the image when image and OCR text
disagree"). Mapper folds the upstream layout's word/line polygons into
OCRResult, closing the bbox gap E04 documented.
Per the user's session-start scope reduction, only variant 1 + gpt-5.4
is implemented; variant 2/3 + gpt-4o/gpt-5 deferred (the plumbing is in
place — variant 3 is `params.includeBboxAnnotations: true`, deployment
swaps via `params.azureOpenAiDeployment`).
Canonical run (cb677a90, 40 samples): pass_rate 0.975 (39/40),
f1.median 0.965 (tied with CU), f1.mean 0.941 (best across all 5
experiments), recall.mean 0.917 (best). Hybrid is the production-stack
winner on this dataset.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5819a0c to
13beb03
Compare
288dce4 to
7454edb
Compare
There was a problem hiding this comment.
fails typescript compilation
There was a problem hiding this comment.
Fixed in #220: experiment-05-vlm-ocr-hybrid.test.ts (with the other four experiment tests) was ported to develop's current GraphWorkflow API — graphWorkflow/getStatus from ./graph-workflow, GraphWorkflowConfig, ctx read via the getStatus query rather than off the result. Verified 2026-07-10 on the cumulative branch: apps/temporal npm run type-check → exit 0, and experiment-01..05 → 120/120 pass against the dev-stack Temporal (paid APIs mocked). Merges to develop via #221.
|
Superseded by #221 (cumulative extraction-experiments merge), now merged into develop. This branch's commits are all contained in develop; closing the review-only PR. Branch retained. |
Summary
Fifth and final "engine" experiment: a VLM + OCR hybrid that feeds both the page image and OCR-extracted text/layout to
gpt-5.4in the same prompt, betting that the model performs better with both modalities than with either alone. Benchmarked against the same canonical 40-sample dataset.This PR adds the hybrid provider, a preflight script for the hybrid path, an iteration harness, and the full results.
What's added
Provider + workflow
apps/temporal/src/scripts/templates/experiment-05-vlm-ocr-hybrid-workflow.json— workflow templatedocs-md/graph-workflows/05-vlm-ocr-hybrid-OCR.md— workflow docTooling
apps/temporal/src/scripts/preflight-hybrid.ts— validates Azure OpenAI deployment + PDF rendering + OCR layout extraction before benchmarkingapps/temporal/src/scripts/iterate-hybrid-extraction.ts— single-sample iteration harness for prompt development on the hybrid pathResults
experiments/results/05-vlm-ocr-hybrid/SUMMARY.mdexperiments/results/05-vlm-ocr-hybrid/benchmark-run.json— canonical 40-sample runexperiments/results/05-vlm-ocr-hybrid/iteration/— request/response/diff/layout captures, field descriptions, converged promptNotes for reviewers
Workflow test placement (tracked in AI-1641). This PR adds
apps/temporal/src/experiment-05-vlm-ocr-hybrid.test.ts, which sits at thetemporal/srcroot and bundles a real Temporal-cluster end-to-end layer (via the sharedapps/temporal/src/__testlib__/integration-harness.ts) that is currently CI-gated / dev-only (process.env.CI ? describe.skip, run againstlocalhost:7233). This placement is intentional for now and consistent across all five experiments. Relocating these into a general, feature-agnostic comprehensive-workflow integration suite — and enabling it in CI — is tracked in AI-1641, not this PR.Stacked-PR note —
azureOcr.readPlainis later removed (R1). This PR introduces a dedicatedazureOcr.readPlainactivity (azure-di-read-plain.ts) for the DI plain/markdown pre-pass. It is later removed (review item R1) in favour of the standardazureOcr.submit+azureOcr.pollactivities withoutputFormat=markdown— commit46d59316, in the 08-part-2 slice (PR PR 12: E08 part 2 — extraction-engine review fixes + mock-only-paid integration harness #220). In the final merged state,azureOcr.readPlainis not a registered activity type andazure-di-read-plain.tsis deleted; the E05 workflow uses the standard submit/poll chain. Reviewing this slice in isolation shows the pre-consolidation state.Stacked-PR note — dev scripts relocated later. The dev tooling this PR adds under
apps/temporal/src/scripts/(iterate-hybrid-extraction.ts, preflight-hybrid.ts) is moved out of the compiled workersrc/intoapps/temporal/scripts/in the 08-part-2 patch PR (PR 12: E08 part 2 — extraction-engine review fixes + mock-only-paid integration harness #220), commite4036113(excluded from the worker build; type-checked viatsconfig.scripts.json). In the final merged state they live atapps/temporal/scripts/; reviewing this slice in isolation shows them at the old path.Hybrid is the most expensive variant in compute (image and OCR), so the preflight is more thorough — it catches deployment, image-rendering, and OCR-layout issues before a real run.
Benchmark JSON (~85k lines) + iteration layout JSON (~9.6k lines) dominate the diff.
Testing
preflight-hybrid.tsexercised before the canonical run.iterate-hybrid-extraction.tsused during prompt convergence.benchmark-run.json.Checklist
By submitting this pull request, I acknowledge that I have attempted to meet the following: