Class: GlimRequest

Inherits:
Object
  • Object
show all
Extended by:
GenericParams
Defined in:
lib/glim_request.rb

Constant Summary collapse

GENERIC_PARAMS =
i[temperature top_p max_tokens stop]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from GenericParams

generic_params

Constructor Details

#initialize(**args) ⇒ GlimRequest

the cache key is generated from this.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/glim_request.rb', line 39

def initialize(**args)
  @use_cached_response = true
  @logged_something = false
  args.each do |k, v| 
    if (GENERIC_PARAMS + i[template_name template_text context llm_name ]).include?(k)
      instance_variable_set("@#{k}", v) 
    else
      raise "Unknown parameter #{k}"
    end
    # puts "GlimRequest.initialize: #{args_with_req.inspect}"
  end
  @request_hash = {}
  request_details.llm_class_changed
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object



54
55
56
57
58
59
60
# File 'lib/glim_request.rb', line 54

def method_missing(method_name, *args, &block)
  if request_details.respond_to?(method_name)
    request_details.send(method_name, *args, &block)
  else
    raise "No method #{method_name} in #{request_details.class}."
  end
end

Instance Attribute Details

#contextObject

Returns the value of attribute context.



128
129
130
# File 'lib/glim_request.rb', line 128

def context
  @context
end

#llm_nameObject

Returns the value of attribute llm_name.



33
34
35
# File 'lib/glim_request.rb', line 33

def llm_name
  @llm_name
end

#no_cacheObject

Returns the value of attribute no_cache.



127
128
129
# File 'lib/glim_request.rb', line 127

def no_cache
  @no_cache
end

#promptObject

Returns the value of attribute prompt.



33
34
35
# File 'lib/glim_request.rb', line 33

def prompt
  @prompt
end

#request_hashObject (readonly)

Returns the value of attribute request_hash.



35
36
37
# File 'lib/glim_request.rb', line 35

def request_hash
  @request_hash
end

#template_nameObject

Returns the value of attribute template_name.



126
127
128
# File 'lib/glim_request.rb', line 126

def template_name
  @template_name
end

#template_textObject

Returns the value of attribute template_text.



126
127
128
# File 'lib/glim_request.rb', line 126

def template_text
  @template_text
end

#use_cached_responseObject

Returns the value of attribute use_cached_response.



127
128
129
# File 'lib/glim_request.rb', line 127

def use_cached_response
  @use_cached_response
end

Class Method Details

.aviary_llmsObject



76
77
78
# File 'lib/glim_request.rb', line 76

def self.aviary_llms
  llama2_llms + codellama_llms
end

.codellama_llmsObject



92
93
94
# File 'lib/glim_request.rb', line 92

def self.codellama_llms
  return ["codellama/CodeLlama-34b-Instruct-hf"]
end

.llama2_llms(size = nil) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/glim_request.rb', line 80

def self.llama2_llms(size = nil)
  sizes = [7,13,70]
  if !size
    return sizes.map { |n| "meta-llama/Llama-2-#{n}b-chat-hf" }
  end
  if sizes.include?(size)
    return "meta-llama/Llama-2-#{size}b-chat-hf"
  else
    raise "Unknown llama size #{size}"
  end
end

.openai_llmsObject



70
71
72
73
74
# File 'lib/glim_request.rb', line 70

def self.openai_llms
  %w[
  gpt-4 gpt-4-0613 gpt-4-32k gpt-4-32k-0613 
  gpt-3.5-turbo gpt-3.5-turbo-0613 gpt-3.5-turbo-16k gpt-3.5-turbo-16k-0613]
end

Instance Method Details

#cache_keyObject



222
223
224
225
226
227
228
# File 'lib/glim_request.rb', line 222

def cache_key
  putt :cache, "Computing cache key based on:"
  # putt :cache, JSON.pretty_generate(deep_copy_with_mods(request_hash, 88,88))
  key = Digest::SHA1.hexdigest(request_hash.to_json)
  putt :cache, "Cache key was: #{key}"
  return key
end

#context_lengthObject



204
205
206
# File 'lib/glim_request.rb', line 204

def context_length
  llm_info[:context_length]
end

#cost_per_completion_tokenObject



200
201
202
# File 'lib/glim_request.rb', line 200

def  cost_per_completion_token
  llm_info[:cost_per_completion_token]
end

#cost_per_prompt_tokenObject



196
197
198
# File 'lib/glim_request.rb', line 196

def cost_per_prompt_token
  llm_info[:cost_per_prompt_token]
end

#count_tokens(s) ⇒ Object

def _generic_params

h = {}
for key in GENERIC_PARAMS
  h[key] = instance_variable_get("@#{key}")
end
h

end



188
189
190
# File 'lib/glim_request.rb', line 188

def count_tokens(s)
  response_class._count_tokens(llm_name, s)
end

#details_class_for_llm_nameObject



