-
Notifications
You must be signed in to change notification settings - Fork 117
fix: use IAM roles for bedrock access #578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
66090ff
caf816f
08eadf1
d9deee4
ff36f3b
651a8cb
998e020
cf4768e
cbc436f
a519865
12592f6
67a93ab
c3ddb47
096d83a
f1d8103
894dd39
d9dbf3e
ce37f62
532bafe
6974d17
048cfdf
7d438c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,18 +22,18 @@ Export it before running Mellea: | |
| export AWS_BEARER_TOKEN_BEDROCK=your-bedrock-key | ||
| ``` | ||
|
|
||
| ## Connecting with `create_bedrock_mantle_backend` | ||
| ## Connecting with `create_bedrock_openai_backend` | ||
|
|
||
| ```python | ||
| # Requires: mellea | ||
| # Returns: ModelOutputThunk | ||
| from mellea import MelleaSession | ||
| from mellea.backends import model_ids | ||
| from mellea.backends.bedrock import create_bedrock_mantle_backend | ||
| from mellea.backends.bedrock import create_bedrock_openai_backend | ||
| from mellea.stdlib.context import ChatContext | ||
|
|
||
| m = MelleaSession( | ||
| backend=create_bedrock_mantle_backend(model_id=model_ids.OPENAI_GPT_OSS_120B), | ||
| backend=create_bedrock_openai_backend(model_id=model_ids.OPENAI_GPT_OSS_120B), | ||
| ctx=ChatContext(), | ||
| ) | ||
|
|
||
|
|
@@ -54,10 +54,10 @@ The default region is `us-east-1`. Pass `region` to target a different region: | |
| # Requires: mellea | ||
| # Returns: MelleaSession | ||
| from mellea import MelleaSession | ||
| from mellea.backends.bedrock import create_bedrock_mantle_backend | ||
| from mellea.backends.bedrock import create_bedrock_openai_backend | ||
|
|
||
| m = MelleaSession( | ||
| backend=create_bedrock_mantle_backend( | ||
| backend=create_bedrock_openai_backend( | ||
| model_id="amazon.nova-pro-v1:0", | ||
| region="eu-west-1", | ||
| ) | ||
|
|
@@ -73,10 +73,10 @@ model ID string directly: | |
| # Requires: mellea | ||
| # Returns: MelleaSession | ||
| from mellea import MelleaSession | ||
| from mellea.backends.bedrock import create_bedrock_mantle_backend | ||
| from mellea.backends.bedrock import create_bedrock_litellm_backend | ||
|
|
||
| m = MelleaSession( | ||
| backend=create_bedrock_mantle_backend( | ||
| backend=create_bedrock_openai_backend( | ||
| model_id="anthropic.claude-3-haiku-20240307-v1:0" | ||
| ) | ||
| ) | ||
|
|
@@ -144,7 +144,7 @@ Model X is not supported in region us-east-1. | |
|
|
||
| Either enable model access for the requested model in your AWS account at | ||
| [Bedrock Model Access](https://us-east-1.console.aws.amazon.com/bedrock/home#/model-access), | ||
| or pass a different `region` to `create_bedrock_mantle_backend`. | ||
| or pass a different `region` to `create_bedrock_litellm_backend`. | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This got caught in the rename sweep — the troubleshooting tip points to |
||
| ## Vision support | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,62 @@ | ||
| """Helpers for creating bedrock backends from openai/litellm.""" | ||
|
|
||
| import logging | ||
| import os | ||
|
|
||
| import boto3 | ||
| import botocore.exceptions | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| from openai import OpenAI | ||
| from openai.pagination import SyncPage | ||
|
|
||
| from mellea.backends.litellm import LiteLLMBackend | ||
| from mellea.backends.model_ids import ModelIdentifier | ||
| from mellea.backends.openai import OpenAIBackend | ||
|
|
||
| # botocore logs a credential-resolution message on every boto3.Session() call. Suppress it. | ||
| logging.getLogger("botocore.credentials").setLevel(logging.WARNING) | ||
|
|
||
|
|
||
| def _assert_region(region: str | None) -> None: | ||
| resolved_region = ( | ||
| region | ||
| or os.environ.get("AWS_REGION_NAME") | ||
| or os.environ.get("AWS_DEFAULT_REGION") | ||
| or os.environ.get("AWS_REGION") | ||
| ) | ||
| assert resolved_region is not None, ( | ||
| "you must specify a region: pass `region` explicitly or set AWS_REGION_NAME, AWS_DEFAULT_REGION, or AWS_REGION." | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ) | ||
|
Comment on lines
+18
to
+27
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do the OpenAI and LiteLLM SDKs check for these same env vars? |
||
|
|
||
|
|
||
| def _assert_bedrock_auth() -> None: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be calling this on the OpenAI path as well? Does the OpenAI SDK work with the creds path? |
||
| """Raises if no valid AWS credentials can be resolved. | ||
|
|
||
| Accepts any credential source that boto3 supports: | ||
| - Static env vars (AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY) | ||
| - Named profile (AWS_PROFILE or ~/.aws/credentials) | ||
| - ECS task role (AWS_CONTAINER_CREDENTIALS_RELATIVE_URI) | ||
| - EC2 / ECS instance profile (IMDSv2) | ||
| - LiteLLM-specific Bedrock API key (AWS_BEARER_TOKEN_BEDROCK) | ||
| """ | ||
| if "AWS_BEARER_TOKEN_BEDROCK" in os.environ: | ||
| return | ||
|
|
||
| try: | ||
| creds = boto3.Session().get_credentials() | ||
| if creds is None: | ||
| raise botocore.exceptions.NoCredentialsError() | ||
| # Resolve to catch expired/invalid assume-role chains early. | ||
| creds.get_frozen_credentials() | ||
| except botocore.exceptions.NoCredentialsError: | ||
| raise AssertionError( | ||
| "No AWS credentials found. Provide one of:\n" | ||
| " - AWS_BEARER_TOKEN_BEDROCK (Bedrock API key)\n" | ||
| " - AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY\n" | ||
| " - AWS_PROFILE pointing to a configured profile\n" | ||
| " - An IAM role attached to the instance/task (EC2, ECS, Lambda)" | ||
| ) | ||
| except botocore.exceptions.NoRegionError: | ||
| pass # Credentials exist; region is validated separately. | ||
|
|
||
|
|
||
| def _make_region_for_uri(region: str | None): | ||
| if region is None: | ||
|
|
@@ -53,7 +102,39 @@ def stringify_mantle_model_ids(region: str | None = None) -> str: | |
| return f" * {model_names}" | ||
|
|
||
|
|
||
| def create_bedrock_mantle_backend( | ||
| def create_bedrock_litellm_backend( | ||
| model_id: ModelIdentifier | str, region: str | None = None, num_retries: int = 15 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 15 seems like a high default for retries. I did a quick search and it seems like Litellm uses exponential waits. I couldn't find a number, but that seems like this might resolve in long hangs. |
||
| ) -> LiteLLMBackend: | ||
| """Returns a LiteLLM backend that points to Bedrock for model `model_id`. | ||
|
|
||
| Use this instead of `create_bedrock_openai_backend` when you need auth with an AWS_ACCESS_KEY_ID. | ||
| """ | ||
| _assert_bedrock_auth() | ||
| _assert_region(region) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
|
|
||
| model_name = "" | ||
| match model_id: | ||
| case ModelIdentifier(): | ||
| if model_id.bedrock_litellm_name is None: | ||
| raise Exception( | ||
| f"We do not have a known bedrock model identifier for {model_id}. If Bedrock supports this model, please pass the model_id string directly and open an issue to add the model id: https://github.com/generative-computing/mellea/issues/new" | ||
| ) | ||
| else: | ||
| model_name = model_id.bedrock_litellm_name | ||
| case str(): | ||
| model_name = model_id | ||
| assert model_name != "", ( | ||
| f"Model identifier {model_id} does not specify a bedrock_name." | ||
| ) | ||
|
|
||
| backend = LiteLLMBackend(model_id=model_name, num_retries=num_retries) | ||
|
|
||
| # TODO litellm doesn't even appear to use this...? | ||
| backend._base_url = None # type: ignore | ||
|
Comment on lines
+132
to
+133
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we remove this? or add a comment why setting the _base_url to None is necessary? |
||
| return backend | ||
|
|
||
|
|
||
| def create_bedrock_openai_backend( | ||
| model_id: ModelIdentifier | str, region: str | None = None | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| ) -> OpenAIBackend: | ||
| """Return an OpenAI backend that points to Bedrock mantle for the given model. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be the litellm path given the import above.