Select your cookie preferences

We use essential cookies and similar tools that are necessary to provide our site and services. We use performance cookies to collect anonymous statistics, so we can understand how customers use our site and make improvements. Essential cookies cannot be deactivated, but you can choose “Customize” or “Decline” to decline performance cookies.

If you agree, AWS and approved third parties will also use cookies to provide useful site features, remember your preferences, and display relevant content, including relevant advertising. To accept or decline all non-essential cookies, choose “Accept” or “Decline.” To make more detailed choices, choose “Customize.”

AWS Logo
Menu
Amazon Bedrock: Enhance HR Support with Function Calling & Knowledge Bases

Amazon Bedrock: Enhance HR Support with Function Calling & Knowledge Bases

Leveraging the Amazon Bedrock Converse API Tool use (function calling) to integrate HR tools, employee data, and custom knowledge bases, enabling HR chatbots and applications to deliver personalized, informed support and optimize HR processes.

Nitin Eusebius
Amazon Employee
Published Jul 9, 2024
Last Modified Oct 1, 2024
You can use the Amazon Bedrock API to give a model access to tools that can help it generate responses for messages that you send to the model. For example, you might have an HR chat application that lets employees find out information about their PTO balance, submit PTO requests, or query the knowledge base for HR policies. To answer a request for the PTO balance or to submit a PTO request, the model needs tools that can query the HR system and return the relevant information or perform the necessary actions. Similarly, to provide information about HR policies, the model needs a tool that can search the knowledge base and retrieve the relevant policy details. Tool use with models is also known as Function calling.
Please visit these great introduction by Jason Stehle to Getting started with the Amazon Bedrock Converse API and Intro to Tool Use with the Amazon Bedrock Converse API in previous posts.
This tutorial demonstrates how to use Amazon Bedrock with the Converse API , function calling and knowledge bases for a sample HR use case. The sample code shows how to retrieve information from a knowledge base, submit PTO requests, and query HR policies using a conversational AI model.
Even though this is an HR use case, you can easily extend this to other use cases very easily like customer support etc.
Image not found

Key Concepts

In Amazon Bedrock, models don't directly call tools. Instead, when sending a message to a model, you also provide tool definitions that could help generate a response. If the model needs a tool, it responds with a request to call the tool, including input parameters. You then call the tool (e.g., an API, database, or Lambda function) and continue the conversation by providing the tool's result. Finally, the model generates a response using the tool results you sent.
To use tools with a model, you can use the Converse API (Converse or ConverseStream). While it's possible to use tools with base inference operations (InvokeModel or InvokeModelWithResponseStream), the Converse API is recommended for consistency across all Amazon Bedrock models that support tool use. Refer here for more detailed information
In this HR use case example, the code defines three tools:
  • pto_balance: Retrieves the PTO balance for an employee.
  • submit_pto: Submits a PTO request for an employee.
  • hr_policy: Retrieves information about a specific HR policy using Knowledge Bases for Amazon Bedrock
The model can request these tools when necessary to generate responses to HR-related queries.
Note: This is demo code for illustrative purposes only. Not intended for production use.

Prerequisites

Note : You can install required libraries using pip install
1
pip install boto3 langchain

Code Overview

Import and initialize
1
2
3
4
5
6
7
8
9
10
import logging
import json
import boto3
from botocore.exceptions import ClientError
from datetime import datetime
from botocore.client import Config
from langchain.prompts import PromptTemplate
import json

