Skip to content

Commit 30a8eca

Browse files
committed
start of bedrock branch
1 parent fc032bf commit 30a8eca

File tree

12 files changed

+4119
-3296
lines changed

12 files changed

+4119
-3296
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
2+
3+
"""
4+
There are various hosting for model providers
5+
- baseten
6+
- bedrock (converse API: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime/client/converse.html#)
7+
- cerebras
8+
- openrouter
9+
- vertex
10+
- fal
11+
- modal
12+
- ollama
13+
- wandb
14+
- azure AI foundry
15+
- together AI (Together SDK)
16+
- novita AI (openai)
17+
- Fireworks
18+
- Replicate
19+
- Hyperbolic
20+
"""
21+
22+
import os
23+
24+
from dotenv import load_dotenv
25+
from openai import OpenAI
26+
27+
load_dotenv()
28+
29+
def main():
30+
31+
client = OpenAI(
32+
api_key=os.environ["BASETEN_API_KEY"],
33+
base_url="https://inference.baseten.co/v1"
34+
)
35+
36+
response = client.chat.completions.create(
37+
model="deepseek-ai/DeepSeek-V3.1",
38+
messages=[
39+
{
40+
"role": "user",
41+
"content": "Implement FizzBuzz in Python"
42+
}
43+
],
44+
stop=[],
45+
stream=True,
46+
stream_options={
47+
"include_usage": True,
48+
"continuous_usage_stats": True
49+
},
50+
top_p=1,
51+
max_tokens=1000,
52+
temperature=1,
53+
presence_penalty=0,
54+
frequency_penalty=0
55+
)
56+
57+
for chunk in response:
58+
if chunk.choices and chunk.choices[0].delta.content is not None:
59+
print(chunk.choices[0].delta.content, end="", flush=True)
60+
61+
62+
if __name__ == '__main__':
63+
main()

