feat(vertex_ai): support GenerateContentConfig labels for Dify app_id propagation#3168
Draft
mas-sakai wants to merge 7 commits into
Draft
feat(vertex_ai): support GenerateContentConfig labels for Dify app_id propagation#3168mas-sakai wants to merge 7 commits into
mas-sakai wants to merge 7 commits into
Conversation
Add `_labels.py` with `normalize_label_value` and `build_dify_labels` helpers that produce GCP-compliant Vertex AI label dicts. UUID app_ids pass through unchanged; other strings are lowercased, restricted to `[a-z0-9_-]`, and truncated to 63 characters. Unit tests cover passthrough, character replacement, truncation, casing, empty input, and the `None`/ empty short-circuits in `build_dify_labels`. Refs: langgenius/dify#35772, langgenius/dify-plugin-sdks#311 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When `enable_request_metadata` is `enabled` in credentials, attach `dify_app_id` and `dify_source` to `GenerateContentConfig.labels` for the Gemini route only. The `get_current_session` import is local to the call site and wrapped in `try/except ImportError` so the plugin keeps working against older `dify_plugin` releases. With the default `disabled` setting, control flow is identical to the previous version. Refs: langgenius/dify#35772, langgenius/dify-plugin-sdks#311 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add an opt-in `enable_request_metadata` credential (select, defaults to `disabled`) so operators can choose to attach Dify metadata to Vertex AI requests for Cloud Billing breakdown. Existing users who do not touch their credentials are unaffected. Refs: langgenius/dify#35772, langgenius/dify-plugin-sdks#311 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refs: langgenius/dify#35772, langgenius/dify-plugin-sdks#311 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Point `dify_plugin` at the `feat/pass-session-to-model-plugins` branch of `ryuta-kobayashi-ug/dify-plugin-sdks` (PR langgenius#313) so the Gemini route can import `get_current_session()`. Refresh `uv.lock` accordingly. This pin is temporary for the review period; revert to a release-version constraint once langgenius#313 is merged and a new SDK is published. Also add `PR_BODY.md` as a draft of the upstream PR body so it is available alongside the branch. Refs: langgenius/dify#35772, langgenius/dify-plugin-sdks#311 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces the capability to track Cloud Billing costs on a per-application basis by attaching Dify metadata as labels to Vertex AI requests. The implementation includes a utility for normalizing label values according to GCP constraints, logic in the Gemini model to extract session metadata, and a new configuration setting to enable this feature. Feedback suggested optimizing the label normalization helper by truncating long input strings prior to processing to enhance performance and reduce memory usage.
Comment on lines
+34
to
+38
| if not s: | ||
| return "" | ||
| lowered = s.lower() | ||
| sanitized = _INVALID_CHAR_RE.sub("_", lowered) | ||
| return sanitized[:_MAX_LABEL_LENGTH] |
Contributor
There was a problem hiding this comment.
入力文字列 s が非常に長い場合、lower() や正規表現による置換処理を行う前に文字列を切り詰めることで、メモリ使用量と処理時間を節約できます。特に app_id が外部から渡される可能性がある場合、事前に制限文字数(63文字)でスライスしておくことが効率的です。
Suggested change
| if not s: | |
| return "" | |
| lowered = s.lower() | |
| sanitized = _INVALID_CHAR_RE.sub("_", lowered) | |
| return sanitized[:_MAX_LABEL_LENGTH] | |
| if not s: | |
| return "" | |
| # 処理負荷を軽減するため、正規化の前に切り詰めを行います | |
| s = s[:_MAX_LABEL_LENGTH] | |
| lowered = s.lower() | |
| sanitized = _INVALID_CHAR_RE.sub("_", lowered) | |
| return sanitized[:_MAX_LABEL_LENGTH] |
Remove `PR_BODY.md` (and the local `PR_BODY_EN.md` working copy) from the repository. The content lives in the PR description on GitHub; the checked-in copies are working notes that would otherwise land in main with the merge. Refs: langgenius/dify#35772, langgenius/dify-plugin-sdks#311 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The descriptive text for the `enable_request_metadata` credential was placed in `placeholder`, but `type: select` is rendered as a dropdown and does not surface placeholder text. Move the description to `help` so it actually shows in the credentials UI, matching the convention used by the openai provider's select credentials. Refs: langgenius/dify#35772, langgenius/dify-plugin-sdks#311 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Note
This is a Draft PR. It depends on
langgenius/dify-plugin-sdks#313
being merged and a new SDK released.
pyproject.toml/uv.lockcurrentlypin
dify_pluginto the #313 branch so the Gemini route can importget_current_session(). The pin will be reverted to a released versionconstraint (
dify_plugin>=0.3.0,<0.6.0) before this PR is marked Readyfor review. The CI "Validate Dependencies" / "Check Plugin Install"
steps may fail until then.
Summary
Enable Cloud Billing visibility per Dify app for the Vertex AI plugin (Gemini
route). When the new
enable_request_metadatacredential is set toenabled,the plugin attaches
dify_app_idanddify_sourcetoGenerateContentConfig.labels, so operators can break Vertex AI cost down bylabels.dify_app_idin GCP Cloud Billing without any ETL.Related issues / PRs:
get_current_session()public API) — this PR depends on itScope (intentionally narrow)
models/llm/llm.py::_generate). The Anthropic-on-Vertexroute (
_generate_anthropic) and other providers are out of scope.dify_app_idanddify_sourceonly.dify_tenant_id/dify_user_idare deferred to a follow-up to keep the surface minimal.enable_request_metadatadefaults todisabled, so existingusers who do not touch their credentials are completely unaffected. With
disabled, the control flow is identical to the previous version.Implementation notes
models/llm/_labels.pywithnormalize_label_valueandbuild_dify_labels. Output conforms to the GCP labels spec (lowercase,[a-z0-9_-]only, 63-char cap). UUID app_ids pass through unchanged.get_current_session()is imported locally inside_generateand wrapped intry/except ImportError, so the plugin keeps working against olderdify_pluginreleases (no hard runtime dependency on fix getnumtoken retrun list[int] #313 once it ships).tests/test_labels.py(passthrough, characterreplacement, truncation, casing, empty input,
None/ empty short-circuitsin
build_dify_labels).Change Type
Screenshots / Videos
🚧 Cloud Billing breakdown screenshots (by
labels.dify_app_id) will beadded once E2E verification completes (currently testing on GCP project
dify-vertex-labels-poc). All 9 unit tests pass (uv run pytest tests/).LLM Plugin Checklist
Areas affected by this change (check all that apply)
Version
versioninmanifest.yaml(not the one undermeta) —0.0.53→0.0.54dify_plugin>=0.3.0,<0.6.0is declared inpyproject.tomland locked inuv.lock(or kept inrequirements.txtfor legacy plugins withoutuv.lock) — SDK docsTesting
dify-vertex-labels-poc)Unit tests:
uv run pytest tests/— 9 passed (label normalization helper).