feat(py/plugins/amazon-bedrock): add model capability registry#5699
feat(py/plugins/amazon-bedrock): add model capability registry#5699cabljac wants to merge 2 commits into
Conversation
Port of the Go plugin's models.go: 47-entry capability registry (verified key-for-key and flag-for-flag against the source), cross-region inference-profile prefix stripping for capability lookup only, and get_model_info() with modern Converse defaults at the unstable stage for unknown chat/text models so newer or profile-only models stay callable.
There was a problem hiding this comment.
Code Review
This pull request introduces a model capability registry for the Amazon Bedrock plugin, mapping model IDs to their respective capabilities (multimodal and tools support) and handling cross-region inference-profile prefixes. The review feedback suggests improving robustness by parsing full Amazon Resource Names (ARNs) to extract the base model ID before stripping prefixes, along with adding corresponding unit tests to verify this behavior.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| def strip_inference_profile_prefix(model_id: str) -> str: | ||
| """Strips a cross-region inference-profile prefix from a model ID. | ||
|
|
||
| Used for capability lookup only; requests always carry the original ID. | ||
|
|
||
| Args: | ||
| model_id: Bedrock model ID, possibly prefixed (e.g. ``us.anthropic...``). | ||
|
|
||
| Returns: | ||
| The base model ID without the inference-profile prefix. | ||
| """ | ||
| for prefix in INFERENCE_PROFILE_PREFIXES: | ||
| if model_id.startswith(prefix): | ||
| return model_id.removeprefix(prefix) | ||
| return model_id |
There was a problem hiding this comment.
In AWS Bedrock, models and inference profiles are frequently referenced by their full Amazon Resource Names (ARNs) rather than just their short IDs (e.g., when configuring IAM policies or using application inference profiles).
Currently, if a full ARN is passed as the model_id, strip_inference_profile_prefix will return the ARN untouched, causing the capability lookup in MODEL_CAPABILITIES to fail and fallback to Stage.UNSTABLE with default capabilities.
We can make this more robust by extracting the base model/profile ID from the ARN (the part after the last /) before stripping the prefix.
| def strip_inference_profile_prefix(model_id: str) -> str: | |
| """Strips a cross-region inference-profile prefix from a model ID. | |
| Used for capability lookup only; requests always carry the original ID. | |
| Args: | |
| model_id: Bedrock model ID, possibly prefixed (e.g. ``us.anthropic...``). | |
| Returns: | |
| The base model ID without the inference-profile prefix. | |
| """ | |
| for prefix in INFERENCE_PROFILE_PREFIXES: | |
| if model_id.startswith(prefix): | |
| return model_id.removeprefix(prefix) | |
| return model_id | |
| def strip_inference_profile_prefix(model_id: str) -> str: | |
| """Strips a cross-region inference-profile prefix from a model ID. | |
| Used for capability lookup only; requests always carry the original ID. | |
| Args: | |
| model_id: Bedrock model ID, possibly prefixed (e.g. ``us.anthropic...``) or an ARN. | |
| Returns: | |
| The base model ID without the inference-profile prefix. | |
| """ | |
| if model_id.startswith('arn:aws:'): | |
| model_id = model_id.split('/')[-1] | |
| for prefix in INFERENCE_PROFILE_PREFIXES: | |
| if model_id.startswith(prefix): | |
| return model_id.removeprefix(prefix) | |
| return model_id |
| def test_strip_leaves_bare_model_id_untouched() -> None: | ||
| assert strip_inference_profile_prefix('amazon.nova-lite-v1:0') == 'amazon.nova-lite-v1:0' |
There was a problem hiding this comment.
To ensure that the ARN parsing logic works correctly, we should add a unit test that verifies strip_inference_profile_prefix correctly extracts and strips prefixes from full Bedrock ARNs.
| def test_strip_leaves_bare_model_id_untouched() -> None: | |
| assert strip_inference_profile_prefix('amazon.nova-lite-v1:0') == 'amazon.nova-lite-v1:0' | |
| def test_strip_leaves_bare_model_id_untouched() -> None: | |
| assert strip_inference_profile_prefix('amazon.nova-lite-v1:0') == 'amazon.nova-lite-v1:0' | |
| def test_strip_handles_arns() -> None: | |
| arn = 'arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-3-5-sonnet-20241022-v2:0' | |
| assert strip_inference_profile_prefix(arn) == 'anthropic.claude-3-5-sonnet-20241022-v2:0' |
…k ARNs Reduce foundation-model and inference-profile ARNs to their resource ID before capability lookup, across all AWS partitions (aws, aws-us-gov, aws-cn). Lookup-only, requests still carry the original identifier. Addresses PR review feedback.
|
Both review points addressed in 075d69d. Went slightly broader than the suggestion: matching on |
Slice 2 of the Amazon Bedrock Python plugin train, into the
py-bedrock-pluginbase branch.Ports the Go plugin's
models.go(aws-bedrock-go-plugin):global. us-gov. us. eu. jp. apac. au.) for capability lookup only; the full original model ID is always sent to Bedrock untouched.get_model_info(): known models arestablewith registry capabilities; unknown chat/text models default to multimodal + tools at theunstablestage so newer or inference-profile-only models remain callable without a plugin release; image models advertise media output only; embedding models advertise nothing.Tests: 12 new (prefix stripping incl.
us-gov.vsus.ordering, registry lookups via profile IDs, unknown-model defaults, image/embedding shapes, registry size + base-ID invariants).ruffclean, 24/24 plugin tests pass.Next slice: generate sync path (Converse).