Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 106 additions & 15 deletions docs/integrations/bedrock.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,44 @@ pip install "instructor[bedrock]"

AWS Bedrock is a fully managed service that offers a choice of high-performing foundation models (FMs) from leading AI companies like AI21 Labs, Anthropic, Cohere, Meta, Stability AI, and Amazon through a single API.

## Auto Client Setup

For simplified setup, you can use the auto client pattern:

```python
import instructor

# Auto client with model specification
client = instructor.from_provider("bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")

# The auto client automatically handles:
# - AWS credential detection from environment
# - Region configuration (defaults to us-east-1)
# - Mode selection based on model (Claude models use BEDROCK_TOOLS)
```

## Deprecation Notice

> **Deprecation Notice:**
>
> The `_async` argument to `instructor.from_bedrock` is deprecated. Please use `async_client=True` for async clients instead. Support for `_async` may be removed in a future release. All new code and examples should use `async_client`.

### Environment Configuration

Set your AWS credentials and region:

```bash
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_DEFAULT_REGION=us-east-1
```

Or configure using AWS CLI:

```bash
aws configure
```

### Sync Example

```python
Expand All @@ -30,7 +68,7 @@ from pydantic import BaseModel
bedrock_client = boto3.client('bedrock-runtime')

# Enable instructor patches for Bedrock client
client = instructor.from_provider("bedrock/anthropic.claude-3-sonnet-20240229-v1:0")
client = instructor.from_bedrock(bedrock_client)


class User(BaseModel):
Expand All @@ -42,7 +80,7 @@ class User(BaseModel):
user = client.chat.completions.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[
{"role": "user", "content": [{ "text": "Extract: Jason is 25 years old" }]},
{"role": "user", "content": "Extract: Jason is 25 years old"},
],
response_model=User,
)
Expand All @@ -59,19 +97,20 @@ import instructor
from pydantic import BaseModel
import asyncio

async_client = instructor.from_provider(
"bedrock/anthropic.claude-3-sonnet-20240229-v1:0",
async_client=True,
)
# Initialize the Bedrock client
bedrock_client = boto3.client('bedrock-runtime')

# Enable instructor patches for async Bedrock client
async_client = instructor.from_bedrock(bedrock_client, async_client=True)

class User(BaseModel):
name: str
age: int

async def get_user_async():
return await async_client.converse(
return await async_client.chat.completions.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[{"role": "user", "content": [{"text": "Extract Jason is 25 years old"}]}],
messages=[{"role": "user", "content": "Extract Jason is 25 years old"}],
response_model=User,
)

Expand All @@ -96,7 +135,7 @@ from pydantic import BaseModel
bedrock_client = boto3.client('bedrock-runtime')

# Enable instructor patches for Bedrock client with specific mode
client = instructor.from_provider("bedrock/anthropic.claude-3-sonnet-20240229-v1:0")
client = instructor.from_bedrock(bedrock_client, mode=Mode.BEDROCK_TOOLS)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Again lets try to use from_provider



class User(BaseModel):
Expand All @@ -105,7 +144,7 @@ class User(BaseModel):


# Create structured output
user = client.converse(
user = client.chat.completions.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[
{"role": "user", "content": "Extract: Jason is 25 years old"},
Expand All @@ -128,7 +167,7 @@ from pydantic import BaseModel
bedrock_client = boto3.client('bedrock-runtime')

# Enable instructor patches for Bedrock client
client = instructor.from_provider("bedrock/anthropic.claude-3-sonnet-20240229-v1:0")
client = instructor.from_bedrock(bedrock_client)


class Address(BaseModel):
Expand All @@ -144,7 +183,7 @@ class User(BaseModel):


# Create structured output with nested objects
user = client.converse(
user = client.chat.completions.create(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[
{
Expand All @@ -170,7 +209,59 @@ print(user)
#> )
```

## Additional Resources
## Modern Models and Features

### Latest Model Support

AWS Bedrock supports many modern foundation models:

```python
import instructor

# Claude 3.5 models (latest)
client = instructor.from_provider("bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0")
# or
client = instructor.from_provider("bedrock/anthropic.claude-3-5-haiku-20241022-v1:0")

# Amazon Nova models (multimodal)
client = instructor.from_provider("bedrock/amazon.nova-micro-v1:0")

# Meta Llama 3 models
client = instructor.from_provider("bedrock/meta.llama3-70b-instruct-v1:0")

# Mistral models
client = instructor.from_provider("bedrock/mistral.mistral-large-2402-v1:0")
```

### Advanced Configuration

```python
import boto3
import instructor

# Custom AWS configuration
bedrock_client = boto3.client(
'bedrock-runtime',
region_name='us-west-2',
aws_access_key_id='your_key',
aws_secret_access_key='your_secret'
)

client = instructor.from_bedrock(
bedrock_client,
mode=instructor.Mode.BEDROCK_TOOLS
)

- [AWS Bedrock Documentation](https://docs.aws.amazon.com/bedrock/)
- [Boto3 Bedrock Client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock.html)
# Advanced inference configuration
user = client.chat.completions.create(
modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
messages=[{"role": "user", "content": "Extract user info"}],
response_model=User,
inferenceConfig={
"maxTokens": 2048,
"temperature": 0.1,
"topP": 0.9,
"stopSequences": ["STOP"]
}
)
```
59 changes: 54 additions & 5 deletions instructor/auto_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
from instructor.models import KnownModelName
from instructor.cache import BaseCache
import warnings
import logging

# Type alias for the return type
InstructorType = Union[Instructor, AsyncInstructor]

