llm.rb 2.1.0 → 3.0.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 +6 -0
- data/lib/llm/bot.rb +4 -4
- data/lib/llm/buffer.rb +0 -9
- data/lib/llm/contract/completion.rb +57 -0
- data/lib/llm/contract.rb +48 -0
- data/lib/llm/error.rb +22 -14
- data/lib/llm/eventhandler.rb +6 -4
- data/lib/llm/eventstream/parser.rb +18 -13
- data/lib/llm/function.rb +1 -1
- data/lib/llm/json_adapter.rb +109 -0
- data/lib/llm/message.rb +7 -28
- data/lib/llm/multipart/enumerator_io.rb +86 -0
- data/lib/llm/multipart.rb +32 -51
- data/lib/llm/object/builder.rb +6 -6
- data/lib/llm/object/kernel.rb +2 -2
- data/lib/llm/object.rb +23 -8
- data/lib/llm/provider.rb +11 -3
- data/lib/llm/providers/anthropic/error_handler.rb +1 -1
- data/lib/llm/providers/anthropic/files.rb +4 -5
- data/lib/llm/providers/anthropic/models.rb +1 -2
- data/lib/llm/providers/anthropic/{format/completion_format.rb → request_adapter/completion.rb} +19 -19
- data/lib/llm/providers/anthropic/{format.rb → request_adapter.rb} +7 -7
- data/lib/llm/providers/anthropic/response_adapter/completion.rb +66 -0
- data/lib/llm/providers/anthropic/{response → response_adapter}/enumerable.rb +1 -1
- data/lib/llm/providers/anthropic/{response → response_adapter}/file.rb +1 -1
- data/lib/llm/providers/anthropic/{response → response_adapter}/web_search.rb +3 -3
- data/lib/llm/providers/anthropic/response_adapter.rb +36 -0
- data/lib/llm/providers/anthropic/stream_parser.rb +6 -6
- data/lib/llm/providers/anthropic.rb +8 -11
- data/lib/llm/providers/deepseek/{format/completion_format.rb → request_adapter/completion.rb} +15 -15
- data/lib/llm/providers/deepseek/{format.rb → request_adapter.rb} +7 -7
- data/lib/llm/providers/deepseek.rb +2 -2
- data/lib/llm/providers/gemini/audio.rb +2 -2
- data/lib/llm/providers/gemini/error_handler.rb +3 -3
- data/lib/llm/providers/gemini/files.rb +4 -7
- data/lib/llm/providers/gemini/images.rb +9 -14
- data/lib/llm/providers/gemini/models.rb +1 -2
- data/lib/llm/providers/gemini/{format/completion_format.rb → request_adapter/completion.rb} +14 -14
- data/lib/llm/providers/gemini/{format.rb → request_adapter.rb} +8 -8
- data/lib/llm/providers/gemini/response_adapter/completion.rb +67 -0
- data/lib/llm/providers/gemini/{response → response_adapter}/embedding.rb +1 -1
- data/lib/llm/providers/gemini/{response → response_adapter}/file.rb +1 -1
- data/lib/llm/providers/gemini/{response → response_adapter}/files.rb +1 -1
- data/lib/llm/providers/gemini/{response → response_adapter}/image.rb +3 -3
- data/lib/llm/providers/gemini/{response → response_adapter}/models.rb +1 -1
- data/lib/llm/providers/gemini/{response → response_adapter}/web_search.rb +3 -3
- data/lib/llm/providers/gemini/response_adapter.rb +42 -0
- data/lib/llm/providers/gemini/stream_parser.rb +37 -32
- data/lib/llm/providers/gemini.rb +10 -14
- data/lib/llm/providers/ollama/error_handler.rb +1 -1
- data/lib/llm/providers/ollama/{format/completion_format.rb → request_adapter/completion.rb} +19 -19
- data/lib/llm/providers/ollama/{format.rb → request_adapter.rb} +7 -7
- data/lib/llm/providers/ollama/response_adapter/completion.rb +61 -0
- data/lib/llm/providers/ollama/{response → response_adapter}/embedding.rb +1 -1
- data/lib/llm/providers/ollama/response_adapter.rb +32 -0
- data/lib/llm/providers/ollama/stream_parser.rb +2 -2
- data/lib/llm/providers/ollama.rb +8 -10
- data/lib/llm/providers/openai/audio.rb +1 -1
- data/lib/llm/providers/openai/error_handler.rb +12 -2
- data/lib/llm/providers/openai/files.rb +3 -6
- data/lib/llm/providers/openai/images.rb +4 -5
- data/lib/llm/providers/openai/models.rb +1 -3
- data/lib/llm/providers/openai/moderations.rb +3 -5
- data/lib/llm/providers/openai/{format/completion_format.rb → request_adapter/completion.rb} +22 -22
- data/lib/llm/providers/openai/{format/moderation_format.rb → request_adapter/moderation.rb} +5 -5
- data/lib/llm/providers/openai/{format/respond_format.rb → request_adapter/respond.rb} +16 -16
- data/lib/llm/providers/openai/{format.rb → request_adapter.rb} +12 -12
- data/lib/llm/providers/openai/{response → response_adapter}/audio.rb +1 -1
- data/lib/llm/providers/openai/response_adapter/completion.rb +62 -0
- data/lib/llm/providers/openai/{response → response_adapter}/embedding.rb +1 -1
- data/lib/llm/providers/openai/{response → response_adapter}/enumerable.rb +1 -1
- data/lib/llm/providers/openai/{response → response_adapter}/file.rb +1 -1
- data/lib/llm/providers/openai/{response → response_adapter}/image.rb +1 -1
- data/lib/llm/providers/openai/{response → response_adapter}/moderations.rb +1 -1
- data/lib/llm/providers/openai/{response → response_adapter}/responds.rb +6 -10
- data/lib/llm/providers/openai/{response → response_adapter}/web_search.rb +3 -3
- data/lib/llm/providers/openai/response_adapter.rb +47 -0
- data/lib/llm/providers/openai/responses/stream_parser.rb +22 -22
- data/lib/llm/providers/openai/responses.rb +6 -8
- data/lib/llm/providers/openai/stream_parser.rb +6 -5
- data/lib/llm/providers/openai/vector_stores.rb +8 -9
- data/lib/llm/providers/openai.rb +12 -14
- data/lib/llm/response.rb +2 -5
- data/lib/llm/usage.rb +10 -0
- data/lib/llm/version.rb +1 -1
- data/lib/llm.rb +33 -1
- metadata +44 -35
- data/lib/llm/providers/anthropic/response/completion.rb +0 -39
- data/lib/llm/providers/gemini/response/completion.rb +0 -35
- data/lib/llm/providers/ollama/response/completion.rb +0 -28
- data/lib/llm/providers/openai/response/completion.rb +0 -40
|
@@ -13,7 +13,6 @@ class LLM::OpenAI
|
|
|
13
13
|
# chunks = llm.vector_stores.search(vector: store, query: "What is Ruby?")
|
|
14
14
|
# chunks.each { |chunk| puts chunk }
|
|
15
15
|
class VectorStores
|
|
16
|
-
require_relative "response/enumerable"
|
|
17
16
|
PollError = Class.new(LLM::Error)
|
|
18
17
|
|
|
19
18
|
INTERVAL = 0.01
|
|
@@ -34,7 +33,7 @@ class LLM::OpenAI
|
|
|
34
33
|
query = URI.encode_www_form(params)
|
|
35
34
|
req = Net::HTTP::Get.new("/v1/vector_stores?#{query}", headers)
|
|
36
35
|
res = execute(request: req)
|
|
37
|
-
|
|
36
|
+
ResponseAdapter.adapt(res, type: :enumerable)
|
|
38
37
|
end
|
|
39
38
|
|
|
40
39
|
##
|
|
@@ -47,7 +46,7 @@ class LLM::OpenAI
|
|
|
47
46
|
# @see https://platform.openai.com/docs/api-reference/vector_stores/create OpenAI docs
|
|
48
47
|
def create(name:, file_ids: nil, **params)
|
|
49
48
|
req = Net::HTTP::Post.new("/v1/vector_stores", headers)
|
|
50
|
-
req.body =
|
|
49
|
+
req.body = LLM.json.dump(params.merge({name:, file_ids:}).compact)
|
|
51
50
|
res = execute(request: req)
|
|
52
51
|
LLM::Response.new(res)
|
|
53
52
|
end
|
|
@@ -85,7 +84,7 @@ class LLM::OpenAI
|
|
|
85
84
|
def modify(vector:, name: nil, **params)
|
|
86
85
|
vector_id = vector.respond_to?(:id) ? vector.id : vector
|
|
87
86
|
req = Net::HTTP::Post.new("/v1/vector_stores/#{vector_id}", headers)
|
|
88
|
-
req.body =
|
|
87
|
+
req.body = LLM.json.dump(params.merge({name:}).compact)
|
|
89
88
|
res = execute(request: req)
|
|
90
89
|
LLM::Response.new(res)
|
|
91
90
|
end
|
|
@@ -114,9 +113,9 @@ class LLM::OpenAI
|
|
|
114
113
|
def search(vector:, query:, **params)
|
|
115
114
|
vector_id = vector.respond_to?(:id) ? vector.id : vector
|
|
116
115
|
req = Net::HTTP::Post.new("/v1/vector_stores/#{vector_id}/search", headers)
|
|
117
|
-
req.body =
|
|
116
|
+
req.body = LLM.json.dump(params.merge({query:}).compact)
|
|
118
117
|
res = execute(request: req)
|
|
119
|
-
|
|
118
|
+
ResponseAdapter.adapt(res, type: :enumerable)
|
|
120
119
|
end
|
|
121
120
|
|
|
122
121
|
##
|
|
@@ -131,7 +130,7 @@ class LLM::OpenAI
|
|
|
131
130
|
query = URI.encode_www_form(params)
|
|
132
131
|
req = Net::HTTP::Get.new("/v1/vector_stores/#{vector_id}/files?#{query}", headers)
|
|
133
132
|
res = execute(request: req)
|
|
134
|
-
|
|
133
|
+
ResponseAdapter.adapt(res, type: :enumerable)
|
|
135
134
|
end
|
|
136
135
|
|
|
137
136
|
##
|
|
@@ -147,7 +146,7 @@ class LLM::OpenAI
|
|
|
147
146
|
vector_id = vector.respond_to?(:id) ? vector.id : vector
|
|
148
147
|
file_id = file.respond_to?(:id) ? file.id : file
|
|
149
148
|
req = Net::HTTP::Post.new("/v1/vector_stores/#{vector_id}/files", headers)
|
|
150
|
-
req.body =
|
|
149
|
+
req.body = LLM.json.dump(params.merge({file_id:, attributes:}).compact)
|
|
151
150
|
res = execute(request: req)
|
|
152
151
|
LLM::Response.new(res)
|
|
153
152
|
end
|
|
@@ -176,7 +175,7 @@ class LLM::OpenAI
|
|
|
176
175
|
vector_id = vector.respond_to?(:id) ? vector.id : vector
|
|
177
176
|
file_id = file.respond_to?(:id) ? file.id : file
|
|
178
177
|
req = Net::HTTP::Post.new("/v1/vector_stores/#{vector_id}/files/#{file_id}", headers)
|
|
179
|
-
req.body =
|
|
178
|
+
req.body = LLM.json.dump(params.merge({attributes:}).compact)
|
|
180
179
|
res = execute(request: req)
|
|
181
180
|
LLM::Response.new(res)
|
|
182
181
|
end
|
data/lib/llm/providers/openai.rb
CHANGED
|
@@ -14,11 +14,9 @@ module LLM
|
|
|
14
14
|
# bot.chat ["Tell me about this photo", File.open("/images/capybara.jpg", "rb")]
|
|
15
15
|
# bot.messages.select(&:assistant?).each { print "[#{_1.role}]", _1.content, "\n" }
|
|
16
16
|
class OpenAI < Provider
|
|
17
|
-
require_relative "openai/response/embedding"
|
|
18
|
-
require_relative "openai/response/completion"
|
|
19
|
-
require_relative "openai/response/web_search"
|
|
20
17
|
require_relative "openai/error_handler"
|
|
21
|
-
require_relative "openai/
|
|
18
|
+
require_relative "openai/request_adapter"
|
|
19
|
+
require_relative "openai/response_adapter"
|
|
22
20
|
require_relative "openai/stream_parser"
|
|
23
21
|
require_relative "openai/models"
|
|
24
22
|
require_relative "openai/responses"
|
|
@@ -28,7 +26,7 @@ module LLM
|
|
|
28
26
|
require_relative "openai/moderations"
|
|
29
27
|
require_relative "openai/vector_stores"
|
|
30
28
|
|
|
31
|
-
include
|
|
29
|
+
include RequestAdapter
|
|
32
30
|
|
|
33
31
|
HOST = "api.openai.com"
|
|
34
32
|
|
|
@@ -48,9 +46,9 @@ module LLM
|
|
|
48
46
|
# @return (see LLM::Provider#embed)
|
|
49
47
|
def embed(input, model: "text-embedding-3-small", **params)
|
|
50
48
|
req = Net::HTTP::Post.new("/v1/embeddings", headers)
|
|
51
|
-
req.body =
|
|
49
|
+
req.body = LLM.json.dump({input:, model:}.merge!(params))
|
|
52
50
|
res = execute(request: req)
|
|
53
|
-
|
|
51
|
+
ResponseAdapter.adapt(res, type: :embedding)
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
##
|
|
@@ -66,17 +64,16 @@ module LLM
|
|
|
66
64
|
def complete(prompt, params = {})
|
|
67
65
|
params = {role: :user, model: default_model}.merge!(params)
|
|
68
66
|
tools = resolve_tools(params.delete(:tools))
|
|
69
|
-
params = [params,
|
|
67
|
+
params = [params, adapt_schema(params), adapt_tools(tools)].inject({}, &:merge!).compact
|
|
70
68
|
role, stream = params.delete(:role), params.delete(:stream)
|
|
71
69
|
params[:stream] = true if stream.respond_to?(:<<) || stream == true
|
|
72
70
|
params[:stream_options] = {include_usage: true}.merge!(params[:stream_options] || {}) if params[:stream]
|
|
73
71
|
req = Net::HTTP::Post.new(completions_path, headers)
|
|
74
72
|
messages = [*(params.delete(:messages) || []), Message.new(role, prompt)]
|
|
75
|
-
body =
|
|
73
|
+
body = LLM.json.dump({messages: adapt(messages, mode: :complete).flatten}.merge!(params))
|
|
76
74
|
set_body_stream(req, StringIO.new(body))
|
|
77
75
|
res = execute(request: req, stream:)
|
|
78
|
-
|
|
79
|
-
.extend(LLM::OpenAI::Response::Completion)
|
|
76
|
+
ResponseAdapter.adapt(res, type: :completion)
|
|
80
77
|
.extend(Module.new { define_method(:__tools__) { tools } })
|
|
81
78
|
end
|
|
82
79
|
|
|
@@ -177,9 +174,10 @@ module LLM
|
|
|
177
174
|
# @param query [String] The search query.
|
|
178
175
|
# @return [LLM::Response] The response from the LLM provider.
|
|
179
176
|
def web_search(query:)
|
|
180
|
-
|
|
181
|
-
.create(query, store: false, tools: [server_tools[:web_search]])
|
|
182
|
-
|
|
177
|
+
ResponseAdapter.adapt(
|
|
178
|
+
responses.create(query, store: false, tools: [server_tools[:web_search]]),
|
|
179
|
+
type: :web_search
|
|
180
|
+
)
|
|
183
181
|
end
|
|
184
182
|
|
|
185
183
|
private
|
data/lib/llm/response.rb
CHANGED
|
@@ -25,12 +25,9 @@ module LLM
|
|
|
25
25
|
|
|
26
26
|
##
|
|
27
27
|
# Returns the response body
|
|
28
|
-
# @return [
|
|
28
|
+
# @return [LLM::Object, String]
|
|
29
29
|
def body
|
|
30
|
-
@body
|
|
31
|
-
when %r|\Aapplication/json\s*| then LLM::Object.from_hash(JSON.parse(@res.body))
|
|
32
|
-
else @res.body
|
|
33
|
-
end
|
|
30
|
+
@res.body
|
|
34
31
|
end
|
|
35
32
|
|
|
36
33
|
##
|
data/lib/llm/usage.rb
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
##
|
|
4
|
+
# The {LLM::Usage LLM::Usage} class represents token usage for
|
|
5
|
+
# a given conversation or completion. As a conversation grows,
|
|
6
|
+
# so does the number of tokens used. This class helps track
|
|
7
|
+
# the number of input, output, and total tokens. It can also help
|
|
8
|
+
# track usage of the context window (which may vary by model).
|
|
9
|
+
class LLM::Usage < Struct.new(:input_tokens, :output_tokens, :total_tokens, keyword_init: true)
|
|
10
|
+
end
|
data/lib/llm/version.rb
CHANGED
data/lib/llm.rb
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module LLM
|
|
4
4
|
require "stringio"
|
|
5
|
+
require_relative "llm/json_adapter"
|
|
6
|
+
require_relative "llm/error"
|
|
7
|
+
require_relative "llm/contract"
|
|
8
|
+
require_relative "llm/usage"
|
|
5
9
|
require_relative "llm/builder"
|
|
6
10
|
require_relative "llm/schema"
|
|
7
11
|
require_relative "llm/object"
|
|
8
12
|
require_relative "llm/version"
|
|
9
13
|
require_relative "llm/utils"
|
|
10
|
-
require_relative "llm/error"
|
|
11
14
|
require_relative "llm/message"
|
|
12
15
|
require_relative "llm/response"
|
|
13
16
|
require_relative "llm/mime"
|
|
@@ -28,6 +31,35 @@ module LLM
|
|
|
28
31
|
|
|
29
32
|
module_function
|
|
30
33
|
|
|
34
|
+
##
|
|
35
|
+
# Returns the JSON adapter used by the library
|
|
36
|
+
# @return [Class]
|
|
37
|
+
# Returns a class that responds to +dump+ and +load+
|
|
38
|
+
def json
|
|
39
|
+
@json ||= JSONAdapter::JSON
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# Sets the JSON adapter used by the library
|
|
44
|
+
# @param [Class, String, Symbol] adapter
|
|
45
|
+
# A JSON adapter class or its name
|
|
46
|
+
# @return [void]
|
|
47
|
+
def json=(adapter)
|
|
48
|
+
@json = case adapter.to_s
|
|
49
|
+
when "JSON", "json" then JSONAdapter::JSON
|
|
50
|
+
when "Oj", "oj" then JSONAdapter::Oj
|
|
51
|
+
when "Yajl", "yajl" then JSONAdapter::Yajl
|
|
52
|
+
else
|
|
53
|
+
is_class = Class === adapter
|
|
54
|
+
is_subclass = is_class && adapter.ancestors.include?(LLM::JSONAdapter)
|
|
55
|
+
if is_subclass
|
|
56
|
+
adapter
|
|
57
|
+
else
|
|
58
|
+
raise TypeError, "Adapter must be a subclass of LLM::JSONAdapter"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
31
63
|
##
|
|
32
64
|
# @param (see LLM::Provider#initialize)
|
|
33
65
|
# @return (see LLM::Anthropic#initialize)
|
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:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Antar Azri
|
|
@@ -182,6 +182,8 @@ files:
|
|
|
182
182
|
- lib/llm/buffer.rb
|
|
183
183
|
- lib/llm/builder.rb
|
|
184
184
|
- lib/llm/client.rb
|
|
185
|
+
- lib/llm/contract.rb
|
|
186
|
+
- lib/llm/contract/completion.rb
|
|
185
187
|
- lib/llm/error.rb
|
|
186
188
|
- lib/llm/eventhandler.rb
|
|
187
189
|
- lib/llm/eventstream.rb
|
|
@@ -189,9 +191,11 @@ files:
|
|
|
189
191
|
- lib/llm/eventstream/parser.rb
|
|
190
192
|
- lib/llm/file.rb
|
|
191
193
|
- lib/llm/function.rb
|
|
194
|
+
- lib/llm/json_adapter.rb
|
|
192
195
|
- lib/llm/message.rb
|
|
193
196
|
- lib/llm/mime.rb
|
|
194
197
|
- lib/llm/multipart.rb
|
|
198
|
+
- lib/llm/multipart/enumerator_io.rb
|
|
195
199
|
- lib/llm/object.rb
|
|
196
200
|
- lib/llm/object/builder.rb
|
|
197
201
|
- lib/llm/object/kernel.rb
|
|
@@ -199,62 +203,66 @@ files:
|
|
|
199
203
|
- lib/llm/providers/anthropic.rb
|
|
200
204
|
- lib/llm/providers/anthropic/error_handler.rb
|
|
201
205
|
- lib/llm/providers/anthropic/files.rb
|
|
202
|
-
- lib/llm/providers/anthropic/format.rb
|
|
203
|
-
- lib/llm/providers/anthropic/format/completion_format.rb
|
|
204
206
|
- lib/llm/providers/anthropic/models.rb
|
|
205
|
-
- lib/llm/providers/anthropic/
|
|
206
|
-
- lib/llm/providers/anthropic/
|
|
207
|
-
- lib/llm/providers/anthropic/
|
|
208
|
-
- lib/llm/providers/anthropic/
|
|
207
|
+
- lib/llm/providers/anthropic/request_adapter.rb
|
|
208
|
+
- lib/llm/providers/anthropic/request_adapter/completion.rb
|
|
209
|
+
- lib/llm/providers/anthropic/response_adapter.rb
|
|
210
|
+
- lib/llm/providers/anthropic/response_adapter/completion.rb
|
|
211
|
+
- lib/llm/providers/anthropic/response_adapter/enumerable.rb
|
|
212
|
+
- lib/llm/providers/anthropic/response_adapter/file.rb
|
|
213
|
+
- lib/llm/providers/anthropic/response_adapter/web_search.rb
|
|
209
214
|
- lib/llm/providers/anthropic/stream_parser.rb
|
|
210
215
|
- lib/llm/providers/deepseek.rb
|
|
211
|
-
- lib/llm/providers/deepseek/
|
|
212
|
-
- lib/llm/providers/deepseek/
|
|
216
|
+
- lib/llm/providers/deepseek/request_adapter.rb
|
|
217
|
+
- lib/llm/providers/deepseek/request_adapter/completion.rb
|
|
213
218
|
- lib/llm/providers/gemini.rb
|
|
214
219
|
- lib/llm/providers/gemini/audio.rb
|
|
215
220
|
- lib/llm/providers/gemini/error_handler.rb
|
|
216
221
|
- lib/llm/providers/gemini/files.rb
|
|
217
|
-
- lib/llm/providers/gemini/format.rb
|
|
218
|
-
- lib/llm/providers/gemini/format/completion_format.rb
|
|
219
222
|
- lib/llm/providers/gemini/images.rb
|
|
220
223
|
- lib/llm/providers/gemini/models.rb
|
|
221
|
-
- lib/llm/providers/gemini/
|
|
222
|
-
- lib/llm/providers/gemini/
|
|
223
|
-
- lib/llm/providers/gemini/
|
|
224
|
-
- lib/llm/providers/gemini/
|
|
225
|
-
- lib/llm/providers/gemini/
|
|
226
|
-
- lib/llm/providers/gemini/
|
|
227
|
-
- lib/llm/providers/gemini/
|
|
224
|
+
- lib/llm/providers/gemini/request_adapter.rb
|
|
225
|
+
- lib/llm/providers/gemini/request_adapter/completion.rb
|
|
226
|
+
- lib/llm/providers/gemini/response_adapter.rb
|
|
227
|
+
- lib/llm/providers/gemini/response_adapter/completion.rb
|
|
228
|
+
- lib/llm/providers/gemini/response_adapter/embedding.rb
|
|
229
|
+
- lib/llm/providers/gemini/response_adapter/file.rb
|
|
230
|
+
- lib/llm/providers/gemini/response_adapter/files.rb
|
|
231
|
+
- lib/llm/providers/gemini/response_adapter/image.rb
|
|
232
|
+
- lib/llm/providers/gemini/response_adapter/models.rb
|
|
233
|
+
- lib/llm/providers/gemini/response_adapter/web_search.rb
|
|
228
234
|
- lib/llm/providers/gemini/stream_parser.rb
|
|
229
235
|
- lib/llm/providers/llamacpp.rb
|
|
230
236
|
- lib/llm/providers/ollama.rb
|
|
231
237
|
- lib/llm/providers/ollama/error_handler.rb
|
|
232
|
-
- lib/llm/providers/ollama/format.rb
|
|
233
|
-
- lib/llm/providers/ollama/format/completion_format.rb
|
|
234
238
|
- lib/llm/providers/ollama/models.rb
|
|
235
|
-
- lib/llm/providers/ollama/
|
|
236
|
-
- lib/llm/providers/ollama/
|
|
239
|
+
- lib/llm/providers/ollama/request_adapter.rb
|
|
240
|
+
- lib/llm/providers/ollama/request_adapter/completion.rb
|
|
241
|
+
- lib/llm/providers/ollama/response_adapter.rb
|
|
242
|
+
- lib/llm/providers/ollama/response_adapter/completion.rb
|
|
243
|
+
- lib/llm/providers/ollama/response_adapter/embedding.rb
|
|
237
244
|
- lib/llm/providers/ollama/stream_parser.rb
|
|
238
245
|
- lib/llm/providers/openai.rb
|
|
239
246
|
- lib/llm/providers/openai/audio.rb
|
|
240
247
|
- lib/llm/providers/openai/error_handler.rb
|
|
241
248
|
- lib/llm/providers/openai/files.rb
|
|
242
|
-
- lib/llm/providers/openai/format.rb
|
|
243
|
-
- lib/llm/providers/openai/format/completion_format.rb
|
|
244
|
-
- lib/llm/providers/openai/format/moderation_format.rb
|
|
245
|
-
- lib/llm/providers/openai/format/respond_format.rb
|
|
246
249
|
- lib/llm/providers/openai/images.rb
|
|
247
250
|
- lib/llm/providers/openai/models.rb
|
|
248
251
|
- lib/llm/providers/openai/moderations.rb
|
|
249
|
-
- lib/llm/providers/openai/
|
|
250
|
-
- lib/llm/providers/openai/
|
|
251
|
-
- lib/llm/providers/openai/
|
|
252
|
-
- lib/llm/providers/openai/
|
|
253
|
-
- lib/llm/providers/openai/
|
|
254
|
-
- lib/llm/providers/openai/
|
|
255
|
-
- lib/llm/providers/openai/
|
|
256
|
-
- lib/llm/providers/openai/
|
|
257
|
-
- lib/llm/providers/openai/
|
|
252
|
+
- lib/llm/providers/openai/request_adapter.rb
|
|
253
|
+
- lib/llm/providers/openai/request_adapter/completion.rb
|
|
254
|
+
- lib/llm/providers/openai/request_adapter/moderation.rb
|
|
255
|
+
- lib/llm/providers/openai/request_adapter/respond.rb
|
|
256
|
+
- lib/llm/providers/openai/response_adapter.rb
|
|
257
|
+
- lib/llm/providers/openai/response_adapter/audio.rb
|
|
258
|
+
- lib/llm/providers/openai/response_adapter/completion.rb
|
|
259
|
+
- lib/llm/providers/openai/response_adapter/embedding.rb
|
|
260
|
+
- lib/llm/providers/openai/response_adapter/enumerable.rb
|
|
261
|
+
- lib/llm/providers/openai/response_adapter/file.rb
|
|
262
|
+
- lib/llm/providers/openai/response_adapter/image.rb
|
|
263
|
+
- lib/llm/providers/openai/response_adapter/moderations.rb
|
|
264
|
+
- lib/llm/providers/openai/response_adapter/responds.rb
|
|
265
|
+
- lib/llm/providers/openai/response_adapter/web_search.rb
|
|
258
266
|
- lib/llm/providers/openai/responses.rb
|
|
259
267
|
- lib/llm/providers/openai/responses/stream_parser.rb
|
|
260
268
|
- lib/llm/providers/openai/stream_parser.rb
|
|
@@ -276,6 +284,7 @@ files:
|
|
|
276
284
|
- lib/llm/server_tool.rb
|
|
277
285
|
- lib/llm/tool.rb
|
|
278
286
|
- lib/llm/tool/param.rb
|
|
287
|
+
- lib/llm/usage.rb
|
|
279
288
|
- lib/llm/utils.rb
|
|
280
289
|
- lib/llm/version.rb
|
|
281
290
|
- llm.gemspec
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module LLM::Anthropic::Response
|
|
4
|
-
module Completion
|
|
5
|
-
def choices = format_choices
|
|
6
|
-
def role = body.role
|
|
7
|
-
def model = body.model
|
|
8
|
-
def prompt_tokens = body.usage["input_tokens"] || 0
|
|
9
|
-
def completion_tokens = body.usage["output_tokens"] || 0
|
|
10
|
-
def total_tokens = prompt_tokens + completion_tokens
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
|
|
14
|
-
def format_choices
|
|
15
|
-
texts.map.with_index do |choice, index|
|
|
16
|
-
extra = {
|
|
17
|
-
index:, response: self,
|
|
18
|
-
tool_calls: format_tool_calls(tools), original_tool_calls: tools
|
|
19
|
-
}
|
|
20
|
-
LLM::Message.new(role, choice["text"], extra)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def format_tool_calls(tools)
|
|
25
|
-
(tools || []).filter_map do |tool|
|
|
26
|
-
tool = {
|
|
27
|
-
id: tool.id,
|
|
28
|
-
name: tool.name,
|
|
29
|
-
arguments: tool.input
|
|
30
|
-
}
|
|
31
|
-
LLM::Object.new(tool)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def parts = body.content
|
|
36
|
-
def texts = @texts ||= LLM::Object.from_hash(parts.select { _1["type"] == "text" })
|
|
37
|
-
def tools = @tools ||= LLM::Object.from_hash(parts.select { _1["type"] == "tool_use" })
|
|
38
|
-
end
|
|
39
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module LLM::Gemini::Response
|
|
4
|
-
module Completion
|
|
5
|
-
def model = body.modelVersion
|
|
6
|
-
def prompt_tokens = body.usageMetadata.promptTokenCount
|
|
7
|
-
def completion_tokens = body.usageMetadata.candidatesTokenCount
|
|
8
|
-
def total_tokens = body.usageMetadata.totalTokenCount
|
|
9
|
-
def choices = format_choices
|
|
10
|
-
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
def format_choices
|
|
14
|
-
candidates.map.with_index do |choice, index|
|
|
15
|
-
choice = LLM::Object.from_hash(choice)
|
|
16
|
-
content = choice.content || LLM::Object.new
|
|
17
|
-
role = content.role || "model"
|
|
18
|
-
parts = content.parts || [{"text" => choice.finishReason}]
|
|
19
|
-
text = parts.filter_map { _1["text"] }.join
|
|
20
|
-
tools = parts.filter_map { _1["functionCall"] }
|
|
21
|
-
extra = {index:, response: self, tool_calls: format_tool_calls(tools), original_tool_calls: tools}
|
|
22
|
-
LLM::Message.new(role, text, extra)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def format_tool_calls(tools)
|
|
27
|
-
(tools || []).map do |tool|
|
|
28
|
-
function = {name: tool.name, arguments: tool.args}
|
|
29
|
-
LLM::Object.new(function)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def candidates = body.candidates || []
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module LLM::Ollama::Response
|
|
4
|
-
module Completion
|
|
5
|
-
def model = body.model
|
|
6
|
-
def prompt_tokens = body.prompt_eval_count || 0
|
|
7
|
-
def completion_tokens = body.eval_count || 0
|
|
8
|
-
def total_tokens = prompt_tokens + completion_tokens
|
|
9
|
-
def message = body.message
|
|
10
|
-
def choices = [format_choices]
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
|
|
14
|
-
def format_choices
|
|
15
|
-
role, content, calls = message.to_h.values_at("role", "content", "tool_calls")
|
|
16
|
-
extra = {response: self, tool_calls: format_tool_calls(calls)}
|
|
17
|
-
LLM::Message.new(role, content, extra)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def format_tool_calls(tools)
|
|
21
|
-
return [] unless tools
|
|
22
|
-
tools.filter_map do |tool|
|
|
23
|
-
next unless tool["function"]
|
|
24
|
-
LLM::Object.new(tool["function"])
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module LLM::OpenAI::Response
|
|
4
|
-
module Completion
|
|
5
|
-
def choices
|
|
6
|
-
body.choices.map.with_index do |choice, index|
|
|
7
|
-
choice = LLM::Object.from_hash(choice)
|
|
8
|
-
message = choice.message
|
|
9
|
-
extra = {
|
|
10
|
-
index:, response: self,
|
|
11
|
-
logprobs: choice.logprobs,
|
|
12
|
-
tool_calls: format_tool_calls(message.tool_calls),
|
|
13
|
-
original_tool_calls: message.tool_calls
|
|
14
|
-
}
|
|
15
|
-
LLM::Message.new(message.role, message.content, extra)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
alias_method :messages, :choices
|
|
19
|
-
|
|
20
|
-
def model = body.model
|
|
21
|
-
def prompt_tokens = usage["prompt_tokens"]
|
|
22
|
-
def completion_tokens = usage["completion_tokens"]
|
|
23
|
-
def total_tokens = usage["total_tokens"]
|
|
24
|
-
def usage = body.usage || {}
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def format_tool_calls(tools)
|
|
29
|
-
(tools || []).filter_map do |tool|
|
|
30
|
-
next unless tool.function
|
|
31
|
-
tool = {
|
|
32
|
-
id: tool.id,
|
|
33
|
-
name: tool.function.name,
|
|
34
|
-
arguments: JSON.parse(tool.function.arguments)
|
|
35
|
-
}
|
|
36
|
-
LLM::Object.new(tool)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|