bedrock_client = boto3.client(service_name='bedrock-runtime')
We will also set up a logger object and configures the logging level to INFO for the current module
1
2
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
Tool Configuration
The tool_config dictionary defines the available tools for the model. Each tool has a name, description, and input schema. In this example, the following tools are defined:
  • pto_balance: Retrieves the PTO balance for an employee.
  • submit_pto: Submits a PTO request for an employee.
  • hr_policy: Retrieves information about a specific HR policy.
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
71
72
73
74
75
76
77
78
79
tool_config = {
"tools": [
{
"toolSpec": {
"name": "pto_balance",
"description": "Get the PTO balance for an employee.",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"employee_id": {
"type": "string",
"description": "The employee ID for which you want to retrieve the PTO balance."
}
},
"required": [
"employee_id"
]
}
}
}
},
{
"toolSpec": {
"name": "submit_pto",
"description": "Submit a PTO request for an employee.",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"employee_id": {
"type": "string",
"description": "The employee ID for which you want to submit a PTO request."
},
"start_date": {
"type": "string",
"description": "The start date of the PTO request in the format YYYY-MM-DD."
},
"end_date": {
"type": "string",
"description": "The end date of the PTO request in the format YYYY-MM-DD."
},
"reason": {
"type": "string",
"description": "The reason for the PTO request."
}
},
"required": [
"employee_id",
"start_date",
"end_date",
"reason"
]
}
}
}
},
{
"toolSpec": {
"name": "hr_policy",
"description": "Get information about a specific HR policy.",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"question": {
"type": "string",
"description": "The HR policy question to query the knowledge base."
}
},
"required": [
"question"
]
}
}
}
}
]
}
The main components of the code are:
  • retrieve(query, kbId, numberOfResults): Retrieves relevant documents from a knowledge base using the provided query.
For more information on how to create your knowledge base using Amazon Bedrock, please refer to the documentation. Here I have used some sample HR policy documents to sync in Amazon S3 data source.
You can also visit our aws samples for knowledge bases to get started with boto3 and its use with knowledge bases for bedrock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def retrieve(query, kbId, numberOfResults=3):
bedrock_config = Config(connect_timeout=120, read_timeout=120, retries={'max_attempts': 0})

bedrock_agent_client = boto3.client("bedrock-agent-runtime",config=bedrock_config)
return bedrock_agent_client.retrieve(
retrievalQuery= {
'text': query
},
knowledgeBaseId=kbId,
retrievalConfiguration= {
'vectorSearchConfiguration': {
'numberOfResults': numberOfResults,
'overrideSearchType': "HYBRID"
}
}
)
  • get_contexts(retrievalResults): Extracts the context from the retrieved documents for further processing. This can be changed based on your requirements.
1
2
3
4
5
6
7
8
9
10
11
def get_contexts(retrievalResults):
contexts = []
#print(retrievalResults)
for retrievedResult in retrievalResults:
text = retrievedResult['content']['text']
# Remove the "Document 1: " prefix if it exists
if text.startswith("Document 1: "):
text = text[len("Document 1: "):]
contexts.append(text)
contexts_string = ', '.join(contexts)
return contexts_string
  • get_pto_balance(employee_id): Retrieves the PTO balance for a given employee ID.
1
2
3
4
5
6
7
8
9
10
def get_pto_balance(employee_id):
"""Returns the PTO balance for the given employee ID."""
pto_balance = 0
if employee_id == "E1234":
pto_balance = 10
elif employee_id == "E5678":
pto_balance = 5
else:
raise ValueError(f"Invalid employee ID: {employee_id}")
return pto_balance
  • submit_pto_request(employee_id, start_date, end_date, reason): Submits a PTO request for an employee.
1
2
3
4
5
6
7
8
9
10
def submit_pto_request(employee_id, start_date, end_date, reason):
"""Submits a PTO request for the given employee ID, start date, end date, and reason."""
pto_balance = get_pto_balance(employee_id)
start_date = datetime.strptime(start_date, "%Y-%m-%d")
end_date = datetime.strptime(end_date, "%Y-%m-%d")
days = (end_date - start_date).days + 1
if days > pto_balance:
raise InsufficientPTOBalanceError(f"Insufficient PTO balance for employee {employee_id}.")
# Simulating PTO request submission
return f"PTO request submitted for employee {employee_id} from {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')} for {reason}."
The InsufficientPTOBalanceError class is a custom exception that is raised when an employee tries to submit a PTO request but doesn't have enough PTO balance to cover the requested time off.
1
2
3
class InsufficientPTOBalanceError(Exception):
"""Raised when an employee doesn't have enough PTO balance."""
pass
  • get_hr_policy(question): Retrieves information about a specific HR policy based on the provided question from Knowledge Bases for Amazon Bedrock and then pass to Amazon Bedrock to generate a response which can be returned as is without further processing.
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
def get_hr_policy(question):
response_retrieve = retrieve(question, "<Your_KnowledgeBase_ID>")["retrievalResults"]
contexts = get_contexts(response_retrieve)
PROMPT_TEMPLATE = """DOCUMENT:
{context}
QUESTION:
{message}
INSTRUCTIONS:
Answer the user's QUESTION using only the DOCUMENT text above.
Keep your answer strictly grounded in the facts provided. Do not refer to the "DOCUMENT," "documents," "provided text," ,"based on.." or any similar phrases in your answer.
If the provided text contains the facts to answer the QUESTION, include all relevant details in your answer.
If the provided text doesn’t contain the facts to answer the QUESTION, respond only with "I don't know" and do not add any further information.
"""

