Fix role mapping in GPTAssistantAgent for OpenAI API compatibility #3555
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Why are these changes needed?
This change addresses a bug where an openai.BadRequestError occurs when using a GPTAssistantAgent and a ConversableAgent that utilizes a tool call within the same GroupChat. Specifically, when the ConversableAgent performs a tool call, messages with internal role 'tool' are added to the chat history. When the GPTAssistantAgent then tries to generate a response, it sends this conversation history to the OpenAI Assistant API, which returns an error because it only accepts messages with roles 'user', 'assistant', per the error message.
Problem Details:
The primary problem occurs when messages with roles like "tool" or "function" are submitted to the OpenAI Assistant API, which expects roles to be either "user" or "assistant". As I was reviewing the best approach to fix this issue, it was clear that modifying the role directly in _append_oai_message can disrupt the internal message history and cause unit tests to fail. Therefore, the recommended solution is to adjust roles within the GPTAssistantAgent when sending to OpenAI API.
Rationale:
By isolating changes to gpt_assistant_agent.py, we avoid impacting other agents and parts of the codebase.
Also we preserve internal logic, so internal AutoGen message roles remain unchanged, ensuring that any internal processing that depends on roles like "function" or "tool" continues to work correctly.
Agents Involved:
A GPTAssistantAgent.
A ConversableAgent that performs tool calls.
A ConversableAgent as user proxy
Error Message:
openai.BadRequestError: Error code: 400 - {'error': {'message': "Invalid value: 'tool'. Supported values are: 'user' and 'assistant'.", 'type': 'invalid_request_error', 'param': 'role', 'code': 'invalid_value'}}
Solution:
Role Mapping: The fix involves mapping internal message roles to roles accepted by the OpenAI Assistant API before sending messages.
Implementation:
Added a _map_role_for_api method in gpt_assistant_agent.py to map internal roles to valid API roles.
Internal roles such as 'tool' and 'function' are mapped to 'assistant'.
Modified the _invoke_assistant method to apply this mapping when constructing messages for the API call.
Benefits:
Ensures compatibility with the OpenAI API by sending only accepted roles, preventing the BadRequestError from occurring. Allows the GPTAssistantAgent to function correctly within a groupchat that includes ConversableAgents utilizing tool calls.
Software versions:
pyautogen=0.2.35
python=3.12.2
tested with both openai=1.30.1 and openai=1.47.0
tested with gpt-4o and gpt-4o-mini
Logging:
if you add logging to the mre program, you can see the role issue in the log:
logging:
import logging
logging.basicConfig(level=logging.DEBUG)
output before fix: (role='tool')
DEBUG:openai._base_client:Request options: {'method': 'post', 'url': '/threads/thread_hSK0dCkoMCgRTwXDjxQOeV8v/messages', 'headers': {'OpenAI-Beta': 'assistants=v2'}, 'files': None, 'json_data': {'content': "This is a message from the 'print_message' function.", 'role': 'tool'}}
after fix: (role='system')
'role': 'user', 'name': 'Analyst'}, {'content': "Read the above conversation. Then select the next role from ['user_proxy', 'FunctionAgent', 'Analyst'] to play. Only return the role.", 'name': 'checking_agent', 'role': 'system'}], 'model': 'gpt-4o', 'stream': False, 'temperature': 0.0}}
A Minimal Reproducible Example (MRE) was created to demonstrate the issue and verify that the fix works consistently.
MRE Overview:
Creates an openai assistant analyst agent, then plugs in the asssistant id into the gpt assistant in the groupchat.
Set up GroupChat with GPTAssistantAgent and a ConversableAgent that performs a tool call.
The ConversableAgent invokes a tool, adding a message with role 'tool' to the chat history.
When the GPTAssistantAgent attempts to process the chat history, it sends the messages to the OpenAI API.
Without the fix, the API returns a BadRequestError due to unrecognized roles.
With the fix, the internal roles are correctly mapped, and no error occurs.
MRE:
Testing:
All unit tests have been run locally to ensure existing functionality remains unaffected.
Related issue number
Closes #3284
#3284
Checks