Class: LlmGateway::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/llm_gateway/client.rb

Class Method Summary collapse

Class Method Details

.build_client(provider, api_key:, model: "none") ⇒ Object



85
86
87
88
89
90
# File 'lib/llm_gateway/client.rb', line 85

def self.build_client(provider, api_key:, model: "none")
  config = get_provider_config(provider)
  client_options = { model_key: model }
  client_options[:api_key] = api_key if api_key
  config[:client].new(**client_options)
end

.chat(model, message, response_format: "text", tools: nil, system: nil, api_key: nil) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/llm_gateway/client.rb', line 38

def self.chat(model, message, response_format: "text", tools: nil, system: nil, api_key: nil)
  provider = provider_from_model(model)
  config = get_provider_config(provider)
  client_options = { model_key: model }
  client_options[:api_key] = api_key if api_key
  client = config[:client].new(**client_options)

  input_mapper = input_mapper_for_client(client)
  normalized_input = input_mapper.map({
    messages: normalize_messages(message),
    response_format: normalize_response_format(response_format),
    tools: tools,
    system: normalize_system(system)
  })
  result = client.chat(
    normalized_input[:messages],
    response_format: normalized_input[:response_format],
    tools: normalized_input[:tools],
    system: normalized_input[:system]
  )
  result_mapper(client).map(result)
end

.download_file(provider, **kwargs) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/llm_gateway/client.rb', line 100

def self.download_file(provider, **kwargs)
  api_key = kwargs.delete(:api_key)
  client = build_client(provider, api_key: api_key)
  result = client.download_file(*kwargs.values)
  config = get_provider_config(provider)
  config[:file_output_mapper].map(result)
end

.get_provider_config(provider_id) ⇒ Object



34
35
36
# File 'lib/llm_gateway/client.rb', line 34

def self.get_provider_config(provider_id)
  provider_configs[provider_id.to_sym] || raise(LlmGateway::Errors::UnsupportedProvider, provider_id)
end

.get_provider_config_by_client(client) ⇒ Object



142
143
144
145
# File 'lib/llm_gateway/client.rb', line 142

def self.get_provider_config_by_client(client)
  provider_id = provider_id_from_client(client)
  get_provider_config(provider_id)
end

.input_mapper_for_client(client) ⇒ Object



119
120
121
122
# File 'lib/llm_gateway/client.rb', line 119

def self.input_mapper_for_client(client)
  config = get_provider_config_by_client(client)
  config[:input_mapper]
end

.normalize_messages(message) ⇒ Object



159
160
161
162
163
164
165
# File 'lib/llm_gateway/client.rb', line 159

def self.normalize_messages(message)
  if message.is_a?(String)
    [ { 'role': "user", 'content': message } ]
  else
    message
  end
end

.normalize_response_format(response_format) ⇒ Object



167
168
169
170
171
172
173
# File 'lib/llm_gateway/client.rb', line 167

def self.normalize_response_format(response_format)
  if response_format.is_a?(String)
    { type: response_format }
  else
    response_format
  end
end

.normalize_system(system) ⇒ Object



147
148
149
150
151
152
153
154
155
156
157
# File 'lib/llm_gateway/client.rb', line 147

def self.normalize_system(system)
  if system.nil?
    []
  elsif system.is_a?(String)
    [ { role: "system", content: system } ]
  elsif system.is_a?(Array)
    system
  else
    raise ArgumentError, "System parameter must be a string or array, got #{system.class}"
  end
end

.provider_configsObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/llm_gateway/client.rb', line 5

def self.provider_configs
  @provider_configs ||= {
    anthropic: {
      input_mapper: LlmGateway::Adapters::Claude::InputMapper,
      output_mapper: LlmGateway::Adapters::Claude::OutputMapper,
      client: LlmGateway::Adapters::Claude::Client,
      file_output_mapper: LlmGateway::Adapters::Claude::FileOutputMapper
    },
    openai: {
      input_mapper: LlmGateway::Adapters::OpenAi::ChatCompletions::InputMapper,
      output_mapper: LlmGateway::Adapters::OpenAi::ChatCompletions::OutputMapper,
      client: LlmGateway::Adapters::OpenAi::Client,
      file_output_mapper: LlmGateway::Adapters::OpenAi::FileOutputMapper
    },
    openai_responses: {
      input_mapper: LlmGateway::Adapters::OpenAi::Responses::InputMapper,
      output_mapper: LlmGateway::Adapters::OpenAi::Responses::OutputMapper,
      client: LlmGateway::Adapters::OpenAi::Client,
      file_output_mapper: LlmGateway::Adapters::OpenAi::FileOutputMapper
    },
    groq: {
      input_mapper: LlmGateway::Adapters::Groq::InputMapper,
      output_mapper: LlmGateway::Adapters::Groq::OutputMapper,
      client: LlmGateway::Adapters::Groq::Client,
      file_output_mapper: nil
    }
  }.freeze
end

.provider_from_model(model) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/llm_gateway/client.rb', line 108

def self.provider_from_model(model)
  return "anthropic" if model.start_with?("claude")
  return "groq" if model.start_with?("llama")
  return "openai" if model.start_with?("gpt") ||
                     model.start_with?("o4-") ||
                     model.start_with?("openai")

  raise LlmGateway::Errors::UnsupportedModel, model
end

.provider_id_from_client(client) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/llm_gateway/client.rb', line 129

def self.provider_id_from_client(client)
  case client
  when LlmGateway::Adapters::Claude::Client
    "anthropic"
  when LlmGateway::Adapters::OpenAi::Client
    "openai"
  when LlmGateway::Adapters::Groq::Client
    "groq"
  else
    raise LlmGateway::Errors::UnsupportedProvider, client.class.name
  end
end

.responses(model, message, response_format: "text", tools: nil, system: nil, api_key: nil) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/llm_gateway/client.rb', line 62

def self.responses(model, message, response_format: "text", tools: nil, system: nil, api_key: nil)
  provider = provider_from_model(model)
  config = provider == "openai" ? get_provider_config("openai_responses") : get_provider_config(provider)
  client_options = { model_key: model }
  client_options[:api_key] = api_key if api_key
  client = config[:client].new(**client_options)
  input_mapper = config[:input_mapper]
  normalized_input = input_mapper.map({
    messages: normalize_messages(message),
    response_format: normalize_response_format(response_format),
    tools: tools,
    system: normalize_system(system)
  })
  method = provider == "openai" ? "responses" : "chat"
  result = client.send(method,
    normalized_input[:messages],
    response_format: normalized_input[:response_format],
    tools: normalized_input[:tools],
    system: normalized_input[:system]
  )
  config[:output_mapper].map(result)
end

.result_mapper(client) ⇒ Object



124
125
126
127
# File 'lib/llm_gateway/client.rb', line 124

def self.result_mapper(client)
  config = get_provider_config_by_client(client)
  config[:output_mapper]
end

.upload_file(provider, **kwargs) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/llm_gateway/client.rb', line 92

def self.upload_file(provider, **kwargs)
  api_key = kwargs.delete(:api_key)
  client = build_client(provider, api_key: api_key)
  result = client.upload_file(*kwargs.values)
  config = get_provider_config(provider)
  config[:file_output_mapper].map(result)
end