Skip to content

feat: add native Content Understanding support - #2815

Open
Bora Elkin (BoraElkin) wants to merge 7 commits into
microsoft:masterfrom
BoraElkin:feat/cu-native-integration
Open

Bora Elkin (BoraElkin) wants to merge 7 commits into
microsoft:masterfrom
BoraElkin:feat/cu-native-integration

Conversation

@BoraElkin

@BoraElkin Bora Elkin (BoraElkin) commented Nov 6, 2026 •

Copy link
Copy Markdown

Related Issues/PRs

Standalone feature contribution targeting master; no prerequisite feature PR.

What changes are proposed in this pull request?

Adds a native Scala/Python Spark transformer for Azure Content Understanding
(CU): document analysis, resumable polling and explicit analyzer management.
Users can process one document per DataFrame row and retain native CU results
alongside their original input columns, without implementing HTTP and polling
logic themselves. Includes shared HTTP and Python parameter-lifecycle changes.

This is the SynapseML connector layer, not the complete managed Fabric
integration: managed authentication, CU routing, capacity policy, billing and
runtime bundling are outside this PR.

Summary and merge impact

The complete delta against master contains 41 source/test/documentation/
configuration files: 18 production files, 18 test/fixture files, two
documentation files and three CI/navigation files
. Ten production files are
new CU implementation files; eight modify existing shared infrastructure.
Review evidence is tracked separately under this PR's numbered directory.

Merging makes this implementation available to subsequent SynapseML builds.
It does not itself publish a release, update installed notebook packages, or
bundle the connector into a Fabric runtime. Consumers need matching Python/JVM
artifacts containing the new class.

Public API and execution flow

Python users import the generated wrapper:

from synapse.ml.services.contentunderstanding import ContentUnderstanding

stage = (
    ContentUnderstanding()
    .setEndpoint(endpoint)
    .setSubscriptionKey(key)
    .setDocumentUrlCol("documentUrl")
    .setOutputCol("analysis")
    .setErrorCol("requestError")
)
results = stage.transform(documents)

transform is lazy; a Spark action performs the HTTP work on executors.
ContentUnderstanding.py is generated from Scala during codegen, not added
as a handwritten implementation or backed by a separate CU SDK dependency.

Capability Behavior added
Input Exactly one document URL or binary source, configured as a scalar or column. Binary content is base64-encoded into inputs[].data; it is not a separate Analyze Binary endpoint.
Analyzer Prebuilt or explicitly provisioned custom analyzer selection; default prebuilt-read.
Request options Scalar/column analyzer ID, document name, MIME type, page/time range, model-deployment mappings, string encoding, processing location and API version. Default API version is 2025-11-01; syntactically valid overrides are forwarded, not discovered dynamically.
analyze Submit once, then poll within configured limits. This is the default mode.
submit Submit once and return the response and any accepted operation handle without polling.
poll Poll an existing validated operation handle without uploading or resubmitting the document.
Output Preserve input rows and columns; add a result struct and standard SynapseML error column. Duplicate rows remain separate requests.
Management Explicit driver-only createAnalyzer and getAnalyzer; never provision during transformation or modify shared resource defaults. Python creation accepts a dictionary or JSON string, with replacement opt-in.
Spark ML lifecycle Copy/extra parameters, Pipeline use, save/load, stage UID and UID-derived column defaults, scalar/column bindings and clearing settings.

The result struct contains operationLocation, id, status, httpStatus,
rawResponse, and error. Native response text retains service fields such as
contents, markdown, extracted fields, usage and future/unknown properties rather
than imposing an extraction schema. Only Succeeded establishes success:
HTTP 200 or the presence of a result object does not. This preserves results;
it does not promise complete REST/SDK feature parity.

Failure, safety and resource behavior

  • Validate schema, scalar configuration, endpoint, analyzer/API identifiers and
    header settings before dispatch. Invalid row-sourced input produces a
    row-level InvalidInput diagnostic without a request; other rows continue.
  • Preserve validated handles and the last useful operation state/diagnostic
    across polling failures, response limits and exhausted budgets.
  • Distinguish definitely unsent/rejected submissions from uncertain acceptance.
    Do not automatically replay POST/PUT submissions. Polling retries use bounded
    GET attempts and honor valid Retry-After seconds or HTTP dates.
  • Detect definitive shared scalar authentication/analyzer/deployment failures
    and stop new submissions within that Spark task/partition. Already-started
    requests finish; other partitions are independent. Row-selected credentials
    and accepted operations are not incorrectly treated as shared submission
    configuration failures.
  • Require HTTPS except literal loopback test endpoints. Restrict operation
    handles to the configured origin and expected analysis/management paths.
    Disable redirects, automatic HTTP retries and cookies.
  • Validate header names/values, prohibit custom framing headers, and retain
    credential-source provenance without sending the internal marker on the wire.
  • Use explicit CU credentials; do not inherit global OpenAI URL/key/version
    settings or Fabric MWC fallback authentication. Tokens are not refreshed.
  • Log feature usage, management outcome/duration and sanitized cleanup/shared-stop
    warnings without putting service bodies or exception messages into those logs.
    Detailed service information remains in result/exception objects.
Control Default / boundary
Concurrent operations 1 per Spark partition; not a global service quota.
HTTP timeout 60 seconds.
Poll attempts / fallback delay 120 GET attempts / 1,000 ms.
Operation budget 600,000 ms (10 minutes), best effort; not a hard Spark task deadline.
Binary document / response limit 32 MiB each. The binary limit does not limit documents fetched by CU from a URL.
DNS work At most 32 outstanding connector DNS lookups per JVM; blocked native lookups keep their slot until they actually finish.
JSON parsing Connector-local depth and numeric-token limits; no shared JSON dependency change.

The generic concurrentTimeout setting is rejected for CU because it could
abandon operations and lose their handles. Response-byte limits are not peak
memory caps: base64, JSON parsing and output conversion add memory overhead.
Expiration does not cancel the remote service operation. Spark task retries or
repeated actions can still repeat submissions; there is no exactly-once or
transactional guarantee. Callers own durable handle/result persistence.

Shared behavior and compatibility

These changes affect existing consumers as well as CU and deserve independent
review. Existing master features such as ServiceParam alias validation, batched
header normalization and classifier raw-prediction mixins are retained baseline
behavior, not new functionality introduced by this PR.

Observable shared parameter changes: JVM scalars/defaults now appear through
Python generic inspection. A column binding is not a scalar value; scalar
getOrDefault raises KeyError for it, while copy/save/load preserve the binding.
This view can expose scalar credentials to parameter collectors such as MLflow.
Description redaction does not sanitize explicit getters, parameter maps or
saved model metadata; credentials are not encrypted by the serializer.