prompt = PromptTemplate(template=PROMPT_TEMPLATE,
input_variables=["context","message"])
prompt_final = prompt.format(context=contexts,
message=question)
body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1000,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt_final
}
]
}
]
})
model_id = 'anthropic.claude-3-sonnet-20240229-v1:0'
accept = 'application/json'
content_type = 'application/json'
response = bedrock_client.invoke_model(body=body, modelId=model_id, accept=accept, contentType=content_type)
response_body = json.loads(response.get('body').read())
response_text = response_body.get('content')[0]['text']
return response_text
  • generate_text(bedrock_client, model_id, tool_config, input_text): Generates text using the Amazon Bedrock model and handles tool use requests.
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
def generate_text(bedrock_client, model_id, tool_config, input_text):
"""Generates text using the supplied Amazon Bedrock model. If necessary,
the function handles tool use requests and sends the result to the model."""

logger.info("Generating text with model %s", model_id)

# Create the initial message from the user input.
messages = [{
"role": "user",
"content": [{"text": input_text}]
}]

response = bedrock_client.converse(
modelId=model_id,
messages=messages,
toolConfig=tool_config
)

output_message = response['output']['message']
messages.append(output_message)
stop_reason = response['stopReason']

if stop_reason == 'tool_use':
# Tool use requested. Call the tool and send the result to the model.
tool_requests = response['output']['message']['content']
print(tool_requests)
for tool_request in tool_requests:
if 'toolUse' in tool_request:
tool = tool_request['toolUse']
logger.info("Requesting tool %s. Request: %s",
tool['name'], tool['toolUseId'])

if tool['name'] == 'pto_balance':
tool_result = {}
try:
pto_balance = get_pto_balance(tool['input']['employee_id'])
tool_result = {
"toolUseId": tool['toolUseId'],
"content": [{"json": {"pto_balance": pto_balance}}]
}
except ValueError as err:
tool_result = {
"toolUseId": tool['toolUseId'],
"content": [{"text": err.args[0]}],
"status": 'error'
}

tool_result_message = {
"role": "user",
"content": [
{
"toolResult": tool_result
}
]
}
messages.append(tool_result_message)

elif tool['name'] == 'submit_pto':
tool_result = {}
try:
pto_request_result = submit_pto_request(
tool['input']['employee_id'],
tool['input']['start_date'],
tool['input']['end_date'],
tool['input']['reason']
)
tool_result = {
"toolUseId": tool['toolUseId'],
"content": [{"text": pto_request_result}]
}
except (ValueError, InsufficientPTOBalanceError) as err:
tool_result = {
"toolUseId": tool['toolUseId'],
"content": [{"text": err.args[0]}],
"status": 'error'
}

tool_result_message = {
"role": "user",
"content": [
{
"toolResult": tool_result
}
]
}
messages.append(tool_result_message)

elif tool['name'] == 'hr_policy':
tool_result = {}
policy = get_hr_policy(input_text)
policy = {
"text": policy
}

print(json.dumps(policy, indent=4))
return

# Send the tool result to the model.
response = bedrock_client.converse(
modelId=model_id,
messages=messages,
toolConfig=tool_config
)
print(response)
output_message = response['output']['message']

# Print the final response from the model.
for content in output_message['content']:
print(json.dumps(content, indent=4))

Handling Tool Requests