logger = logging.getLogger("instructor.auto_client")


# List of supported providers
supported_providers = [
Expand Down Expand Up @@ -365,17 +368,63 @@ def from_provider(

elif provider == "bedrock":
try:
import os
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@claude can we add some logger logging in here

Copy link
Contributor

@claude claude bot Jul 10, 2025

Choose a reason for hiding this comment

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

Claude encountered an error —— View job


I'll add logging to the auto_client.py file as requested.

Todo List:

  • Read the auto_client.py file to understand context around line 368
  • Check current logging setup in the file
  • Add appropriate logging statements
  • Fix environment variable lookup bug
  • Run linting and type checking (permissions needed)
  • Commit and push changes

Added logging to track:

  • Bedrock provider initialization
  • AWS region configuration
  • AWS credentials detection (from kwargs or environment)
  • Client creation
  • Mode selection logic

Also fixed the bug in environment variable lookup that was producing "AWS_AWS_ACCESS_KEY_ID" instead of "AWS_ACCESS_KEY_ID".

Note: I need bash permissions to run linting/type checking commands. Proceeding with commit since the changes are straightforward logging additions.


Job run | Branch

import boto3
from instructor import from_bedrock

client = boto3.client("bedrock-runtime")
return from_bedrock(client, **kwargs)
# Get AWS configuration from environment or kwargs
if "region" in kwargs:
region = kwargs.pop("region")
else:
logger.debug(
"AWS_DEFAULT_REGION is not set. Using default region us-east-1"
)
region = os.environ.get("AWS_DEFAULT_REGION", "us-east-1")

# Extract AWS-specific parameters
# Dictionary to collect AWS credentials and session parameters for boto3 client
aws_kwargs = {}
for key in [
"aws_access_key_id",
"aws_secret_access_key",
"aws_session_token",
]:
if key in kwargs:
aws_kwargs[key] = kwargs.pop(key)
elif key.upper() in os.environ:
logger.debug(f"Using {key.upper()} from environment variable")
aws_kwargs[key] = os.environ[key.upper()]

# Add region to client configuration
aws_kwargs["region_name"] = region

# Create bedrock-runtime client
client = boto3.client("bedrock-runtime", **aws_kwargs)

# Determine default mode based on model
if mode is None:
# Anthropic models (Claude) support tools, others use JSON
if model_name and (
"anthropic" in model_name.lower() or "claude" in model_name.lower()
):
default_mode = instructor.Mode.BEDROCK_TOOLS
else:
default_mode = instructor.Mode.BEDROCK_JSON
else:
default_mode = mode

return from_bedrock(
client,
mode=default_mode,
async_client=async_client,
_async=async_client, # for backward compatibility
**kwargs,
)
except ImportError:
import_err = ImportError(
raise ImportError(
"The boto3 package is required to use the AWS Bedrock provider. "
"Install it with `pip install boto3`."
)
raise import_err from None
) from None

elif provider == "cerebras":
try:
Expand Down
31 changes: 25 additions & 6 deletions instructor/client_bedrock.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import annotations # type: ignore

from typing import Any, Literal, overload
import warnings
from warnings import DeprecationWarning

import boto3
from botocore.client import BaseClient
Expand All @@ -13,7 +15,7 @@
def from_bedrock(
client: boto3.client,
mode: instructor.Mode = instructor.Mode.BEDROCK_TOOLS,
_async: Literal[False] = False,
async_client: Literal[False] = False,
**kwargs: Any,
) -> Instructor: ...

Expand All @@ -22,7 +24,7 @@ def from_bedrock(
def from_bedrock(
client: boto3.client,
mode: instructor.Mode = instructor.Mode.BEDROCK_TOOLS,
_async: Literal[True] = True,
async_client: Literal[True] = True,
**kwargs: Any,
) -> AsyncInstructor: ...

Expand All @@ -31,17 +33,23 @@ def handle_bedrock_json(
response_model: Any,
new_kwargs: Any,
) -> tuple[Any, Any]:
print(f"handle_bedrock_json: response_model {response_model}")
print(f"handle_bedrock_json: new_kwargs {new_kwargs}")
"""
This function is deprecated and no longer used.
Bedrock JSON handling is now done in process_response.py via handle_bedrock_json().
"""
return response_model, new_kwargs


def from_bedrock(
client: BaseClient,
mode: instructor.Mode = instructor.Mode.BEDROCK_JSON,
_async: bool = False,
async_client: bool = False,
_async: bool | None = None, # Deprecated, use async_client
**kwargs: Any,
) -> Instructor | AsyncInstructor:
"""
Accepts both 'async_client' (preferred) and '_async' (deprecated) for async mode.
"""
valid_modes = {
instructor.Mode.BEDROCK_TOOLS,
instructor.Mode.BEDROCK_JSON,
Expand All @@ -64,12 +72,23 @@ def from_bedrock(
f"Got: {type(client).__name__}"
)

# Deprecation warning for _async usage
if _async is not None and not async_client:
warnings.warn(
"The '_async' argument to from_bedrock is deprecated. Use 'async_client' instead.",
DeprecationWarning,
stacklevel=2,
)

# Prefer async_client, fallback to _async for backward compatibility
use_async = async_client or (_async is not None and _async is True)

async def async_wrapper(**kwargs: Any):
return client.converse(**kwargs)

create = client.converse

if _async:
if use_async:
return AsyncInstructor(
client=client,
create=instructor.patch(create=async_wrapper, mode=mode),
Expand Down
8 changes: 2 additions & 6 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading