parameter: messages with role 'tool' must be a response to a preceeding message with 'tool_calls' #189
-
Hello, I am having an issue with my code and I can't figure out the problem, I get the function working and everything, you can talk to the AI just fine, this is using chat completions api, by the way. The trouble is, when I have it run the function, it outputs 1 assistant message that's blank, has a finish reason of tool_calls, and then another message is outputted from a tool with the finish reason stop. The issue is, when I message it again, I get an error " parameter: messages with role 'tool' must be a response to a preceeding message with 'tool_calls' " and I don't know what it means. I tried reading the code in the documentation, but I'm new to C# programming so I haven't got any idea of what it means. My code might not be as clear either, but I tried asking chatgpt, tried looking at the sample code, and finally tried reading the documentation code, and I still haven't yet figured it out. Can anyone help me? this is my script: public class ChatManager : MonoBehaviour
{
public ScoreTracker scoreTracker;
public List<Message> messages;
public List<Tool> tools;
private OpenAIClient api;
public ChatHistoryTracker chatHistoryTracker;
/// <summary>
/// Sends a message and receives a response asynchronously.
/// </summary>
/// <param name="content">The content of the message to send.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public new async Task SendMessage(string content)
{
AddMessage(
new Message(
Role.User,
content
)
);
// Define the tools that the assistant is able to use
tools = new List<Tool>{
new Function(
nameof(scoreTracker.AddPoints),
"Grant the user a point",
new JObject
{
["type"] = "object",
["properties"] = new JObject {
["score"] = new JObject {
["type"] = "integer",
["description"] = "The number of points to add"
}
},
["required"] = new JArray { "score" }
})
};
var chatRequest = new ChatRequest(messages, tools: tools, toolChoice: "auto", Model.GPT4);
var response = await api.ChatEndpoint.GetCompletionAsync(chatRequest);
var choice = response.FirstChoice;
var reason = choice.FinishReason;
AddMessage(choice.Message, reason);
}
void AddMessage(Message message, string reason = "stop")
{
messages.Add(new Message(message.Role, message, reason));
Debug.Log($"{message.Role}: {message} | {reason}");
if (!string.IsNullOrEmpty(message))
{
chatHistoryTracker.Append(message.Role.ToString(), message);
}
if (reason != "stop")
{
var toolChoice = message.ToolCalls[0];
var usedTool = toolChoice;
if (toolChoice.Function.Name == "AddPoints")
{
// Deserialize the function arguments
var functionArgs = JsonConvert.DeserializeObject<JObject>(usedTool.Function.Arguments.ToString());
var functionResult = scoreTracker.AddPoints(functionArgs["score"].Value<int>());
AddMessage(
new Message(
Role.Tool,
functionResult,
Role.Tool.ToString()
)
);
}
}
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 9 replies
-
Hi @Lexian-droid thanks for using my package. I see a few problems out the gate. First, remove the I think part of the problem is that your public method is stomping your private one and the code is not executing exactly like you think it is. |
Beta Was this translation helpful? Give feedback.
Found the issue, you have to add the message, but use "usedTool" as the role, like this:
I didn't notice until just now that in the sample code (in the readme.md) there is the tool message that is using usedTool as it's role, and I thought that was invalid, so I changed it to Role.Tool, I did it because the type was OpenAI.Tool, not OpenAI.Role, which until now I didn't know that type of syntax was possible. That was definitely a big mistake on my part, thanks for the help, and I apologize for any time that I may have wasted.