Scope boundaries

This is the native SynapseML connector component of the broader CU effort,
not the complete Fabric managed-client integration. Runtime bundling, the
Fabric CU controller/routing, managed authentication, capacity/tenant policy
enforcement, and billing are separate workstreams.

No automatic durable journal, job restart, Lakehouse writes, document splitting,
schema inference, AI Functions API, token refresh, or customer-resource
provisioning is added. Analyzer creation is an explicit opt-in management call
against an existing resource. The connector currently requires an explicit CU
endpoint and credentials.

The branch starts directly from master
6c2699defcfb24d5bff5ba55f2252ba2d8cbea24. Original contribution authorship is
retained in the commit trailers.

How is this patch tested?

  • Local (41b54ec47d): 310 Scala and 73 Python tests passed, including all
    174 CU Scala tests and the combined persistence regression. Style, compilation,
    codegen and pinned formatting passed; one existing fuzzing check remains ignored.

  • Final-head CI: Azure build 245595083
    passed all 66 executed jobs on the exact rebased merge (manual queue).
    Published results confirm all 174 CU Scala tests, the combined persistence
    regression and the Python inspection/schema regressions passed.

  • Review: The focused integration review is clean; final-head Copilot reports
    no open issues. Earlier findings remain resolved; CLA and all required checks pass.
    Reports and index
    link the full review history.

  • Exclusions: seven opt-in live CU tests lacked credentials; existing ignored
    tests remain unchanged. Fabric E2E, InternalCompat and coverage uploads are
    excluded by the existing fork/manual-run conditions.

Live CU, packaged-runtime and representative performance validation remain
unproven; passing local and CI checks is not a production-readiness claim.

Does this PR change any dependencies?

  • No.
  • Yes.

Does this PR add a new feature? If so, have you added samples on website?

  • No.
  • Yes. The Content Understanding guide includes Python and Scala examples,
    configuration, response handling, submit/poll recovery, authentication,
    persistence and operational limits, with a website sidebar entry.

All 111 published website-sample tests passed in the current Azure validation.

@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown

Hey Bora Elkin (@BoraElkin) 👋!
Thank you so much for contributing to our repository 🙌.
Someone from SynapseML Team will be reviewing this pull request soon.

We use semantic commit messages to streamline the release process.
Before your pull request can be merged, you should make sure your first commit and PR title start with a semantic prefix.
This helps us to create release messages and credit you for your hard work!

Examples of commit messages with semantic prefixes:

  • fix: Fix LightGBM crashes with empty partitions
  • feat: Make HTTP on Spark back-offs configurable
  • docs: Update Spark Serving usage
  • build: Add codecov support
  • perf: improve LightGBM memory usage
  • refactor: make python code generation rely on classes
  • style: Remove nulls from CNTKModel
  • test: Add test coverage for CNTKModel

To test your commit locally, please follow our guild on building from source.
Check out the developer guide for additional guidance on testing your change.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Bora Elkin (BoraElkin) pushed a commit to BoraElkin/SynapseML that referenced this pull request Nov 6, 2026
AB#5837660

## Summary
Resolve the native Content Understanding review findings across task
cancellation, bounded FIFO DNS admission, Python parameter lifecycle, Spark
schema planning and operation diagnostics. Preserve the full six-stage review,
all five targeted correction passes, original findings and their resolution
history in reviews/pr-2815.

## Prompting Intent
The engineer requested focused fixes, regression coverage and an iterative
targeted review-fix loop, rather than restarting six stages. They explicitly
selected GPT/high, Grok/low and Opus/high and emphasized avoiding new defects
while correcting the findings. Keep the native contribution and detailed draft
PR scope intact; do not claim remote, live-service or merge readiness.

## Linked Sources
- Draft PR: microsoft#2815
- User-provided CU scope document and subsequent scope/review decisions in the
  authoring session; the private input document is not included in this commit.
- Connector contract: docs/Explore Algorithms/AI Services/Content Understanding.md
- Complete review and driver history:
  reviews/pr-2815/task-5837660-attempt-3-stage-attempt-2-review-1-gpt-6.1-sol.md
- Independent final targeted reports:
  reviews/pr-2815/task-5837660-attempt-4-stage-attempt-5-review-4-gpt-6.1-sol.md
  reviews/pr-2815/task-5837660-attempt-4-stage-attempt-5-review-4-grok-4.7.md
  reviews/pr-2815/task-5837660-attempt-4-stage-attempt-5-review-4-claude-opus-5.5.md
- Repository guidance: AGENTS.md and applicable .github/skills/
- Verified integration target: d3f3af6

## Rationale
Keep service behavior in Scala and reuse existing parameter setters, Spark type
coercion and bounded diagnostic merging instead of adding independent policies.
Carry and restore owning task context so queued/asynchronous calls can observe
cancellation; keep native DNS workers bounded and retain FIFO position and
permit ownership through waits and interruption. Cancellation remains local
best effort, not remote rollback.

Validate service parameters before mutation while preserving ordinary None
no-ops. Restore ordinary JVM defaults on Python transfer and convert sequences
without sending raw bytes through pickle. Plan HTTP schemas explicitly without
session/RDD inference, matching resolver, coercion and nullability behavior.

Preserve accepted creation state on unavailable lookup responses and retain
specific body/transport errors and arbitrary service-error shapes. Discarded
creation handles report uncertainty and recovery without following unsafe URLs
or replaying submissions. Normalize the post-admission DNS interruption without
changing native-worker or permit cleanup behavior.

All three final targeted reviewers returned CLEAN and passed independent
transport/scope audits on the frozen source. Historical dirty, false-positive
and invalid-invocation evidence is retained rather than rewritten. Final local
validation passed 174 CU Scala tests and four affected Python paths after style
and compilation. Earlier complete 12-test shared HTTP, 60-method Python and
code-generation gates retain their original snapshot attribution. Live CU,
Azure CI, packaged-install and representative performance evidence remain
outstanding; the PR stays draft.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
@BoraElkin
Bora Elkin (BoraElkin) marked this pull request as ready for review November 6, 2026 23:39
Copilot AI balanced review requested due to automatic review settings November 6, 2026 23:39

Copilot AI 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.

🟡 Changes recommended

Generic inspection of JVM-configured or loaded case-class-valued sequences returns JavaObject elements instead of dictionaries, causing getOrDefault and extractParamMap values to fail JSON serialization.

1 open issue
What changed in this PR

Adds native Azure Content Understanding support to SynapseML’s Scala/Python service layer, with document analysis, resumable polling, and explicit analyzer management. The connector preserves native service responses and does not provide the broader managed Fabric integration.

