llm.rb 0.10.1 → 0.12.0
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/README.md +120 -119
- data/lib/llm/bot/builder.rb +2 -2
- data/lib/llm/bot.rb +13 -22
- data/lib/llm/buffer.rb +7 -0
- data/lib/llm/file.rb +22 -12
- data/lib/llm/function.rb +8 -7
- data/lib/llm/message.rb +8 -0
- data/lib/llm/multipart.rb +0 -1
- data/lib/llm/object/kernel.rb +8 -0
- data/lib/llm/object.rb +9 -3
- data/lib/llm/provider.rb +10 -12
- data/lib/llm/providers/anthropic/format/completion_format.rb +10 -5
- data/lib/llm/providers/anthropic/models.rb +4 -9
- data/lib/llm/providers/anthropic/response/completion.rb +39 -0
- data/lib/llm/providers/anthropic.rb +13 -25
- data/lib/llm/providers/deepseek/format/completion_format.rb +3 -3
- data/lib/llm/providers/deepseek.rb +16 -1
- data/lib/llm/providers/gemini/audio.rb +9 -13
- data/lib/llm/providers/gemini/files.rb +19 -34
- data/lib/llm/providers/gemini/format/completion_format.rb +20 -5
- data/lib/llm/providers/gemini/images.rb +12 -11
- data/lib/llm/providers/gemini/models.rb +4 -10
- data/lib/llm/providers/gemini/{response_parser/completion_parser.rb → response/completion.rb} +10 -24
- data/lib/llm/providers/gemini/response/embedding.rb +8 -0
- data/lib/llm/providers/gemini/response/file.rb +11 -0
- data/lib/llm/providers/gemini/response/image.rb +26 -0
- data/lib/llm/providers/gemini.rb +18 -29
- data/lib/llm/providers/llamacpp.rb +18 -1
- data/lib/llm/providers/ollama/format/completion_format.rb +8 -5
- data/lib/llm/providers/ollama/models.rb +2 -8
- data/lib/llm/providers/ollama/response/completion.rb +28 -0
- data/lib/llm/providers/ollama/response/embedding.rb +9 -0
- data/lib/llm/providers/ollama.rb +13 -19
- data/lib/llm/providers/openai/audio.rb +10 -10
- data/lib/llm/providers/openai/files.rb +22 -34
- data/lib/llm/providers/openai/format/completion_format.rb +11 -4
- data/lib/llm/providers/openai/format/moderation_format.rb +2 -2
- data/lib/llm/providers/openai/format/respond_format.rb +7 -4
- data/lib/llm/providers/openai/images.rb +18 -17
- data/lib/llm/providers/openai/models.rb +4 -9
- data/lib/llm/providers/openai/moderations.rb +9 -11
- data/lib/llm/providers/openai/response/audio.rb +7 -0
- data/lib/llm/providers/openai/{response_parser/completion_parser.rb → response/completion.rb} +14 -30
- data/lib/llm/providers/openai/response/embedding.rb +9 -0
- data/lib/llm/providers/openai/response/file.rb +7 -0
- data/lib/llm/providers/openai/response/image.rb +16 -0
- data/lib/llm/providers/openai/response/moderations.rb +34 -0
- data/lib/llm/providers/openai/{response_parser/respond_parser.rb → response/responds.rb} +7 -29
- data/lib/llm/providers/openai/responses.rb +16 -34
- data/lib/llm/providers/openai/stream_parser.rb +1 -0
- data/lib/llm/providers/openai/vector_stores.rb +188 -0
- data/lib/llm/providers/openai.rb +24 -9
- data/lib/llm/providers/xai/images.rb +58 -0
- data/lib/llm/providers/xai.rb +72 -0
- data/lib/llm/response.rb +42 -13
- data/lib/llm/version.rb +1 -1
- data/lib/llm.rb +12 -13
- data/llm.gemspec +5 -5
- metadata +29 -38
- data/lib/llm/model.rb +0 -32
- data/lib/llm/providers/anthropic/response_parser/completion_parser.rb +0 -51
- data/lib/llm/providers/anthropic/response_parser.rb +0 -24
- data/lib/llm/providers/gemini/response_parser.rb +0 -46
- data/lib/llm/providers/ollama/response_parser/completion_parser.rb +0 -42
- data/lib/llm/providers/ollama/response_parser.rb +0 -30
- data/lib/llm/providers/openai/response_parser.rb +0 -65
- data/lib/llm/providers/voyageai/error_handler.rb +0 -32
- data/lib/llm/providers/voyageai/response_parser.rb +0 -13
- data/lib/llm/providers/voyageai.rb +0 -44
- data/lib/llm/response/audio.rb +0 -13
- data/lib/llm/response/audio_transcription.rb +0 -14
- data/lib/llm/response/audio_translation.rb +0 -14
- data/lib/llm/response/completion.rb +0 -51
- data/lib/llm/response/download_file.rb +0 -15
- data/lib/llm/response/embedding.rb +0 -23
- data/lib/llm/response/file.rb +0 -42
- data/lib/llm/response/filelist.rb +0 -18
- data/lib/llm/response/image.rb +0 -29
- data/lib/llm/response/modellist.rb +0 -18
- data/lib/llm/response/moderationlist/moderation.rb +0 -47
- data/lib/llm/response/moderationlist.rb +0 -51
- data/lib/llm/response/respond.rb +0 -56
- /data/lib/llm/{event_handler.rb → eventhandler.rb} +0 -0
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: llm.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Antar Azri
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '1.
|
117
|
+
version: '1.50'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '1.
|
124
|
+
version: '1.50'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: vcr
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,9 +151,9 @@ dependencies:
|
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '2.8'
|
153
153
|
description: llm.rb is a zero-dependency Ruby toolkit for Large Language Models that
|
154
|
-
includes OpenAI, Gemini, Anthropic, DeepSeek, Ollama, and LlamaCpp.
|
155
|
-
includes full support for chat, streaming, tool calling, audio, images,
|
156
|
-
JSON Schema generation.
|
154
|
+
includes OpenAI, Gemini, Anthropic, xAI (grok), DeepSeek, Ollama, and LlamaCpp.
|
155
|
+
The toolkit includes full support for chat, streaming, tool calling, audio, images,
|
156
|
+
files, and JSON Schema generation.
|
157
157
|
email:
|
158
158
|
- azantar@proton.me
|
159
159
|
- 0x1eef@proton.me
|
@@ -171,7 +171,7 @@ files:
|
|
171
171
|
- lib/llm/bot/prompt/respond.rb
|
172
172
|
- lib/llm/buffer.rb
|
173
173
|
- lib/llm/error.rb
|
174
|
-
- lib/llm/
|
174
|
+
- lib/llm/eventhandler.rb
|
175
175
|
- lib/llm/eventstream.rb
|
176
176
|
- lib/llm/eventstream/event.rb
|
177
177
|
- lib/llm/eventstream/parser.rb
|
@@ -189,7 +189,6 @@ files:
|
|
189
189
|
- lib/llm/json/schema/version.rb
|
190
190
|
- lib/llm/message.rb
|
191
191
|
- lib/llm/mime.rb
|
192
|
-
- lib/llm/model.rb
|
193
192
|
- lib/llm/multipart.rb
|
194
193
|
- lib/llm/object.rb
|
195
194
|
- lib/llm/object/builder.rb
|
@@ -200,8 +199,7 @@ files:
|
|
200
199
|
- lib/llm/providers/anthropic/format.rb
|
201
200
|
- lib/llm/providers/anthropic/format/completion_format.rb
|
202
201
|
- lib/llm/providers/anthropic/models.rb
|
203
|
-
- lib/llm/providers/anthropic/
|
204
|
-
- lib/llm/providers/anthropic/response_parser/completion_parser.rb
|
202
|
+
- lib/llm/providers/anthropic/response/completion.rb
|
205
203
|
- lib/llm/providers/anthropic/stream_parser.rb
|
206
204
|
- lib/llm/providers/deepseek.rb
|
207
205
|
- lib/llm/providers/deepseek/format.rb
|
@@ -214,8 +212,10 @@ files:
|
|
214
212
|
- lib/llm/providers/gemini/format/completion_format.rb
|
215
213
|
- lib/llm/providers/gemini/images.rb
|
216
214
|
- lib/llm/providers/gemini/models.rb
|
217
|
-
- lib/llm/providers/gemini/
|
218
|
-
- lib/llm/providers/gemini/
|
215
|
+
- lib/llm/providers/gemini/response/completion.rb
|
216
|
+
- lib/llm/providers/gemini/response/embedding.rb
|
217
|
+
- lib/llm/providers/gemini/response/file.rb
|
218
|
+
- lib/llm/providers/gemini/response/image.rb
|
219
219
|
- lib/llm/providers/gemini/stream_parser.rb
|
220
220
|
- lib/llm/providers/llamacpp.rb
|
221
221
|
- lib/llm/providers/ollama.rb
|
@@ -223,8 +223,8 @@ files:
|
|
223
223
|
- lib/llm/providers/ollama/format.rb
|
224
224
|
- lib/llm/providers/ollama/format/completion_format.rb
|
225
225
|
- lib/llm/providers/ollama/models.rb
|
226
|
-
- lib/llm/providers/ollama/
|
227
|
-
- lib/llm/providers/ollama/
|
226
|
+
- lib/llm/providers/ollama/response/completion.rb
|
227
|
+
- lib/llm/providers/ollama/response/embedding.rb
|
228
228
|
- lib/llm/providers/ollama/stream_parser.rb
|
229
229
|
- lib/llm/providers/openai.rb
|
230
230
|
- lib/llm/providers/openai/audio.rb
|
@@ -237,34 +237,25 @@ files:
|
|
237
237
|
- lib/llm/providers/openai/images.rb
|
238
238
|
- lib/llm/providers/openai/models.rb
|
239
239
|
- lib/llm/providers/openai/moderations.rb
|
240
|
-
- lib/llm/providers/openai/
|
241
|
-
- lib/llm/providers/openai/
|
242
|
-
- lib/llm/providers/openai/
|
240
|
+
- lib/llm/providers/openai/response/audio.rb
|
241
|
+
- lib/llm/providers/openai/response/completion.rb
|
242
|
+
- lib/llm/providers/openai/response/embedding.rb
|
243
|
+
- lib/llm/providers/openai/response/file.rb
|
244
|
+
- lib/llm/providers/openai/response/image.rb
|
245
|
+
- lib/llm/providers/openai/response/moderations.rb
|
246
|
+
- lib/llm/providers/openai/response/responds.rb
|
243
247
|
- lib/llm/providers/openai/responses.rb
|
244
248
|
- lib/llm/providers/openai/stream_parser.rb
|
245
|
-
- lib/llm/providers/
|
246
|
-
- lib/llm/providers/
|
247
|
-
- lib/llm/providers/
|
249
|
+
- lib/llm/providers/openai/vector_stores.rb
|
250
|
+
- lib/llm/providers/xai.rb
|
251
|
+
- lib/llm/providers/xai/images.rb
|
248
252
|
- lib/llm/response.rb
|
249
|
-
- lib/llm/response/audio.rb
|
250
|
-
- lib/llm/response/audio_transcription.rb
|
251
|
-
- lib/llm/response/audio_translation.rb
|
252
|
-
- lib/llm/response/completion.rb
|
253
|
-
- lib/llm/response/download_file.rb
|
254
|
-
- lib/llm/response/embedding.rb
|
255
|
-
- lib/llm/response/file.rb
|
256
|
-
- lib/llm/response/filelist.rb
|
257
|
-
- lib/llm/response/image.rb
|
258
|
-
- lib/llm/response/modellist.rb
|
259
|
-
- lib/llm/response/moderationlist.rb
|
260
|
-
- lib/llm/response/moderationlist/moderation.rb
|
261
|
-
- lib/llm/response/respond.rb
|
262
253
|
- lib/llm/utils.rb
|
263
254
|
- lib/llm/version.rb
|
264
255
|
- llm.gemspec
|
265
256
|
homepage: https://github.com/llmrb/llm
|
266
257
|
licenses:
|
267
|
-
-
|
258
|
+
- 0BSD
|
268
259
|
metadata:
|
269
260
|
homepage_uri: https://github.com/llmrb/llm
|
270
261
|
source_code_uri: https://github.com/llmrb/llm
|
@@ -282,10 +273,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
282
273
|
- !ruby/object:Gem::Version
|
283
274
|
version: '0'
|
284
275
|
requirements: []
|
285
|
-
rubygems_version: 3.
|
276
|
+
rubygems_version: 3.6.9
|
286
277
|
specification_version: 4
|
287
278
|
summary: llm.rb is a zero-dependency Ruby toolkit for Large Language Models that includes
|
288
|
-
OpenAI, Gemini, Anthropic, DeepSeek, Ollama, and LlamaCpp. The toolkit
|
289
|
-
full support for chat, streaming, tool calling, audio, images, files, and
|
290
|
-
generation.
|
279
|
+
OpenAI, Gemini, Anthropic, xAI (grok), DeepSeek, Ollama, and LlamaCpp. The toolkit
|
280
|
+
includes full support for chat, streaming, tool calling, audio, images, files, and
|
281
|
+
JSON Schema generation.
|
291
282
|
test_files: []
|
data/lib/llm/model.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
##
|
4
|
-
# The {LLM::Model LLM::Model} class represents an LLM model that
|
5
|
-
# is available to use. Its properties are delegated to the underlying
|
6
|
-
# response body, and vary by provider.
|
7
|
-
class LLM::Model < LLM::Object
|
8
|
-
##
|
9
|
-
# Returns a subclass of {LLM::Provider LLM::Provider}
|
10
|
-
# @return [LLM::Provider]
|
11
|
-
attr_accessor :provider
|
12
|
-
|
13
|
-
##
|
14
|
-
# Returns the model ID
|
15
|
-
# @return [String]
|
16
|
-
def id
|
17
|
-
case @provider.class.to_s
|
18
|
-
when "LLM::Ollama"
|
19
|
-
self["name"]
|
20
|
-
when "LLM::Gemini"
|
21
|
-
self["name"].sub(%r|\Amodels/|, "")
|
22
|
-
else
|
23
|
-
self["id"]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
##
|
28
|
-
# @return [String]
|
29
|
-
def to_json(*)
|
30
|
-
id.to_json(*)
|
31
|
-
end
|
32
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM::Anthropic::ResponseParser
|
4
|
-
##
|
5
|
-
# @private
|
6
|
-
class CompletionParser
|
7
|
-
def initialize(body)
|
8
|
-
@body = LLM::Object.from_hash(body)
|
9
|
-
end
|
10
|
-
|
11
|
-
def format(response)
|
12
|
-
{
|
13
|
-
model:,
|
14
|
-
prompt_tokens:,
|
15
|
-
completion_tokens:,
|
16
|
-
total_tokens:,
|
17
|
-
choices: format_choices(response)
|
18
|
-
}
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def format_choices(response)
|
24
|
-
texts.map.with_index do |choice, index|
|
25
|
-
extra = {index:, response:, tool_calls: format_tool_calls(tools), original_tool_calls: tools}
|
26
|
-
LLM::Message.new(role, choice.text, extra)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def format_tool_calls(tools)
|
31
|
-
(tools || []).filter_map do |tool|
|
32
|
-
tool = {
|
33
|
-
id: tool.id,
|
34
|
-
name: tool.name,
|
35
|
-
arguments: tool.input
|
36
|
-
}
|
37
|
-
LLM::Object.new(tool)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def body = @body
|
42
|
-
def role = body.role
|
43
|
-
def model = body.model
|
44
|
-
def prompt_tokens = body.usage&.input_tokens
|
45
|
-
def completion_tokens = body.usage&.output_tokens
|
46
|
-
def total_tokens = body.usage&.total_tokens
|
47
|
-
def parts = body.content
|
48
|
-
def texts = parts.select { _1["type"] == "text" }
|
49
|
-
def tools = parts.select { _1["type"] == "tool_use" }
|
50
|
-
end
|
51
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class LLM::Anthropic
|
4
|
-
##
|
5
|
-
# @private
|
6
|
-
module ResponseParser
|
7
|
-
require_relative "response_parser/completion_parser"
|
8
|
-
def parse_embedding(body)
|
9
|
-
{
|
10
|
-
model: body["model"],
|
11
|
-
embeddings: body["data"].map { _1["embedding"] },
|
12
|
-
total_tokens: body.dig("usage", "total_tokens")
|
13
|
-
}
|
14
|
-
end
|
15
|
-
|
16
|
-
##
|
17
|
-
# @param [Hash] body
|
18
|
-
# The response body from the LLM provider
|
19
|
-
# @return [Hash]
|
20
|
-
def parse_completion(body)
|
21
|
-
CompletionParser.new(body).format(self)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class LLM::Gemini
|
4
|
-
##
|
5
|
-
# @private
|
6
|
-
module ResponseParser
|
7
|
-
require_relative "response_parser/completion_parser"
|
8
|
-
|
9
|
-
##
|
10
|
-
# @param [Hash] body
|
11
|
-
# The response body from the LLM provider
|
12
|
-
# @return [Hash]
|
13
|
-
def parse_completion(body)
|
14
|
-
CompletionParser.new(body).format(self)
|
15
|
-
end
|
16
|
-
|
17
|
-
##
|
18
|
-
# @param [Hash] body
|
19
|
-
# The response body from the LLM provider
|
20
|
-
# @return [Hash]
|
21
|
-
def parse_embedding(body)
|
22
|
-
{
|
23
|
-
model: "text-embedding-004",
|
24
|
-
embeddings: body.dig("embedding", "values")
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
##
|
29
|
-
# @param [Hash] body
|
30
|
-
# The response body from the LLM provider
|
31
|
-
# @return [Hash]
|
32
|
-
def parse_image(body)
|
33
|
-
{
|
34
|
-
urls: [],
|
35
|
-
images: body["candidates"].flat_map do |c|
|
36
|
-
parts = c["content"]["parts"]
|
37
|
-
parts.filter_map do
|
38
|
-
data = _1.dig("inlineData", "data")
|
39
|
-
next unless data
|
40
|
-
StringIO.new(data.unpack1("m0"))
|
41
|
-
end
|
42
|
-
end
|
43
|
-
}
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM::Ollama::ResponseParser
|
4
|
-
##
|
5
|
-
# @private
|
6
|
-
class CompletionParser
|
7
|
-
def initialize(body)
|
8
|
-
@body = LLM::Object.from_hash(body)
|
9
|
-
end
|
10
|
-
|
11
|
-
def format(response)
|
12
|
-
{
|
13
|
-
model:,
|
14
|
-
choices: [format_choices(response)],
|
15
|
-
prompt_tokens:,
|
16
|
-
completion_tokens:
|
17
|
-
}
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def format_choices(response)
|
23
|
-
role, content, calls = message.to_h.values_at(:role, :content, :tool_calls)
|
24
|
-
extra = {response:, tool_calls: format_tool_calls(calls)}
|
25
|
-
LLM::Message.new(role, content, extra)
|
26
|
-
end
|
27
|
-
|
28
|
-
def format_tool_calls(tools)
|
29
|
-
return [] unless tools
|
30
|
-
tools.filter_map do |tool|
|
31
|
-
next unless tool["function"]
|
32
|
-
LLM::Object.new(tool["function"])
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def body = @body
|
37
|
-
def model = body.model
|
38
|
-
def prompt_tokens = body.prompt_eval_count
|
39
|
-
def completion_tokens = body.eval_count
|
40
|
-
def message = body.message
|
41
|
-
end
|
42
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class LLM::Ollama
|
4
|
-
##
|
5
|
-
# @private
|
6
|
-
module ResponseParser
|
7
|
-
require_relative "response_parser/completion_parser"
|
8
|
-
|
9
|
-
##
|
10
|
-
# @param [Hash] body
|
11
|
-
# The response body from the LLM provider
|
12
|
-
# @return [Hash]
|
13
|
-
def parse_completion(body)
|
14
|
-
CompletionParser.new(body).format(self)
|
15
|
-
end
|
16
|
-
|
17
|
-
##
|
18
|
-
# @param [Hash] body
|
19
|
-
# The response body from the LLM provider
|
20
|
-
# @return [Hash]
|
21
|
-
def parse_embedding(body)
|
22
|
-
{
|
23
|
-
model: body["model"],
|
24
|
-
embeddings: body["data"].map { _1["embedding"] },
|
25
|
-
prompt_tokens: body.dig("usage", "prompt_tokens"),
|
26
|
-
total_tokens: body.dig("usage", "total_tokens")
|
27
|
-
}
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class LLM::OpenAI
|
4
|
-
##
|
5
|
-
# @private
|
6
|
-
module ResponseParser
|
7
|
-
require_relative "response_parser/completion_parser"
|
8
|
-
require_relative "response_parser/respond_parser"
|
9
|
-
|
10
|
-
##
|
11
|
-
# @param [Hash] body
|
12
|
-
# The response body from the LLM provider
|
13
|
-
# @return [Hash]
|
14
|
-
def parse_completion(body)
|
15
|
-
CompletionParser.new(body).format(self)
|
16
|
-
end
|
17
|
-
|
18
|
-
##
|
19
|
-
# @param [Hash] body
|
20
|
-
# The response body from the LLM provider
|
21
|
-
# @return [Hash]
|
22
|
-
def parse_respond_response(body)
|
23
|
-
RespondParser.new(body).format(self)
|
24
|
-
end
|
25
|
-
|
26
|
-
##
|
27
|
-
# @param [Hash] body
|
28
|
-
# The response body from the LLM provider
|
29
|
-
# @return [Hash]
|
30
|
-
def parse_moderation_list(body)
|
31
|
-
{
|
32
|
-
id: body["id"],
|
33
|
-
model: body["model"],
|
34
|
-
moderations: body["results"].map { LLM::Response::ModerationList::Moderation.new(_1) }
|
35
|
-
}
|
36
|
-
end
|
37
|
-
|
38
|
-
##
|
39
|
-
# @param [Hash] body
|
40
|
-
# The response body from the LLM provider
|
41
|
-
# @return [Hash]
|
42
|
-
def parse_embedding(body)
|
43
|
-
{
|
44
|
-
model: body["model"],
|
45
|
-
embeddings: body["data"].map { _1["embedding"] },
|
46
|
-
prompt_tokens: body.dig("usage", "prompt_tokens"),
|
47
|
-
total_tokens: body.dig("usage", "total_tokens")
|
48
|
-
}
|
49
|
-
end
|
50
|
-
|
51
|
-
##
|
52
|
-
# @param [Hash] body
|
53
|
-
# The response body from the LLM provider
|
54
|
-
# @return [Hash]
|
55
|
-
def parse_image(body)
|
56
|
-
{
|
57
|
-
urls: body["data"].filter_map { _1["url"] },
|
58
|
-
images: body["data"].filter_map do
|
59
|
-
next unless _1["b64_json"]
|
60
|
-
StringIO.new(_1["b64_json"].unpack1("m0"))
|
61
|
-
end
|
62
|
-
}
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class LLM::VoyageAI
|
4
|
-
class ErrorHandler
|
5
|
-
##
|
6
|
-
# @return [Net::HTTPResponse]
|
7
|
-
# Non-2XX response from the server
|
8
|
-
attr_reader :res
|
9
|
-
|
10
|
-
##
|
11
|
-
# @param [Net::HTTPResponse] res
|
12
|
-
# The response from the server
|
13
|
-
# @return [LLM::OpenAI::ErrorHandler]
|
14
|
-
def initialize(res)
|
15
|
-
@res = res
|
16
|
-
end
|
17
|
-
|
18
|
-
##
|
19
|
-
# @raise [LLM::Error]
|
20
|
-
# Raises a subclass of {LLM::Error LLM::Error}
|
21
|
-
def raise_error!
|
22
|
-
case res
|
23
|
-
when Net::HTTPUnauthorized
|
24
|
-
raise LLM::UnauthorizedError.new { _1.response = res }, "Authentication error"
|
25
|
-
when Net::HTTPTooManyRequests
|
26
|
-
raise LLM::RateLimitError.new { _1.response = res }, "Too many requests"
|
27
|
-
else
|
28
|
-
raise LLM::ResponseError.new { _1.response = res }, "Unexpected response"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class LLM::VoyageAI
|
4
|
-
module ResponseParser
|
5
|
-
def parse_embedding(body)
|
6
|
-
{
|
7
|
-
model: body["model"],
|
8
|
-
embeddings: body["data"].map { _1["embedding"] },
|
9
|
-
total_tokens: body.dig("usage", "total_tokens")
|
10
|
-
}
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM
|
4
|
-
class VoyageAI < Provider
|
5
|
-
require_relative "voyageai/error_handler"
|
6
|
-
require_relative "voyageai/response_parser"
|
7
|
-
HOST = "api.voyageai.com"
|
8
|
-
|
9
|
-
##
|
10
|
-
# @param key (see LLM::Provider#initialize)
|
11
|
-
def initialize(**)
|
12
|
-
super(host: HOST, **)
|
13
|
-
end
|
14
|
-
|
15
|
-
##
|
16
|
-
# Provides an embedding via VoyageAI per
|
17
|
-
# [Anthropic's recommendation](https://docs.anthropic.com/en/docs/build-with-claude/embeddings)
|
18
|
-
# @param input (see LLM::Provider#embed)
|
19
|
-
# @return (see LLM::Provider#embed)
|
20
|
-
def embed(input, model: "voyage-2", **params)
|
21
|
-
req = Net::HTTP::Post.new("/v1/embeddings", headers)
|
22
|
-
req.body = JSON.dump({input:, model:}.merge!(params))
|
23
|
-
res = execute(request: req)
|
24
|
-
Response::Embedding.new(res).extend(response_parser)
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def headers
|
30
|
-
{
|
31
|
-
"Content-Type" => "application/json",
|
32
|
-
"Authorization" => "Bearer #{@key}"
|
33
|
-
}
|
34
|
-
end
|
35
|
-
|
36
|
-
def response_parser
|
37
|
-
LLM::VoyageAI::ResponseParser
|
38
|
-
end
|
39
|
-
|
40
|
-
def error_handler
|
41
|
-
LLM::VoyageAI::ErrorHandler
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/llm/response/audio.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM
|
4
|
-
##
|
5
|
-
# The {LLM::Response::Audio LLM::Response::Audio} class represents an
|
6
|
-
# audio file that has been returned by a provider. It wraps an IO object
|
7
|
-
# that can be used to read the contents of an audio stream (as binary data).
|
8
|
-
class Response::Audio < Response
|
9
|
-
##
|
10
|
-
# @return [StringIO]
|
11
|
-
attr_accessor :audio
|
12
|
-
end
|
13
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM
|
4
|
-
##
|
5
|
-
# The {LLM::Response::AudioTranscription LLM::Response::AudioTranscription}
|
6
|
-
# class represents an audio transcription that has been returned by
|
7
|
-
# a provider (eg OpenAI, Gemini, etc)
|
8
|
-
class Response::AudioTranscription < Response
|
9
|
-
##
|
10
|
-
# Returns the text of the transcription
|
11
|
-
# @return [String]
|
12
|
-
attr_accessor :text
|
13
|
-
end
|
14
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM
|
4
|
-
##
|
5
|
-
# The {LLM::Response::AudioTranslation LLM::Response::AudioTranslation}
|
6
|
-
# class represents an audio translation that has been returned by
|
7
|
-
# a provider (eg OpenAI, Gemini, etc)
|
8
|
-
class Response::AudioTranslation < Response
|
9
|
-
##
|
10
|
-
# Returns the text of the translation
|
11
|
-
# @return [String]
|
12
|
-
attr_accessor :text
|
13
|
-
end
|
14
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM
|
4
|
-
class Response::Completion < Response
|
5
|
-
##
|
6
|
-
# @return [String]
|
7
|
-
# Returns the model name used for the completion
|
8
|
-
def model
|
9
|
-
parsed[:model]
|
10
|
-
end
|
11
|
-
|
12
|
-
##
|
13
|
-
# @return [Array<LLM::Message>]
|
14
|
-
# Returns an array of messages
|
15
|
-
def choices
|
16
|
-
parsed[:choices]
|
17
|
-
end
|
18
|
-
alias_method :messages, :choices
|
19
|
-
|
20
|
-
##
|
21
|
-
# @return [Integer]
|
22
|
-
# Returns the count of prompt tokens
|
23
|
-
def prompt_tokens
|
24
|
-
parsed[:prompt_tokens]
|
25
|
-
end
|
26
|
-
|
27
|
-
##
|
28
|
-
# @return [Integer]
|
29
|
-
# Returns the count of completion tokens
|
30
|
-
def completion_tokens
|
31
|
-
parsed[:completion_tokens]
|
32
|
-
end
|
33
|
-
|
34
|
-
##
|
35
|
-
# @return [Integer]
|
36
|
-
# Returns the total count of tokens
|
37
|
-
def total_tokens
|
38
|
-
prompt_tokens + completion_tokens
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
##
|
44
|
-
# @private
|
45
|
-
# @return [Hash]
|
46
|
-
# Returns the parsed completion response from the provider
|
47
|
-
def parsed
|
48
|
-
@parsed ||= parse_completion(body)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM
|
4
|
-
##
|
5
|
-
# The {LLM::Response::DownloadFile LLM::Response::DownloadFile} class
|
6
|
-
# represents the contents of a file that has been returned by a
|
7
|
-
# provider. It wraps an IO object that can be used to read the file
|
8
|
-
# contents.
|
9
|
-
class Response::DownloadFile < Response
|
10
|
-
##
|
11
|
-
# Returns a StringIO object
|
12
|
-
# @return [StringIO]
|
13
|
-
attr_accessor :file
|
14
|
-
end
|
15
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module LLM
|
4
|
-
class Response::Embedding < Response
|
5
|
-
def model
|
6
|
-
parsed[:model]
|
7
|
-
end
|
8
|
-
|
9
|
-
def embeddings
|
10
|
-
parsed[:embeddings]
|
11
|
-
end
|
12
|
-
|
13
|
-
def total_tokens
|
14
|
-
parsed[:total_tokens]
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def parsed
|
20
|
-
@parsed ||= parse_embedding(body)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|