require 'net/http' require 'uri' require 'json' module BuilderApm module Doctor class OpenAIChatGPT MAX_RETRIES = 3 TIMEOUT_IN_SECONDS = 300 # equivalent to 5 minutes def initialize(api_key, model = "gpt-3.5-turbo") @api_key = api_key @uri = URI.parse("https://api.openai.com/v1/chat/completions") @role = "You are to be my assistant" @model = model @temperature = 0.2 end def role(ai_role = nil) @role = ai_role unless ai_role.nil? @role end def temperature(temp = nil) @temperature = temp unless temp.nil? @temperature end def chat(messages) request = Net::HTTP::Post.new(@uri) request.content_type = "application/json" request["Authorization"] = "Bearer #{@api_key}" request.body = JSON.dump({ "model" => @model, "temperature" => temperature, "messages" => construct_messages(messages) }) req_options = { use_ssl: @uri.scheme == "https", } begin retries ||= 0 response = Net::HTTP.start(@uri.hostname, @uri.port, req_options) do |http| http.read_timeout = TIMEOUT_IN_SECONDS http.request(request) end rescue Net::ReadTimeout => e if retries < MAX_RETRIES retries += 1 retry else raise e end end data = JSON.parse(response.body)["choices"] raise data.dig("error", "message") if data.is_a?(Hash) && data.dig("error", "message") data.dig(0, "message", "content") end private def construct_messages(messages) messages_array = case messages when String [{"role" => "user", "content" => messages}] when Array messages.map { |hash| hash.transform_keys(&:to_s) } else raise ArgumentError, "Unsupported message format" end [{"role" => "system", "content" => role}] + messages_array end end end end