rager 0.5.0 → 0.7.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 +49 -7
- data/lib/rager/chat/message.rb +10 -0
- data/lib/rager/chat/message_content.rb +7 -0
- data/lib/rager/chat/message_delta.rb +7 -0
- data/lib/rager/chat/options.rb +12 -9
- data/lib/rager/chat/providers/openai.rb +64 -48
- data/lib/rager/chat/schema.rb +3 -4
- data/lib/rager/config.rb +16 -20
- data/lib/rager/context.rb +326 -97
- data/lib/rager/context_options.rb +23 -0
- data/lib/rager/embed/options.rb +4 -3
- data/lib/rager/embed/providers/openai.rb +14 -6
- data/lib/rager/errors/credentials_error.rb +24 -0
- data/lib/rager/errors/dependency_error.rb +23 -0
- data/lib/rager/errors/http_error.rb +12 -5
- data/lib/rager/errors/options_error.rb +10 -5
- data/lib/rager/errors/parse_error.rb +9 -5
- data/lib/rager/errors/template_error.rb +10 -4
- data/lib/rager/errors/timeout_error.rb +25 -0
- data/lib/rager/http/adapters/async_http.rb +66 -14
- data/lib/rager/http/adapters/mock.rb +41 -45
- data/lib/rager/http/adapters/net_http.rb +144 -0
- data/lib/rager/http/request.rb +2 -0
- data/lib/rager/{image_gen → image}/options.rb +5 -4
- data/lib/rager/{image_gen → image}/output_format.rb +1 -1
- data/lib/rager/{image_gen → image}/providers/abstract.rb +4 -4
- data/lib/rager/{image_gen → image}/providers/replicate.rb +19 -14
- data/lib/rager/{logger.rb → log_strategy.rb} +2 -1
- data/lib/rager/{mesh_gen → mesh}/options.rb +4 -3
- data/lib/rager/{mesh_gen → mesh}/providers/abstract.rb +4 -4
- data/lib/rager/{mesh_gen → mesh}/providers/replicate.rb +20 -14
- data/lib/rager/operation.rb +2 -2
- data/lib/rager/options.rb +1 -1
- data/lib/rager/outcome.rb +25 -0
- data/lib/rager/providers.rb +61 -0
- data/lib/rager/rerank/{query.rb → input.rb} +8 -1
- data/lib/rager/rerank/options.rb +3 -2
- data/lib/rager/rerank/providers/abstract.rb +2 -2
- data/lib/rager/rerank/providers/cohere.rb +24 -15
- data/lib/rager/rerank/result.rb +8 -1
- data/lib/rager/result.rb +98 -108
- data/lib/rager/search/options.rb +4 -1
- data/lib/rager/search/providers/jina.rb +68 -0
- data/lib/rager/search/result.rb +9 -2
- data/lib/rager/template/input.rb +9 -0
- data/lib/rager/template/options.rb +1 -1
- data/lib/rager/template/providers/erb.rb +3 -3
- data/lib/rager/template/providers/mustache.rb +30 -0
- data/lib/rager/types.rb +28 -17
- data/lib/rager/utils/http.rb +92 -27
- data/lib/rager/utils/replicate.rb +40 -21
- data/lib/rager/utils/runtime.rb +21 -0
- data/lib/rager/version.rb +1 -1
- metadata +22 -36
- data/lib/rager/chat.rb +0 -35
- data/lib/rager/embed.rb +0 -35
- data/lib/rager/errors/missing_credentials_error.rb +0 -19
- data/lib/rager/errors/unknown_provider_error.rb +0 -17
- data/lib/rager/image_gen.rb +0 -31
- data/lib/rager/mesh_gen.rb +0 -31
- data/lib/rager/rerank.rb +0 -35
- data/lib/rager/search/providers/brave.rb +0 -59
- data/lib/rager/search.rb +0 -35
- data/lib/rager/template.rb +0 -35
@@ -8,11 +8,16 @@ module Rager
|
|
8
8
|
class OptionsError < Rager::Error
|
9
9
|
extend T::Sig
|
10
10
|
|
11
|
-
sig { params(invalid_keys: T::Array[String],
|
12
|
-
def initialize(invalid_keys
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
sig { params(options: Rager::Types::Options, invalid_keys: T::Array[String], details: T.nilable(String)).void }
|
12
|
+
def initialize(options, invalid_keys, details: nil)
|
13
|
+
error_data = {
|
14
|
+
type: "options",
|
15
|
+
options: options.serialize_safe,
|
16
|
+
invalid_keys: invalid_keys,
|
17
|
+
details: details
|
18
|
+
}
|
19
|
+
|
20
|
+
super(error_data.to_json)
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
@@ -8,11 +8,15 @@ module Rager
|
|
8
8
|
class ParseError < Rager::Error
|
9
9
|
extend T::Sig
|
10
10
|
|
11
|
-
sig { params(
|
12
|
-
def initialize(
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
sig { params(body: String, details: T.nilable(String)).void }
|
12
|
+
def initialize(body, details: nil)
|
13
|
+
error_data = {
|
14
|
+
type: "parse",
|
15
|
+
body: body,
|
16
|
+
details: details
|
17
|
+
}
|
18
|
+
|
19
|
+
super(error_data.to_json)
|
16
20
|
end
|
17
21
|
end
|
18
22
|
end
|
@@ -8,10 +8,16 @@ module Rager
|
|
8
8
|
class TemplateError < Rager::Error
|
9
9
|
extend T::Sig
|
10
10
|
|
11
|
-
sig { params(
|
12
|
-
def initialize(
|
13
|
-
|
14
|
-
|
11
|
+
sig { params(template: String, variables: T::Hash[Symbol, T.untyped], details: T.nilable(String)).void }
|
12
|
+
def initialize(template, variables, details: nil)
|
13
|
+
error_data = {
|
14
|
+
type: "template",
|
15
|
+
template: template,
|
16
|
+
variables: variables,
|
17
|
+
details: details
|
18
|
+
}
|
19
|
+
|
20
|
+
super(error_data.to_json)
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Errors
|
8
|
+
class TimeoutError < Rager::Error
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
sig { params(operation: String, timeout_seconds: T.nilable(Numeric), attempts: T.nilable(Integer), details: T.nilable(String)).void }
|
12
|
+
def initialize(operation, timeout_seconds: nil, attempts: nil, details: nil)
|
13
|
+
error_data = {
|
14
|
+
type: "timeout",
|
15
|
+
operation: operation,
|
16
|
+
timeout_seconds: timeout_seconds,
|
17
|
+
attempts: attempts,
|
18
|
+
details: details
|
19
|
+
}
|
20
|
+
|
21
|
+
super(error_data.to_json)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -11,7 +11,11 @@ module Rager
|
|
11
11
|
|
12
12
|
sig { void }
|
13
13
|
def initialize
|
14
|
-
|
14
|
+
begin
|
15
|
+
require "async/http"
|
16
|
+
rescue LoadError
|
17
|
+
raise Rager::Errors::DependencyError.new("async-http", details: "Please install the async-http gem to use the AsyncHttp adapter")
|
18
|
+
end
|
15
19
|
|
16
20
|
@internet = T.let(Async::HTTP::Internet.new, Async::HTTP::Internet)
|
17
21
|
end
|
@@ -22,22 +26,21 @@ module Rager
|
|
22
26
|
).returns(Rager::Http::Response)
|
23
27
|
}
|
24
28
|
def make_request(request)
|
25
|
-
response =
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
response = wrap_if_timeout(request.timeout) do
|
30
|
+
@internet.call(
|
31
|
+
request.verb.serialize,
|
32
|
+
request.url,
|
33
|
+
request.headers.to_a,
|
34
|
+
request.body
|
35
|
+
)
|
36
|
+
end
|
31
37
|
|
32
38
|
body = if response.body.nil?
|
33
39
|
nil
|
34
|
-
elsif
|
35
|
-
response.headers["content-type"]&.downcase&.include?("text/event-stream")
|
40
|
+
elsif request.streaming
|
36
41
|
body_enum(response)
|
37
42
|
else
|
38
|
-
|
39
|
-
response.body.each { |chunk| body_parts << chunk }
|
40
|
-
body_parts.join.force_encoding("UTF-8")
|
43
|
+
response.body.join
|
41
44
|
end
|
42
45
|
|
43
46
|
Response.new(
|
@@ -45,9 +48,58 @@ module Rager
|
|
45
48
|
headers: response.headers.to_h,
|
46
49
|
body: body
|
47
50
|
)
|
51
|
+
rescue SocketError => e
|
52
|
+
raise Rager::Errors::HttpError.new(
|
53
|
+
self,
|
54
|
+
request.url,
|
55
|
+
0,
|
56
|
+
body: nil,
|
57
|
+
details: "DNS resolution failed: #{e.message}"
|
58
|
+
)
|
59
|
+
rescue Errno::ECONNREFUSED => e
|
60
|
+
raise Rager::Errors::HttpError.new(
|
61
|
+
self,
|
62
|
+
request.url,
|
63
|
+
0,
|
64
|
+
body: nil,
|
65
|
+
details: "Connection refused: #{e.message}"
|
66
|
+
)
|
67
|
+
rescue Errno::ETIMEDOUT => e
|
68
|
+
raise Rager::Errors::HttpError.new(
|
69
|
+
self,
|
70
|
+
request.url,
|
71
|
+
0,
|
72
|
+
body: nil,
|
73
|
+
details: "Connection timed out: #{e.message}"
|
74
|
+
)
|
75
|
+
rescue Async::TimeoutError => e
|
76
|
+
raise Rager::Errors::HttpError.new(
|
77
|
+
self,
|
78
|
+
request.url,
|
79
|
+
0,
|
80
|
+
body: nil,
|
81
|
+
details: "Request timed out: #{e.message}"
|
82
|
+
)
|
83
|
+
rescue EOFError => e
|
84
|
+
raise Rager::Errors::HttpError.new(
|
85
|
+
self,
|
86
|
+
request.url,
|
87
|
+
0,
|
88
|
+
body: nil,
|
89
|
+
details: "Connection closed unexpectedly: #{e.message}"
|
90
|
+
)
|
48
91
|
end
|
49
92
|
|
50
|
-
|
93
|
+
sig { params(timeout: T.nilable(Numeric), block: T.proc.returns(T.untyped)).returns(T.untyped) }
|
94
|
+
def wrap_if_timeout(timeout, &block)
|
95
|
+
if timeout
|
96
|
+
Async::Task.current.with_timeout(timeout) do
|
97
|
+
block.call
|
98
|
+
end
|
99
|
+
else
|
100
|
+
block.call
|
101
|
+
end
|
102
|
+
end
|
51
103
|
|
52
104
|
sig {
|
53
105
|
params(
|
@@ -56,7 +108,7 @@ module Rager
|
|
56
108
|
}
|
57
109
|
def body_enum(response)
|
58
110
|
Enumerator.new do |yielder|
|
59
|
-
response.body.each { |chunk| yielder << chunk
|
111
|
+
response.body.each { |chunk| yielder << chunk }
|
60
112
|
ensure
|
61
113
|
response.close
|
62
114
|
end
|
@@ -1,8 +1,10 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "base64"
|
4
5
|
require "fileutils"
|
5
6
|
require "json"
|
7
|
+
|
6
8
|
require "sorbet-runtime"
|
7
9
|
|
8
10
|
module Rager
|
@@ -20,13 +22,9 @@ module Rager
|
|
20
22
|
chunk_delimiter: T.nilable(String)
|
21
23
|
).void
|
22
24
|
end
|
23
|
-
def initialize(
|
24
|
-
test_file_path,
|
25
|
-
fallback_adapter = nil,
|
26
|
-
chunk_delimiter = nil
|
27
|
-
)
|
25
|
+
def initialize(test_file_path, fallback_adapter = nil, chunk_delimiter = nil)
|
28
26
|
@test_file_path = T.let(test_file_path, String)
|
29
|
-
@fallback_adapter = T.let(fallback_adapter || Rager::Http::Adapters::
|
27
|
+
@fallback_adapter = T.let(fallback_adapter || Rager::Http::Adapters::NetHttp.new, Rager::Http::Adapters::Abstract)
|
30
28
|
@cache = T.let(load_cache, Cache)
|
31
29
|
end
|
32
30
|
|
@@ -34,48 +32,48 @@ module Rager
|
|
34
32
|
def make_request(request)
|
35
33
|
key = request.serialize.to_json
|
36
34
|
cached_entry = @cache[key]
|
37
|
-
|
38
|
-
build_response_from_cache(cached_entry)
|
39
|
-
else
|
40
|
-
fetch_and_cache_response(request, key)
|
41
|
-
end
|
35
|
+
cached_entry ? build_response_from_cache(cached_entry) : fetch_and_cache_response(request, key)
|
42
36
|
end
|
43
37
|
|
44
|
-
sig {
|
45
|
-
params(
|
46
|
-
request: Rager::Http::Request,
|
47
|
-
key: String
|
48
|
-
).returns(Rager::Http::Response)
|
49
|
-
}
|
38
|
+
sig { params(request: Rager::Http::Request, key: String).returns(Rager::Http::Response) }
|
50
39
|
def fetch_and_cache_response(request, key)
|
51
40
|
response = @fallback_adapter.make_request(request)
|
52
41
|
|
53
|
-
serialized_response =
|
42
|
+
serialized_response = {
|
54
43
|
"status" => response.status,
|
55
44
|
"headers" => response.headers
|
56
|
-
}
|
45
|
+
}
|
57
46
|
|
58
|
-
if response.body.is_a?(Enumerator)
|
59
|
-
|
47
|
+
if request.streaming && response.body.is_a?(Enumerator)
|
48
|
+
raw_chunks = T.let([], T::Array[String])
|
49
|
+
T.cast(response.body, T::Enumerator[String]).each { |chunk| raw_chunks << chunk }
|
60
50
|
|
61
|
-
|
62
|
-
|
63
|
-
end
|
51
|
+
has_binary = raw_chunks.any? { |chunk| binary_content?(chunk) }
|
52
|
+
chunks = raw_chunks.map { |chunk| binary_content?(chunk) ? Base64.strict_encode64(chunk) : chunk }
|
64
53
|
|
65
54
|
serialized_response["body"] = chunks
|
66
55
|
serialized_response["is_stream"] = true
|
56
|
+
serialized_response["is_binary"] = has_binary
|
67
57
|
|
68
58
|
response_body = Enumerator.new do |yielder|
|
69
|
-
|
59
|
+
raw_chunks.each { |chunk| yielder << chunk }
|
70
60
|
end
|
71
61
|
else
|
72
|
-
|
62
|
+
body = T.cast(response.body, T.nilable(String)) || ""
|
63
|
+
|
64
|
+
if binary_content?(body)
|
65
|
+
serialized_response["body"] = Base64.strict_encode64(body)
|
66
|
+
serialized_response["is_binary"] = true
|
67
|
+
else
|
68
|
+
serialized_response["body"] = body
|
69
|
+
serialized_response["is_binary"] = false
|
70
|
+
end
|
71
|
+
|
73
72
|
serialized_response["is_stream"] = false
|
74
|
-
response_body =
|
73
|
+
response_body = body
|
75
74
|
end
|
76
75
|
|
77
76
|
@cache[key] = serialized_response
|
78
|
-
|
79
77
|
save_cache
|
80
78
|
|
81
79
|
Rager::Http::Response.new(
|
@@ -85,19 +83,19 @@ module Rager
|
|
85
83
|
)
|
86
84
|
end
|
87
85
|
|
88
|
-
sig {
|
89
|
-
params(
|
90
|
-
entry: T::Hash[String, T.untyped]
|
91
|
-
).returns(Rager::Http::Response)
|
92
|
-
}
|
86
|
+
sig { params(entry: T::Hash[String, T.untyped]).returns(Rager::Http::Response) }
|
93
87
|
def build_response_from_cache(entry)
|
94
88
|
body = entry["body"]
|
95
89
|
is_stream = entry["is_stream"] || false
|
90
|
+
is_binary = entry["is_binary"] || false
|
96
91
|
|
97
92
|
body = if is_stream
|
98
|
-
T.cast(body, T::Array[String])
|
93
|
+
chunks = T.cast(body, T::Array[String])
|
94
|
+
Enumerator.new do |yielder|
|
95
|
+
chunks.each { |chunk| yielder << (is_binary ? Base64.strict_decode64(chunk) : chunk) }
|
96
|
+
end
|
99
97
|
else
|
100
|
-
body
|
98
|
+
is_binary ? Base64.strict_decode64(T.cast(body, String)) : body
|
101
99
|
end
|
102
100
|
|
103
101
|
Rager::Http::Response.new(
|
@@ -116,21 +114,19 @@ module Rager
|
|
116
114
|
sig { returns(Cache) }
|
117
115
|
def load_cache
|
118
116
|
create_file_if_not_exists
|
119
|
-
JSON.parse(File.read(@test_file_path
|
117
|
+
JSON.parse(File.read(@test_file_path))
|
120
118
|
end
|
121
119
|
|
122
120
|
sig { void }
|
123
121
|
def save_cache
|
124
|
-
current_file_content =
|
125
|
-
if File.exist?(@test_file_path)
|
126
|
-
JSON.parse(File.read(@test_file_path, encoding: "UTF-8"))
|
127
|
-
else
|
128
|
-
{}
|
129
|
-
end
|
130
|
-
|
122
|
+
current_file_content = File.exist?(@test_file_path) ? JSON.parse(File.read(@test_file_path)) : {}
|
131
123
|
output = current_file_content.merge(@cache)
|
132
|
-
|
133
|
-
|
124
|
+
File.write(@test_file_path, JSON.generate(output))
|
125
|
+
end
|
126
|
+
|
127
|
+
sig { params(content: String).returns(T::Boolean) }
|
128
|
+
def binary_content?(content)
|
129
|
+
content.include?("\0")
|
134
130
|
end
|
135
131
|
end
|
136
132
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "net/http"
|
5
|
+
require "uri"
|
6
|
+
require "sorbet-runtime"
|
7
|
+
|
8
|
+
module Rager
|
9
|
+
module Http
|
10
|
+
module Adapters
|
11
|
+
class NetHttp < Rager::Http::Adapters::Abstract
|
12
|
+
extend T::Sig
|
13
|
+
|
14
|
+
sig { void }
|
15
|
+
def initialize
|
16
|
+
end
|
17
|
+
|
18
|
+
sig {
|
19
|
+
override.params(
|
20
|
+
request: Rager::Http::Request
|
21
|
+
).returns(Rager::Http::Response)
|
22
|
+
}
|
23
|
+
def make_request(request)
|
24
|
+
uri = URI(request.url)
|
25
|
+
|
26
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
27
|
+
http.use_ssl = uri.scheme == "https"
|
28
|
+
|
29
|
+
if request.timeout
|
30
|
+
http.open_timeout = request.timeout
|
31
|
+
http.read_timeout = request.timeout
|
32
|
+
end
|
33
|
+
|
34
|
+
http_request = build_http_request(request, uri)
|
35
|
+
|
36
|
+
http.request(http_request) do |response|
|
37
|
+
body = if request.streaming
|
38
|
+
body_enum(response)
|
39
|
+
else
|
40
|
+
response.body
|
41
|
+
end
|
42
|
+
|
43
|
+
return Rager::Http::Response.new(
|
44
|
+
status: response.code.to_i,
|
45
|
+
headers: response.to_hash,
|
46
|
+
body: body
|
47
|
+
)
|
48
|
+
end
|
49
|
+
rescue SocketError => e
|
50
|
+
raise Rager::Errors::HttpError.new(
|
51
|
+
self,
|
52
|
+
request.url,
|
53
|
+
0,
|
54
|
+
body: nil,
|
55
|
+
details: "DNS resolution failed: #{e.message}"
|
56
|
+
)
|
57
|
+
rescue Errno::ECONNREFUSED => e
|
58
|
+
raise Rager::Errors::HttpError.new(
|
59
|
+
self,
|
60
|
+
request.url,
|
61
|
+
0,
|
62
|
+
body: nil,
|
63
|
+
details: "Connection refused: #{e.message}"
|
64
|
+
)
|
65
|
+
rescue Errno::EBUSY => e
|
66
|
+
raise Rager::Errors::HttpError.new(
|
67
|
+
self,
|
68
|
+
request.url,
|
69
|
+
0,
|
70
|
+
body: nil,
|
71
|
+
details: "Device or resource busy: #{e.message}"
|
72
|
+
)
|
73
|
+
rescue Net::OpenTimeout => e
|
74
|
+
raise Rager::Errors::HttpError.new(
|
75
|
+
self,
|
76
|
+
request.url,
|
77
|
+
0,
|
78
|
+
body: nil,
|
79
|
+
details: "Connection timed out: #{e.message}"
|
80
|
+
)
|
81
|
+
rescue Net::ReadTimeout => e
|
82
|
+
raise Rager::Errors::HttpError.new(
|
83
|
+
self,
|
84
|
+
request.url,
|
85
|
+
0,
|
86
|
+
body: nil,
|
87
|
+
details: "Read timed out: #{e.message}"
|
88
|
+
)
|
89
|
+
rescue EOFError => e
|
90
|
+
raise Rager::Errors::HttpError.new(
|
91
|
+
self,
|
92
|
+
request.url,
|
93
|
+
0,
|
94
|
+
body: nil,
|
95
|
+
details: "Connection closed unexpectedly: #{e.message}"
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
sig {
|
100
|
+
params(
|
101
|
+
response: Net::HTTPResponse
|
102
|
+
).returns(T::Enumerator[String])
|
103
|
+
}
|
104
|
+
def body_enum(response)
|
105
|
+
chunks = T.let([], T::Array[String])
|
106
|
+
|
107
|
+
response.read_body do |chunk|
|
108
|
+
chunks << chunk
|
109
|
+
end
|
110
|
+
|
111
|
+
chunks.to_enum
|
112
|
+
end
|
113
|
+
|
114
|
+
sig {
|
115
|
+
params(
|
116
|
+
request: Rager::Http::Request,
|
117
|
+
uri: URI::Generic
|
118
|
+
).returns(Net::HTTPRequest)
|
119
|
+
}
|
120
|
+
def build_http_request(request, uri)
|
121
|
+
http_request = case request.verb
|
122
|
+
when Rager::Http::Verb::Get then Net::HTTP::Get.new(uri)
|
123
|
+
when Rager::Http::Verb::Post then Net::HTTP::Post.new(uri)
|
124
|
+
when Rager::Http::Verb::Put then Net::HTTP::Put.new(uri)
|
125
|
+
when Rager::Http::Verb::Patch then Net::HTTP::Patch.new(uri)
|
126
|
+
when Rager::Http::Verb::Delete then Net::HTTP::Delete.new(uri)
|
127
|
+
when Rager::Http::Verb::Head then Net::HTTP::Head.new(uri)
|
128
|
+
when Rager::Http::Verb::Options then Net::HTTP::Options.new(uri)
|
129
|
+
end
|
130
|
+
|
131
|
+
request.headers.each do |key, value|
|
132
|
+
http_request[key] = value
|
133
|
+
end
|
134
|
+
|
135
|
+
if request.body && http_request.request_body_permitted?
|
136
|
+
http_request.body = request.body
|
137
|
+
end
|
138
|
+
|
139
|
+
http_request
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/lib/rager/http/request.rb
CHANGED
@@ -10,6 +10,8 @@ module Rager
|
|
10
10
|
const :verb, Rager::Http::Verb, default: Rager::Http::Verb::Get
|
11
11
|
const :headers, T::Hash[String, String]
|
12
12
|
const :body, T.nilable(String)
|
13
|
+
const :streaming, T::Boolean, default: false
|
14
|
+
const :timeout, T.nilable(Numeric)
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -4,16 +4,17 @@
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
|
6
6
|
module Rager
|
7
|
-
module
|
7
|
+
module Image
|
8
8
|
class Options < T::Struct
|
9
9
|
extend T::Sig
|
10
10
|
include Rager::Options
|
11
11
|
|
12
|
-
const :provider,
|
12
|
+
const :provider, Symbol, default: :replicate
|
13
13
|
const :model, String, default: "black-forest-labs/flux-schnell"
|
14
|
-
const :output_format, T.nilable(Rager::
|
15
|
-
const :api_key, T.nilable(String)
|
14
|
+
const :output_format, T.nilable(Rager::Image::OutputFormat)
|
16
15
|
const :seed, T.nilable(Integer)
|
16
|
+
const :api_key, T.nilable(String)
|
17
|
+
const :timeout, T.nilable(Numeric)
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
|
6
6
|
module Rager
|
7
|
-
module
|
7
|
+
module Image
|
8
8
|
module Providers
|
9
9
|
class Abstract
|
10
10
|
extend T::Sig
|
@@ -14,10 +14,10 @@ module Rager
|
|
14
14
|
sig do
|
15
15
|
abstract.params(
|
16
16
|
prompt: String,
|
17
|
-
options: Rager::
|
18
|
-
).returns(Rager::Types::
|
17
|
+
options: Rager::Image::Options
|
18
|
+
).returns(Rager::Types::ImageOutput)
|
19
19
|
end
|
20
|
-
def
|
20
|
+
def image(prompt, options)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -5,15 +5,23 @@ require "sorbet-runtime"
|
|
5
5
|
require "json"
|
6
6
|
|
7
7
|
module Rager
|
8
|
-
module
|
8
|
+
module Image
|
9
9
|
module Providers
|
10
|
-
class Replicate < Rager::
|
10
|
+
class Replicate < Rager::Image::Providers::Abstract
|
11
11
|
extend T::Sig
|
12
12
|
|
13
|
-
sig { override.params(prompt: String, options: Rager::
|
14
|
-
def
|
13
|
+
sig { override.params(prompt: String, options: Rager::Image::Options).returns(Rager::Types::ImageOutput) }
|
14
|
+
def image(prompt, options)
|
15
15
|
api_key = options.api_key || ENV["REPLICATE_API_KEY"]
|
16
|
-
raise Rager::Errors::
|
16
|
+
raise Rager::Errors::CredentialsError.new("Replicate", env_var: ["REPLICATE_API_KEY"]) if api_key.nil?
|
17
|
+
|
18
|
+
url = "https://api.replicate.com/v1/models/#{options.model}/predictions"
|
19
|
+
|
20
|
+
headers = {
|
21
|
+
"Authorization" => "Bearer #{api_key}",
|
22
|
+
"Content-Type" => "application/json",
|
23
|
+
"Prefer" => "wait"
|
24
|
+
}
|
17
25
|
|
18
26
|
body = {
|
19
27
|
input: {
|
@@ -25,25 +33,22 @@ module Rager
|
|
25
33
|
end
|
26
34
|
|
27
35
|
request = Rager::Http::Request.new(
|
28
|
-
url:
|
36
|
+
url: url,
|
29
37
|
verb: Rager::Http::Verb::Post,
|
30
|
-
headers:
|
31
|
-
|
32
|
-
|
33
|
-
"Prefer" => "wait"
|
34
|
-
},
|
35
|
-
body: body.to_json
|
38
|
+
headers: headers,
|
39
|
+
body: body.to_json,
|
40
|
+
timeout: options.timeout || Rager.config.timeout
|
36
41
|
)
|
37
42
|
|
38
43
|
response = Rager.config.http_adapter.make_request(request)
|
39
44
|
response_body = T.cast(T.must(response.body), String)
|
40
45
|
|
41
|
-
raise Rager::Errors::HttpError.new(Rager.config.http_adapter, response.status, response_body) unless [200, 201].include?(response.status)
|
46
|
+
raise Rager::Errors::HttpError.new(Rager.config.http_adapter, request.url, response.status, body: response_body) unless [200, 201].include?(response.status)
|
42
47
|
|
43
48
|
parsed = JSON.parse(response_body)
|
44
49
|
parsed.fetch("output").first
|
45
50
|
rescue JSON::ParserError, KeyError => e
|
46
|
-
raise Rager::Errors::ParseError.new(e.message
|
51
|
+
raise Rager::Errors::ParseError.new(response_body || "", details: e.message)
|
47
52
|
end
|
48
53
|
end
|
49
54
|
end
|
@@ -4,16 +4,17 @@
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
|
6
6
|
module Rager
|
7
|
-
module
|
7
|
+
module Mesh
|
8
8
|
class Options < T::Struct
|
9
9
|
extend T::Sig
|
10
10
|
include Rager::Options
|
11
11
|
|
12
|
-
const :provider,
|
12
|
+
const :provider, Symbol, default: :replicate
|
13
13
|
const :model, String, default: "firoz/trellis"
|
14
14
|
const :version, String, default: "4876f2a8da1c544772dffa32e8889da4a1bab3a1f5c1937bfcfccb99ae347251"
|
15
|
-
const :api_key, T.nilable(String)
|
16
15
|
const :seed, T.nilable(Integer)
|
16
|
+
const :api_key, T.nilable(String)
|
17
|
+
const :timeout, T.nilable(Numeric)
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|