Changes:

  • Adds bounded transport, DNS admission, cancellation handling, diagnostic preservation, and header validation.
  • Updates shared HTTP schema planning, parameter persistence, and Python ServiceParam inspection.
  • Adds fixtures, regression coverage, opt-in live tests, documentation, CI selection, and review records.
File Description
website/​sidebars.js Adds Content Understanding navigation.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-5-review-4-grok-4.7.md Records final targeted review evidence.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-5-review-4-gpt-6.1-sol.md Records final targeted review evidence.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-5-review-4-claude-opus-5.5.md Records final targeted review evidence.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-4-review-4-grok-4.7.md Preserves targeted review results.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-4-review-4-gpt-6.1-sol.md Preserves targeted review results.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-3-review-4-grok-4.7.md Preserves correction review evidence.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-3-review-4-gpt-6.1-sol.md Preserves correction review evidence.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-2-review-4-grok-4.7.md Records diagnostic corrections and dispositions.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-2-review-4-gpt-6.1-sol.md Records diagnostic-preservation correction history.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-1-review-4-grok-4.7.md Records submission-diagnostic correction history.
reviews/​pr-2815/​task-5837660-attempt-4-stage-attempt-1-review-4-gpt-6.1-sol.md Records schema-planning correction history.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-3-review-3-grok-4.7.md Documents deadline-race assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-6-grok-4.7.md Records resource and documentation checks.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-6-gpt-6.1-sol.md Records hardening review and validation limits.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-6-claude-opus-5.5.md Documents row-validation performance assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-5-grok-4.7.md Records proposed protocol coverage improvements.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-5-gpt-6.1-sol.md Records interruption and collision coverage assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-4-grok-4.7.md Records protocol and parameter checks.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-4-gpt-6.1-sol.md Documents parameter-explanation disposition.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-4-claude-opus-5.5.md Records detailed correctness checks.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-3-grok-4.7.md Records cancellation and timeout assessments.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-3-gpt-6.1-sol.md Records operation-state correction evidence.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-3-claude-opus-5.5.md Records collection-conversion assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-2-grok-4.7.md Documents clear-return compatibility disposition.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-2-gpt-6.1-sol.md Records persisted-default restoration assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-1-grok-4.7.md Preserves broad review and provenance audit.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-2-review-1-claude-opus-5.5.md Preserves failed review and recovery record.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-6-grok-4.7.md Records polling-documentation assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-6-gpt-6.1-sol.md Records hardening review evidence.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-6-claude-opus-5.5.md Records documentation and operational checks.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-5-grok-4.7.md Records URL and authentication coverage assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-5-gpt-6.1-sol.md Records interruption and HTTP coverage assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-4-grok-4.7.md Documents timeout-conversion disposition.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-4-gpt-6.1-sol.md Documents parameter-explanation disposition.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-4-claude-opus-5.5.md Records protocol and lifecycle checks.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-3-grok-4.7.md Records robustness review evidence.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-3-gpt-6.1-sol.md Records robustness and validation boundaries.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-2-grok-4.7.md Documents clear-return compatibility disposition.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-2-gpt-6.1-sol.md Records schema-planning dependency assessment.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-1-grok-4.7.md Preserves initial review and audit disposition.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-1-gpt-6.1-sol.md Records setter-validation correction and evidence.
reviews/​pr-2815/​task-5837660-attempt-3-stage-attempt-1-review-1-claude-opus-5.5.md Records CI authorization and execution boundaries.
pipeline.yaml Adds a dedicated Content Understanding test leg.
docs/​Use with MLFlow/​Autologging.md Warns about scalar credential logging.
core/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​logging/​VerifyFeatureNames.scala Tests the new telemetry identifier.
core/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​io/​split1/​SimpleHTTPTransformerSuite.scala Tests schema planning, collisions, and coercion.
core/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​core/​serialize/​ValidateComplexParamSerializer.scala Tests explicit/default persistence compatibility.
core/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​core/​schema/​VerifyDatasetExtensions.scala Tests session-aware column naming.
core/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​codegen/​PyCodegenSuite.scala Checks inherited Python inspection signatures.
core/​src/​main/​scala/​org/​apache/​spark/​ml/​ComplexParamsSerializer.scala Adds opt-in separation of defaults and explicit settings.
core/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​logging/​FeatureNames.scala Registers Content Understanding telemetry.
core/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​io/​http/​SimpleHTTPTransformer.scala Adds explicit error-schema planning and collision protection.
core/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​io/​http/​Clients.scala Propagates task ownership to asynchronous requests.
core/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​core/​schema/​DatasetExtensions.scala Makes generated column names resolver-aware.
core/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​codegen/​Wrappable.scala Preserves pending Python values in generated getters.
core/​src/​main/​python/​synapse/​ml/​core/​schema/​Utils.py Adds JVM-backed scalar inspection and safe byte handling.
cognitive/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingStub.scala Provides loopback HTTP and logging fixtures.
cognitive/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingOutputParserFuzzingSuite.scala Tests parser persistence and telemetry.
cognitive/​src/​test/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingFuzzingSuite.scala Tests transformer execution and serialization.
cognitive/​src/​test/​python/​synapsemltest/​services/​test_ServiceParamPythonBridge.py Updates parameter lifecycle regression expectations.
cognitive/​src/​test/​python/​synapsemltest/​services/​test_ContentUnderstandingE2E.py Adds credential-gated live integration tests.
cognitive/​src/​test/​python/​synapsemltest/​services/​content_understanding_fixtures.py Generates deterministic synthetic documents.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingTransport.scala Tracks submission uncertainty and recovery diagnostics.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingResponseParsing.scala Bounds parsing and preserves handle diagnostics.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingLogging.scala Adds sanitized cleanup and shared-stop warnings.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingHeaderValidation.scala Rejects unsafe and connector-managed headers.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingException.scala Retains responses while sanitizing exception messages.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingDnsResolver.scala Bounds DNS work with cancellation-aware admission.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​contentunderstanding/​ContentUnderstandingBudget.scala Implements operation budgets and cancellable delays.
cognitive/​src/​main/​scala/​com/​microsoft/​azure/​synapse/​ml/​services/​CognitiveServiceBase.scala Adds header accessors and Content-Type normalization.

Review effort: Balanced

Bora Elkin (BoraElkin) pushed a commit to BoraElkin/SynapseML that referenced this pull request Nov 6, 2026
AB#5837660

## Summary
Remove 50 superseded review reports from the current PR file diff. Retain the
three final source-review reports unchanged and add a concise index linking
the complete published history. Include the artifact-only cleanup review.
No implementation, test, build or configuration file changes.

## Prompting Intent
The engineer said "we shouldn't keep all of them" after comparing committed
review artifacts in other SynapseML PRs. Reduce reviewer-facing clutter while
preserving original findings, dispositions, failed invocations and provenance.

