ox-ai-workers 1.1.0.1 → 1.1.1.1
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/CHANGELOG.md +4 -0
- data/lib/oxaiworkers/iterator.rb +4 -4
- data/lib/oxaiworkers/models/anthropic_max.rb +1 -1
- data/lib/oxaiworkers/models/gemini_pro.rb +151 -0
- data/lib/oxaiworkers/models/llm_base.rb +2 -2
- data/lib/oxaiworkers/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c834fb5bda0eea743e7a05d9f9f895f17f0ba566a19933e5e8fab2d55239e2a
|
4
|
+
data.tar.gz: cee14714d3c1fffb86eae51f23f036b7bc9bfa8cac57e87c51fd314406ed4eca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0231e2b17097087d373e0108993425be918e189cd2ad8acd587ea33ae5492965162f2cf11ef02ef241b3358db29843c6ff26a5d5c90afeb11bb708adc3ebef51
|
7
|
+
data.tar.gz: 31f417a2415d3424e61ace88d4f3876e93843d06d8dcf6101e1f2f1b936729eca15f5c699c764ffdbb848c644746ec4fde4892ed19201daf492fb7d684966175
|
data/CHANGELOG.md
CHANGED
data/lib/oxaiworkers/iterator.rb
CHANGED
@@ -131,7 +131,7 @@ module OxAiWorkers
|
|
131
131
|
@worker.append(role: :user, content: tool.context) if tool.respond_to?(:context) && tool.context.present?
|
132
132
|
end
|
133
133
|
@worker.append(messages: @messages)
|
134
|
-
@tasks.each { |task| @worker.append(role: :user, content: "<task>\n#{task}\n</task>") }
|
134
|
+
# @tasks.each { |task| @worker.append(role: :user, content: "<task>\n#{task}\n</task>") }
|
135
135
|
@worker.tools = [function_schemas]
|
136
136
|
return unless @tools.present?
|
137
137
|
|
@@ -264,15 +264,15 @@ module OxAiWorkers
|
|
264
264
|
add_raw_context({ role:, content: text })
|
265
265
|
end
|
266
266
|
|
267
|
-
def add_file(pdf:,
|
268
|
-
content = @worker.model.add_base64(binary: pdf,
|
267
|
+
def add_file(pdf:, text:, role: :user)
|
268
|
+
content = @worker.model.add_base64(binary: pdf, text:, mime_type: 'application/pdf')
|
269
269
|
add_raw_context({ role:, content: })
|
270
270
|
end
|
271
271
|
|
272
272
|
def add_image(text:, url: nil, binary: nil, role: :user, detail: 'auto', mime_type: 'image/png')
|
273
273
|
content = []
|
274
274
|
if binary.present?
|
275
|
-
content = @worker.model.add_base64(binary:,
|
275
|
+
content = @worker.model.add_base64(binary:, text:, mime_type:, detail:)
|
276
276
|
elsif url.present?
|
277
277
|
content = @worker.model.add_url(url:, text:, detail:, mime_type:)
|
278
278
|
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OxAiWorkers
|
4
|
+
module Models
|
5
|
+
class GeminiPro < LLMBase
|
6
|
+
def initialize(uri_base: nil, api_key: nil, model: nil, max_tokens: nil, temperature: nil, frequency_penalty: nil)
|
7
|
+
@model = model || 'gemini-pro'
|
8
|
+
@uri_base = uri_base # || 'https://api.anthropic.com/v1/'
|
9
|
+
@api_key = api_key || OxAiWorkers.configuration.access_token_gemini
|
10
|
+
super(uri_base: @uri_base, api_key: @api_key, model: @model, max_tokens:, temperature:, frequency_penalty:)
|
11
|
+
end
|
12
|
+
|
13
|
+
def client
|
14
|
+
Gemini.new(
|
15
|
+
credentials: {
|
16
|
+
service: 'generative-language-api',
|
17
|
+
api_key: ENV['GOOGLE_API_KEY']
|
18
|
+
},
|
19
|
+
options: { model: 'gemini-pro', server_sent_events: true }
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def request(parameters)
|
24
|
+
client.messages(parameters:)
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_parameters(messages:, tools: [], filtered_functions: [], tool_choice: nil)
|
28
|
+
parameters = {
|
29
|
+
model: @model,
|
30
|
+
system: messages.select { |m| m[:role] == :system }.map { |m| m[:content] }.join("\n\n"),
|
31
|
+
messages: messages.reject { |m| m[:role] == :system },
|
32
|
+
temperature: @temperature,
|
33
|
+
max_tokens: @max_tokens
|
34
|
+
}
|
35
|
+
if tools.present?
|
36
|
+
functions = tools.map(&:to_anthropic_format).flatten
|
37
|
+
|
38
|
+
@names = functions.map { |f| f[:name] }
|
39
|
+
|
40
|
+
parameters[:tools] = functions.reject { |f| filtered_functions.include?(f[:name]) }
|
41
|
+
|
42
|
+
parameters[:tool_choice] =
|
43
|
+
tool_choice.nil? ? { type: 'any' } : { type: 'tool', name: tool_choice }
|
44
|
+
end
|
45
|
+
parameters
|
46
|
+
end
|
47
|
+
|
48
|
+
def tool_call(name:, args:, call_id:, out:)
|
49
|
+
[
|
50
|
+
{
|
51
|
+
role: :assistant,
|
52
|
+
content: [
|
53
|
+
{
|
54
|
+
type: 'tool_use',
|
55
|
+
id: "call_#{call_id}",
|
56
|
+
name:,
|
57
|
+
input: args
|
58
|
+
}
|
59
|
+
]
|
60
|
+
},
|
61
|
+
{
|
62
|
+
role: :user,
|
63
|
+
content: [
|
64
|
+
{
|
65
|
+
type: 'tool_result',
|
66
|
+
tool_use_id: "call_#{call_id}",
|
67
|
+
content: out.present? ? out : "Tool call #{name} successful."
|
68
|
+
}
|
69
|
+
]
|
70
|
+
}
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_base64(binary:, filename:, text:, mime_type:)
|
75
|
+
content = []
|
76
|
+
content << { type: 'text', text: } if text.present?
|
77
|
+
content << {
|
78
|
+
type: mime_type.include?('image') ? 'image' : 'document',
|
79
|
+
source: {
|
80
|
+
type: 'base64',
|
81
|
+
media_type: mime_type,
|
82
|
+
data: Base64.strict_encode64(binary)
|
83
|
+
}
|
84
|
+
}
|
85
|
+
content
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_url(url:, text:, mime_type:)
|
89
|
+
content = []
|
90
|
+
content << { type: 'text', text: } if text.present?
|
91
|
+
content << {
|
92
|
+
type: mime_type.include?('image') ? 'image' : 'document',
|
93
|
+
source: {
|
94
|
+
type: 'url',
|
95
|
+
url: url
|
96
|
+
}
|
97
|
+
}
|
98
|
+
content
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_response(response, &)
|
102
|
+
choices = response['content']
|
103
|
+
@is_truncated = (response['stop_reason'] == 'max_tokens')
|
104
|
+
return if choices.nil? || choices.empty?
|
105
|
+
|
106
|
+
choices.each do |choice|
|
107
|
+
result, tool_calls = parse_one_choice(choice)
|
108
|
+
yield(result, @is_truncated, tool_calls)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def parse_one_choice(choice)
|
113
|
+
return unless choice # Skip if there's no choice
|
114
|
+
|
115
|
+
# Initialize result variables
|
116
|
+
@result = nil
|
117
|
+
@tool_calls = []
|
118
|
+
|
119
|
+
# Process content item
|
120
|
+
if choice['type'] == 'tool_use'
|
121
|
+
# Handle tool use
|
122
|
+
begin
|
123
|
+
# Attempt to parse arguments, handle potential JSON errors
|
124
|
+
args = JSON.parse(choice['input'].to_json, symbolize_names: true)
|
125
|
+
rescue JSON::ParserError => e
|
126
|
+
OxAiWorkers.logger.error("Failed to parse tool call arguments: #{e.message}", for: self.class)
|
127
|
+
OxAiWorkers.logger.debug("Raw arguments: #{choice['input']}", for: self.class)
|
128
|
+
end
|
129
|
+
|
130
|
+
fname = @names.find { |n| n.end_with?(choice['name']) }
|
131
|
+
if fname != choice['name']
|
132
|
+
OxAiWorkers.logger.error("Tool call name #{choice['name']} not found. Using #{fname} instead.",
|
133
|
+
for: self.class)
|
134
|
+
end
|
135
|
+
|
136
|
+
tool_call = {
|
137
|
+
class: fname.split('__').first,
|
138
|
+
name: fname.split('__').last,
|
139
|
+
args:
|
140
|
+
}
|
141
|
+
@tool_calls << tool_call
|
142
|
+
elsif choice['type'] == 'text'
|
143
|
+
# Handle text content
|
144
|
+
@result = choice['text']
|
145
|
+
end
|
146
|
+
|
147
|
+
[@result, @tool_calls]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -66,7 +66,7 @@ module OxAiWorkers
|
|
66
66
|
]
|
67
67
|
end
|
68
68
|
|
69
|
-
def add_base64(binary:,
|
69
|
+
def add_base64(binary:, text:, mime_type:, detail: 'auto')
|
70
70
|
content = []
|
71
71
|
content << { type: 'text', text: } if text.present?
|
72
72
|
content << if mime_type.include?('image')
|
@@ -80,7 +80,7 @@ module OxAiWorkers
|
|
80
80
|
{
|
81
81
|
type: 'file',
|
82
82
|
file: {
|
83
|
-
filename
|
83
|
+
filename: "file.#{mime_type.split('/').last}",
|
84
84
|
file_data: "data:#{mime_type};base64,#{Base64.strict_encode64(binary)}"
|
85
85
|
}
|
86
86
|
}
|
data/lib/oxaiworkers/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox-ai-workers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Smolev
|
@@ -159,6 +159,7 @@ files:
|
|
159
159
|
- lib/oxaiworkers/load_i18n.rb
|
160
160
|
- lib/oxaiworkers/models/anthropic_max.rb
|
161
161
|
- lib/oxaiworkers/models/deepseek_max.rb
|
162
|
+
- lib/oxaiworkers/models/gemini_pro.rb
|
162
163
|
- lib/oxaiworkers/models/images_base.rb
|
163
164
|
- lib/oxaiworkers/models/llm_base.rb
|
164
165
|
- lib/oxaiworkers/models/openai_dalle3.rb
|