The generate_text function sends the user's input to the model using the converse API. If the model responds with a tool use request (stop_reason == 'tool_use'), the function handles the request based on the tool name:
  • For pto_balance, it calls the get_pto_balance function with the provided employee ID and returns the PTO balance.
  • For submit_pto, it calls the submit_pto_request function with the provided employee ID, start date, end date, and reason, and returns the result.
  • For hr_policy, it calls the get_hr_policy function with the user's input and returns the retrieved policy information from the knowledge base.
After handling the tool request, the function sends the tool result back to the model using the converse API, allowing the model to generate a final response.

Usage

Update the example_questions list with your own HR-related questions. Below is a sample set
1
2
3
4
5
6
7
8
9
10
11
12
13
example_questions = [
"What is the PTO balance for employee E5678?",
"Submit a PTO request for employee E1234 from 2023-07-10 to 2023-07-12 for a family vacation.",
"What is the dress code policy?",
"Can you tell me how many PTO days employee E1234 has left?",
"I want to request PTO for employee E5678 starting from 2023-08-01 to 2023-08-05 for a personal trip.",
"What are the standard working hours?",
"I need to know the remaining PTO balance for employee E9012.",
"Employee E9012 needs to take PTO from 2023-09-15 to 2023-09-20 for a medical procedure.",
"What is the overtime policy?",
"What is the policy for vacation",
"What is the policy for work from home?"
]
Run the script :
1
2
3
4
5
6
7
8
9
for question in example_questions:
try:
print(f"Question: {question}")
generate_text(bedrock_client, model_id, tool_config, question)
print("\n")
except ClientError as err:
message = err.response['Error']['Message']
logger.error("A client error occurred: %s", message)
print(f"A client error occurred: {message}")
Output : You can see based on user's input appropriate tools use is called and executed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Question: What is the PTO balance for employee E5678?
INFO:__main__:Generating text with model anthropic.claude-3-sonnet-20240229-v1:0
[{'text': 'To get the PTO balance for an employee, we can use the "pto_balance" tool:'}, {'toolUse': {'toolUseId': 'tooluse_00kL9hLpQOelFoaQjbDSlw', 'name': 'pto_balance', 'input': {'employee_id': 'E5678'}}}]
INFO:__main__:Requesting tool pto_balance. Request: tooluse_00kL9hLpQOelFoaQjbDSlw
{
"text": "The PTO balance for employee E5678 is 5 days."
}

Question: Submit a PTO request for employee E1234 from 2023-07-10 to 2023-07-12 for a family vacation.
INFO:__main__:Generating text with model anthropic.claude-3-sonnet-20240229-v1:0
[{'text': 'Here is how to submit the PTO request using the tool:'}, {'toolUse': {'toolUseId': 'tooluse_ywjLWDjfSISVP91AfBAmag', 'name': 'submit_pto', 'input': {'employee_id': 'E1234', 'start_date': '2023-07-10', 'end_date': '2023-07-12', 'reason': 'family vacation'}}}]
INFO:__main__:Requesting tool submit_pto. Request: tooluse_ywjLWDjfSISVP91AfBAmag
{
"text": "The PTO request has been successfully submitted for the specified dates and reason."
}

Question: What is the dress code policy?
INFO:__main__:Generating text with model anthropic.claude-3-sonnet-20240229-v1:0
[{'text': 'To get information about the dress code policy, we can use the `hr_policy` tool like this:'}, {'toolUse': {'toolUseId': 'tooluse_ZGMnL4HSRfKlZ9S8wbSZoA', 'name': 'hr_policy', 'input': {'question': 'What is the dress code policy?'}}}]
INFO:__main__:Requesting tool hr_policy. Request: tooluse_ZGMnL4HSRfKlZ9S8wbSZoA
Dress Code Policy Purpose: This policy outlines the dress code requirements for employees to maintain a professional appearance and create a positive work environment. It applies to all employees, regardless of their position or department. Policy: 1.1 All employees are expected to dress in a manner appropriate for their job roles and responsibilities. Refer to the Job Descriptions for specific requirements. 1.2 Business casual attire is required for office-based employees, including collared shirts, dress slacks, skirts, and dresses. See the Business Casual Guidelines for more information. 1.3 Employees in customer-facing roles should wear company-provided uniforms or adhere to a more formal dress code. Consult the Uniform Policy for details. 1.4 Clothing with offensive or inappropriate language, graphics, or logos is strictly prohibited. Review the Inappropriate Attire Examples for guidance. 1.5 Supervisors have the authority to determine the appropriateness of an employee's attire and may send employees home to change if necessary. Refer to the Supervisor Responsibilities for more information. Compliance: Failure to comply with this dress code policy may result in disciplinary action, up to and including termination of employment. Progressive disciplinary steps are outlined in the Disciplinary Action Policy., Document 3: Social Media Policy Purpose: This policy provides guidelines for employees' use of social media platforms, both personally and professionally, to protect the company's reputation and confidential information. It applies to all employees, contractors, and temporary workers. Policy: 3.1 Employees are expected to conduct themselves professionally on social media and avoid posting content that may harm the company's reputation. Review the Social Media Best Practices for guidance. 3.2 Confidential company information, including client data, financial information, and intellectual property, should never be shared on social media. Refer to the Confidentiality Agreement for more details. 3.3 Employees should not post disparaging comments about the company, its employees, clients, or competitors. See the Anti-Harassment Policy for more information. 3.4 When posting content related to the company, employees must clearly state that their views are personal and do not necessarily reflect those of the company. Use the Social Media Disclaimer when necessary. 3.5 The company reserves the right to monitor employees' public social media activity and take appropriate action if necessary. Consult the Employee Monitoring Policy for details. Compliance: Violations of this social media policy may lead to disciplinary action, up to and including termination of employment. Employees should exercise good judgment and seek guidance from their supervisors or the HR department if unsure about the appropriateness of their social media activity. Refer to the Social Media FAQs for common questions and answers., Document 2: Vacation Leave Policy Purpose: This policy outlines the guidelines for employees to request and take vacation leave. It ensures fair and consistent application of vacation benefits across the organization. Policy: 2.1 Full-time employees are eligible for paid vacation leave based on their years of service with the company. See the Vacation Accrual Schedule for details. 2.2 Vacation leave accrues at a rate of X days per month, up to a maximum of Y days per year. Refer to the Vacation Accrual Calculator to determine your accrual rate. 2.3 Employees must submit vacation leave requests to their supervisors at least Z weeks in advance for approval. Use the Vacation Request Form to submit your request. 2.4 Vacation leave requests will be approved based on business needs and the order in which they are received. Check the Vacation Scheduling Guidelines for more information. 2.5 Unused vacation leave may be carried over to the next year, up to a maximum of W days. Consult the Vacation Carryover Policy for details. Compliance: Employees are encouraged to use their earned vacation leave to maintain a healthy work-life balance. Managers should work with their teams to ensure adequate coverage during employee vacations. Refer to the Manager's Guide to Vacation Planning for best practices.
{
"text": "All employees are expected to dress in a manner appropriate for their job roles and responsibilities. Business casual attire is required for office-based employees, including collared shirts, dress slacks, skirts, and dresses. Employees in customer-facing roles should wear company-provided uniforms or adhere to a more formal dress code. Clothing with offensive or inappropriate language, graphics, or logos is strictly prohibited. Supervisors have the authority to determine the appropriateness of an employee's attire and may send employees home to change if necessary."
}

Customization

  • Modify the get_pto_balance() and submit_pto_request() functions to integrate with your own HR systems and databases.
  • Update the get_hr_policy() function to retrieve information from your own HR knowledge base.
  • Adjust the tool_config dictionary to add, remove, or modify the available tools based on your specific HR use case.

Conclusion

This tutorial showcased how to use Amazon Bedrock with the Converse API and Knowledge bases for Amazon Bedrock for an HR use case. By leveraging conversational AI, tool use (function calling), and integrating with HR tools and knowledge bases, you can create a powerful system for handling HR-related queries and tasks. The sample code example demonstrates how to configure tools, handle tool requests, and generate responses using the Amazon Bedrock model.
Happy Building !
 

Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.

Comments