## Linked Sources
- Current PR: microsoft#2815
- Published 53-report archive: https://github.com/BoraElkin/SynapseML/tree/1bab6fb4aef3d00b616f09b023a03062abc9695e/reviews/pr-2815
- Review decisions and resolution history: https://github.com/BoraElkin/SynapseML/blob/1bab6fb4aef3d00b616f09b023a03062abc9695e/reviews/pr-2815/task-5837660-attempt-3-stage-attempt-2-review-1-gpt-6.1-sol.md
- Comparable merged evidence-pruning precedent: microsoft#2775

## Rationale
Keep current source signoffs visible without retaining every intermediate
report in the final tree. Verified all 53 hosted paths, blob hashes and modes
against the published ancestor before pruning. Immutable links retain the
full history without rewriting commits or relabeling historical outcomes.
The index distinguishes targeted final review from the earlier six-stage
review and preserves outstanding external-validation limits.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
Copilot AI balanced review requested due to automatic review settings November 6, 2026 23:54

Copilot AI 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.

🟡 Changes recommended

JVM-configured or loaded textAndTranslation sequences retain JavaObject proxies in getOrDefault and extractParamMap, making those returned values non-JSON-serializable.

2 open issues

Review effort: Balanced

@BoraElkin

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree company="Microsoft"

Bora Elkin (BoraElkin) pushed a commit to BoraElkin/SynapseML that referenced this pull request Nov 7, 2026
AB#5837660

## Summary
Use the existing parameter-aware whole-scalar converter in getOrDefault and
extractParamMap, matching generated typed getters for JVM-backed ServiceParams.
Remove the redundant recursive converter and preserve the raw-byte guard.
Add a regression for empty and nonempty case-class sequences in configured and
restored wrappers, and record the scoped follow-up review in the review index.

## Prompting Intent
The engineer requested fixing Copilot's confirmed parameter-conversion finding
and continuing validation until the PR is ready for human review, without
introducing unrelated changes or losing existing review history.

## Linked Sources
- PR: microsoft#2815
- Original Copilot finding: microsoft#2815 (comment)
- Repeated current-head finding: microsoft#2815 (comment)
- Prior source and review archive: https://github.com/BoraElkin/SynapseML/tree/1bab6fb4aef3d00b616f09b023a03062abc9695e/reviews/pr-2815

## Rationale
Reuse the converter that already knows the ServiceParam's JSON format rather
than extending a separate recursive converter without parameter type metadata.
The regression failed in four expected subcases before the change. Core
code generation, all 35 selected Python compatibility tests and pinned Black
passed afterward, including map, sequence, column, default and raw/pickle-byte
paths. No Scala API, persisted format, dependency or pipeline change is needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
Copilot AI balanced review requested due to automatic review settings November 7, 2026 00:19

Copilot AI 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.

🔵 Needs a closer look

The new service/cancellation state machine and shared HTTP/Python parameter changes require maintainer review because current-head Azure CI, live CU contract, packaged-runtime, and performance validation remain outstanding.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

Bora Elkin (BoraElkin) pushed a commit to BoraElkin/SynapseML that referenced this pull request Nov 7, 2026
AB#5837660

## Summary
Update both Codecov notification upload counts from 54 to 55 and document the
41 UnitTests legs. Include the focused clean review evidence.

## Prompting Intent
The engineer requested making the native Content Understanding PR ready for
reviewer handoff, authorized validation, and reported the failed CI Helpers job.
Correct the directly coupled failure without removing tests or weakening gates.

## Linked Sources
- Feature PR: microsoft#2815
- Failed validation: https://dev.azure.com/msdata/b9b2accc-2d1c-45b3-9d24-0eb5d78cc47f/_build/results?buildId=245266944
- Existing regression: tools/ci/tests/test_e2e_impact.py::test_selection_preserves_all_expected_coverage_uploads
- Focused review: reviews/pr-2815/task-5837660-attempt-8-review-0-harness.md

## Rationale
The added CU unit-test matrix leg produces one additional coverage upload.
Both Codecov consumers must wait for that report. The existing assertion
correctly caught the mismatch, so retain it and the full test matrix unchanged.
The affected helper module now passes all 121 tests locally. No coverage
percentage threshold, pipeline execution, dependency pin, or product code changes.
Full Azure validation is still required on the corrected merge revision.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
Copilot AI balanced review requested due to automatic review settings November 7, 2026 00:35

Copilot AI 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.

🔵 Needs a closer look

The billable REST connector and shared HTTP/Python changes require outstanding maintainer validation of current-head Azure CI, live CU behavior, and matching packaged Python/JVM artifacts beyond what this source-only review can establish.

No open issues 🎉

Review effort: Balanced

Bora Elkin (BoraElkin) pushed a commit to BoraElkin/SynapseML that referenced this pull request Nov 7, 2026
AB#5837660

## Summary
Use the established Testable naming convention for two serialization fixtures
and align the OpenAI schema-setter regression with JVM-visible scalar state.
Include the focused clean review evidence.

## Prompting Intent
The engineer requested following the reviewer-handoff plan: fix CI failures
caused by the CU PR, validate compatibility, publish corrections, and verify
full current-head CI without weakening tests or expanding feature scope.

## Linked Sources
- Feature PR: microsoft#2815
- Failed validation: https://dev.azure.com/msdata/A365/_build/results?buildId=245268757
- Existing fixture discovery: src/test/scala/com/microsoft/azure/synapse/ml/core/test/fuzzing/FuzzingTest.scala
- Existing schema-setter contract: cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/openai/HasOpenAIResponseSchema.scala
- Focused review: reviews/pr-2815/task-5837660-attempt-9-review-0-harness.md
- Separate anomaly baseline evidence: https://dev.azure.com/msdata/A365/_build/results?buildId=245261452

## Rationale
Test-only persistence fixtures must not be discovered as exported stages.
The existing Testable convention handles this without adding exemptions or
changing global stage checks; both persistence variants retain their assertions.
The OpenAI test must distinguish stale pending Python state from a deliberately
configured JVM scalar. Check pending-map removal directly, retain the schema
assertion after transfer, and require public isSet to observe the JVM value.

Core style and compilation passed, as did 10 serializer tests, 10 global
discovery tests, and 36 OpenAI/ServiceParam Python tests. The one pre-existing
ignored fuzzing check is unchanged. Pinned Black passed. The original Azure
run supplies failing-before evidence for both corrections.

No product implementation or pipeline changes. The independent anomaly
failure also occurs on exact master before a built-in successful retry; the
VW R failure happened during TLS setup before tests. Neither is silently
waived or repaired here. A fresh exact-revision Azure run remains required.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
Copilot AI balanced review requested due to automatic review settings November 7, 2026 02:54

