Skip to content

Commit

Permalink
Refactor AsyncSimpleOpenai and SimpleOpenai to streamline tool call h…
Browse files Browse the repository at this point in the history
…andling and improve response management
  • Loading branch information
schleising committed Dec 21, 2024
1 parent acc2cd7 commit 30e4712
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 104 deletions.
17 changes: 0 additions & 17 deletions src/simple_openai/async_simple_openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@ async def get_function_response(
else:
tool_choice = "none"

print(f"\nTool choice: {tool_choice}\n")

# Create the request body
request_body = open_ai_models.ChatRequest(
messages=messages,
Expand Down Expand Up @@ -246,12 +244,6 @@ async def get_chat_response(
response_text
)

print(f"Finish reason 1: {response_body.choices[0].finish_reason}")

print()
print(response_body.model_dump_json(indent=2))
print()

# Set the Tool Call counter to 0
tool_call_counter = 0

Expand Down Expand Up @@ -303,15 +295,6 @@ async def get_chat_response(
False, response_body.error.message
)

print(
f"Finish reason 2: {response_body.choices[0].finish_reason}"
)

print()
print(response_body.model_dump_json(indent=2))
print()


# Create the response
if response_body.choices[0].message.content is not None:
open_ai_response = SimpleOpenaiResponse(
Expand Down
212 changes: 125 additions & 87 deletions src/simple_openai/simple_openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,81 @@ def add_tool(
"""
self._tool_manager.add_tool(tool_definition, function)

def get_function_response(
self,
chat_id: str,
function_name: str,
allow_tool_calls: bool = True,
add_date_time: bool = False,
**kwargs,
) -> open_ai_models.ChatResponse | open_ai_models.ErrorResponse:
"""Get a function response
Args:
chat_id (str): The ID of the chat
function_name (str): The name of the function
allow_tool_calls (bool, optional): Whether to allow tool calls. Defaults to True
add_date_time (bool, optional): Whether to add the date and time to the message. Defaults to False.
Returns:
open_ai_models.ChatResponse | open_ai_models.ErrorResponse: The chat response or error response
"""

# Call the function
new_prompt = self._tool_manager.call_function(
function_name=function_name,
**kwargs,
)

# Add the message to the chat
messages = self._chat.add_message(
open_ai_models.ChatMessage(
role="function", content=new_prompt, name="Botto"
),
chat_id=chat_id,
add_date_time=add_date_time,
).messages

# Set the tool choice to auto if tool calls are allowed
if allow_tool_calls:
tool_choice = "auto"
else:
tool_choice = "none"

# Create the request body
request_body = open_ai_models.ChatRequest(
messages=messages,
tools=self._tool_manager.get_json_tool_list(),
tool_choice=tool_choice,
)

# Send the request
response = requests.post(constants.CHAT_URL, json=request_body.model_dump())

# Check the status code
if response.status_code == requests.codes.OK:
# Get the response content
response_text = response.text

# Parse the response body
response_body = open_ai_models.ChatResponse.model_validate_json(
response_text
)
else:
# Parse the error response body
response_body = open_ai_models.ErrorResponse.model_validate_json(
response.text
)

# Return the response
return response_body

def get_chat_response(
self,
prompt: str,
name: str,
chat_id: str = constants.DEFAULT_CHAT_ID,
max_tool_calls: int = 1,
add_date_time: bool = False,
) -> SimpleOpenaiResponse:
"""Get a chat response from OpenAI
Expand All @@ -122,15 +192,16 @@ def get_chat_response(
Args:
prompt (str): The prompt to use for the chat response
name (str): The name of the person talking to the bot
name (str): The name of the user
chat_id (str, optional): The ID of the chat to continue. Defaults to DEFAULT_CHAT_ID.
add_date_time (bool, optional): Whether to add the date and time to the start of the prompt. Defaults to False.
max_tool_calls (int, optional): The maximum number of tool calls. Defaults to 1.
add_date_time (bool, optional): Whether to add the date and time to the message. Defaults to False.
Returns:
SimpleOpenaiResponse: The chat response, the value of `success` should be checked before using the value of `message`
"""
# Create the request body
"""
# Add the message to the chat
messages = self._chat.add_message(
open_ai_models.ChatMessage(role="user", content=prompt, name=name),
chat_id=chat_id,
Expand All @@ -144,36 +215,35 @@ def get_chat_response(
tool_choice="auto",
)

# Delete the tools from the request body if there are no tool
# Delete the tools from the request body if there are no tools
if request_body.tools is None:
del request_body.tools
del request_body.tool_choice

# Send the request
response1 = requests.post(
constants.FULL_CHAT_URL,
json=request_body.model_dump(),
headers=self._headers,
)
response = requests.post(constants.CHAT_URL, json=request_body.model_dump())

# Check the status code
if response1.status_code == requests.codes.OK:
if response.status_code == requests.codes.OK:
# Get the response content
response_text = response.text

# Parse the response body
response_body = open_ai_models.ChatResponse.model_validate_json(
response1.text
response_text
)

# Check if a function was called
if (
# Set the Tool Call counter to 0
tool_call_counter = 0

# Check if a function was called, and loop until no more functions are called
while (
response_body.choices[0].finish_reason == constants.OPEN_AI_TOOL_CALLS
and response_body.choices[0].message.tool_calls is not None
):
# Call the function
new_prompt = self._tool_manager.call_function(
response_body.choices[0].message.tool_calls[0].function.name,
**json.loads(response_body.choices[0].message.tool_calls[0].function.arguments),
print(
f"Calling {response_body.choices[0].message.tool_calls[0].function.name}"
)

# Add the response to the chat
self._chat.add_message(
open_ai_models.ChatMessage(
Expand All @@ -187,85 +257,53 @@ def get_chat_response(
add_date_time=add_date_time,
)

# Add the message to the chat
messages = self._chat.add_message(
open_ai_models.ChatMessage(
role="function", content=new_prompt, name="Botto"
),
# Increment the tool call counter
tool_call_counter += 1

# Call the function
response_body = self.get_function_response(
chat_id=chat_id,
function_name=response_body.choices[0]
.message.tool_calls[0]
.function.name,
allow_tool_calls=tool_call_counter < max_tool_calls,
add_date_time=add_date_time,
).messages

# Create the request body
request_body = open_ai_models.ChatRequest(
messages=messages,
tools=self._tool_manager.get_json_tool_list(),
tool_choice="none",
**json.loads(
response_body.choices[0]
.message.tool_calls[0]
.function.arguments
),
)

# Send the request
response2 = requests.post(
constants.FULL_CHAT_URL,
json=request_body.model_dump(),
headers=self._headers,
# Check if the response is an error
if isinstance(response_body, open_ai_models.ErrorResponse):
# Return the error response
return SimpleOpenaiResponse(False, response_body.error.message)

# Create the response
if response_body.choices[0].message.content is not None:
open_ai_response = SimpleOpenaiResponse(
True, response_body.choices[0].message.content
)

# Check the status code
if response2.status_code == requests.codes.OK:
# Parse the response body
response_body = open_ai_models.ChatResponse.model_validate_json(
response2.text
)

# Create the response
if response_body.choices[0].message.content is not None:
open_ai_response = SimpleOpenaiResponse(
True, response_body.choices[0].message.content
)
else:
open_ai_response = SimpleOpenaiResponse(True, "No response")

# Add the response to the chat
self._chat.add_message(
open_ai_models.ChatMessage(
role="assistant",
content=open_ai_response.message,
name="Botto",
),
chat_id=chat_id,
add_date_time=add_date_time,
)
else:
# Parse the error response body
response_body = open_ai_models.ErrorResponse.model_validate_json(
response2.text
)

# Create the response
open_ai_response = SimpleOpenaiResponse(
False, response_body.error.message
)
else:
# Create the response
if response_body.choices[0].message.content is not None:
open_ai_response = SimpleOpenaiResponse(
True, response_body.choices[0].message.content
)
else:
open_ai_response = SimpleOpenaiResponse(True, "No response")
open_ai_response = SimpleOpenaiResponse(True, "No response")

# Add the response to the chat
self._chat.add_message(
open_ai_models.ChatMessage(
role="assistant",
content=open_ai_response.message,
name="Botto",
),
chat_id=chat_id,
add_date_time=add_date_time,
)

# Add the response to the chat
self._chat.add_message(
open_ai_models.ChatMessage(
role="assistant", content=open_ai_response.message, name="Botto"
),
chat_id=chat_id,
add_date_time=add_date_time,
)
else:
# Parse the error response body
response_body = open_ai_models.ErrorResponse.model_validate_json(
response1.text
response.text
)

# Create the response
Expand Down

0 comments on commit 30e4712

Please sign in to comment.