durable-llm 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CLI.md +0 -2
- data/README.md +564 -31
- data/Rakefile +10 -0
- data/devenv.lock +76 -8
- data/devenv.nix +4 -1
- data/devenv.yaml +5 -12
- data/durable-llm.gemspec +16 -8
- data/examples/openai_quick_complete.rb +1 -1
- data/lib/durable/llm/cli.rb +25 -22
- data/lib/durable/llm/client.rb +149 -8
- data/lib/durable/llm/convenience.rb +102 -0
- data/lib/durable/llm/provider_utilities.rb +201 -0
- data/lib/durable/llm/providers/base.rb +146 -19
- data/lib/durable/llm/providers/cohere.rb +19 -0
- data/lib/durable/llm/providers/fireworks.rb +26 -0
- data/lib/durable/llm/providers/google.rb +26 -0
- data/lib/durable/llm/providers/groq.rb +26 -0
- data/lib/durable/llm/providers.rb +10 -0
- data/lib/durable/llm/response_helpers.rb +185 -0
- data/lib/durable/llm/version.rb +1 -1
- data/lib/durable/llm.rb +75 -2
- data/lib/durable.rb +1 -1
- data/sig/durable/llm.rbs +2 -1
- metadata +71 -5
- data/Gemfile.lock +0 -103
|
@@ -83,6 +83,16 @@ module Durable
|
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
+
# Returns a list of all available provider names as strings.
|
|
87
|
+
#
|
|
88
|
+
# Alias for providers that returns strings instead of symbols, useful for
|
|
89
|
+
# display purposes in error messages and documentation.
|
|
90
|
+
#
|
|
91
|
+
# @return [Array<String>] Array of provider names
|
|
92
|
+
def self.available_providers
|
|
93
|
+
providers.map(&:to_s).sort
|
|
94
|
+
end
|
|
95
|
+
|
|
86
96
|
# Returns a flat list of all model IDs across all providers.
|
|
87
97
|
#
|
|
88
98
|
# This method aggregates model IDs from all available providers by calling
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This module provides helper methods for extracting and formatting responses from
|
|
4
|
+
# LLM API calls. It offers convenient methods to work with response objects from
|
|
5
|
+
# different providers, abstracting away the complexity of response structure variations.
|
|
6
|
+
|
|
7
|
+
module Durable
|
|
8
|
+
module Llm
|
|
9
|
+
# Helper methods for working with LLM responses
|
|
10
|
+
#
|
|
11
|
+
# This module provides convenience methods for extracting content, messages,
|
|
12
|
+
# and metadata from LLM response objects. It handles the common patterns of
|
|
13
|
+
# response processing across different providers.
|
|
14
|
+
#
|
|
15
|
+
# @example Using response helpers
|
|
16
|
+
# response = client.chat(messages: [...])
|
|
17
|
+
# content = ResponseHelpers.extract_content(response)
|
|
18
|
+
# tokens = ResponseHelpers.token_usage(response)
|
|
19
|
+
module ResponseHelpers
|
|
20
|
+
module_function
|
|
21
|
+
|
|
22
|
+
# Extracts the text content from a completion response
|
|
23
|
+
#
|
|
24
|
+
# @param response [Object] The API response object
|
|
25
|
+
# @return [String, nil] The extracted content or nil if not found
|
|
26
|
+
# @example Extract content from response
|
|
27
|
+
# response = client.completion(messages: [...])
|
|
28
|
+
# text = ResponseHelpers.extract_content(response)
|
|
29
|
+
# puts text
|
|
30
|
+
def extract_content(response)
|
|
31
|
+
return nil unless response
|
|
32
|
+
return nil unless response.respond_to?(:choices)
|
|
33
|
+
return nil if response.choices.empty?
|
|
34
|
+
|
|
35
|
+
choice = response.choices.first
|
|
36
|
+
return nil unless choice.respond_to?(:message)
|
|
37
|
+
|
|
38
|
+
message = choice.message
|
|
39
|
+
return nil unless message.respond_to?(:content)
|
|
40
|
+
|
|
41
|
+
message.content
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Extracts all choice contents from a response
|
|
45
|
+
#
|
|
46
|
+
# @param response [Object] The API response object
|
|
47
|
+
# @return [Array<String>] Array of content strings from all choices
|
|
48
|
+
# @example Get all alternatives
|
|
49
|
+
# response = client.completion(messages: [...], n: 3)
|
|
50
|
+
# alternatives = ResponseHelpers.all_contents(response)
|
|
51
|
+
def all_contents(response)
|
|
52
|
+
return [] unless response&.respond_to?(:choices)
|
|
53
|
+
|
|
54
|
+
response.choices.map do |choice|
|
|
55
|
+
next unless choice.respond_to?(:message)
|
|
56
|
+
|
|
57
|
+
message = choice.message
|
|
58
|
+
message.content if message.respond_to?(:content)
|
|
59
|
+
end.compact
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Extracts token usage information from a response
|
|
63
|
+
#
|
|
64
|
+
# @param response [Object] The API response object
|
|
65
|
+
# @return [Hash, nil] Hash with :prompt_tokens, :completion_tokens, :total_tokens
|
|
66
|
+
# @example Get token usage
|
|
67
|
+
# response = client.completion(messages: [...])
|
|
68
|
+
# usage = ResponseHelpers.token_usage(response)
|
|
69
|
+
# puts "Used #{usage[:total_tokens]} tokens"
|
|
70
|
+
def token_usage(response)
|
|
71
|
+
return nil unless response&.respond_to?(:usage)
|
|
72
|
+
|
|
73
|
+
usage = response.usage
|
|
74
|
+
return nil unless usage
|
|
75
|
+
|
|
76
|
+
{
|
|
77
|
+
prompt_tokens: usage.prompt_tokens,
|
|
78
|
+
completion_tokens: usage.completion_tokens,
|
|
79
|
+
total_tokens: usage.total_tokens
|
|
80
|
+
}
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Extracts the finish reason from a response
|
|
84
|
+
#
|
|
85
|
+
# @param response [Object] The API response object
|
|
86
|
+
# @return [String, nil] The finish reason (e.g., 'stop', 'length', 'content_filter')
|
|
87
|
+
# @example Check why completion finished
|
|
88
|
+
# response = client.completion(messages: [...])
|
|
89
|
+
# reason = ResponseHelpers.finish_reason(response)
|
|
90
|
+
# puts "Finished because: #{reason}"
|
|
91
|
+
def finish_reason(response)
|
|
92
|
+
return nil unless response&.respond_to?(:choices)
|
|
93
|
+
return nil if response.choices.empty?
|
|
94
|
+
|
|
95
|
+
choice = response.choices.first
|
|
96
|
+
choice.finish_reason if choice.respond_to?(:finish_reason)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Checks if a response was truncated due to length
|
|
100
|
+
#
|
|
101
|
+
# @param response [Object] The API response object
|
|
102
|
+
# @return [Boolean] True if response was truncated
|
|
103
|
+
# @example Check if truncated
|
|
104
|
+
# response = client.completion(messages: [...])
|
|
105
|
+
# if ResponseHelpers.truncated?(response)
|
|
106
|
+
# puts "Response was cut off. Consider increasing max_tokens."
|
|
107
|
+
# end
|
|
108
|
+
def truncated?(response)
|
|
109
|
+
finish_reason(response) == 'length'
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Formats a response as a simple hash with common fields
|
|
113
|
+
#
|
|
114
|
+
# @param response [Object] The API response object
|
|
115
|
+
# @return [Hash] Simplified response hash
|
|
116
|
+
# @example Format response
|
|
117
|
+
# response = client.completion(messages: [...])
|
|
118
|
+
# simple = ResponseHelpers.to_hash(response)
|
|
119
|
+
# # => { content: "...", tokens: {...}, finish_reason: "stop" }
|
|
120
|
+
def to_hash(response)
|
|
121
|
+
{
|
|
122
|
+
content: extract_content(response),
|
|
123
|
+
tokens: token_usage(response),
|
|
124
|
+
finish_reason: finish_reason(response),
|
|
125
|
+
all_contents: all_contents(response)
|
|
126
|
+
}
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Extracts model information from response
|
|
130
|
+
#
|
|
131
|
+
# @param response [Object] The API response object
|
|
132
|
+
# @return [String, nil] The model used for the completion
|
|
133
|
+
# @example Get model name
|
|
134
|
+
# response = client.completion(messages: [...])
|
|
135
|
+
# model = ResponseHelpers.model_used(response)
|
|
136
|
+
# puts "Model: #{model}"
|
|
137
|
+
def model_used(response)
|
|
138
|
+
return nil unless response&.respond_to?(:model)
|
|
139
|
+
|
|
140
|
+
response.model
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Calculates the cost of a response (approximate)
|
|
144
|
+
#
|
|
145
|
+
# This is a rough estimate based on common pricing. For accurate costs,
|
|
146
|
+
# consult your provider's pricing page.
|
|
147
|
+
#
|
|
148
|
+
# @param response [Object] The API response object
|
|
149
|
+
# @param model [String, nil] Optional model name for pricing lookup
|
|
150
|
+
# @return [Float, nil] Estimated cost in USD
|
|
151
|
+
# @example Estimate cost
|
|
152
|
+
# response = client.completion(messages: [...])
|
|
153
|
+
# cost = ResponseHelpers.estimate_cost(response)
|
|
154
|
+
# puts "Estimated cost: $#{cost}"
|
|
155
|
+
def estimate_cost(response, model = nil)
|
|
156
|
+
usage = token_usage(response)
|
|
157
|
+
return nil unless usage
|
|
158
|
+
|
|
159
|
+
model ||= model_used(response)
|
|
160
|
+
return nil unless model
|
|
161
|
+
|
|
162
|
+
# Rough pricing estimates (as of 2025)
|
|
163
|
+
pricing = case model
|
|
164
|
+
when /gpt-4-turbo/
|
|
165
|
+
{ prompt: 0.01 / 1000, completion: 0.03 / 1000 }
|
|
166
|
+
when /gpt-4/
|
|
167
|
+
{ prompt: 0.03 / 1000, completion: 0.06 / 1000 }
|
|
168
|
+
when /gpt-3.5-turbo/
|
|
169
|
+
{ prompt: 0.0015 / 1000, completion: 0.002 / 1000 }
|
|
170
|
+
when /claude-3-opus/
|
|
171
|
+
{ prompt: 0.015 / 1000, completion: 0.075 / 1000 }
|
|
172
|
+
when /claude-3-sonnet/
|
|
173
|
+
{ prompt: 0.003 / 1000, completion: 0.015 / 1000 }
|
|
174
|
+
else
|
|
175
|
+
return nil # Unknown model
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
(usage[:prompt_tokens] * pricing[:prompt]) +
|
|
179
|
+
(usage[:completion_tokens] * pricing[:completion])
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
data/lib/durable/llm/version.rb
CHANGED
data/lib/durable/llm.rb
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
#
|
|
22
22
|
# # Create a client and make a request
|
|
23
23
|
# client = Durable::Llm.new(:openai, model: 'gpt-4')
|
|
24
|
-
# response = client.
|
|
24
|
+
# response = client.complete('Hello, world!')
|
|
25
25
|
# puts response # => "Hello! How can I help you today?"
|
|
26
26
|
# ```
|
|
27
27
|
#
|
|
@@ -91,7 +91,7 @@ module Durable
|
|
|
91
91
|
# end
|
|
92
92
|
#
|
|
93
93
|
# client = Durable::Llm.new(:openai)
|
|
94
|
-
# response = client.
|
|
94
|
+
# response = client.complete('Hello!')
|
|
95
95
|
#
|
|
96
96
|
# @see Durable::Llm::Client
|
|
97
97
|
# @see Durable::Llm::Configuration
|
|
@@ -155,6 +155,73 @@ module Durable
|
|
|
155
155
|
self.configuration ||= Configuration.new
|
|
156
156
|
yield(configuration)
|
|
157
157
|
end
|
|
158
|
+
|
|
159
|
+
# Creates a quick completion with minimal setup.
|
|
160
|
+
#
|
|
161
|
+
# This is a convenience method for one-off completions that automatically
|
|
162
|
+
# creates a client, performs the completion, and returns the text result.
|
|
163
|
+
#
|
|
164
|
+
# @param text [String] The input text to complete
|
|
165
|
+
# @param provider [Symbol] The provider to use (default: :openai)
|
|
166
|
+
# @param model [String] The model to use (required)
|
|
167
|
+
# @param options [Hash] Additional options for the client
|
|
168
|
+
# @return [String] The completion text
|
|
169
|
+
# @raise [ArgumentError] If required parameters are missing
|
|
170
|
+
# @example Quick completion with OpenAI
|
|
171
|
+
# result = Durable::Llm.complete('What is Ruby?', model: 'gpt-4')
|
|
172
|
+
# puts result
|
|
173
|
+
# @example Quick completion with Anthropic
|
|
174
|
+
# result = Durable::Llm.complete('Explain AI', provider: :anthropic, model: 'claude-3-opus-20240229')
|
|
175
|
+
# puts result
|
|
176
|
+
def self.complete(text, provider: :openai, model: nil, **options)
|
|
177
|
+
raise ArgumentError, 'text is required' if text.nil? || text.to_s.strip.empty?
|
|
178
|
+
raise ArgumentError, 'model is required' if model.nil? || model.to_s.strip.empty?
|
|
179
|
+
|
|
180
|
+
client = new(provider, options.merge(model: model))
|
|
181
|
+
client.complete(text)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Creates a chat completion with minimal setup.
|
|
185
|
+
#
|
|
186
|
+
# This is a convenience method for quick chat interactions that automatically
|
|
187
|
+
# creates a client and performs the chat completion.
|
|
188
|
+
#
|
|
189
|
+
# @param messages [Array<Hash>] Array of message hashes with :role and :content
|
|
190
|
+
# @param provider [Symbol] The provider to use (default: :openai)
|
|
191
|
+
# @param model [String] The model to use (required)
|
|
192
|
+
# @param options [Hash] Additional options for the client and request
|
|
193
|
+
# @return [Object] The chat response object
|
|
194
|
+
# @raise [ArgumentError] If required parameters are missing
|
|
195
|
+
# @example Simple chat
|
|
196
|
+
# response = Durable::Llm.chat(
|
|
197
|
+
# [{ role: 'user', content: 'Hello!' }],
|
|
198
|
+
# model: 'gpt-4'
|
|
199
|
+
# )
|
|
200
|
+
# puts response.choices.first.message.content
|
|
201
|
+
def self.chat(messages, provider: :openai, model: nil, **options)
|
|
202
|
+
raise ArgumentError, 'messages are required' if messages.nil? || messages.empty?
|
|
203
|
+
raise ArgumentError, 'model is required' if model.nil? || model.to_s.strip.empty?
|
|
204
|
+
|
|
205
|
+
request_keys = %i[temperature max_tokens top_p frequency_penalty presence_penalty]
|
|
206
|
+
request_params = options.select { |k, _| request_keys.include?(k) }
|
|
207
|
+
client_options = options.reject { |k, _| request_keys.include?(k) }
|
|
208
|
+
|
|
209
|
+
client = new(provider, client_options.merge(model: model))
|
|
210
|
+
client.chat(messages: messages, **request_params)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Lists available models for a provider.
|
|
214
|
+
#
|
|
215
|
+
# @param provider [Symbol] The provider name (default: :openai)
|
|
216
|
+
# @param options [Hash] Provider options (e.g., api_key)
|
|
217
|
+
# @return [Array<String>] List of available model IDs
|
|
218
|
+
# @example List OpenAI models
|
|
219
|
+
# models = Durable::Llm.models(:openai)
|
|
220
|
+
# puts models.inspect
|
|
221
|
+
def self.models(provider = :openai, **options)
|
|
222
|
+
client = new(provider, options)
|
|
223
|
+
client.provider.models
|
|
224
|
+
end
|
|
158
225
|
end
|
|
159
226
|
end
|
|
160
227
|
|
|
@@ -163,5 +230,11 @@ end
|
|
|
163
230
|
|
|
164
231
|
require 'durable/llm/providers'
|
|
165
232
|
require 'durable/llm/client'
|
|
233
|
+
require 'durable/llm/response_helpers'
|
|
234
|
+
require 'durable/llm/provider_utilities'
|
|
235
|
+
|
|
236
|
+
# Load global convenience functions for easier access
|
|
237
|
+
# Users can skip this by requiring 'durable/llm/core' instead of 'durable/llm'
|
|
238
|
+
require 'durable/llm/convenience' unless ENV['DLLM_NO_CONVENIENCE']
|
|
166
239
|
|
|
167
240
|
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
data/lib/durable.rb
CHANGED
data/sig/durable/llm.rbs
CHANGED
|
@@ -69,7 +69,8 @@ module Durable
|
|
|
69
69
|
|
|
70
70
|
def initialize: (Symbol | String provider_name, ?Hash[Symbol | String, untyped] options) -> void
|
|
71
71
|
def default_params: () -> Hash[Symbol, String?]
|
|
72
|
-
def
|
|
72
|
+
def complete: (String text, ?Hash[Symbol, untyped] _opts) -> String
|
|
73
|
+
alias quick_complete complete
|
|
73
74
|
def completion: (?Hash[Symbol, untyped] params) -> untyped
|
|
74
75
|
def chat: (?Hash[Symbol, untyped] params) -> untyped
|
|
75
76
|
def embed: (?Hash[Symbol, untyped] params) -> untyped
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: durable-llm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Durable Programming Team
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 1980-01-
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: event_stream_parser
|
|
@@ -16,6 +16,9 @@ dependencies:
|
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
18
|
version: '1.0'
|
|
19
|
+
- - ">="
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 1.0.0
|
|
19
22
|
type: :runtime
|
|
20
23
|
prerelease: false
|
|
21
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -23,20 +26,29 @@ dependencies:
|
|
|
23
26
|
- - "~>"
|
|
24
27
|
- !ruby/object:Gem::Version
|
|
25
28
|
version: '1.0'
|
|
29
|
+
- - ">="
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: 1.0.0
|
|
26
32
|
- !ruby/object:Gem::Dependency
|
|
27
33
|
name: faraday
|
|
28
34
|
requirement: !ruby/object:Gem::Requirement
|
|
29
35
|
requirements:
|
|
30
|
-
- - "
|
|
36
|
+
- - ">="
|
|
31
37
|
- !ruby/object:Gem::Version
|
|
32
38
|
version: '1.0'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '3.0'
|
|
33
42
|
type: :runtime
|
|
34
43
|
prerelease: false
|
|
35
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
45
|
requirements:
|
|
37
|
-
- - "
|
|
46
|
+
- - ">="
|
|
38
47
|
- !ruby/object:Gem::Version
|
|
39
48
|
version: '1.0'
|
|
49
|
+
- - "<"
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: '3.0'
|
|
40
52
|
- !ruby/object:Gem::Dependency
|
|
41
53
|
name: highline
|
|
42
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -44,6 +56,9 @@ dependencies:
|
|
|
44
56
|
- - "~>"
|
|
45
57
|
- !ruby/object:Gem::Version
|
|
46
58
|
version: '3.1'
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 3.1.0
|
|
47
62
|
type: :runtime
|
|
48
63
|
prerelease: false
|
|
49
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -51,6 +66,9 @@ dependencies:
|
|
|
51
66
|
- - "~>"
|
|
52
67
|
- !ruby/object:Gem::Version
|
|
53
68
|
version: '3.1'
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: 3.1.0
|
|
54
72
|
- !ruby/object:Gem::Dependency
|
|
55
73
|
name: json
|
|
56
74
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -58,6 +76,9 @@ dependencies:
|
|
|
58
76
|
- - "~>"
|
|
59
77
|
- !ruby/object:Gem::Version
|
|
60
78
|
version: '2.6'
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: 2.6.0
|
|
61
82
|
type: :runtime
|
|
62
83
|
prerelease: false
|
|
63
84
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -65,6 +86,23 @@ dependencies:
|
|
|
65
86
|
- - "~>"
|
|
66
87
|
- !ruby/object:Gem::Version
|
|
67
88
|
version: '2.6'
|
|
89
|
+
- - ">="
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: 2.6.0
|
|
92
|
+
- !ruby/object:Gem::Dependency
|
|
93
|
+
name: ostruct
|
|
94
|
+
requirement: !ruby/object:Gem::Requirement
|
|
95
|
+
requirements:
|
|
96
|
+
- - "~>"
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: 0.6.0
|
|
99
|
+
type: :runtime
|
|
100
|
+
prerelease: false
|
|
101
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
102
|
+
requirements:
|
|
103
|
+
- - "~>"
|
|
104
|
+
- !ruby/object:Gem::Version
|
|
105
|
+
version: 0.6.0
|
|
68
106
|
- !ruby/object:Gem::Dependency
|
|
69
107
|
name: thor
|
|
70
108
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -72,6 +110,9 @@ dependencies:
|
|
|
72
110
|
- - "~>"
|
|
73
111
|
- !ruby/object:Gem::Version
|
|
74
112
|
version: '1.3'
|
|
113
|
+
- - ">="
|
|
114
|
+
- !ruby/object:Gem::Version
|
|
115
|
+
version: 1.3.0
|
|
75
116
|
type: :runtime
|
|
76
117
|
prerelease: false
|
|
77
118
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -79,6 +120,9 @@ dependencies:
|
|
|
79
120
|
- - "~>"
|
|
80
121
|
- !ruby/object:Gem::Version
|
|
81
122
|
version: '1.3'
|
|
123
|
+
- - ">="
|
|
124
|
+
- !ruby/object:Gem::Version
|
|
125
|
+
version: 1.3.0
|
|
82
126
|
- !ruby/object:Gem::Dependency
|
|
83
127
|
name: zeitwerk
|
|
84
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,6 +130,9 @@ dependencies:
|
|
|
86
130
|
- - "~>"
|
|
87
131
|
- !ruby/object:Gem::Version
|
|
88
132
|
version: '2.6'
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
version: 2.6.0
|
|
89
136
|
type: :runtime
|
|
90
137
|
prerelease: false
|
|
91
138
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -93,6 +140,9 @@ dependencies:
|
|
|
93
140
|
- - "~>"
|
|
94
141
|
- !ruby/object:Gem::Version
|
|
95
142
|
version: '2.6'
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: 2.6.0
|
|
96
146
|
- !ruby/object:Gem::Dependency
|
|
97
147
|
name: dotenv
|
|
98
148
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -163,6 +213,20 @@ dependencies:
|
|
|
163
213
|
- - "~>"
|
|
164
214
|
- !ruby/object:Gem::Version
|
|
165
215
|
version: '6.0'
|
|
216
|
+
- !ruby/object:Gem::Dependency
|
|
217
|
+
name: yard
|
|
218
|
+
requirement: !ruby/object:Gem::Requirement
|
|
219
|
+
requirements:
|
|
220
|
+
- - "~>"
|
|
221
|
+
- !ruby/object:Gem::Version
|
|
222
|
+
version: '0.9'
|
|
223
|
+
type: :development
|
|
224
|
+
prerelease: false
|
|
225
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
226
|
+
requirements:
|
|
227
|
+
- - "~>"
|
|
228
|
+
- !ruby/object:Gem::Version
|
|
229
|
+
version: '0.9'
|
|
166
230
|
description: Durable-LLM is a unified interface for interacting with multiple Large
|
|
167
231
|
Language Model APIs, simplifying integration of AI capabilities into Ruby applications.
|
|
168
232
|
email:
|
|
@@ -176,7 +240,6 @@ files:
|
|
|
176
240
|
- CLI.md
|
|
177
241
|
- CONFIGURE.md
|
|
178
242
|
- Gemfile
|
|
179
|
-
- Gemfile.lock
|
|
180
243
|
- LICENSE.txt
|
|
181
244
|
- README.md
|
|
182
245
|
- Rakefile
|
|
@@ -193,7 +256,9 @@ files:
|
|
|
193
256
|
- lib/durable/llm/cli.rb
|
|
194
257
|
- lib/durable/llm/client.rb
|
|
195
258
|
- lib/durable/llm/configuration.rb
|
|
259
|
+
- lib/durable/llm/convenience.rb
|
|
196
260
|
- lib/durable/llm/errors.rb
|
|
261
|
+
- lib/durable/llm/provider_utilities.rb
|
|
197
262
|
- lib/durable/llm/providers.rb
|
|
198
263
|
- lib/durable/llm/providers/anthropic.rb
|
|
199
264
|
- lib/durable/llm/providers/azure_openai.rb
|
|
@@ -211,6 +276,7 @@ files:
|
|
|
211
276
|
- lib/durable/llm/providers/perplexity.rb
|
|
212
277
|
- lib/durable/llm/providers/together.rb
|
|
213
278
|
- lib/durable/llm/providers/xai.rb
|
|
279
|
+
- lib/durable/llm/response_helpers.rb
|
|
214
280
|
- lib/durable/llm/version.rb
|
|
215
281
|
- sig/durable/llm.rbs
|
|
216
282
|
homepage: https://github.com/durableprogramming/durable-llm
|
data/Gemfile.lock
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
durable-llm (0.1.5)
|
|
5
|
-
event_stream_parser (~> 1.0)
|
|
6
|
-
faraday (> 1.0)
|
|
7
|
-
highline (~> 3.1)
|
|
8
|
-
json (~> 2.6)
|
|
9
|
-
thor (~> 1.3)
|
|
10
|
-
zeitwerk (~> 2.6)
|
|
11
|
-
|
|
12
|
-
GEM
|
|
13
|
-
remote: https://rubygems.org/
|
|
14
|
-
specs:
|
|
15
|
-
addressable (2.8.7)
|
|
16
|
-
public_suffix (>= 2.0.2, < 7.0)
|
|
17
|
-
ast (2.4.2)
|
|
18
|
-
base64 (0.2.0)
|
|
19
|
-
bigdecimal (3.1.8)
|
|
20
|
-
crack (1.0.0)
|
|
21
|
-
bigdecimal
|
|
22
|
-
rexml
|
|
23
|
-
dotenv (2.8.1)
|
|
24
|
-
event_stream_parser (1.0.0)
|
|
25
|
-
faraday (2.12.0)
|
|
26
|
-
faraday-net_http (>= 2.0, < 3.4)
|
|
27
|
-
json
|
|
28
|
-
logger
|
|
29
|
-
faraday-multipart (1.0.4)
|
|
30
|
-
multipart-post (~> 2)
|
|
31
|
-
faraday-net_http (3.3.0)
|
|
32
|
-
net-http
|
|
33
|
-
hashdiff (1.1.1)
|
|
34
|
-
highline (3.1.1)
|
|
35
|
-
reline
|
|
36
|
-
io-console (0.7.2)
|
|
37
|
-
json (2.7.2)
|
|
38
|
-
language_server-protocol (3.17.0.3)
|
|
39
|
-
logger (1.6.1)
|
|
40
|
-
minitest (5.25.1)
|
|
41
|
-
mocha (2.4.5)
|
|
42
|
-
ruby2_keywords (>= 0.0.5)
|
|
43
|
-
multipart-post (2.4.1)
|
|
44
|
-
net-http (0.4.1)
|
|
45
|
-
uri
|
|
46
|
-
parallel (1.26.3)
|
|
47
|
-
parser (3.3.5.0)
|
|
48
|
-
ast (~> 2.4.1)
|
|
49
|
-
racc
|
|
50
|
-
public_suffix (6.0.1)
|
|
51
|
-
racc (1.8.1)
|
|
52
|
-
rainbow (3.1.1)
|
|
53
|
-
rake (13.2.1)
|
|
54
|
-
regexp_parser (2.9.2)
|
|
55
|
-
reline (0.5.10)
|
|
56
|
-
io-console (~> 0.5)
|
|
57
|
-
rexml (3.3.8)
|
|
58
|
-
rubocop (1.66.1)
|
|
59
|
-
json (~> 2.3)
|
|
60
|
-
language_server-protocol (>= 3.17.0)
|
|
61
|
-
parallel (~> 1.10)
|
|
62
|
-
parser (>= 3.3.0.2)
|
|
63
|
-
rainbow (>= 2.2.2, < 4.0)
|
|
64
|
-
regexp_parser (>= 2.4, < 3.0)
|
|
65
|
-
rubocop-ast (>= 1.32.2, < 2.0)
|
|
66
|
-
ruby-progressbar (~> 1.7)
|
|
67
|
-
unicode-display_width (>= 2.4.0, < 3.0)
|
|
68
|
-
rubocop-ast (1.32.3)
|
|
69
|
-
parser (>= 3.3.1.0)
|
|
70
|
-
ruby-openai (7.1.0)
|
|
71
|
-
event_stream_parser (>= 0.3.0, < 2.0.0)
|
|
72
|
-
faraday (>= 1)
|
|
73
|
-
faraday-multipart (>= 1)
|
|
74
|
-
ruby-progressbar (1.13.0)
|
|
75
|
-
ruby2_keywords (0.0.5)
|
|
76
|
-
thor (1.3.2)
|
|
77
|
-
unicode-display_width (2.6.0)
|
|
78
|
-
uri (0.13.1)
|
|
79
|
-
vcr (6.3.1)
|
|
80
|
-
base64
|
|
81
|
-
webmock (3.24.0)
|
|
82
|
-
addressable (>= 2.8.0)
|
|
83
|
-
crack (>= 0.3.2)
|
|
84
|
-
hashdiff (>= 0.4.0, < 2.0.0)
|
|
85
|
-
zeitwerk (2.6.18)
|
|
86
|
-
|
|
87
|
-
PLATFORMS
|
|
88
|
-
x86_64-linux
|
|
89
|
-
|
|
90
|
-
DEPENDENCIES
|
|
91
|
-
dotenv (~> 2.8)
|
|
92
|
-
durable-llm!
|
|
93
|
-
minitest (~> 5.0)
|
|
94
|
-
mocha (~> 2.1)
|
|
95
|
-
rake (~> 13.0)
|
|
96
|
-
rubocop (~> 1.21, ~> 1.0)
|
|
97
|
-
ruby-openai (~> 7.1)
|
|
98
|
-
thor (~> 1.3)
|
|
99
|
-
vcr (~> 6.0)
|
|
100
|
-
webmock (~> 3.24)
|
|
101
|
-
|
|
102
|
-
BUNDLED WITH
|
|
103
|
-
2.7.1
|