Copilot AI 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.

🔵 Needs a closer look

The billable CU connector and shared HTTP/Python lifecycle changes need maintainer assessment because final-head Azure CI, live-service behavior, and packaged Python/JVM validation remain unverified.

No open issues 🎉

Review effort: Balanced

Bora Elkin and others added 4 commits November 8, 2026 17:40
AB#5837660

## Summary
Add a native Scala-first Content Understanding transformer with a generated
Python API, document URL and binary inputs, analyzer request options, analyze/
submit/poll modes, raw results, and explicit analyzer management. Preserve
operation handles and diagnostic state across bounded polling, transport,
deadline, and response-limit failures. Include parameter lifecycle, logging,
schema, serialization, documentation, and offline/live test integration.

## Prompting Intent
Deliver the entire native CU contribution as a standalone feature on the latest
master baseline, preserving functionality and resolving shared bridge/generator
conflicts. The engineer approved creating this draft after integrated local
validation and before a fresh full High review, so review evidence can first
be committed under the numbered PR directory required by repository policy.
SynapseML is one component of the broader work, not the complete Fabric client.

## Linked Sources
- User-provided CU scope document and subsequent scope decisions in the
  authoring session; these are not included in the repository.
- Connector contract and examples: docs/Explore Algorithms/AI Services/Content Understanding.md
- Parameter collection guidance: docs/Use with MLFlow/Autologging.md
- Repository guidance: AGENTS.md and .github/skills/
- Integration target: d3f3af6

## Rationale
Keep service behavior in Scala and generate Python wrappers through SynapseML's
existing mechanisms instead of adding a separate SDK dependency. Retain native
results and handles rather than imposing extraction semantics or a storage
format. Keep provisioning explicit and never reuse unrelated Fabric/OpenAI
credentials. Preserve master service-parameter validation and accessor behavior
while retaining pending Python values, safe binary conversion, and JVM-backed
scalar inspection. Put shared isSet behavior in the existing Python mixin.
Reconcile bookkeeping assertions without removing stale-value, atomicity, or
lookup-cost checks. Retain legacy serialization defaults for other stages.

Local validation includes core/cognitive style, compile and codegen; 45 core
tests; 178 cognitive tests with the sole obsolete source-layout assertion fixed
and rechecked; 32 CU Python tests and 23 reconciled upstream bridge tests; pinned
Black and whitespace checks. The new full High review and remote CI remain
pending. No live CU resources were provisioned or billable tests run here.

Co-authored-by: Rana Singh <ranadeep.dtu@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
AB#5837660

## Summary
Resolve the native Content Understanding review findings across task
cancellation, bounded FIFO DNS admission, Python parameter lifecycle, Spark
schema planning and operation diagnostics. Preserve the full six-stage review,
all five targeted correction passes, original findings and their resolution
history in reviews/pr-2815.

## Prompting Intent
The engineer requested focused fixes, regression coverage and an iterative
targeted review-fix loop, rather than restarting six stages. They explicitly
selected GPT/high, Grok/low and Opus/high and emphasized avoiding new defects
while correcting the findings. Keep the native contribution and detailed draft
PR scope intact; do not claim remote, live-service or merge readiness.

## Linked Sources
- Draft PR: microsoft#2815
- User-provided CU scope document and subsequent scope/review decisions in the
  authoring session; the private input document is not included in this commit.
- Connector contract: docs/Explore Algorithms/AI Services/Content Understanding.md
- Complete review and driver history:
  reviews/pr-2815/task-5837660-attempt-3-stage-attempt-2-review-1-gpt-6.1-sol.md
- Independent final targeted reports:
  reviews/pr-2815/task-5837660-attempt-4-stage-attempt-5-review-4-gpt-6.1-sol.md
  reviews/pr-2815/task-5837660-attempt-4-stage-attempt-5-review-4-grok-4.7.md
  reviews/pr-2815/task-5837660-attempt-4-stage-attempt-5-review-4-claude-opus-5.5.md
- Repository guidance: AGENTS.md and applicable .github/skills/
- Verified integration target: d3f3af6

## Rationale
Keep service behavior in Scala and reuse existing parameter setters, Spark type
coercion and bounded diagnostic merging instead of adding independent policies.
Carry and restore owning task context so queued/asynchronous calls can observe
cancellation; keep native DNS workers bounded and retain FIFO position and
permit ownership through waits and interruption. Cancellation remains local
best effort, not remote rollback.

Validate service parameters before mutation while preserving ordinary None
no-ops. Restore ordinary JVM defaults on Python transfer and convert sequences
without sending raw bytes through pickle. Plan HTTP schemas explicitly without
session/RDD inference, matching resolver, coercion and nullability behavior.

Preserve accepted creation state on unavailable lookup responses and retain
specific body/transport errors and arbitrary service-error shapes. Discarded
creation handles report uncertainty and recovery without following unsafe URLs
or replaying submissions. Normalize the post-admission DNS interruption without
changing native-worker or permit cleanup behavior.

All three final targeted reviewers returned CLEAN and passed independent
transport/scope audits on the frozen source. Historical dirty, false-positive
and invalid-invocation evidence is retained rather than rewritten. Final local
validation passed 174 CU Scala tests and four affected Python paths after style
and compilation. Earlier complete 12-test shared HTTP, 60-method Python and
code-generation gates retain their original snapshot attribution. Live CU,
Azure CI, packaged-install and representative performance evidence remain
outstanding; the PR stays draft.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
AB#5837660

## Summary
Remove 50 superseded review reports from the current PR file diff. Retain the
three final source-review reports unchanged and add a concise index linking
the complete published history. Include the artifact-only cleanup review.
No implementation, test, build or configuration file changes.

## Prompting Intent
The engineer said "we shouldn't keep all of them" after comparing committed
review artifacts in other SynapseML PRs. Reduce reviewer-facing clutter while
preserving original findings, dispositions, failed invocations and provenance.

## Linked Sources
- Current PR: microsoft#2815
- Published 53-report archive: https://github.com/BoraElkin/SynapseML/tree/1bab6fb4aef3d00b616f09b023a03062abc9695e/reviews/pr-2815
- Review decisions and resolution history: https://github.com/BoraElkin/SynapseML/blob/1bab6fb4aef3d00b616f09b023a03062abc9695e/reviews/pr-2815/task-5837660-attempt-3-stage-attempt-2-review-1-gpt-6.1-sol.md
- Comparable merged evidence-pruning precedent: microsoft#2775

## Rationale
Keep current source signoffs visible without retaining every intermediate
report in the final tree. Verified all 53 hosted paths, blob hashes and modes
against the published ancestor before pruning. Immutable links retain the
full history without rewriting commits or relabeling historical outcomes.
The index distinguishes targeted final review from the earlier six-stage
review and preserves outstanding external-validation limits.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
AB#5837660

## Summary
Use the existing parameter-aware whole-scalar converter in getOrDefault and
extractParamMap, matching generated typed getters for JVM-backed ServiceParams.
Remove the redundant recursive converter and preserve the raw-byte guard.
Add a regression for empty and nonempty case-class sequences in configured and
restored wrappers, and record the scoped follow-up review in the review index.

## Prompting Intent
The engineer requested fixing Copilot's confirmed parameter-conversion finding
and continuing validation until the PR is ready for human review, without
introducing unrelated changes or losing existing review history.

## Linked Sources
- PR: microsoft#2815
- Original Copilot finding: microsoft#2815 (comment)
- Repeated current-head finding: microsoft#2815 (comment)
- Prior source and review archive: https://github.com/BoraElkin/SynapseML/tree/1bab6fb4aef3d00b616f09b023a03062abc9695e/reviews/pr-2815

## Rationale
Reuse the converter that already knows the ServiceParam's JSON format rather
than extending a separate recursive converter without parameter type metadata.
The regression failed in four expected subcases before the change. Core
code generation, all 35 selected Python compatibility tests and pinned Black
passed afterward, including map, sequence, column, default and raw/pickle-byte
paths. No Scala API, persisted format, dependency or pipeline change is needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
Bora Elkin and others added 3 commits November 8, 2026 17:40
AB#5837660

## Summary
Update both Codecov notification upload counts from 54 to 55 and document the
41 UnitTests legs. Include the focused clean review evidence.

## Prompting Intent
The engineer requested making the native Content Understanding PR ready for
reviewer handoff, authorized validation, and reported the failed CI Helpers job.
Correct the directly coupled failure without removing tests or weakening gates.

## Linked Sources
- Feature PR: microsoft#2815
- Failed validation: https://dev.azure.com/msdata/b9b2accc-2d1c-45b3-9d24-0eb5d78cc47f/_build/results?buildId=245266944
- Existing regression: tools/ci/tests/test_e2e_impact.py::test_selection_preserves_all_expected_coverage_uploads
- Focused review: reviews/pr-2815/task-5837660-attempt-8-review-0-harness.md

## Rationale
The added CU unit-test matrix leg produces one additional coverage upload.
Both Codecov consumers must wait for that report. The existing assertion
correctly caught the mismatch, so retain it and the full test matrix unchanged.
The affected helper module now passes all 121 tests locally. No coverage
percentage threshold, pipeline execution, dependency pin, or product code changes.
Full Azure validation is still required on the corrected merge revision.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
AB#5837660

## Summary
Use the established Testable naming convention for two serialization fixtures
and align the OpenAI schema-setter regression with JVM-visible scalar state.
Include the focused clean review evidence.

## Prompting Intent
The engineer requested following the reviewer-handoff plan: fix CI failures
caused by the CU PR, validate compatibility, publish corrections, and verify
full current-head CI without weakening tests or expanding feature scope.

## Linked Sources
- Feature PR: microsoft#2815
- Failed validation: https://dev.azure.com/msdata/A365/_build/results?buildId=245268757
- Existing fixture discovery: src/test/scala/com/microsoft/azure/synapse/ml/core/test/fuzzing/FuzzingTest.scala
- Existing schema-setter contract: cognitive/src/main/scala/com/microsoft/azure/synapse/ml/services/openai/HasOpenAIResponseSchema.scala
- Focused review: reviews/pr-2815/task-5837660-attempt-9-review-0-harness.md
- Separate anomaly baseline evidence: https://dev.azure.com/msdata/A365/_build/results?buildId=245261452

## Rationale
Test-only persistence fixtures must not be discovered as exported stages.
The existing Testable convention handles this without adding exemptions or
changing global stage checks; both persistence variants retain their assertions.
The OpenAI test must distinguish stale pending Python state from a deliberately
configured JVM scalar. Check pending-map removal directly, retain the schema
assertion after transfer, and require public isSet to observe the JVM value.

Core style and compilation passed, as did 10 serializer tests, 10 global
discovery tests, and 36 OpenAI/ServiceParam Python tests. The one pre-existing
ignored fuzzing check is unchanged. Pinned Black passed. The original Azure
run supplies failing-before evidence for both corrections.

No product implementation or pipeline changes. The independent anomaly
failure also occurs on exact master before a built-in successful retry; the
VW R failure happened during TLS setup before tests. Neither is silently
waived or repaired here. A fresh exact-revision Azure run remains required.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
AB#5837660

## Summary
Add a combined persistence regression after integrating the latest master fixes.
Verify that an explicitly assigned Spark session is used without promoting
default scalar parameters into explicit values. Preserve the historical review
archive through rebased links and include the focused integration review.

## Prompting Intent
The engineer approved resolving the newly introduced merge conflicts without
losing either CU behavior or upstream fixes, validating and reviewing the
result, publishing with an explicit force-with-lease, and rerunning CI.

## Linked Sources
- Feature PR: microsoft#2815
- Python method extraction: microsoft#2810
- Assigned Spark sessions: microsoft#2809
- Response cleanup: microsoft#2808
- Attachment cancellation: microsoft#2807
- Global parameter synchronization: microsoft#2806
- Integration target: 6c2699d
- Focused review: reviews/pr-2815/task-5837660-attempt-10-review-0-harness.md

## Rationale
Keep both sides of the code-generation and persistence conflicts rather than
choosing one wholesale. A combined public save/load test checks the interaction
that independent upstream and CU tests do not explicitly cover. Rebase preserves
the six original changes and their messages; all 53 archived report blobs and
modes are unchanged. Local validation passed 310 Scala and 73 Python tests,
with one existing ignored global-fuzzing test, plus style, compilation, codegen
and pinned formatting. New-head CI remains a separate post-publication gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 653e4257-0554-408f-9e0e-b23750249edb
Copilot AI balanced review requested due to automatic review settings November 9, 2026 01:21

Copilot AI 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.

🔵 Needs a closer look

Maintainer review is needed to confirm live CU contract compatibility and current-head packaged Python/JVM behavior for the new billable connector and shared lifecycle changes.

No open issues 🎉

Review effort: Balanced

