Skip to content

feat(llm): add generation artifact delivery protocol (1/6) - #14977

Open
biswapanda wants to merge 1 commit into
mainfrom
biswapanda/generation-artifact-01-protocol
Open

biswapanda wants to merge 1 commit into
mainfrom
biswapanda/generation-artifact-01-protocol

Conversation

@biswapanda

@biswapanda biswapanda commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Establish the backend-neutral control-plane contract for delivering large generation artifacts out of band. Dynamo validates and forwards the delivery request and returns an opaque receipt; it does not interpret the uploaded artifact bytes or enumerate backend-specific content schemas.

What changes

  • Adds typed nvext.generation_artifact request support for OpenAI requests and the Generate API.
  • Defines the common envelope: non-empty format, unique non-empty contents, zstd codec, object_store delivery, and a tagged target.
  • Defines two delivery targets: presigned_http_put with URL, expiry, byte limit, required signed headers, and opaque object ID; and managed_fsspec with an operator profile and relative object key.
  • Passes the request through preprocessing as extra_args.nvext.generation_artifact without converting the artifact payload schema into Rust types.
  • Projects engine_data.generation_artifact into the public response. Chat/completions expose it as nvext.generation_artifact; Generate exposes it as generation_artifact.
  • Produces a terminal artifact_receipt_missing failure receipt if a backend accepted the request but returned no receipt.
  • Redacts presigned URLs and all required-header values from debug output, request traces, and recursively nested observable JSON.

Contract boundary

Dynamo core is aware of delivery metadata, requested content names as opaque strings, and receipt state. It is not aware of vLLM routed-expert tensor layouts, selected-logprob arrays, or any training-experience schema. Backend-specific encoding starts in #14979, while storage I/O starts in #14980.

Response behavior

A successful backend receipt can contain format, contents, state=ready, actual_bytes, sha256, and object_id. Failure receipts remain structured and safe to return without exposing a presigned URL, credentials, or provider exception text.

Reviewer guide

  • lib/llm/src/protocols/common/extensions.rs: request types, response selection, validation, and redaction.
  • lib/llm/src/preprocessor.rs: backend passthrough.
  • lib/llm/src/protocols/openai/generate.rs: Generate request and receipt aggregation.
  • lib/llm/src/request_trace/payload.rs: observability redaction.

Validation

  • cargo fmt --check
  • cargo test -p dynamo-llm --no-default-features generation_artifact --lib
  • Result: 6 focused tests passed.

PR stack

Review and merge bottom-up. Each PR is based on the preceding stack branch, so its diff contains only that layer. The original umbrella #14385 remains open and unchanged as a reference.

Order PR Layer
1 #14977 Protocol and opaque receipt projection
2 #14979 vLLM binary format
3 #14980 Presigned HTTP PUT delivery
4 #14976 Managed fsspec storage
5 #14975 Bounded vLLM capture
6 #14978 vLLM and frontend integration

Signed-off-by: Biswa Panda <biswa.panda@gmail.com>
@biswapanda
biswapanda requested review from a team as code owners September 17, 2026 04:00
@github-actions github-actions Bot added feat frontend `python -m dynamo.frontend` and `dynamo-run in=http|text|grpc` labels Sep 17, 2026
@coderabbitai

coderabbitai Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6c498045-32e2-4f72-ada6-8b2d4a174928

📥 Commits

Reviewing files that changed from the base of the PR and between 99dae1f and b7bc6e3.

📒 Files selected for processing (5)
  • lib/llm/src/http/service/generate.rs
  • lib/llm/src/preprocessor.rs
  • lib/llm/src/protocols/common/extensions.rs
  • lib/llm/src/protocols/openai/generate.rs
  • lib/llm/src/request_trace/payload.rs

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.


Walkthrough

The change adds typed generation-artifact request and response support, validates delivery settings, forwards nvext data to backends, aggregates artifact receipts, synthesizes missing-receipt failures, and redacts artifact secrets from traces and payloads.

Changes

Generation artifact flow

Layer / File(s) Summary
Artifact contracts and response projection
lib/llm/src/protocols/common/extensions.rs
Adds generation-artifact request and response models, validation, secret redaction, response selection, receipt projection, and failure records for missing terminal receipts.
OpenAI request and response aggregation
lib/llm/src/protocols/openai/generate.rs
Adds typed nvext request handling, backend artifact aggregation, response receipts, missing-receipt failures, and related tests.
Backend envelope and passthrough forwarding
lib/llm/src/http/service/generate.rs, lib/llm/src/preprocessor.rs
Forwards nvext and nested generation_artifact data through the vLLM envelope and backend passthrough arguments.
Trace and payload secret redaction
lib/llm/src/preprocessor.rs, lib/llm/src/request_trace/payload.rs
Redacts generation-artifact URLs and required-header values from trace logging and stored request payloads. Tests verify the redacted output.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to b7bc6