100
101
102
# File 'lib/glim_request.rb', line 100

def details_class_for_llm_name
  llm_name&.start_with?('claude')  ?  AnthropicRequestDetails : ChatRequestDetails
end

#generic_params_hashObject



62
63
64
65
66
67
68
# File 'lib/glim_request.rb', line 62

def generic_params_hash
  h = {}
  GENERIC_PARAMS.each do |attr_name|
    h[attr_name] = instance_variable_get("@#{attr_name}")
  end
  h
end

#inspectObject



242
243
244
# File 'lib/glim_request.rb', line 242

def inspect
  "#<GlimRequest: prompt_size=#{@prompt ? @prompt.size : 'nil'}, template_name=#{@template_name}>"
end

#llm_infoObject



192
193
194
# File 'lib/glim_request.rb', line 192

def llm_info
  response_class._llm_info(llm_name)
end

#log_base_this_requestObject



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

def log_base_this_request
  @log_base_this_request ||= begin
    timestamp = Time.now.strftime('%a-%H:%M:%S.%3N')
    template_name_sanitized = (template_name || "no_template").gsub(/[^0-9A-Za-z.\-]/, '_')
    subdir = File.join(context.log_base, "#{timestamp}-#{template_name_sanitized}")
    FileUtils.mkdir_p(subdir) unless Dir.exist?(subdir)
    putt :log, "Log path: #{@log_base_this_request}"
    subdir
  end
  @log_base_this_request
end

#max_costObject



217
218
219
220
# File 'lib/glim_request.rb', line 217

def max_cost
  # TODO this doesn't work yet. 
  return cost_per_prompt_token * prompt_token_count + cost_per_completion_token * max_tokens
end

#min_costObject



213
214
215
# File 'lib/glim_request.rb', line 213

def min_cost
  return prompt_token_count * cost_per_prompt_token
end

#process_template(template_name, **template_args) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/glim_request.rb', line 142

def process_template(template_name, **template_args)
  # TODO - think through how to handle paths
  # basedir = File.dirname(File.expand_path($PROGRAM_NAME))

  for c in caller
    calling_file = c.split(':').first
    break unless calling_file && calling_file.include?("/lib")
  end
  dir_path = File.dirname(calling_file)
  template_path = File.join(dir_path, 'templates', "#{template_name}.erb")

  unless File.exist?(template_path)
    raise "Template #{template_name} not found: #{template_path}"
  end

  putt :config, template_path

  #template_path = File.join("#{basedir}","templates","#{template_name}.erb")
  
  template_text = File.read(template_path)
  template = ERB.new(template_text)

  wrapper = Object.new
  wrapper.extend(GlimHelpers) 
  template_args.each do |key, value|
    wrapper.define_singleton_method(key) { value }
  end  
  req_instance = self # this way, we can access it in the define_method below
  wrapper.define_singleton_method(:req) { req_instance } # caution: can't use self directly here, otherwise self == wrapper
  @prompt = template.result(wrapper.instance_eval { binding })
  @template_name = template_name
  @template_text = template_text
  request_details.update_request_hash
  save_log_file("template_text.txt", template_text)
  save_log_file("prompt.txt", prompt)
  return nil
end

#prompt_token_countObject



208
209
210
211
# File 'lib/glim_request.rb', line 208

def prompt_token_count
  # careful; for open_ai, this needs prepare() first and we want to look at messages[]
  count_tokens(prompt)
end

#request_detailsObject



96
97
98
# File 'lib/glim_request.rb', line 96

def request_details
  @request_details ||= details_class_for_llm_name.new(self) #  raise("Set llm_name first!")
end

#responseObject

this will create a response and, unless it’s cached, send off the request to the API



231
232
233
234
# File 'lib/glim_request.rb', line 231

def response
  response = response_class.new(self)
  return response
end

#response_classObject



122
123
124
# File 'lib/glim_request.rb', line 122

def response_class
  @request_details.response_class
end

#save_log_file(section_name, content) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/glim_request.rb', line 247

def save_log_file(section_name, content)
  file_path = File.join(log_base_this_request, section_name)
  putt(:log, "Saving to: #{file_path}")
  File.write(file_path, content)
  
  log_dir = ENV['GLIM_LOG_DIRECTORY']
  if !@logged_something
    @logged_something = true
    last_all_files = File.join(log_dir,"_last","*")
    #puts "deleting #{last_all_files}"
    Dir.glob(last_all_files).each do |file|
      File.delete(file) if File.file?(file)
    end
  end
  last_file = File.join(log_dir,"_last",section_name)
  FileUtils.mkdir_p(File.dirname(last_file)) unless Dir.exist?(File.dirname(last_file))
  File.write(last_file, content)
end

#to_sObject



236
237
238
239
240
# File 'lib/glim_request.rb', line 236

def to_s
  s = "Req to #{llm_name}"
  s += " from #{template_name}" if template_name
  s += request_details.to_s if request_details
end