@ranadeepsingh Rana Singh (ranadeepsingh) left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Bora, I mixed bug fixes with feature requests in the previous wording. Here is the full follow-up list, in the order I'd tackle it.

  1. Fix credential logging for existing connectors. Fix or remove the shared Python inspection change so MLflow's parameter collector does not receive subscriptionKey or AADToken. Preserve the values needed for execution and copying. Add a pipeline/autologging regression using synthetic credentials. Redacting explainParams alone does not cover this path. Inline finding.

  2. Stop the guide from submitting documents twice. After writing analysis results, read them back before extracting or displaying markdown. Apply this to both URL and binary examples. A loopback test should confirm that reading the saved results sends no additional POST. Inline finding.

  3. Add unlimited recovery from transient 429s. Cover both submission and polling, honor Retry-After, and allow cancellation. In this mode, the existing attempt and duration limits must not cut off throttling recovery. Do not retry a submission whose acceptance is uncertain. Cover POST 429 -> 202 -> success, repeated polling 429s, and cancellation during the wait. Inline request.

  4. Expose the preview allowInputTruncation option. Add scalar/column setters and request tests for omitted, true, and false. Preserve the distinction between unset and explicit false; do not send the option on GA requests by default. This is a preview API addition, not a defect in the GA request format. Inline request.

  5. Clarify the polling controls in the guide. Explain maxPollAttempts, maxOperationDuration, and why CU rejects concurrentTimeout. Make clear that polling runs inside Spark tasks, rather than in a detached background service.

  6. Add the runnable example notebook. Include setup, sample input, semantic field extraction, confidence and source grounding, and saved-handle submit/poll recovery. Read saved results before displaying them. Link the notebook and API/SDK references from the guide, but keep the notebook SDK-free. Inline request.

  7. Provide a live run before approval. Run the notebook against CU with packaged Python and JVM artifacts from the same PR head. Post the artifact/runtime versions and redacted semantic-extraction output. The current offline tests passed, but the live CU tests were skipped.

On consistency with other SynapseML callers, the native REST implementation, generated Python API, and per-partition setConcurrency already fit. I am not asking for a rewrite onto BasicAsyncReply or removal of CU's saved handles, explicit authentication, or protection against replaying ambiguous submissions. Item 3 is the retry change: the shared direct-HTTP handler retries transient 429s without consuming its retry budget. The separate Fabric-authenticated path has bounded retries, so this is not a claim that every caller behaves identically.

Review scope and evidence

Reviewed head 41b54ec47d514aac82494c70ed2963a8bc69ff5d against master 6c2699defcfb24d5bff5ba55f2252ba2d8cbea24.

Azure build 245595083 includes that exact head and base. Published results show 174 CU Scala tests, 37 CU Python tests, and 24 shared service-parameter Python tests passed. Seven live CU tests were skipped.

Local checks at that head:

  • sbt core/scalastyle core/Test/scalastyle cognitive/scalastyle cognitive/Test/scalastyle with JDK 11: all four passed.
  • sbt "cognitive/testOnly *ContentUnderstanding*Suite": 174 passed across seven suites, none skipped or canceled.
  • black --check --extend-exclude 'docs/' . with Black 22.3.0: all 219 files unchanged.

The credential check used the actual base/head mixins, PySpark Params, the unmodified MLflow 2.21.3 collector function, and simulated JVM values. Only the PR head exposed the two synthetic credentials. This was not a full autologging run.

I also compared the GA Analyze API, preview Analyze API, and Python SDK. I did not call a live CU resource.

Comment on lines +150 to +156
def isSet(self, param):
param = self._resolveParam(param)
if param.doc.startswith("ServiceParam:"):
return super().isSet(param) or (
self._java_obj.isSet(self._java_obj.getParam(param.name))
and self._java_service_value(param).isLeft()
)

@ranadeepsingh Rana Singh (ranadeepsingh) Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This makes scalar subscriptionKey and AADToken values visible to MLflow's parameter collector. It affects existing service stages too, not just CU. A fitted pipeline can now log those credentials even with log_models=False; explainParams redaction does not protect that path.

In a before/after check using the actual mixins and collector function with simulated JVM values, the base exposed neither credential and this head exposed both. That was a collector check, not a full autologging run.

Keep credentials out of automatic parameter logging without replacing the real values needed for execution/copying. Please add a pipeline/autologging regression with synthetic credentials. A documentation warning is not enough for existing callers.

Comment on lines +640 to +644
val raw = exchange(client, settings, request, budget)
val submitted = safeSubmission(settings, raw)
checkSharedFailure(settings, request, submitted, acceptedHandle = submitted.operationLocation.isDefined)
val resumable = ongoing(submitted) || (submitted.status == "Unknown" && submitted.operationLocation.isDefined)
if (mode == "analyze" && resumable) {

@ranadeepsingh Rana Singh (ranadeepsingh) Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A POST 429 without an operation handle returns Rejected here after one attempt, even with Retry-After. Polling retries 429s but consumes maxPollAttempts and is limited by maxOperationDuration.

That misses the requested unlimited throttling recovery and differs from the shared direct-HTTP handler, where transient 429s do not consume the retry budget. Add a cancellable unlimited mode that honors Retry-After and is not cut short by those limits. Keep the no-replay rule when submission acceptance is uncertain.

Please cover POST 429 -> 202 -> success, polling through repeated 429s, and cancellation during the wait.

Comment on lines +313 to +317
private def analyzeUrl(row: Row): String = {
val query = Seq("api-version" -> getValue(row, apiVersion)) ++
Seq(stringEncoding, processingLocation).flatMap(param =>
getValueOpt(row, param).map(value => param.payloadName -> value))
buildUrl(s"$AnalyzersPath/${getValue(row, analyzerId)}:analyze", query)

@ranadeepsingh Rana Singh (ranadeepsingh) Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The guide uses 2026-06-01-preview, but this builder cannot send its allowInputTruncation query parameter. A caller cannot override a shared analyzer's truncation setting for one request.

For preview coverage, add scalar/column setters and test omitted, true, and false values. Unset must remain different from explicit false; don't send this option on GA requests by default. This is a missing preview option, not a GA request bug.

Comment on lines +216 to +219
completed = results.where("analysis.status = 'Succeeded'")
markdown = completed.selectExpr(
"get_json_object(analysis.rawResponse, '$.result.contents[0].markdown') AS markdown"
)

@ranadeepsingh Rana Singh (ranadeepsingh) Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

results.write.parquet(output_path) above does not cache results. This code still uses the lazy analysis plan, so a later markdown.show() or write submits the documents to CU again and can charge for a second analysis.

Read the saved output first:

saved = spark.read.parquet(output_path)
completed = saved.where("analysis.status = 'Succeeded'")

Use the same save/read pattern for the binary example. A loopback check should confirm that extracting markdown from saved results sends no additional POST.

Comment on lines +33 to +39
## Setup and first analysis

Install matching SynapseML Python and JVM artifacts that include this class.
A runtime's preinstalled SynapseML version may not include a newly released
connector. Follow the [installation guide](../../Get%20Started/Install%20SynapseML.md)
for your runtime. You also need an existing CU resource with access to the
selected analyzer and any required model deployments.

@ranadeepsingh Rana Singh (ranadeepsingh) Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The requested example notebook is missing. These snippets assume documents, endpoint, and storage paths already exist, and the custom-analyzer example stops after creation.

Please add a runnable notebook with sample input and a semantic analyzer, then show the extracted fields, confidence, and source grounding. Include saved-handle submit/poll recovery and read saved results before displaying them. That would demonstrate CU beyond prebuilt-read OCR.

Link it here with the Analyze API and SDK reference, but keep the notebook SDK-free. This is an examples request, not a runtime bug.

Rana Singh (ranadeepsingh) added a commit to ranadeepsingh/SynapseML that referenced this pull request Nov 9, 2026
## Summary
Retry definite Content Understanding 429 responses indefinitely by default,
honor Retry-After, and preserve the existing no-replay rules for accepted or
uncertain submissions. Add optional preview input truncation and a runnable
invoice notebook that reads saved results rather than repeating submissions.
Restore the generated binary getter after the rebase changed shared service
parameter conversion.

## Prompting Intent
Apply the concrete findings from the review of microsoft#2815 to
the engineer's existing microsoft#2698. Keep direct REST calls,
follow SynapseML HTTP conventions, cover concurrency and parameter behavior,
and make the documentation and examples clear and safe to rerun.
No Azure DevOps task ID was supplied.

## Linked Sources
- Existing PR: microsoft#2698
- Related review: microsoft#2815 (review)
- REST analyze API: https://learn.microsoft.com/rest/api/contentunderstanding/content-analyzers/analyze?view=rest-contentunderstanding-2026-06-01-preview
- Python SDK API: https://learn.microsoft.com/python/api/azure-ai-contentunderstanding/azure.ai.contentunderstanding.contentunderstandingclient
- Invoice schema: https://github.com/Azure/content-understanding-toolkit/blob/main/prebuilt-schema/2025-11-01/procurement/invoice.md
- Model setup: https://learn.microsoft.com/azure/ai-services/content-understanding/concepts/models-deployments
- Service limits: https://learn.microsoft.com/azure/ai-services/content-understanding/service-limits

## Rationale
A definite 429 without an operation handle can be retried without treating it
as uncertain acceptance. Keep other POST failures and all handle-bearing
submissions out of that retry path. Preserve an explicit opt-out for callers
that need bounded retries. Do not spend the ordinary poll budget on throttling.

Use the shared HTTP scheduler rather than a detached CU worker. Carry the
owning Spark task context into asynchronous requests so cancellation and task
completion terminate their retry loops. Convert InterruptedException into a
nonfatal cancellation failure because Scala Future otherwise leaves its
promise unfinished. Do not claim that a Python-only interrupt cancels a
driver-side JVM request.

Keep omitted, false, and null-column truncation behavior distinct. Include the
analysis option in request identity but exclude the execution retry policy.
The notebook generates deterministic synthetic input, journals the operation
before polling, and extracts invoice fields from storage. Preserve the
single-writer and acceptance-to-journal crash-window limitations.

The generated document-bytes getter bypasses the shared scalar converter:
Py4J already returns raw bytes, while PySpark's generic converter treats a
bytearray as a pickled return value. The existing save/load test reproduced
the failure against the newly generated wrappers. Keep the fix local to CU.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 51d494ca-e7e5-44a3-9bd6-353038a5c877
Rana Singh (ranadeepsingh) added a commit to ranadeepsingh/SynapseML that referenced this pull request Nov 9, 2026
## Summary
Preserve validated analyzer-management operation handles when a response fails,
exclude inactive poll-only columns from durable writes, and reject explicit
input-truncation settings on API versions older than 2026-06-01-preview.
Add public-path regressions and document the version requirement. Format the
invoice notebook with CI's Black Jupyter support.

## Prompting Intent
Improve the existing Content Understanding PR using the integration review
findings. Keep direct REST calls, safe submission recovery, generated Python
support, and normal SynapseML parameter behavior. Address concrete review
findings without adding SDK dependencies or changing other connectors.

## Linked Sources
- User PR: microsoft#2698
- Related review: microsoft#2815
- Management handle: microsoft#2698 (comment)
- Preview validation: microsoft#2698 (comment)
- Writer projection: microsoft#2698 (comment)
- SDK validation: https://github.com/Azure/azure-sdk-for-python/blob/a35469f4df2fe3cbfed42efbc240b270f0b26dda/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_allow_input_truncation_gating.py
- REST analyze: https://learn.microsoft.com/rest/api/contentunderstanding/content-analyzers/analyze?view=rest-contentunderstanding-2026-06-01-preview
- Notebook style failure: https://dev.azure.com/msdata/A365/_build/results?buildId=245646399

## Rationale
Keep management failures visible without replaying a potentially accepted PUT.
Validate the handle before attaching it to an exception, so unsafe URLs remain
unusable. Derive writer columns from the transformer's existing active-parameter
map instead of maintaining a second list.

Validate the effective API version before each submission, including mixed
scalar/column bindings and explicit false. Null still omits the option. A
minimum date avoids rejecting future versions merely because SynapseML does
not yet name them. Four new regressions failed against the previous code.
No ADO task was supplied for this GitHub follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 51d494ca-e7e5-44a3-9bd6-353038a5c877
Rana Singh (ranadeepsingh) added a commit to ranadeepsingh/SynapseML that referenced this pull request Nov 9, 2026
## Summary
Use the shared generated-setter helper for Content Understanding setParams.
Reject conflicting scalar and column arguments before mutating the stage.
Preserve ignored None arguments and changes made through separate setter calls.
Add Python regressions and document the behavior.

## Prompting Intent
Improve the user's existing Content Understanding PR using the integration
review findings. Keep it consistent with other SynapseML callers and address
concrete findings from the review of the pushed head.

## Linked Sources
- User PR: microsoft#2698
- Current-head review: microsoft#2698 (review)
- Related integration review: microsoft#2815 (review)
- Shared setter validation: https://github.com/microsoft/SynapseML/blob/6c2699defcfb24d5bff5ba55f2252ba2d8cbea24/core/src/main/python/synapse/ml/core/schema/Utils.py

## Rationale
The custom setter loop silently accepted conflicting arguments and chose a
binding by insertion order. Reuse the same helper as the generated constructor
instead of duplicating its validation. Keep skip_none=True so existing CU calls
continue to ignore None, and retain the CU-specific byte and persistence
overrides. The regression reproduces the failure with string, byte, map, and
false boolean values in both argument orders.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 51d494ca-e7e5-44a3-9bd6-353038a5c877

This branch has not been deployed

No deployments
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