Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(readme): Move 'messages << message' outside of loop to prevent duplicatentries #554

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

taro1025
Copy link

@taro1025 taro1025 commented Dec 6, 2024

Issue

When executing the provided code, the following error is encountered:

Error: {"message"=>"An assistant message with 'tool_calls' must be followed by tool messages responding to each 'tool_call_id'. The following tool_call_ids did not have response messages: call_EiPgaP98DOD7sgXMXgVNITDa", "type"=>"invalid_request_error", "param"=>"messages.[3].role", "code"=>nil}

This error occurs because, when handling multiple tool_calls in the message["tool_calls"].each loop, the same message is added to the messages array for every iteration of the loop. This results in duplicate entries for the assistant's message, causing the OpenAI API to fail to correctly process subsequent tool responses.

Reproduction Steps

Ask about the weather in two different locations (e.g., San Francisco and Japan) in the same request. This ensures that the assistant generates multiple tool_calls.

Execute the following Ruby code:

require 'openai'

client = OpenAI::Client.new(access_token: ENV["OPENAI_ACCESS_TOKEN"])

def get_current_weather(location:, unit: "fahrenheit")
  # Here you could use a weather api to fetch the weather.
  "The weather in #{location} is nice 🌞 #{unit}"
end

messages = [
  {
    "role": "user",
    "content": "What is the weather like in San Francisco and Japan?",
  },
]

response =
  client.chat(
    parameters: {
      model: "gpt-4o",
      messages: messages,  # Defined above because we'll use it again
      tools: [
        {
          type: "function",
          function: {
            name: "get_current_weather",
            description: "Get the current weather in a given location",
            parameters: {  # Format: https://json-schema.org/understanding-json-schema
                           type: :object,
                           properties: {
                             location: {
                               type: :string,
                               description: "The city and state, e.g. San Francisco, CA",
                             },
                             unit: {
                               type: "string",
                               enum: %w[celsius fahrenheit],
                             },
                           },
                           required: ["location"],
            },
          },
        }
      ],
      # Optional, defaults to "auto"
      # Can also put "none" or specific functions, see docs
      tool_choice: "required"
    },
    )

message = response.dig("choices", 0, "message")

if message["role"] == "assistant" && message["tool_calls"]
  message["tool_calls"].each do |tool_call|
    tool_call_id = tool_call.dig("id")
    function_name = tool_call.dig("function", "name")
    function_args = JSON.parse(
      tool_call.dig("function", "arguments"),
      { symbolize_names: true },
      )
    function_response =
      case function_name
      when "get_current_weather"
        get_current_weather(**function_args)  # => "The weather is nice 🌞"
      else
        # decide how to handle
      end

    # For a subsequent message with the role "tool", OpenAI requires the preceding message to have a tool_calls argument.
    messages << message

    messages << {
      tool_call_id: tool_call_id,
      role: "tool",
      name: function_name,
      content: function_response
    }  # Extend the conversation with the results of the functions
  end

  second_response = client.chat(
    parameters: {
      model: "gpt-4o",
      messages: messages
    }
  )

  puts second_response.dig("choices", 0, "message", "content")
  if second_response.dig("error")
    puts "Error: #{second_response.dig("error")}"
  end
end

All Submissions:

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?

@taro1025 taro1025 changed the title Fix: Move 'messages << message' outside of loop to prevent duplicatentries docs(readme): Move 'messages << message' outside of loop to prevent duplicatentries Dec 6, 2024
@taro1025
Copy link
Author

@alexrudall
When you have a moment, I’d appreciate it if you could review my PR.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant