Class: OpenAIClient

Inherits:
Object
  • Object
show all
Defined in:
lib/simple-openai-client.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key:, model:, messages: [], functions: [], callbacks: [], version: 'v2') ⇒ OpenAIClient

Returns a new instance of OpenAIClient.



12
13
14
15
16
17
18
19
# File 'lib/simple-openai-client.rb', line 12

def initialize(api_key:, model:, messages: [], functions: [], callbacks: [], version: 'v2')
  self.api_key = api_key
  self.model = model
  self.messages = messages
  self.functions = functions
  self.callbacks = callbacks
  self.version = version
end

Instance Attribute Details

#api_keyObject

Returns the value of attribute api_key.



10
11
12
# File 'lib/simple-openai-client.rb', line 10

def api_key
  @api_key
end

#callbacksObject

Returns the value of attribute callbacks.



10
11
12
# File 'lib/simple-openai-client.rb', line 10

def callbacks
  @callbacks
end

#functionsObject

Returns the value of attribute functions.



10
11
12
# File 'lib/simple-openai-client.rb', line 10

def functions
  @functions
end

#messagesObject

Returns the value of attribute messages.



10
11
12
# File 'lib/simple-openai-client.rb', line 10

def messages
  @messages
end

#modelObject

Returns the value of attribute model.



10
11
12
# File 'lib/simple-openai-client.rb', line 10

def model
  @model
end

#versionObject

Returns the value of attribute version.



10
11
12
# File 'lib/simple-openai-client.rb', line 10

def version
  @version
end

Instance Method Details

#ask(s, context: []) ⇒ Object

Ask something to GPT. Return the response.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/simple-openai-client.rb', line 55

def ask(s, context: [])
    # Use v1 chat completions endpoint (with functions support)
    uri = URI("https://api.openai.com/v1/chat/completions")

    # add contenxt to the history of messages
    self.messages += context

    # add new question asked by the user to the history of messages
    self.messages << { "role" => "user", "content" => s }

    request_body = {
        "model" => self.model, # A known model that supports function calling; update as needed
        "messages" => self.messages
        # To let the model decide if and when to call a function, omit "function_call"
        # If you want the model to call a function explicitly, you can add: "function_call" => "auto"
    }

    request_body["functions"] = self.functions if self.functions.size > 0

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    request = Net::HTTP::Post.new(uri.path, {
        "Content-Type" => "application/json",
        "Authorization" => "Bearer #{self.api_key}",
        "OpenAI-Beta" => "assistants=#{version}"
    })
    request.body = JSON.dump(request_body)

    response = http.request(request)

    if response.is_a?(Net::HTTPSuccess)
        response_json = JSON.parse(response.body)

        # Check if the assistant decided to call a function
        function_call = response_json.dig("choices", 0, "message", "function_call")

        unless function_call
            # add new response from AI to the history of messages
            assistant_reply = response_json.dig("choices", 0, "message", "content")
            self.messages << { "role" => "assistant", "content" => assistant_reply }
            # return the resonse from AI
            return assistant_reply
        else
            function_call_name = function_call["name"]
            function_call_args = JSON.parse(function_call["arguments"]) rescue {}
            
            # Handle the function call
            result = self.callbacks[function_call_name.to_sym].call(function_call_args);

            # Now we send the function result back to the assistant as another message:
            follow_up_uri = URI("https://api.openai.com/v1/chat/completions")
            follow_up_messages = messages.dup
            follow_up_messages << {
                "role" => "function",
                "name" => function_call_name,
                "content" => JSON.dump(result)
            }

            follow_up_request_body = {
                "model" => self.model,
                "messages" => follow_up_messages
            }

            follow_up_http = Net::HTTP.new(follow_up_uri.host, follow_up_uri.port)
            follow_up_http.use_ssl = true

            follow_up_request = Net::HTTP::Post.new(follow_up_uri.path, {
                "Content-Type" => "application/json",
                "Authorization" => "Bearer #{self.api_key}",
                "OpenAI-Beta" => "assistants=#{version}"
            })
            follow_up_request.body = JSON.dump(follow_up_request_body)
            
            follow_up_response = follow_up_http.request(follow_up_request)
            if follow_up_response.is_a?(Net::HTTPSuccess)
                follow_up_response_json = JSON.parse(follow_up_response.body)
                final_reply = follow_up_response_json.dig("choices", 0, "message", "content")
                # add new response from AI to the history of messages
                self.messages << { "role" => "assistant", "content" => final_reply }
                # return the response form the AI.
                return final_reply
            else
                raise "Error after function call: #{follow_up_response.code} - #{follow_up_response.message} - #{follow_up_response.body}"
            end
        end
    else
        raise "Error: #{response.code} - #{response.message} - #{response.body}"
    end
end

#consoleObject

manage copilot from terminal



147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/simple-openai-client.rb', line 147

def console
    puts "Mass-Copilot Console".blue
    puts "Type 'exit' to quit.".blue
    while true
        print "You: ".green
        prompt = gets.chomp
        break if prompt.downcase.strip == 'exit'
        begin
            puts "Mass-Copilot: #{ask(prompt)}".blue
        rescue => e
            puts "Error: #{e.to_console}".red
        end
    end
end

#modelsObject

Return an array with the available models



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/simple-openai-client.rb', line 22

def models
  uri = URI("https://api.openai.com/v1/models")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  
  # Create a GET request instead of POST
  request = Net::HTTP::Get.new(uri.request_uri, {
    "Authorization" => "Bearer #{self.api_key}",
    "Content-Type" => "application/json"
    # Removed "OpenAI-Beta" header as it's typically not required
  })
  
  response = http.request(request)
  
  if response.is_a?(Net::HTTPSuccess)
    parsed_response = JSON.parse(response.body)
    # Extract and return the list of models
    parsed_response['data'].map { |model| model['id'] }
  else
    raise "Error: #{response.code} #{response.message}"
    #puts response.body
    #[]
  end
rescue JSON::ParserError => e
  raise "Failed to parse JSON response: #{e.message}"
  #[]
rescue StandardError => e
  raise "An error occurred: #{e.message}"
  #[]
end