|
import httpx |
|
import json |
|
from datetime import datetime |
|
import hashlib |
|
import hmac |
|
import base64 |
|
import os |
|
|
|
|
|
AWS_ACCESS_KEY = os.environ.get('AWS_ACCESS_KEY') |
|
AWS_SECRET_KEY = os.environ.get('AWS_SECRET_KEY') |
|
REGION = 'us-east-1' |
|
SERVICE = 'bedrock' |
|
ENDPOINT = f'https://bedrock-runtime.{REGION}.amazonaws.com' |
|
|
|
|
|
def sign(key, msg): |
|
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest() |
|
|
|
def getSignatureKey(key, dateStamp, regionName, serviceName): |
|
kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp) |
|
kRegion = sign(kDate, regionName) |
|
kService = sign(kRegion, serviceName) |
|
kSigning = sign(kService, 'aws4_request') |
|
return kSigning |
|
|
|
def create_authorization_header(method, url, payload, headers): |
|
t = datetime.utcnow() |
|
amzdate = t.strftime('%Y%m%dT%H%M%SZ') |
|
datestamp = t.strftime('%Y%m%d') |
|
|
|
canonical_uri = url.split(ENDPOINT)[1] |
|
canonical_querystring = '' |
|
canonical_headers = '\n'.join([f"{h.lower()}:{headers[h]}" for h in sorted(headers)]) + '\n' |
|
signed_headers = ';'.join([h.lower() for h in sorted(headers)]) |
|
payload_hash = hashlib.sha256(payload.encode('utf-8')).hexdigest() |
|
|
|
canonical_request = f"{method}\n{canonical_uri}\n{canonical_querystring}\n{canonical_headers}\n{signed_headers}\n{payload_hash}" |
|
|
|
algorithm = 'AWS4-HMAC-SHA256' |
|
credential_scope = f"{datestamp}/{REGION}/{SERVICE}/aws4_request" |
|
string_to_sign = f"{algorithm}\n{amzdate}\n{credential_scope}\n{hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()}" |
|
|
|
signing_key = getSignatureKey(AWS_SECRET_KEY, datestamp, REGION, SERVICE) |
|
signature = hmac.new(signing_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest() |
|
|
|
authorization_header = ( |
|
f"{algorithm} " |
|
f"Credential={AWS_ACCESS_KEY}/{credential_scope}, " |
|
f"SignedHeaders={signed_headers}, " |
|
f"Signature={signature}" |
|
) |
|
|
|
return authorization_header |
|
|
|
|
|
def invoke_bedrock_model(): |
|
url = f"{ENDPOINT}/model/anthropic.claude-3-sonnet-20240229-v1:0/invoke" |
|
|
|
payload = json.dumps({ |
|
"max_tokens": 256, |
|
"messages": [{"role": "user", "content": "Hello, world"}], |
|
"anthropic_version": "bedrock-2023-05-31" |
|
}) |
|
|
|
t = datetime.utcnow() |
|
amzdate = t.strftime('%Y%m%dT%H%M%SZ') |
|
|
|
headers = { |
|
'Content-Type': 'application/json', |
|
'Accept': 'application/json', |
|
'X-Amz-Date': amzdate, |
|
'Host': f'bedrock-runtime.{REGION}.amazonaws.com' |
|
} |
|
|
|
authorization_header = create_authorization_header('POST', url, payload, headers) |
|
headers['Authorization'] = authorization_header |
|
|
|
with httpx.Client() as client: |
|
response = client.post(url, headers=headers, data=payload) |
|
|
|
if response.status_code == 200: |
|
response_body = response.json() |
|
print(response_body.get("content")) |
|
else: |
|
print(f"Error: {response.status_code}") |
|
print(response.text) |
|
|
|
|
|
invoke_bedrock_model() |