feat: add generic and OpenRouter attribution headers#542
Conversation
|
All contributors have signed the DCO ✍️ ✅ |
Code Review: PR #542 — feat: add generic and OpenRouter attribution headersSummaryThis PR adds outbound attribution headers to all model API requests made by DataDesigner. A generic Scope: 4 files changed, 59 additions, 4 deletions — a small, well-scoped feature. FindingsPositive
Suggestions (Non-blocking)
IssuesNo blocking issues found. VerdictApprove. This is a clean, well-tested, narrowly scoped feature. The attribution headers follow the existing patterns for header injection, respect the telemetry opt-out, and correctly preserve user overrides. The test coverage is thorough. No architectural concerns. |
Greptile SummaryThis PR adds outbound attribution headers (
|
| Filename | Overview |
|---|---|
| packages/data-designer-engine/src/data_designer/engine/models/facade.py | Adds framework attribution header injection to consolidate_kwargs() under the TELEMETRY_ENABLED guard; precedence logic (caller → provider → framework X-Title → OpenRouter defaults) is correct and the or {} fix for explicit None extra_headers is a welcome correctness improvement. |
| packages/data-designer-config/src/data_designer/config/utils/constants.py | Defines ATTRIBUTION_TITLE, ATTRIBUTION_REFERER, and OPENROUTER_ATTRIBUTION_HEADERS constants; PREDEFINED_PROVIDERS correctly left without extra_headers so OpenRouter headers are fully gated by the engine-side telemetry check. |
| packages/data-designer-engine/tests/engine/models/test_facade.py | Comprehensive test coverage added for all header-injection scenarios: telemetry on/off, OpenRouter vs. non-OpenRouter, provider-level vs. caller-level precedence, and explicit None extra_headers. All cases are correctly asserted. |
| packages/data-designer-config/tests/config/test_default_model_settings.py | Adds extra_headers is None assertions for all three builtin providers, correctly documenting the design choice that attribution headers are injected by the engine, not baked into provider configs. |
Sequence Diagram
sequenceDiagram
participant Caller
participant ModelFacade
participant Constants
Caller->>ModelFacade: "consolidate_kwargs(**kwargs)"
ModelFacade->>ModelFacade: merge generate_kwargs + caller kwargs
alt model_provider.extra_headers is truthy
ModelFacade->>ModelFacade: merge provider extra_headers (provider wins over caller)
end
alt "TELEMETRY_ENABLED == True"
ModelFacade->>Constants: ATTRIBUTION_TITLE
alt "X-Title" not already in headers
ModelFacade->>ModelFacade: prepend X-Title (framework default, lowest priority)
end
alt "provider.name == "openrouter""
ModelFacade->>Constants: OPENROUTER_ATTRIBUTION_HEADERS
ModelFacade->>ModelFacade: "merge {**OPENROUTER_DEFAULTS, **current_headers}<br/>(current_headers win → user/provider values preserved)"
end
end
ModelFacade-->>Caller: kwargs with attribution headers
Reviews (7): Last reviewed commit: "fix telemetry gating for OpenRouter head..." | Re-trigger Greptile
Inject X-Title header on all provider requests when telemetry is enabled, and add OpenRouter-specific attribution headers (HTTP-Referer, X-OpenRouter-Title, X-OpenRouter-Categories) to the predefined OpenRouter provider entry. - Add ATTRIBUTION_TITLE, ATTRIBUTION_REFERER, and OPENROUTER_ATTRIBUTION_HEADERS constants - Add extra_headers to the OpenRouter predefined provider - Inject X-Title in ModelFacade.consolidate_kwargs() gated on TELEMETRY_ENABLED, with user/provider headers taking precedence - Update and extend tests for both config and engine packages Fixes #519 Signed-off-by: Eric W. Tramel <[email protected]>
aa593c5 to
a047ccf
Compare
andreatgretel
left a comment
There was a problem hiding this comment.
lgtm, two small nits: kwargs.get("extra_headers", {}) doesn't guard against explicit None (or {} fixes it), and the X-Title override test only covers the provider path, not caller kwargs. neither blocking
Existing users have extra_headers: null in their model_providers.yaml for the openrouter provider, which causes the OpenRouter-specific attribution headers (HTTP-Referer, X-OpenRouter-Title, X-OpenRouter-Categories) to be silently dropped. This injects those headers programmatically in consolidate_kwargs() when the provider is openrouter and telemetry is enabled, using the same fill-missing-only pattern as X-Title. Provider-level and caller-supplied headers still take precedence. Adds 5 unit tests covering injection, precedence, telemetry opt-out, and non-openrouter provider isolation. Signed-off-by: Eric W. Tramel <[email protected]>
|
Hey @andreatgretel — your two nits from the last review are addressed:
Also found a real bug during wire-level testing: existing users have |
packages/data-designer-config/src/data_designer/config/utils/constants.py
Show resolved
Hide resolved
- keep default OpenRouter provider extra_headers unset - rely on facade injection so telemetry opt-out suppresses attribution - align default provider test with the gated behavior
📋 Summary
Add outbound attribution headers to all model requests (
X-Title: NeMo Data Designer) and OpenRouter-specific headers on the built-in OpenRouter provider, gated on the existingNEMO_TELEMETRY_ENABLEDopt-out.🔗 Related Issue
Closes #519
🔄 Changes
ATTRIBUTION_TITLE,ATTRIBUTION_REFERER, andOPENROUTER_ATTRIBUTION_HEADERSconstantsextra_headersinto the predefined OpenRouter provider entry inPREDEFINED_PROVIDERSX-TitleinModelFacade.consolidate_kwargs()when telemetry is enabled, applied last so user-supplied or provider-level values take precedenceNEMO_TELEMETRY_ENABLED=false; userextra_headersstill honored🧪 Testing
make testpassesAdded:
test_consolidate_kwargs_telemetry_disabled— no framework headers when opted outtest_consolidate_kwargs_user_x_title_override— userX-Titletakes precedenceUpdated:
test_consolidate_kwargs— verifyX-Titleinjection under default telemetry-ontest_get_builtin_model_providers— verify OpenRouterextra_headersand confirm NVIDIA/OpenAI have none✅ Checklist