No actionable correctness, security, or availability risk remains.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.94% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 47 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description thoroughly explains the purpose, protocol changes, reviewer entry points, validation, and PR stack. However, it omits the template's required Related Issues section and does not confir… Add the required Related Issues section. Either specify the linked issue, such as "Closes #XXXX" or "Relates to #XXXX", or check the confirmation that no related issue exists. Consider mapping the existing Purpose, What changes, and Reviewe…
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the main change: adding the LLM generation artifact delivery protocol. The stack marker is acceptable and does not obscure the change.
Full details: Description check

Explanation

The description thoroughly explains the purpose, protocol changes, reviewer entry points, validation, and PR stack. However, it omits the template's required Related Issues section and does not confirm whether the PR is linked to an issue.

Resolution

Add the required Related Issues section. Either specify the linked issue, such as "Closes #XXXX" or "Relates to #XXXX", or check the confirmation that no related issue exists. Consider mapping the existing Purpose, What changes, and Reviewer guide sections to the template headings if required by repository conventions.

  • Fix all pre-merge checks with AI

Comment @coderabbitai help to get the list of available commands.

pub struct ManagedFsspecTarget {
#[serde(deserialize_with = "deserialize_non_empty_string")]
pub profile: String,
#[serde(deserialize_with = "deserialize_non_empty_string")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

object_key is validated only as non-empty, so absolute paths and traversal keys such as /artifact or ../artifact are accepted and forwarded despite the managed-fsspec contract requiring a relative object key.

🤖 AI Fix

Add a dedicated object-key deserializer that rejects absolute paths and traversal components, and apply it to ManagedFsspecTarget::object_key.

#[serde(deserialize_with = "deserialize_non_empty_string")]
pub profile: String,
#[serde(deserialize_with = "deserialize_non_empty_string")]
pub object_key: String,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

managed_fsspec.object_key is documented as relative but only checked for non-emptiness. Inputs such as /other/profile/object or ../../other-profile/object are accepted and forwarded as storage control data, allowing a managed-storage backend to escape its configured profile prefix. Reject absolute keys and keys containing parent-directory traversal when deserializing this target.

🤖 AI Fix

Replace the non-empty deserializer on object_key with validation that requires a normalized relative object key and rejects absolute and parent-directory components.

None
};

let generation_artifact = if let Some(artifact) = self.generation_artifact.as_ref() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The missing-receipt fallback is decided from only the current delta. A backend may emit engine_data.generation_artifact in a metadata-only chunk before its terminal finish chunk, which this frontend otherwise supports. The receipt is emitted on that earlier chunk, but the terminal chunk has no receipt and emits artifact_receipt_missing; non-streaming aggregation then overwrites the valid receipt with that synthetic failure. Retain an observed artifact receipt across deltas and synthesize the failure only when the whole response reaches a terminal finish without one.

🤖 AI Fix

Track the requested generation-artifact receipt in the response generator across deltas and emit artifact_receipt_missing only if no receipt was observed by terminal completion.

serde_json::json!(["moe_routes"])
);

for invalid in [

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

These invalid-contract cases combine the field being checked with an empty contents array, while the generation artifact contract is for non-empty requested contents. That makes the codec, format, URL, and byte-limit cases non-discriminating against the contents validator; the duplicate-contents case already protects the content-specific rejection. Use valid non-empty contents in the non-content invalid cases so each case exercises one observable contract.

🤖 AI Fix

Change the codec, format, presigned URL, and max_bytes invalid cases to use a representative non-empty contents array, retaining the duplicate-contents case as the content validation case.

"nvext": {
"generation_artifact": {
"format": "generation_artifact_v1",
"contents": [],

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This redaction test builds the artifact request with empty contents, which is outside the supported non-empty generation-artifact contract and is unrelated to the URL/header redaction behavior it verifies. The same redaction coverage remains protected with a representative requested content.

🤖 AI Fix

Replace the empty contents array with a representative non-empty content name in this test fixture.

@ishandhanani

Copy link
Copy Markdown
Contributor

will has #11470. feels similar

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

feat frontend `python -m dynamo.frontend` and `dynamo-run in=http|text|grpc` size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants