Generating JSON with the Amazon Bedrock Converse API
Learn how to return JSON output from large language models using Amazon Bedrock Converse API’s tool use capabilities.
- The calling application passes (A) a tool definition that includes the desired JSON schema and (B) a triggering message to the large language model.
- The model generates a tool use request, including the JSON conforming to the tool definition’s JSON schema.
- The calling application extracts the JSON from the model’s tool use request and processes it.
- Set up the Boto3 AWS SDK and Python: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html
- Select an AWS region that supports the Anthropic Claude 3 Sonnet model. I'm using us-west-2 (Oregon). You can check the documentation for model support by region.
- Configure Amazon Bedrock model access for your account and region. Example here: https://catalog.workshops.aws/building-with-amazon-bedrock/en-US/prerequisites/bedrock-setup
- If you don’t have your own local integrated development environment, you can try AWS Cloud9. Setup instructions here: https://catalog.workshops.aws/building-with-amazon-bedrock/en-US/prerequisites/cloud9-setup
- Large language models are non-deterministic. You should expect different results than those shown in this article.
- If you run this code from your own AWS account, you will be charged for the tokens consumed.
- I generally subscribe to a “Minimum Viable Prompt” philosophy. You may need to write more detailed prompts for your use case.
- Not every model supports all of the capabilities of the Converse API, so it’s important to review the supported model features in the official documentation.
Dear Acme Investments,I am writing to compliment one of your customer service representatives, Shirley Scarry. I recently had the pleasure of speaking with Shirley regarding my account deposit. Shirley was extremely helpful and knowledgeable, and went above and beyond to ensure that all of my questions were answered. Shirley also had Robert Herbford join the call, who franky seemed distracted. My wife Clara had some more detailed questions that Shirley was able to resolve for us.Shirley's professionalism and expertise were greatly appreciated, and I would be happy to recommend Acme Investments to others based on my experience.Sincerely,Carson Bradford
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"summary": "Customer compliments Acme Investments employee Shirley Scarry for her excellent customer service in resolving account deposit questions, but notes Robert Herbford seemed distracted on the call.",
"escalate_complaint": false,
"overall_sentiment": "Positive",
"supporting_business_unit": "Customer Service",
"level_of_concern": 2,
"customer_names": [
"Carson Bradford",
"Clara Bradford"
],
"sentiment_towards_employees": [
{
"employee_name": "Shirley Scarry",
"sentiment": "Positive"
},
{
"employee_name": "Robert Herbford",
"sentiment": "Negative"
}
]
}
- Defining a tool that specifies a JSON Schema for the desired output.
- Directly using the JSON generated by a Converse API tool use request.
1
2
3
4
{
"toolSpec": {
"name": "summarize_email",
"description": "Summarize email content.",
1
2
3
4
"inputSchema": {
"json": {
"type": "object",
"properties": {
1
2
3
4
"summary": {
"type": "string",
"description": "A brief one-line or two-line summary of the email."
},
1
"summary": "Customer compliments Acme Investments employee Shirley Scarry for her excellent customer service in resolving account deposit questions, but notes Robert Herbford seemed distracted on the call.",
1
2
3
4
"escalate_complaint": {
"type": "boolean",
"description": "Indicates if this email is serious enough to be immediately escalated for further review."
},
1
"escalate_complaint": false,
1
2
3
4
5
6
"level_of_concern": {
"type": "integer",
"description": "Rate the level of concern for the above content on a scale from 1-10",
"minimum": 1,
"maximum": 10
},
1
"level_of_concern": 2,
1
2
3
4
5
"overall_sentiment": {
"type": "string",
"description": "The sender's overall sentiment.",
"enum": ["Positive", "Neutral", "Negative"]
},
1
2
3
4
5
"supporting_business_unit": {
"type": "string",
"description": "The internal business unit that this email should be routed to.",
"enum": ["Sales", "Operations", "Customer Service", "Fund Management"]
},
1
2
"overall_sentiment": "Positive",
"supporting_business_unit": "Customer Service",
array
and the items have type string
.1
2
3
4
5
"customer_names": {
"type": "array",
"description": "An array of customer names mentioned in the email.",
"items": { "type": "string" }
},
1
2
3
4
"customer_names": [
"Carson Bradford",
"Clara Bradford"
],
array
and the items have type object
. We then define the properties for the objects in the list (employee_name
and sentiment
).1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"sentiment_towards_employees": {
"type": "array",
"items": {
"type": "object",
"properties": {
"employee_name": {
"type": "string",
"description": "The employee's name."
},
"sentiment": {
"type": "string",
"description": "The sender's sentiment towards the employee.",
"enum": ["Positive", "Neutral", "Negative"]
}
}
}
}
1
2
3
4
5
6
7
8
9
10
"sentiment_towards_employees": [
{
"employee_name": "Shirley Scarry",
"sentiment": "Positive"
},
{
"employee_name": "Robert Herbford",
"sentiment": "Negative"
}
]
1
2
3
4
5
6
7
8
9
"required": [
"summary",
"escalate_complaint",
"overall_sentiment",
"supporting_business_unit",
"level_of_concern",
"customer_names",
"sentiment_towards_employees"
]
required
keyword here: https://json-schema.org/understanding-json-schema/reference/object#requiredbedrock-runtime
service name to make calls to Amazon Bedrock models.1
2
3
4
import boto3, json
session = boto3.Session()
bedrock = session.client(service_name='bedrock-runtime')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
tool_list = [
{
"toolSpec": {
"name": "summarize_email",
"description": "Summarize email content.",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"summary": {
"type": "string",
"description": "A brief one-line or two-line summary of the email."
},
"escalate_complaint": {
"type": "boolean",
"description": "Indicates if this email is serious enough to be immediately escalated for further review."
},
"level_of_concern": {
"type": "integer",
"description": "Rate the level of concern for the above content on a scale from 1-10",
"minimum": 1,
"maximum": 10
},
"overall_sentiment": {
"type": "string",
"description": "The sender's overall sentiment.",
"enum": ["Positive", "Neutral", "Negative"]
},
"supporting_business_unit": {
"type": "string",
"description": "The internal business unit that this email should be routed to.",
"enum": ["Sales", "Operations", "Customer Service", "Fund Management"]
},
"customer_names": {
"type": "array",
"description": "An array of customer names mentioned in the email.",
"items": { "type": "string" }
},
"sentiment_towards_employees": {
"type": "array",
"items": {
"type": "object",
"properties": {
"employee_name": {
"type": "string",
"description": "The employee's name."
},
"sentiment": {
"type": "string",
"description": "The sender's sentiment towards the employee.",
"enum": ["Positive", "Neutral", "Negative"]
}
}
}
}
},
"required": [
"summary",
"escalate_complaint",
"overall_sentiment",
"supporting_business_unit",
"level_of_concern",
"customer_names",
"sentiment_towards_employees"
]
}
}
}
}
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
content = """Dear Acme Investments,
I am writing to compliment one of your customer service representatives, Shirley Scarry. I recently had the pleasure of speaking with Shirley regarding my account deposit. Shirley was extremely helpful and knowledgeable, and went above and beyond to ensure that all of my questions were answered. Shirley also had Robert Herbford join the call, who wasn't quite as helpful. My wife, Clara Bradford, didn't like him at all.
Shirley's professionalism and expertise were greatly appreciated, and I would be happy to recommend Acme Investments to others based on my experience.
Sincerely,
Carson Bradford
"""
message = {
"role": "user",
"content": [
{ "text": f"<content>{content}</content>" },
{ "text": "Please use the summarize_email tool to generate the email summary JSON based on the content within the <content> tags." }
],
}
summarize_email
tool.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
response = bedrock.converse(
modelId="anthropic.claude-3-sonnet-20240229-v1:0",
messages=[message],
inferenceConfig={
"maxTokens": 2000,
"temperature": 0
},
toolConfig={
"tools": tool_list,
"toolChoice": {
"tool": {
"name": "summarize_email"
}
}
}
)
1
2
3
4
5
6
7
8
9
10
11
response_message = response['output']['message']
response_content_blocks = response_message['content']
content_block = next((block for block in response_content_blocks if 'toolUse' in block), None)
tool_use_block = content_block['toolUse']
tool_result_dict = tool_use_block['input']
print(json.dumps(tool_result_dict, indent=4))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"summary": "Customer compliments Acme Investments employee Shirley Scarry for her excellent customer service in resolving account deposit questions, but notes that Robert Herbford seemed distracted during the call.",
"escalate_complaint": false,
"overall_sentiment": "Positive",
"supporting_business_unit": "Customer Service",
"level_of_concern": 2,
"customer_names": [
"Carson Bradford",
"Clara Bradford"
],
"sentiment_towards_employees": [
{
"employee_name": "Shirley Scarry",
"sentiment": "Positive"
},
{
"employee_name": "Robert Herbford",
"sentiment": "Negative"
}
]
}
- Not every model supports every capability of the Converse API, so it’s important to review the supported model features in the official documentation.
- You can find more generative AI hands-on activities at the Building with Amazon Bedrock workshop guide.
Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.