PlanOpticon

planopticon / video_processor / providers / bedrock_provider.py
Blame History Raw 194 lines
1
"""AWS Bedrock provider implementation."""
2
3
import base64
4
import json
5
import logging
6
import os
7
from pathlib import Path
8
from typing import Optional
9
10
from dotenv import load_dotenv
11
12
from video_processor.providers.base import BaseProvider, ModelInfo, ProviderRegistry
13
14
load_dotenv()
15
logger = logging.getLogger(__name__)
16
17
# Curated list of popular Bedrock models
18
_BEDROCK_MODELS = [
19
ModelInfo(
20
id="anthropic.claude-3-5-sonnet-20241022-v2:0",
21
provider="bedrock",
22
display_name="Claude 3.5 Sonnet v2",
23
capabilities=["chat", "vision"],
24
),
25
ModelInfo(
26
id="anthropic.claude-3-sonnet-20240229-v1:0",
27
provider="bedrock",
28
display_name="Claude 3 Sonnet",
29
capabilities=["chat", "vision"],
30
),
31
ModelInfo(
32
id="anthropic.claude-3-haiku-20240307-v1:0",
33
provider="bedrock",
34
display_name="Claude 3 Haiku",
35
capabilities=["chat", "vision"],
36
),
37
ModelInfo(
38
id="amazon.titan-text-express-v1",
39
provider="bedrock",
40
display_name="Amazon Titan Text Express",
41
capabilities=["chat"],
42
),
43
ModelInfo(
44
id="meta.llama3-70b-instruct-v1:0",
45
provider="bedrock",
46
display_name="Llama 3 70B Instruct",
47
capabilities=["chat"],
48
),
49
ModelInfo(
50
id="mistral.mistral-large-2402-v1:0",
51
provider="bedrock",
52
display_name="Mistral Large",
53
capabilities=["chat"],
54
),
55
]
56
57
58
class BedrockProvider(BaseProvider):
59
"""AWS Bedrock provider using boto3."""
60
61
provider_name = "bedrock"
62
63
def __init__(
64
self,
65
aws_access_key_id: Optional[str] = None,
66
aws_secret_access_key: Optional[str] = None,
67
region_name: Optional[str] = None,
68
):
69
try:
70
import boto3
71
except ImportError:
72
raise ImportError("boto3 package not installed. Install with: pip install boto3")
73
74
self._boto3 = boto3
75
self._region = region_name or os.getenv("AWS_DEFAULT_REGION", "us-east-1")
76
self._client = boto3.client(
77
"bedrock-runtime",
78
aws_access_key_id=aws_access_key_id or os.getenv("AWS_ACCESS_KEY_ID"),
79
aws_secret_access_key=aws_secret_access_key or os.getenv("AWS_SECRET_ACCESS_KEY"),
80
region_name=self._region,
81
)
82
self._last_usage = {}
83
84
def chat(
85
self,
86
messages: list[dict],
87
max_tokens: int = 4096,
88
temperature: float = 0.7,
89
model: Optional[str] = None,
90
) -> str:
91
model = model or "anthropic.claude-3-sonnet-20240229-v1:0"
92
# Strip bedrock/ prefix if present
93
if model.startswith("bedrock/"):
94
model = model[len("bedrock/") :]
95
96
body = json.dumps(
97
{
98
"anthropic_version": "bedrock-2023-05-31",
99
"max_tokens": max_tokens,
100
"temperature": temperature,
101
"messages": messages,
102
}
103
)
104
105
response = self._client.invoke_model(
106
modelId=model,
107
contentType="application/json",
108
accept="application/json",
109
body=body,
110
)
111
112
result = json.loads(response["body"].read())
113
self._last_usage = {
114
"input_tokens": result.get("usage", {}).get("input_tokens", 0),
115
"output_tokens": result.get("usage", {}).get("output_tokens", 0),
116
}
117
return result.get("content", [{}])[0].get("text", "")
118
119
def analyze_image(
120
self,
121
image_bytes: bytes,
122
prompt: str,
123
max_tokens: int = 4096,
124
model: Optional[str] = None,
125
) -> str:
126
model = model or "anthropic.claude-3-sonnet-20240229-v1:0"
127
if model.startswith("bedrock/"):
128
model = model[len("bedrock/") :]
129
130
b64 = base64.b64encode(image_bytes).decode()
131
body = json.dumps(
132
{
133
"anthropic_version": "bedrock-2023-05-31",
134
"max_tokens": max_tokens,
135
"messages": [
136
{
137
"role": "user",
138
"content": [
139
{
140
"type": "image",
141
"source": {
142
"type": "base64",
143
"media_type": "image/jpeg",
144
"data": b64,
145
},
146
},
147
{"type": "text", "text": prompt},
148
],
149
}
150
],
151
}
152
)
153
154
response = self._client.invoke_model(
155
modelId=model,
156
contentType="application/json",
157
accept="application/json",
158
body=body,
159
)
160
161
result = json.loads(response["body"].read())
162
self._last_usage = {
163
"input_tokens": result.get("usage", {}).get("input_tokens", 0),
164
"output_tokens": result.get("usage", {}).get("output_tokens", 0),
165
}
166
return result.get("content", [{}])[0].get("text", "")
167
168
def transcribe_audio(
169
self,
170
audio_path: str | Path,
171
language: Optional[str] = None,
172
model: Optional[str] = None,
173
) -> dict:
174
raise NotImplementedError(
175
"AWS Bedrock does not support audio transcription directly. "
176
"Use Amazon Transcribe or another provider for transcription."
177
)
178
179
def list_models(self) -> list[ModelInfo]:
180
return list(_BEDROCK_MODELS)
181
182
183
ProviderRegistry.register(
184
name="bedrock",
185
provider_class=BedrockProvider,
186
env_var="AWS_ACCESS_KEY_ID",
187
model_prefixes=["bedrock/"],
188
default_models={
189
"chat": "anthropic.claude-3-sonnet-20240229-v1:0",
190
"vision": "anthropic.claude-3-sonnet-20240229-v1:0",
191
"audio": "",
192
},
193
)
194

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button