plugins/bedrock/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# AWS Bedrock Plugin for Vision Agents
2+
3+
AWS Bedrock LLM integration for Vision Agents framework.
4+
5+
## Installation
6+
7+
```bash
8+
pip install vision-agents-plugins-bedrock
9+
```
10+
11+
## Usage
12+
13+
```python
14+
from vision_agents.plugins import bedrock
15+
16+
# Initialize the Bedrock LLM
17+
llm = bedrock.LLM(
18+
model="anthropic.claude-3-5-sonnet-20241022-v2:0",
19+
region_name="us-east-1"
20+
)
21+
22+
# Simple response
23+
response = await llm.simple_response("Hello, how are you?")
24+
print(response.text)
25+
```
26+
27+
## Configuration
28+
29+
The plugin uses boto3 for AWS authentication. You can configure credentials using:
30+
- AWS credentials file (~/.aws/credentials)
31+
- Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
32+
- IAM roles (when running on AWS services)
33+
34+
## Supported Models
35+
36+
All AWS Bedrock models are supported, including:
37+
- Claude 3.5 models (anthropic.claude-*)
38+
- Amazon Titan models (amazon.titan-*)
39+
- Meta Llama models (meta.llama-*)
40+
- And more
41+
42+
See [AWS Bedrock documentation](https://docs.aws.amazon.com/bedrock/) for available models.
43+

plugins/bedrock/py.typed

Whitespace-only changes.

plugins/bedrock/pyproject.toml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[build-system]
2+
requires = ["hatchling", "hatch-vcs"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "vision-agents-plugins-bedrock"
7+
dynamic = ["version"]
8+
description = "AWS Bedrock LLM integration for Vision Agents"
9+
readme = "README.md"
10+
keywords = ["bedrock", "aws", "LLM", "AI", "voice agents", "agents"]
11+
requires-python = ">=3.10"
12+
license = "MIT"
13+
dependencies = [
14+
"vision-agents",
15+
"boto3>=1.28.0",
16+
]
17+
18+
[project.urls]
19+
Documentation = "https://visionagents.ai/"
20+
Website = "https://visionagents.ai/"
21+
Source = "https://github.com/GetStream/Vision-Agents"
22+
23+
[tool.hatch.version]
24+
source = "vcs"
25+
raw-options = { root = "..", search_parent_directories = true, fallback_version = "0.0.0" }
26+
27+
[tool.hatch.build.targets.wheel]
28+
packages = ["."]
29+
30+
[tool.hatch.build.targets.sdist]
31+
include = ["/vision_agents"]
32+
33+
[tool.uv.sources]
34+
vision-agents = { workspace = true }
35+
36+
[dependency-groups]
37+
dev = [
38+
"pytest>=8.4.1",
39+
"pytest-asyncio>=1.0.0",
40+
]
41+

plugins/bedrock/tests/__init__.py

Whitespace-only changes.
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"""Tests for AWS Bedrock plugin."""
2+
import pytest
3+
from dotenv import load_dotenv
4+
5+
from plugins.bedrock.vision_agents.plugins.bedrock.bedrock_llm import BedrockLLM
6+
from vision_agents.core.agents.conversation import InMemoryConversation
7+
from vision_agents.core.agents.conversation import Message
8+
from vision_agents.core.llm.events import LLMResponseChunkEvent
9+
10+
load_dotenv()
11+
12+
13+
class TestBedrockLLM:
14+
"""Test suite for BedrockLLM class with real API calls."""
15+
16+
@pytest.fixture
17+
async def llm(self) -> BedrockLLM:
18+
"""Test BedrockLLM initialization with a provided client."""
19+
llm = BedrockLLM(
20+
model="anthropic.claude-3-5-sonnet-20241022-v2:0",
21+
region_name="us-east-1"
22+
)
23+
llm._conversation = InMemoryConversation("be friendly", [])
24+
return llm
25+
26+
@pytest.mark.asyncio
27+
async def test_message(self, llm: BedrockLLM):
28+
messages = BedrockLLM._normalize_message("say hi")
29+
assert isinstance(messages[0], Message)
30+
message = messages[0]
31+
assert message.original is not None
32+
assert message.content == "say hi"
33+
34+
@pytest.mark.asyncio
35+
async def test_advanced_message(self, llm: BedrockLLM):
36+
advanced = {
37+
"role": "user",
38+
"content": [{"text": "Explain quantum entanglement in simple terms."}],
39+
}
40+
messages2 = BedrockLLM._normalize_message(advanced)
41+
assert messages2[0].original is not None
42+
43+
@pytest.mark.integration
44+
async def test_simple(self, llm: BedrockLLM):
45+
response = await llm.simple_response(
46+
"Explain quantum computing in 1 paragraph",
47+
)
48+
assert response.text
49+
50+
@pytest.mark.integration
51+
async def test_native_api(self, llm: BedrockLLM):
52+
response = await llm.converse(
53+
messages=[{"role": "user", "content": [{"text": "say hi"}]}],
54+
)
55+
56+
# Assertions
57+
assert response.text
58+
59+
@pytest.mark.integration
60+
async def test_stream(self, llm: BedrockLLM):
61+
streamingWorks = False
62+
63+
@llm.events.subscribe
64+
async def passed(event: LLMResponseChunkEvent):
65+
nonlocal streamingWorks
66+
streamingWorks = True
67+
68+
await llm.converse_stream(
69+
messages=[{"role": "user", "content": [{"text": "Explain magma to a 5 year old"}]}]
70+
)
71+
# Wait for all events in queue to be processed
72+
await llm.events.wait()
73+
74+
assert streamingWorks
75+
76+
@pytest.mark.integration
77+
async def test_memory(self, llm: BedrockLLM):
78+
await llm.simple_response(
79+
text="There are 2 dogs in the room",
80+
)
81+
response = await llm.simple_response(
82+
text="How many paws are there in the room?",
83+
)
84+
85+
assert "8" in response.text or "eight" in response.text
86+
87+
@pytest.mark.integration
88+
async def test_native_memory(self, llm: BedrockLLM):
89+
await llm.converse(
90+
messages=[{"role": "user", "content": [{"text": "There are 2 dogs in the room"}]}],
91+
)
92+
response = await llm.converse(
93+
messages=[
94+
{"role": "user", "content": [{"text": "How many paws are there in the room?"}]}
95+
],
96+
)
97+
assert "8" in response.text or "eight" in response.text
98+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Namespace package
2+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .bedrock_llm import BedrockLLM as LLM
2+
3+
__all__ = ["LLM"]
4+

0 commit comments

Comments
 (0)