Skip to content

Commit 27364f5

Browse files
committed
Update botocore.py sink to add support for InvokeModel
1 parent e654f6c commit 27364f5

2 files changed

Lines changed: 38 additions & 42 deletions

File tree

aikido_zen/sinks/botocore.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@
44
from aikido_zen.sinks import after, on_import, patch_function, before
55

66

7+
def get_tokens_from_converse(api_response):
8+
usage = api_response.get("usage", {})
9+
input_tokens = usage.get("inputTokens", 0)
10+
output_tokens = usage.get("outputTokens", 0)
11+
return int(input_tokens), int(output_tokens)
12+
13+
14+
def get_tokens_from_invoke_model(api_response):
15+
headers = api_response.get("ResponseMetadata", {}).get("HTTPHeaders", {})
16+
input_tokens_str = headers.get("x-amzn-bedrock-input-token-count", "0")
17+
output_tokens_str = headers.get("x-amzn-bedrock-output-token-count", "0")
18+
return int(input_tokens_str), int(output_tokens_str)
19+
20+
721
@after
822
def make_api_call_after(func, instance, args, kwargs, return_value):
923
# Extract arguments to validate later
@@ -21,13 +35,13 @@ def make_api_call_after(func, instance, args, kwargs, return_value):
2135
if not model_id:
2236
return None
2337

24-
usage = return_value.get("usage", {})
25-
on_ai_call(
26-
provider="bedrock",
27-
model=model_id,
28-
input_tokens=usage.get("inputTokens", 0),
29-
output_tokens=usage.get("outputTokens", 0),
30-
)
38+
input_tokens, output_tokens = (0, 0)
39+
if operation_name == "Converse":
40+
input_tokens, output_tokens = get_tokens_from_converse(return_value)
41+
elif operation_name == "InvokeModel":
42+
input_tokens, output_tokens = get_tokens_from_invoke_model(return_value)
43+
44+
on_ai_call("bedrock", model_id, input_tokens, output_tokens)
3145

3246

3347
@on_import("botocore.client")

aikido_zen/sinks/tests/aws_bedrock_test.py

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def setup():
2121

2222
@pytest.fixture
2323
def client():
24-
client = boto3.client(service_name="bedrock-runtime", region_name="eu-west-1")
24+
client = boto3.client(service_name="bedrock-runtime", region_name="us-east-1")
2525
return client
2626

2727

@@ -48,51 +48,33 @@ def test_boto3_converse(client):
4848
)
4949
output = response["output"]["message"]["content"][0]["text"]
5050

51-
assert get_ai_stats()[0]["model"] == "claude-3-sonnet-20240229"
51+
assert get_ai_stats()[0]["model"] == "anthropic.claude-3-sonnet-20240229-v1:0"
5252
assert get_ai_stats()[0]["calls"] == 1
53-
assert get_ai_stats()[0]["provider"] == "anthropic"
53+
assert get_ai_stats()[0]["provider"] == "bedrock"
5454
assert get_ai_stats()[0]["tokens"]["input"] == 13
5555
assert get_ai_stats()[0]["tokens"]["output"] == 20
5656
assert get_ai_stats()[0]["tokens"]["total"] == 33
5757

5858

5959
@skip_no_api_key
6060
def test_boto3_invoke_model_claude_3_sonnet(client):
61-
model_id = (
62-
"anthropic.claude-3-sonnet-20240229-v1:0" # Example model ID for Amazon Bedrock
63-
)
61+
model_id = "us.anthropic.claude-3-5-sonnet-20241022-v2:0" # Example model ID for Amazon Bedrock
6462
input_payload = {
65-
"inputText": "Hello, how are you?",
66-
"textGenerationConfig": {"maxTokenCount": 100, "temperature": 0.7},
67-
}
68-
response = client.invoke_model(modelId=model_id, body=json.dumps(input_payload))
69-
stats = get_ai_stats()[0]
70-
assert stats["model"] == "llama2-70b-chat"
71-
assert stats["calls"] == 1
72-
assert stats["provider"] == "meta"
73-
assert stats["tokens"]["input"] == 0
74-
assert stats["tokens"]["output"] == 30
75-
76-
77-
@skip_no_api_key
78-
def test_boto3_invoke_model_meta_llama3_8b(client):
79-
metadata = {
80-
"model": "meta.llama3-8b-instruct-v1:0",
81-
"prompt": "Who painted the Mona Lisa?",
63+
"messages": [
64+
{
65+
"role": "user",
66+
"content": [{"type": "text", "text": "Are tomatoes a vegetable?"}],
67+
}
68+
],
8269
"max_tokens": 20,
70+
"anthropic_version": "bedrock-2023-05-31",
8371
}
84-
body = {
85-
"prompt": metadata["prompt"],
86-
"max_gen_len": metadata["max_tokens"],
87-
"temperature": 0.5,
88-
}
89-
response = client.invoke_model(
90-
modelId=metadata["model"],
91-
body=json.dumps(body).encode("utf-8"),
92-
)
72+
response = client.invoke_model(modelId=model_id, body=json.dumps(input_payload))
73+
print(response)
9374
stats = get_ai_stats()[0]
94-
assert stats["model"] == "llama3-8b-instruct"
75+
assert stats["model"] == "us.anthropic.claude-3-5-sonnet-20241022-v2:0"
9576
assert stats["calls"] == 1
96-
assert stats["provider"] == "meta"
97-
assert stats["tokens"]["input"] == 3
77+
assert stats["provider"] == "bedrock"
78+
assert stats["tokens"]["input"] == 14
9879
assert stats["tokens"]["output"] == 20
80+
assert stats["tokens"]["total"] == 34

0 commit comments

Comments
 (0)