functions = [
{
"type": "function",
"function": {
"name": "call_rest_api",
"description": "Sends a request to the REST API",
"parameters": {
"type": "object",
"properties": {
"method": {
"type": "string",
"description": "The HTTP method to be used",
"enum": ["GET", "POST", "PUT", "DELETE"],
},
"url": {
"type": "string",
"description": "The URL of the endpoint. Value placeholders must be replaced with actual values.",
},
"body": {
"type": "string",
"description": "A string representation of the JSON that should be sent as the request body.",
},
},
"required": ["method", "url"],
},
}
}
]
available_apis = [
{'method': 'GET', 'url': '/api/users?page=[page_id]', 'description': 'Lists employees. The response is paginated. You may need to request more than one to get them all. For example,/api/users?page=2.'},
{'method': 'GET', 'url': '/api/users/[user_id]', 'description': 'Returns information about the employee identified by the given id. For example,/api/users/2'},
{'method': 'POST', 'url': '/api/users', 'description': 'Creates a new employee profile. This function accepts JSON body containing two fields: name and job'},
{'method': 'PUT', 'url': '/api/users/[user_id]', 'description': 'Updates employee information. This function accepts JSON body containing two fields: name and job. The user_id in the URL must be a valid identifier of an existing employee.'},
{'method': 'DELETE', 'url': '/api/users/[user_id]', 'description': 'Removes the employee identified by the given id. Before you call this function, find the employee information and make sure the id is correct. Do NOT call this function if you didn\'t retrieve user info. Iterate over all pages until you find it or make sure it doesn\'t exist'}
]
接着需要定义AI的任务和可用的功能。为此,准备以下系统提示词。
12345678
messages = [
{"role": "system",
"content": "You are an HR helper who makes API calls on behalf of an HR representative,You have access to the following APIs: "
+ json.dumps(self.available_apis)
+ "If a function requires an identifier, list all employees first to find the proper value. You may need to list more than one page"
+ "If you were asked to create, update, or delete a user, perform the action and reply with a confirmation telling what you have done"
}
]
def call_ai(self, new_message):
if new_message:
self.messages.append({"role": "user", "content": new_message})
response = self.client.chat.completions.create(
model="gpt-3.5-turbo-1106",
messages=self.messages,
tools=self.functions,
tool_choice="auto",
)
msg = response.choices[0].message
self.messages.append(msg)
if msg.content:
logging.debug(msg.content)
if tool_calls:
msg.content = "" # required due to a bug in the SDK. We cannot send a message with None content
for tool_call in tool_calls:
# we may get a request to call more than one function(!)
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
if function_name == 'call_rest_api':
# ['function_call']['arguments'] contains the arguments of the function
logging.debug(function_args)
# Here, we call the requested function and get a response as a string
function_response = self.call_rest_api(function_args)
logging.debug(function_response)
# We add the response to messages
self.messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": function_response
})
self.call_ai(new_message=None) # pass the function response back to AI
else:
# return the final response
return msg
To use a tool, please use the following format:
Thought: Do I need to use a tool? Yes
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:
Thought: Do I need to use a tool? No
{ai_prefix}: [your response here]
## https://github.com/langchain-ai/langchain/blob/9731ce5a406d5a7bb1878a54b265a6f7c728effc/libs/langchain/langchain/agents/conversational/prompt.py
import json
import requests
from langchain import OpenAI
from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
def call_rest_api(method_and_url):
method, url = method_and_url.split(' ')
url = 'https://reqres.in' + url
response = None
if method == 'GET':
response = requests.get(url)
elif method == 'DELETE':
response = requests.delete(url)
else:
raise ValueError(method)
if response.status_code == 200:
return response.json()
else:
return f"Status code: {response.status_code}"
available_apis = [
{'api ': 'GET /api/users?page=[page_id]', 'description': 'Lists employees. The response is paginated. You may need to request more than one to get them all. For example,/api/users?page=2.'},
{'api': 'DELETE /api/users/[numeric user_id]', 'description': 'Removes the employee identified by the given id. Before you call this function, find the employee information and make sure the id is correct. Do NOT call this function if you didn\'t retrieve user info. Iterate over all pages until you find it or make sure it doesn\'t exist'}
]
api_description = json.dumps(available_apis)
function_description = f"""Sends a request to the REST API.
Accepts a single parameter containing two parts:
* method - The HTTP method to be used (GET, POST, PUT, or DELETE)
* url - The URL of the endpoint. Value placeholders must be replaced with actual values.
For example: GET /api/users?page=1 or DELETE /api/users/13
To find users by name, use the GET method first.
Available endpoints:
{api_description}"""
llm = ChatOpenAI(temperature=0, model="gpt-4", openai_api_key='sk-...')
tools = [
Tool(
name = "REST",
func=call_rest_api,
description=function_description
)
]
agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS, verbose=True)
agent.run("Fire Lawson")
在控制台中,可以看到Agent的详细日志:
12345678910
Invoking: `REST` with `GET /api/users?page=1`
{'page': 1, 'per_page': 6, 'total': 12, 'total_pages': 2, 'data': [...
Invoking: `REST` with `GET /api/users?page=2`
{'page': 2, 'per_page': 6, 'total': 12, 'total_pages': 2, 'data': [{'id': 7, 'email': 'michael.lawson@reqres.in', 'first_name': 'Michael', 'last_name': 'Lawson', 'avatar': 'https://reqres.in/img/faces/7-image.jpg'}, ...
Invoking: `REST` with `DELETE /api/users/7`
Status code: 204
User Lawson has been successfully removed from the system.