class ActiveGenie::Clients::OpenaiClient

def function_calling(messages, function)

Returns:
  • (Hash, nil) - The parsed JSON object matching the schema, or nil if parsing fails or content is empty.

Parameters:
  • function (Hash) -- A JSON schema definition describing the desired output format.
  • messages (Array) -- A list of messages representing the conversation history.
def function_calling(messages, function)
  payload = {
    messages:,
    tools: [function_to_tool(function)],
    tool_choice: { type: 'function', function: { name: function[:name] } },
    stream: false,
    model:
  }
  retry_with_backoff do
    response = request(payload)
    raise InvalidResponseError, "Invalid response: #{response}" if response.nil? || response.keys.empty?
    ActiveGenie::Logger.call({ code: :function_calling, fine_tune: true, payload:, response: })
    response
  end
end

def function_to_tool(function)

def function_to_tool(function)
  {
    type: 'function',
    function: {
      **function,
      parameters: {
        **function[:parameters],
        additionalProperties: false
      },
      strict: true
    }.compact
  }
end

def headers

def headers
  {
    Authorization: "Bearer #{provider_config.api_key}",
    'Content-Type': 'application/json'
  }.compact
end

def model

def model
  @config.llm.model || provider_config.tier_to_model(@config.llm.model_tier)
end

def provider_config

def provider_config
  @config.providers.openai
end

def request(payload)

def request(payload)
  response = post(url, payload, headers: headers)
  return nil if response.nil?
  ActiveGenie::Logger.call(
    {
      code: :llm_usage,
      input_tokens: response.dig('usage', 'prompt_tokens'),
      output_tokens: response.dig('usage', 'completion_tokens'),
      total_tokens: response.dig('usage', 'total_tokens'),
      model:,
      usage: response['usage']
    }
  )
  parsed_response = JSON.parse(response.dig('choices', 0, 'message', 'tool_calls', 0, 'function', 'arguments'))
  parsed_response['message'] || parsed_response
end

def url

def url
  "#{provider_config.api_url}/chat/completions"
end