Skip to content

[integrations][python] Apply DashScope native structured output - #1090

Open
weiqingy wants to merge 1 commit into
apache:mainfrom
weiqingy:280-pr5-tongyi-native
Open

[integrations][python] Apply DashScope native structured output#1090
weiqingy wants to merge 1 commit into
apache:mainfrom
weiqingy:280-pr5-tongyi-native

Conversation

@weiqingy

@weiqingy weiqingy commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Linked issue: #280

Purpose of change

Passing an output_schema to the Tongyi connection raised NotImplementedError, because the connection had no native translation. DashScope does support schema-enforced structured output, so this adds it.

The catch is that it applies to fewer models than you might expect. DashScope documents json_schema for five model families, but four of them are served on its multimodal interface, while this connection calls Generation.call on the text-generation interface. Calling one through the other fails with url error. That leaves the Qwen3.7-Max family as the only place native enforcement is reachable here.

So the connection reports the capability for that family, and for everything else, including the qwen-plus default, it sends nothing new and keeps the existing prompt-based fallback. No behavior changes for anyone not on Qwen3.7-Max.

Sources for the two halves of that intersection, both worth checking against the allowlist in the diff:

Heads-up on the docs: the DashScope API reference pages still list only text and json_object for response_format and never mention json_schema. The feature guide above is the current source, and the error reference corroborates it by naming json_schema as a recognised key.

Tests

New file test_tongyi_native_structured_output.py, 16 cases, no API key or network needed. It asserts the request the SDK would actually receive: the parameter is present and correctly shaped on a capable model, absent on every other model, absent when no schema is passed, and a non-Pydantic schema falls back instead of failing. The capability check is tested against capable names, incapable names, a lookalike (qwen3.7-maximum), empty string and None.

Each assertion was verified by mutating the source and confirming the intended test fails, so the tests are not passing by accident.

One limitation, stated plainly. No vendor source shows json_schema on Generation.call. It is documented as a parameter of the native API, with the placement rule for HTTP callers, but the only native sample uses MultiModalConversation.call with a model this connection excludes. Every test here is a mock and I had no DashScope key, so the suite cannot settle it. What is established: the parameter provably reaches the request body, and if the provider rejects it the call fails loudly with a RuntimeError rather than silently returning an unconstrained answer. If a reviewer has a key, one live call against qwen3.7-max would close this.

API

No public API change. supports_native_structured_output is an existing hook this connection now overrides, and no dependency changes. Python only, since there is no Java Tongyi connection.

Documentation

  • doc-needed
  • doc-not-needed
  • doc-included

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

  • Yes
  • No

Generated-by: Claude Code 2.1.251 (Claude Opus 5)

TongyiChatModelConnection.chat refused an output schema outright, because
the connection had no native translation. DashScope does support
schema-enforced structured output, so translate an OutputSchema into the
provider's response_format={"type": "json_schema", ...} parameter.

Capability is reported only for models that can honor it. DashScope
documents json_schema for five model families, but four of them are served
on the multimodal interface while this connection calls Generation.call on
the text-generation interface, and a mismatched pairing answers "url error".
The Qwen3.7-Max family is that intersection. Every other model, including
the qwen-plus default, sends no response_format and keeps the existing
prompt-engineered fallback rather than raising.

The translation resolves the schema payload, then refuses a caller-supplied
response_format that would be overwritten, then renders. Rendering earlier
would mask the conflict behind an unrenderable-schema TypeError; refusing
earlier would raise on a RowTypeInfo payload that was never going to be
translated.

The schema is rendered with bare pydantic through render_output_schema
rather than the OpenAI-family helper, which rewrites required to include
every property to satisfy a rule DashScope does not impose.

Generated-by: Claude Code 2.1.251 (Claude Opus 5)
@github-actions github-actions Bot added doc-included Your PR already contains the necessary documentation updates. fixVersion/0.4.0 priority/major Default priority of the PR or issue. labels Sep 2, 2026
@weiqingy

weiqingy commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

The one failing check is unrelated to this PR:

  • it-java [ubuntu-latest] [java-21] [flink-2.2]: 429 Too Many Requests from Maven Central while resolving the Apache parent POM org.apache:apache:pom:34. It failed in the "Install flink-agents Java" step after 42 seconds, so nothing was compiled and no test ran. Job log.

This PR only changes Python and docs. It touches no .java and no pom.xml, and the other four it-java jobs in the same run passed on the same commit.

I have re-triggered the failed job.

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

Labels

doc-included Your PR already contains the necessary documentation updates. fixVersion/0.4.0 priority/major Default priority of the PR or issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant