feat(model-runtime): thread request_metadata through to model runtimes#191
Merged
WH-2099 merged 2 commits intoJun 26, 2026
Conversation
`invocation_context` already existed in graphon but was only wired to the LLM observability callbacks. It was never forwarded to the model runtime (`model_runtime.invoke_*`), so per-invocation metadata (e.g. the originating Dify `app_id`) could not reach a runtime/plugin for provider-side cost attribution. This threads the existing `invocation_context: Mapping[str, object] | None` from the public `invoke()` surface down to the runtime for all six model types, and adds it to the corresponding runtime protocols: - LLM: `invoke()` -> `_invoke_llm_via_runtime()` -> `model_runtime.invoke_llm`, and to the before/after/error/stream callbacks. - text embedding, rerank, tts, speech2text, moderation: `invoke()` -> `model_runtime.invoke_*`. The parameter is keyword-only with a default of `None`, so existing callers and the standard invoke paths are unaffected. The structured-output runtime entry point is intentionally out of scope and can follow separately. Enables langgenius/dify#35859 (pass app_id to model plugins).
|
All contributors on this pull request have signed the CLA. |
Merged
3 tasks
Contributor
Author
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
Pull request overview
This PR threads the existing invocation_context metadata from the public model invoke() methods down into each model runtime protocol surface, enabling runtimes/providers to receive per-invocation metadata for attribution/observability.
Changes:
- Added
invocation_context: Mapping[str, object] | None = Noneto the six model runtime protocols (invoke_llm,invoke_text_embedding,invoke_multimodal_embedding,invoke_rerank,invoke_multimodal_rerank,invoke_tts,invoke_speech_to_text,invoke_moderation). - Updated the corresponding base model wrappers to forward
invocation_contextintomodel_runtime.invoke_*calls (and for LLM, also through callback plumbing). - Extended dispatch tests to ensure
invocation_contextreaches the runtime and defaults toNone.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/model_runtime/test_model_dispatch.py | Updates runtime stubs and adds assertions that invocation_context is forwarded and defaults to None. |
| src/graphon/model_runtime/protocols/llm_runtime.py | Adds invocation_context to the LLM runtime protocol method overloads/abstract method. |
| src/graphon/model_runtime/protocols/text_embedding_runtime.py | Adds invocation_context to text and multimodal embedding runtime protocol methods. |
| src/graphon/model_runtime/protocols/rerank_runtime.py | Adds invocation_context to rerank runtime protocol methods. |
| src/graphon/model_runtime/protocols/tts_runtime.py | Adds invocation_context to the TTS runtime protocol method. |
| src/graphon/model_runtime/protocols/speech_to_text_runtime.py | Adds invocation_context to the speech-to-text runtime protocol method. |
| src/graphon/model_runtime/protocols/moderation_runtime.py | Adds invocation_context to the moderation runtime protocol method. |
| src/graphon/model_runtime/model_providers/base/large_language_model.py | Threads invocation_context through runtime invocation and callback triggers. |
| src/graphon/model_runtime/model_providers/base/text_embedding_model.py | Forwards invocation_context into embedding runtime invocations. |
| src/graphon/model_runtime/model_providers/base/rerank_model.py | Forwards invocation_context into rerank runtime invocations (text + multimodal). |
| src/graphon/model_runtime/model_providers/base/tts_model.py | Forwards invocation_context into TTS runtime invocation. |
| src/graphon/model_runtime/model_providers/base/speech2text_model.py | Forwards invocation_context into speech-to-text runtime invocation. |
| src/graphon/model_runtime/model_providers/base/moderation_model.py | Forwards invocation_context into moderation runtime invocation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
WH-2099
approved these changes
Jun 26, 2026
This was referenced Jul 6, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Thread
request_metadatafrom the public modelinvoke()surfaces down tomodel_runtime.invoke_*for all six model types, and add it to the corresponding runtime protocols.Why
Dify needs to pass request-level metadata such as the originating
app_idthrough Graphon to model runtimes and plugins.That enables provider-side cost attribution and observability for providers that accept request metadata, including Amazon Bedrock
requestMetadata, OpenAI and Azure OpenAImetadata, and Vertex AIlabels.Changes
request_metadata: Mapping[str, object] | None = Noneto the model runtime protocol methods for LLM, text embedding, rerank, TTS, speech-to-text, and moderation.request_metadatafrom the public model wrappers to the correspondingmodel_runtime.invoke_*calls.request_metadatathrough the LLM callback path so observability hooks receive the same request metadata.request_metadatakeyword-only on the public model wrapper surfaces to avoid accidental positional argument shifts.request_metadataname consistently.Compatibility
request_metadatadefaults toNone, so existing callers that do not pass request metadata continue to behave the same.Runtime implementations need to accept the new keyword parameter if they implement the updated protocol surface.
Out of scope
The structured-output runtime entry
invoke_llm_with_structured_output()is intentionally not touched here and can follow separately if needed.Tests
uv run ruff format src/graphon/model_runtime tests/model_runtime/test_model_dispatch.pyuv run ruff check src/graphon/model_runtime tests/model_runtime/test_model_dispatch.pyuv run ty checkuv run pytest tests/model_runtime/test_model_dispatch.py tests/test_protocol_abstract_contracts.py tests/test_protocols_exports.py tests/model_runtime/test_text_embedding_model.pygit diff --checkRelated