rager 0.1.0 → 0.2.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/LICENSE.md +0 -0
- data/README.md +5 -2
- data/lib/rager/chat/message.rb +0 -0
- data/lib/rager/chat/message_content.rb +0 -0
- data/lib/rager/chat/message_content_image_type.rb +0 -0
- data/lib/rager/chat/message_content_type.rb +0 -0
- data/lib/rager/chat/message_delta.rb +0 -0
- data/lib/rager/chat/message_role.rb +0 -0
- data/lib/rager/chat/options.rb +0 -0
- data/lib/rager/chat/providers/abstract.rb +0 -0
- data/lib/rager/chat/providers/openai.rb +1 -1
- data/lib/rager/chat/schema.rb +0 -0
- data/lib/rager/chat.rb +0 -0
- data/lib/rager/config.rb +0 -0
- data/lib/rager/context.rb +71 -5
- data/lib/rager/embed/options.rb +30 -0
- data/lib/rager/embed/providers/abstract.rb +25 -0
- data/lib/rager/embed/providers/openai.rb +61 -0
- data/lib/rager/embed.rb +35 -0
- data/lib/rager/error.rb +0 -0
- data/lib/rager/errors/http_error.rb +0 -0
- data/lib/rager/errors/missing_credentials_error.rb +0 -0
- data/lib/rager/errors/options_error.rb +0 -0
- data/lib/rager/errors/parse_error.rb +0 -0
- data/lib/rager/errors/template_error.rb +18 -0
- data/lib/rager/errors/unknown_provider_error.rb +0 -0
- data/lib/rager/http/adapters/abstract.rb +0 -0
- data/lib/rager/http/adapters/async_http.rb +3 -1
- data/lib/rager/http/adapters/mock.rb +0 -0
- data/lib/rager/http/request.rb +0 -0
- data/lib/rager/http/response.rb +0 -0
- data/lib/rager/http/verb.rb +0 -0
- data/lib/rager/image_gen/options.rb +0 -0
- data/lib/rager/image_gen/providers/abstract.rb +0 -0
- data/lib/rager/image_gen/providers/replicate.rb +0 -0
- data/lib/rager/image_gen.rb +0 -0
- data/lib/rager/logger.rb +0 -0
- data/lib/rager/mesh_gen/options.rb +0 -0
- data/lib/rager/mesh_gen/providers/abstract.rb +0 -0
- data/lib/rager/mesh_gen/providers/replicate.rb +0 -0
- data/lib/rager/mesh_gen.rb +0 -0
- data/lib/rager/operation.rb +4 -0
- data/lib/rager/options.rb +0 -0
- data/lib/rager/rerank/options.rb +30 -0
- data/lib/rager/rerank/providers/abstract.rb +25 -0
- data/lib/rager/rerank/providers/cohere.rb +73 -0
- data/lib/rager/rerank/query.rb +13 -0
- data/lib/rager/rerank/result.rb +13 -0
- data/lib/rager/rerank.rb +35 -0
- data/lib/rager/result.rb +38 -6
- data/lib/rager/search/options.rb +28 -0
- data/lib/rager/search/providers/abstract.rb +25 -0
- data/lib/rager/search/providers/brave.rb +76 -0
- data/lib/rager/search/result.rb +14 -0
- data/lib/rager/search.rb +35 -0
- data/lib/rager/template/input.rb +11 -0
- data/lib/rager/template/options.rb +22 -0
- data/lib/rager/template/providers/abstract.rb +26 -0
- data/lib/rager/template/providers/erb.rb +26 -0
- data/lib/rager/template.rb +35 -0
- data/lib/rager/types.rb +29 -6
- data/lib/rager/version.rb +1 -1
- data/lib/rager.rb +0 -0
- metadata +22 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e401a4ed178d55d22d62a7b7af27f0657b39c10a894bc3a4abbfbab4464a056e
|
4
|
+
data.tar.gz: c228006086780e6926c4510dcdc0a4caf34a21cfebeba921a2d314bfdcfe8360
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c940c14f9e301b27742e48f3a817931d14e02c53c32fd70e85f3087a7905629e3470ae06a0a2859bd5ddf9a56e25685f4d01d232f255d8fb132650912f370fb
|
7
|
+
data.tar.gz: 57b9001ce21f873d71831e2655c54e585af5109e6ecdc26ede198ffcee79e568b31b23f93e2516d2c66bf49678a3ccc9ea400be8286ad0bc5846719a61e650ea
|
data/LICENSE.md
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# rager_rb
|
2
2
|
|
3
|
-
[](https://badge.fury.io/rb/rager)
|
4
|
+
[](https://github.com/mvkvc/rager_rb/actions/workflows/publish.yml)
|
5
|
+
[](https://github.com/mvkvc/rager_rb/actions/workflows/test.yml)
|
6
|
+
[](https://github.com/mvkvc/rager_rb/actions/workflows/lint.yml)
|
4
7
|
|
5
8
|
Build continuously improving AI applications.
|
6
9
|
|
@@ -15,7 +18,7 @@ bundle add rager
|
|
15
18
|
Otherwise you can add it to your Gemfile directly:
|
16
19
|
|
17
20
|
```Ruby
|
18
|
-
gem "rager", "~> 0.
|
21
|
+
gem "rager", "~> 0.2.0"
|
19
22
|
```
|
20
23
|
|
21
24
|
## License
|
data/lib/rager/chat/message.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/rager/chat/options.rb
CHANGED
File without changes
|
File without changes
|
@@ -23,7 +23,7 @@ module Rager
|
|
23
23
|
raise Rager::Errors::MissingCredentialsError.new("OpenAI", "OPENAI_API_KEY") if api_key.nil?
|
24
24
|
|
25
25
|
url = options.url || ENV["OPENAI_URL"] || "https://api.openai.com/v1/chat/completions"
|
26
|
-
model = options.model || "gpt-
|
26
|
+
model = options.model || "gpt-4.1"
|
27
27
|
|
28
28
|
openai_messages = build_openai_messages(messages, options.history, options.system_prompt)
|
29
29
|
|
data/lib/rager/chat/schema.rb
CHANGED
File without changes
|
data/lib/rager/chat.rb
CHANGED
File without changes
|
data/lib/rager/config.rb
CHANGED
File without changes
|
data/lib/rager/context.rb
CHANGED
@@ -44,6 +44,25 @@ module Rager
|
|
44
44
|
) { |options| Chat.chat(messages, options) }
|
45
45
|
end
|
46
46
|
|
47
|
+
sig do
|
48
|
+
params(
|
49
|
+
text: T.any(String, T::Array[String]),
|
50
|
+
kwargs: T.untyped
|
51
|
+
).returns(Rager::Result)
|
52
|
+
end
|
53
|
+
def embed(text, **kwargs)
|
54
|
+
if text.is_a?(String)
|
55
|
+
text = [text]
|
56
|
+
end
|
57
|
+
|
58
|
+
execute(
|
59
|
+
Rager::Operation::Embed,
|
60
|
+
Rager::Embed::Options,
|
61
|
+
kwargs,
|
62
|
+
text
|
63
|
+
) { |options| Embed.embed(text, options) }
|
64
|
+
end
|
65
|
+
|
47
66
|
sig do
|
48
67
|
params(
|
49
68
|
prompt: String,
|
@@ -74,6 +93,51 @@ module Rager
|
|
74
93
|
) { |options| MeshGen.mesh_gen(prompt, options) }
|
75
94
|
end
|
76
95
|
|
96
|
+
sig do
|
97
|
+
params(
|
98
|
+
query: Rager::Rerank::Query,
|
99
|
+
kwargs: T.untyped
|
100
|
+
).returns(Rager::Result)
|
101
|
+
end
|
102
|
+
def rerank(query, **kwargs)
|
103
|
+
execute(
|
104
|
+
Rager::Operation::Rerank,
|
105
|
+
Rager::Rerank::Options,
|
106
|
+
kwargs,
|
107
|
+
query
|
108
|
+
) { |options| Rager::Rerank.rerank(query, options) }
|
109
|
+
end
|
110
|
+
|
111
|
+
sig do
|
112
|
+
params(
|
113
|
+
query: String,
|
114
|
+
kwargs: T.untyped
|
115
|
+
).returns(Rager::Result)
|
116
|
+
end
|
117
|
+
def search(query, **kwargs)
|
118
|
+
execute(
|
119
|
+
Rager::Operation::Search,
|
120
|
+
Rager::Search::Options,
|
121
|
+
kwargs,
|
122
|
+
query
|
123
|
+
) { |options| Search.search(query, options) }
|
124
|
+
end
|
125
|
+
|
126
|
+
sig do
|
127
|
+
params(
|
128
|
+
input: Rager::Template::Input,
|
129
|
+
kwargs: T.untyped
|
130
|
+
).returns(Rager::Result)
|
131
|
+
end
|
132
|
+
def template(input, **kwargs)
|
133
|
+
execute(
|
134
|
+
Rager::Operation::Template,
|
135
|
+
Rager::Template::Options,
|
136
|
+
kwargs,
|
137
|
+
input
|
138
|
+
) { |options| Template.template(input, options) }
|
139
|
+
end
|
140
|
+
|
77
141
|
private
|
78
142
|
|
79
143
|
sig do
|
@@ -81,11 +145,13 @@ module Rager
|
|
81
145
|
operation: Rager::Operation,
|
82
146
|
options_struct: T::Class[Rager::Options],
|
83
147
|
kwargs: T.untyped,
|
84
|
-
input:
|
148
|
+
input: Rager::Types::Input,
|
85
149
|
block: T.proc.params(options: T.untyped).returns(T.untyped)
|
86
150
|
).returns(Rager::Result)
|
87
151
|
end
|
88
152
|
def execute(operation, options_struct, kwargs, input, &block)
|
153
|
+
input_ids = kwargs.delete(:input_ids)
|
154
|
+
|
89
155
|
options = options_struct.new(**kwargs)
|
90
156
|
options.validate
|
91
157
|
|
@@ -94,6 +160,7 @@ module Rager
|
|
94
160
|
output = yield(options)
|
95
161
|
|
96
162
|
Result.new(
|
163
|
+
id: @id,
|
97
164
|
context_id: @id,
|
98
165
|
hash: @hash,
|
99
166
|
operation: operation,
|
@@ -101,12 +168,11 @@ module Rager
|
|
101
168
|
options: options,
|
102
169
|
start_time: start_time.to_i,
|
103
170
|
end_time: Time.now.to_i,
|
104
|
-
output: output
|
105
|
-
|
171
|
+
output: output,
|
172
|
+
input_ids: input_ids
|
173
|
+
).tap(&:log)
|
106
174
|
end
|
107
175
|
|
108
|
-
private
|
109
|
-
|
110
176
|
sig { returns(T.nilable(String)) }
|
111
177
|
def lookup_git_hash
|
112
178
|
result = `git rev-parse HEAD`
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Embed
|
8
|
+
class Options < T::Struct
|
9
|
+
extend T::Sig
|
10
|
+
include Rager::Options
|
11
|
+
|
12
|
+
const :provider, String, default: "openai"
|
13
|
+
const :url, T.nilable(String)
|
14
|
+
const :model, T.nilable(String)
|
15
|
+
const :api_key, T.nilable(String)
|
16
|
+
const :seed, T.nilable(Integer)
|
17
|
+
|
18
|
+
sig { override.returns(T::Hash[String, T.untyped]) }
|
19
|
+
def serialize_safe
|
20
|
+
result = serialize
|
21
|
+
result["api_key"] = "[REDACTED]" if result.key?("api_key")
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { override.void }
|
26
|
+
def validate
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Embed
|
8
|
+
module Providers
|
9
|
+
class Abstract
|
10
|
+
extend T::Sig
|
11
|
+
extend T::Helpers
|
12
|
+
abstract!
|
13
|
+
|
14
|
+
sig do
|
15
|
+
abstract.params(
|
16
|
+
text: T::Array[String],
|
17
|
+
options: Rager::Embed::Options
|
18
|
+
).returns(Rager::Types::EmbedOutput)
|
19
|
+
end
|
20
|
+
def embed(text, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
require "sorbet-runtime"
|
6
|
+
|
7
|
+
module Rager
|
8
|
+
module Embed
|
9
|
+
module Providers
|
10
|
+
class Openai < Rager::Embed::Providers::Abstract
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
sig do
|
14
|
+
override.params(
|
15
|
+
text: T::Array[String],
|
16
|
+
options: Rager::Embed::Options
|
17
|
+
).returns(Rager::Types::EmbedOutput)
|
18
|
+
end
|
19
|
+
def embed(text, options)
|
20
|
+
api_key = options.api_key || ENV["OPENAI_API_KEY"]
|
21
|
+
raise Rager::Errors::MissingCredentialsError.new("OpenAI", "OPENAI_API_KEY") if api_key.nil?
|
22
|
+
|
23
|
+
url = options.url || ENV["OPENAI_URL"] || "https://api.openai.com/v1/embeddings"
|
24
|
+
model = options.model || "text-embedding-3-large"
|
25
|
+
|
26
|
+
headers = {
|
27
|
+
"Content-Type" => "application/json"
|
28
|
+
}
|
29
|
+
headers["Authorization"] = "Bearer #{api_key}" if api_key
|
30
|
+
|
31
|
+
body = {
|
32
|
+
model: model,
|
33
|
+
input: text
|
34
|
+
}
|
35
|
+
|
36
|
+
request = Rager::Http::Request.new(
|
37
|
+
verb: Rager::Http::Verb::Post,
|
38
|
+
url: url,
|
39
|
+
headers: headers,
|
40
|
+
body: body.to_json
|
41
|
+
)
|
42
|
+
|
43
|
+
http_adapter = Rager.config.http_adapter
|
44
|
+
response = http_adapter.make_request(request)
|
45
|
+
response_body = T.cast(T.must(response.body), String)
|
46
|
+
|
47
|
+
if response.status != 200
|
48
|
+
raise Rager::Errors::HttpError.new(
|
49
|
+
http_adapter,
|
50
|
+
response.status,
|
51
|
+
response_body
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
parsed_response = JSON.parse(response_body)
|
56
|
+
parsed_response["data"].map { |item| item["embedding"] }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/rager/embed.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Embed
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig do
|
11
|
+
params(
|
12
|
+
text: T::Array[String],
|
13
|
+
options: Rager::Embed::Options
|
14
|
+
).returns(Rager::Types::EmbedOutput)
|
15
|
+
end
|
16
|
+
def self.embed(text, options = Rager::Embed::Options.new)
|
17
|
+
provider = get_provider(options.provider)
|
18
|
+
provider.embed(text, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
key: String
|
24
|
+
).returns(Rager::Embed::Providers::Abstract)
|
25
|
+
end
|
26
|
+
def self.get_provider(key)
|
27
|
+
case key.downcase
|
28
|
+
when "openai"
|
29
|
+
Rager::Embed::Providers::Openai.new
|
30
|
+
else
|
31
|
+
raise Rager::Errors::UnknownProviderError.new(Rager::Operation::Embed, key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/rager/error.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Errors
|
8
|
+
class TemplateError < Rager::Error
|
9
|
+
extend T::Sig
|
10
|
+
|
11
|
+
sig { params(input: Rager::Template::Input, message: String).void }
|
12
|
+
def initialize(input, message)
|
13
|
+
message = "Template Error: #{message} in #{input.template}"
|
14
|
+
super(message)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
File without changes
|
File without changes
|
@@ -35,7 +35,9 @@ module Rager
|
|
35
35
|
response.headers["content-type"]&.downcase&.include?("text/event-stream")
|
36
36
|
body_enum(response)
|
37
37
|
else
|
38
|
-
|
38
|
+
body_parts = []
|
39
|
+
response.body.each { |chunk| body_parts << chunk }
|
40
|
+
body_parts.join.force_encoding("UTF-8")
|
39
41
|
end
|
40
42
|
|
41
43
|
Response.new(
|
File without changes
|
data/lib/rager/http/request.rb
CHANGED
File without changes
|
data/lib/rager/http/response.rb
CHANGED
File without changes
|
data/lib/rager/http/verb.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/rager/image_gen.rb
CHANGED
File without changes
|
data/lib/rager/logger.rb
CHANGED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/lib/rager/mesh_gen.rb
CHANGED
File without changes
|
data/lib/rager/operation.rb
CHANGED
@@ -7,8 +7,12 @@ module Rager
|
|
7
7
|
class Operation < T::Enum
|
8
8
|
enums do
|
9
9
|
Chat = new("chat")
|
10
|
+
Embed = new("embed")
|
10
11
|
ImageGen = new("image_gen")
|
11
12
|
MeshGen = new("mesh_gen")
|
13
|
+
Rerank = new("rerank")
|
14
|
+
Search = new("search")
|
15
|
+
Template = new("template")
|
12
16
|
end
|
13
17
|
end
|
14
18
|
end
|
data/lib/rager/options.rb
CHANGED
File without changes
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Rerank
|
8
|
+
class Options < T::Struct
|
9
|
+
extend T::Sig
|
10
|
+
include Rager::Options
|
11
|
+
|
12
|
+
const :provider, String, default: "cohere"
|
13
|
+
const :url, T.nilable(String)
|
14
|
+
const :model, T.nilable(String)
|
15
|
+
const :n, T.nilable(Integer)
|
16
|
+
const :api_key, T.nilable(String)
|
17
|
+
|
18
|
+
sig { override.returns(T::Hash[String, T.untyped]) }
|
19
|
+
def serialize_safe
|
20
|
+
result = serialize
|
21
|
+
result["api_key"] = "[REDACTED]" if result.key?("api_key")
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { override.void }
|
26
|
+
def validate
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Rerank
|
8
|
+
module Providers
|
9
|
+
class Abstract
|
10
|
+
extend T::Sig
|
11
|
+
extend T::Helpers
|
12
|
+
abstract!
|
13
|
+
|
14
|
+
sig do
|
15
|
+
abstract.params(
|
16
|
+
query: Rager::Rerank::Query,
|
17
|
+
options: Rager::Rerank::Options
|
18
|
+
).returns(Rager::Types::RerankOutput)
|
19
|
+
end
|
20
|
+
def rerank(query, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
require "sorbet-runtime"
|
6
|
+
|
7
|
+
module Rager
|
8
|
+
module Rerank
|
9
|
+
module Providers
|
10
|
+
class Cohere < Rager::Rerank::Providers::Abstract
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
sig do
|
14
|
+
override.params(
|
15
|
+
query: Rager::Rerank::Query,
|
16
|
+
options: Rager::Rerank::Options
|
17
|
+
).returns(Rager::Types::RerankOutput)
|
18
|
+
end
|
19
|
+
def rerank(query, options)
|
20
|
+
api_key = options.api_key || ENV["COHERE_API_KEY"]
|
21
|
+
raise Rager::Errors::MissingCredentialsError.new("Cohere", "COHERE_API_KEY") if api_key.nil?
|
22
|
+
|
23
|
+
url = options.url || ENV["COHERE_URL"] || "https://api.cohere.com/v2/rerank"
|
24
|
+
model = options.model || "rerank-v3.5"
|
25
|
+
|
26
|
+
headers = {
|
27
|
+
"Content-Type" => "application/json"
|
28
|
+
}
|
29
|
+
headers["Authorization"] = "Bearer #{api_key}" if api_key
|
30
|
+
|
31
|
+
body = {
|
32
|
+
model: model,
|
33
|
+
query: query.query,
|
34
|
+
documents: query.documents
|
35
|
+
}
|
36
|
+
body[:top_n] = options.n if options.n
|
37
|
+
|
38
|
+
request = Rager::Http::Request.new(
|
39
|
+
verb: Rager::Http::Verb::Post,
|
40
|
+
url: url,
|
41
|
+
headers: headers,
|
42
|
+
body: body.to_json
|
43
|
+
)
|
44
|
+
|
45
|
+
http_adapter = Rager.config.http_adapter
|
46
|
+
response = http_adapter.make_request(request)
|
47
|
+
response_body = T.cast(T.must(response.body), String)
|
48
|
+
|
49
|
+
if response.status != 200
|
50
|
+
raise Rager::Errors::HttpError.new(
|
51
|
+
http_adapter,
|
52
|
+
response.status,
|
53
|
+
response_body
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
parsed_response = JSON.parse(response_body)
|
58
|
+
|
59
|
+
results = parsed_response["results"] || []
|
60
|
+
results.map do |result|
|
61
|
+
index = result["index"]
|
62
|
+
score = result["relevance_score"]
|
63
|
+
|
64
|
+
Rager::Rerank::Result.new(
|
65
|
+
score: score,
|
66
|
+
index: index
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/rager/rerank.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Rerank
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig do
|
11
|
+
params(
|
12
|
+
query: Rager::Rerank::Query,
|
13
|
+
options: Rager::Rerank::Options
|
14
|
+
).returns(Rager::Types::RerankOutput)
|
15
|
+
end
|
16
|
+
def self.rerank(query, options = Rager::Rerank::Options.new)
|
17
|
+
provider = get_provider(options.provider)
|
18
|
+
provider.rerank(query, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
key: String
|
24
|
+
).returns(Rager::Rerank::Providers::Abstract)
|
25
|
+
end
|
26
|
+
def self.get_provider(key)
|
27
|
+
case key.downcase
|
28
|
+
when "cohere"
|
29
|
+
Rager::Rerank::Providers::Cohere.new
|
30
|
+
else
|
31
|
+
raise Rager::Errors::UnknownProviderError.new(Rager::Operation::Rerank, key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/rager/result.rb
CHANGED
@@ -9,6 +9,9 @@ module Rager
|
|
9
9
|
class Result
|
10
10
|
extend T::Sig
|
11
11
|
|
12
|
+
sig { returns(String) }
|
13
|
+
attr_reader :id
|
14
|
+
|
12
15
|
sig { returns(Rager::Operation) }
|
13
16
|
attr_reader :operation
|
14
17
|
|
@@ -33,8 +36,12 @@ module Rager
|
|
33
36
|
sig { returns(T.nilable(String)) }
|
34
37
|
attr_reader :hash
|
35
38
|
|
39
|
+
sig { returns(T.nilable(T::Array[String])) }
|
40
|
+
attr_reader :input_ids
|
41
|
+
|
36
42
|
sig do
|
37
43
|
params(
|
44
|
+
id: String,
|
38
45
|
operation: Rager::Operation,
|
39
46
|
options: Rager::Options,
|
40
47
|
input: Rager::Types::Input,
|
@@ -42,10 +49,12 @@ module Rager
|
|
42
49
|
start_time: Integer,
|
43
50
|
end_time: Integer,
|
44
51
|
context_id: T.nilable(String),
|
45
|
-
hash: T.nilable(String)
|
52
|
+
hash: T.nilable(String),
|
53
|
+
input_ids: T.nilable(T::Array[String])
|
46
54
|
).void
|
47
55
|
end
|
48
56
|
def initialize(
|
57
|
+
id:,
|
49
58
|
operation:,
|
50
59
|
options:,
|
51
60
|
input:,
|
@@ -53,8 +62,10 @@ module Rager
|
|
53
62
|
start_time:,
|
54
63
|
end_time:,
|
55
64
|
context_id: nil,
|
56
|
-
hash: nil
|
65
|
+
hash: nil,
|
66
|
+
input_ids: nil
|
57
67
|
)
|
68
|
+
@id = id
|
58
69
|
@operation = operation
|
59
70
|
@options = options
|
60
71
|
@input = input
|
@@ -67,6 +78,7 @@ module Rager
|
|
67
78
|
@result_id = T.let(SecureRandom.uuid, T.nilable(String))
|
68
79
|
@context_id = T.let(context_id, T.nilable(String))
|
69
80
|
@hash = T.let(hash, T.nilable(String))
|
81
|
+
@input_ids = T.let(input_ids, T.nilable(T::Array[String]))
|
70
82
|
end
|
71
83
|
|
72
84
|
sig { returns(T::Boolean) }
|
@@ -117,13 +129,31 @@ module Rager
|
|
117
129
|
.map { |_, content| content }
|
118
130
|
end
|
119
131
|
|
120
|
-
sig
|
132
|
+
sig do
|
133
|
+
returns(
|
134
|
+
T.any(
|
135
|
+
String,
|
136
|
+
T::Hash[String, T.untyped],
|
137
|
+
T::Array[T.untyped]
|
138
|
+
)
|
139
|
+
)
|
140
|
+
end
|
121
141
|
def serialize_input
|
122
142
|
case @input
|
123
143
|
when String
|
124
144
|
@input
|
145
|
+
when Rager::Rerank::Query
|
146
|
+
@input.serialize
|
147
|
+
when Rager::Template::Input
|
148
|
+
@input.serialize
|
125
149
|
when Array
|
126
|
-
@input.map
|
150
|
+
@input.map do |item|
|
151
|
+
if !item.is_a?(String)
|
152
|
+
item.serialize
|
153
|
+
else
|
154
|
+
item
|
155
|
+
end
|
156
|
+
end
|
127
157
|
end
|
128
158
|
end
|
129
159
|
|
@@ -141,6 +171,7 @@ module Rager
|
|
141
171
|
sig { returns(T::Hash[String, T.untyped]) }
|
142
172
|
def to_h
|
143
173
|
{
|
174
|
+
id: @id,
|
144
175
|
operation: @operation.serialize,
|
145
176
|
options: @options.serialize_safe,
|
146
177
|
input: serialize_input,
|
@@ -155,7 +186,8 @@ module Rager
|
|
155
186
|
end_time: @end_time,
|
156
187
|
result_id: @result_id,
|
157
188
|
context_id: @context_id,
|
158
|
-
hash: @hash
|
189
|
+
hash: @hash,
|
190
|
+
input_ids: @input_ids
|
159
191
|
}
|
160
192
|
end
|
161
193
|
|
@@ -167,7 +199,7 @@ module Rager
|
|
167
199
|
|
168
200
|
case Rager.config.logger
|
169
201
|
when Rager::Logger::Stdout
|
170
|
-
puts "
|
202
|
+
puts "\nLOG: #{json}"
|
171
203
|
when Rager::Logger::Remote
|
172
204
|
http_adapter = Rager.config.http_adapter
|
173
205
|
url = Rager.config.url
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Search
|
8
|
+
class Options < T::Struct
|
9
|
+
extend T::Sig
|
10
|
+
include Rager::Options
|
11
|
+
|
12
|
+
const :provider, String, default: "brave"
|
13
|
+
const :n, T.nilable(Integer)
|
14
|
+
const :api_key, T.nilable(String)
|
15
|
+
|
16
|
+
sig { override.returns(T::Hash[String, T.untyped]) }
|
17
|
+
def serialize_safe
|
18
|
+
result = serialize
|
19
|
+
result["api_key"] = "[REDACTED]" if result.key?("api_key")
|
20
|
+
result
|
21
|
+
end
|
22
|
+
|
23
|
+
sig { override.void }
|
24
|
+
def validate
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Search
|
8
|
+
module Providers
|
9
|
+
class Abstract
|
10
|
+
extend T::Sig
|
11
|
+
extend T::Helpers
|
12
|
+
abstract!
|
13
|
+
|
14
|
+
sig do
|
15
|
+
abstract.params(
|
16
|
+
query: String,
|
17
|
+
options: Rager::Search::Options
|
18
|
+
).returns(Rager::Types::SearchOutput)
|
19
|
+
end
|
20
|
+
def search(query, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "json"
|
5
|
+
require "uri"
|
6
|
+
require "sorbet-runtime"
|
7
|
+
|
8
|
+
module Rager
|
9
|
+
module Search
|
10
|
+
module Providers
|
11
|
+
class Brave < Rager::Search::Providers::Abstract
|
12
|
+
extend T::Sig
|
13
|
+
|
14
|
+
sig do
|
15
|
+
override.params(
|
16
|
+
query: String,
|
17
|
+
options: Rager::Search::Options
|
18
|
+
).returns(Rager::Types::SearchOutput)
|
19
|
+
end
|
20
|
+
def search(query, options)
|
21
|
+
api_key = options.api_key || ENV["BRAVE_API_KEY"]
|
22
|
+
raise Rager::Errors::MissingCredentialsError.new("Brave", "BRAVE_API_KEY") if api_key.nil?
|
23
|
+
|
24
|
+
params = {"q" => query}
|
25
|
+
params["count"] = options.n.to_s if options.n
|
26
|
+
|
27
|
+
query_string = URI.encode_www_form(params)
|
28
|
+
url = "https://api.search.brave.com/res/v1/web/search?#{query_string}"
|
29
|
+
|
30
|
+
headers = {
|
31
|
+
"Accept" => "application/json",
|
32
|
+
"Accept-Encoding" => "gzip",
|
33
|
+
"x-subscription-token" => api_key
|
34
|
+
}
|
35
|
+
|
36
|
+
request = Rager::Http::Request.new(
|
37
|
+
verb: Rager::Http::Verb::Get,
|
38
|
+
url: url,
|
39
|
+
headers: headers
|
40
|
+
)
|
41
|
+
|
42
|
+
http_adapter = Rager.config.http_adapter
|
43
|
+
response = http_adapter.make_request(request)
|
44
|
+
response_body = T.cast(T.must(response.body), String)
|
45
|
+
|
46
|
+
if response.status != 200
|
47
|
+
raise Rager::Errors::HttpError.new(
|
48
|
+
http_adapter,
|
49
|
+
response.status,
|
50
|
+
response_body
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
parsed_response = JSON.parse(response_body)
|
55
|
+
|
56
|
+
results = []
|
57
|
+
|
58
|
+
if parsed_response["web"] && parsed_response["web"]["results"]
|
59
|
+
web_results = parsed_response["web"]["results"]
|
60
|
+
web_results.each do |result|
|
61
|
+
next unless result["title"] && result["url"] && result["description"]
|
62
|
+
|
63
|
+
results << Rager::Search::Result.new(
|
64
|
+
title: result["title"],
|
65
|
+
url: result["url"],
|
66
|
+
description: result["description"]
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
results
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/rager/search.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Search
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig do
|
11
|
+
params(
|
12
|
+
query: String,
|
13
|
+
options: Rager::Search::Options
|
14
|
+
).returns(Rager::Types::SearchOutput)
|
15
|
+
end
|
16
|
+
def self.search(query, options = Rager::Search::Options.new)
|
17
|
+
provider = get_provider(options.provider)
|
18
|
+
provider.search(query, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
key: String
|
24
|
+
).returns(Rager::Search::Providers::Abstract)
|
25
|
+
end
|
26
|
+
def self.get_provider(key)
|
27
|
+
case key.downcase
|
28
|
+
when "brave"
|
29
|
+
Rager::Search::Providers::Brave.new
|
30
|
+
else
|
31
|
+
raise Rager::Errors::UnknownProviderError.new(Rager::Operation::Search, key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Rager
|
5
|
+
module Template
|
6
|
+
class Options < T::Struct
|
7
|
+
include Rager::Options
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
const :provider, String, default: "erb"
|
11
|
+
|
12
|
+
sig { override.returns(T::Hash[String, T.untyped]) }
|
13
|
+
def serialize_safe
|
14
|
+
serialize.transform_keys(&:to_s)
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { override.void }
|
18
|
+
def validate
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Template
|
8
|
+
module Providers
|
9
|
+
class Abstract
|
10
|
+
extend T::Sig
|
11
|
+
extend T::Helpers
|
12
|
+
|
13
|
+
abstract!
|
14
|
+
|
15
|
+
sig do
|
16
|
+
abstract.params(
|
17
|
+
input: Rager::Template::Input,
|
18
|
+
options: Rager::Template::Options
|
19
|
+
).returns(Rager::Types::TemplateOutput)
|
20
|
+
end
|
21
|
+
def template(input, options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "erb"
|
5
|
+
require "ostruct"
|
6
|
+
|
7
|
+
module Rager
|
8
|
+
module Template
|
9
|
+
module Providers
|
10
|
+
class Erb < Rager::Template::Providers::Abstract
|
11
|
+
extend T::Sig
|
12
|
+
|
13
|
+
sig do
|
14
|
+
override.params(
|
15
|
+
input: Rager::Template::Input,
|
16
|
+
options: Rager::Template::Options
|
17
|
+
).returns(Rager::Types::TemplateOutput)
|
18
|
+
end
|
19
|
+
def template(input, options)
|
20
|
+
scope = OpenStruct.new(input.variables)
|
21
|
+
ERB.new(input.template).result(scope.instance_eval { binding })
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Rager
|
7
|
+
module Template
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig do
|
11
|
+
params(
|
12
|
+
input: Rager::Template::Input,
|
13
|
+
options: Rager::Template::Options
|
14
|
+
).returns(Rager::Types::TemplateOutput)
|
15
|
+
end
|
16
|
+
def self.template(input, options = Rager::Template::Options.new)
|
17
|
+
provider = get_provider(options.provider)
|
18
|
+
provider.template(input, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
key: String
|
24
|
+
).returns(Rager::Template::Providers::Abstract)
|
25
|
+
end
|
26
|
+
def self.get_provider(key)
|
27
|
+
case key.downcase
|
28
|
+
when "erb"
|
29
|
+
Rager::Template::Providers::Erb.new
|
30
|
+
else
|
31
|
+
raise Rager::Errors::UnknownProviderError.new(Rager::Operation::Template, key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/rager/types.rb
CHANGED
@@ -5,40 +5,63 @@ module Rager
|
|
5
5
|
module Types
|
6
6
|
extend T::Sig
|
7
7
|
|
8
|
-
ChatInput = T.type_alias { T
|
8
|
+
ChatInput = T.type_alias { T::Array[Rager::Chat::Message] }
|
9
|
+
EmbedInput = T.type_alias { T::Array[String] }
|
9
10
|
ImageGenInput = T.type_alias { String }
|
10
11
|
MeshGenInput = T.type_alias { String }
|
12
|
+
RerankInput = T.type_alias { Rager::Rerank::Query }
|
13
|
+
SearchInput = T.type_alias { String }
|
14
|
+
TemplateInput = T.type_alias { Rager::Template::Input }
|
11
15
|
Input = T.type_alias {
|
12
16
|
T.any(
|
13
17
|
ChatInput,
|
18
|
+
EmbedInput,
|
14
19
|
ImageGenInput,
|
15
|
-
MeshGenInput
|
20
|
+
MeshGenInput,
|
21
|
+
RerankInput,
|
22
|
+
SearchInput,
|
23
|
+
TemplateInput
|
16
24
|
)
|
17
25
|
}
|
18
26
|
|
27
|
+
ChatNonStream = T.type_alias { T::Array[String] }
|
28
|
+
|
19
29
|
ChatStream = T.type_alias { T::Enumerator[Rager::Chat::MessageDelta] }
|
20
30
|
Stream = T.type_alias { ChatStream }
|
21
31
|
|
22
32
|
ChatBuffer = T.type_alias { T::Array[Rager::Chat::MessageDelta] }
|
23
33
|
Buffer = T.type_alias { ChatBuffer }
|
24
34
|
|
25
|
-
ChatOutput = T.type_alias { T.any(
|
35
|
+
ChatOutput = T.type_alias { T.any(ChatNonStream, ChatStream) }
|
36
|
+
EmbedOutput = T.type_alias { T::Array[T::Array[Float]] }
|
26
37
|
ImageGenOutput = T.type_alias { String }
|
27
38
|
MeshGenOutput = T.type_alias { String }
|
39
|
+
RerankOutput = T.type_alias { T::Array[Rager::Rerank::Result] }
|
40
|
+
SearchOutput = T.type_alias { T::Array[Rager::Search::Result] }
|
41
|
+
TemplateOutput = T.type_alias { String }
|
28
42
|
Output = T.type_alias {
|
29
43
|
T.any(
|
30
44
|
ChatOutput,
|
45
|
+
EmbedOutput,
|
31
46
|
ImageGenOutput,
|
32
|
-
MeshGenOutput
|
47
|
+
MeshGenOutput,
|
48
|
+
RerankOutput,
|
49
|
+
SearchOutput,
|
50
|
+
TemplateOutput
|
33
51
|
)
|
34
52
|
}
|
35
53
|
|
36
|
-
ChatNonStreamOutput = T.type_alias {
|
54
|
+
ChatNonStreamOutput = T.type_alias { ChatNonStream }
|
55
|
+
|
37
56
|
NonStreamOutput = T.type_alias {
|
38
57
|
T.any(
|
39
58
|
ChatNonStreamOutput,
|
59
|
+
EmbedOutput,
|
40
60
|
ImageGenOutput,
|
41
|
-
MeshGenOutput
|
61
|
+
MeshGenOutput,
|
62
|
+
RerankOutput,
|
63
|
+
SearchOutput,
|
64
|
+
TemplateOutput
|
42
65
|
)
|
43
66
|
}
|
44
67
|
end
|
data/lib/rager/version.rb
CHANGED
data/lib/rager.rb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mvkvc
|
@@ -73,11 +73,16 @@ files:
|
|
73
73
|
- lib/rager/chat/schema.rb
|
74
74
|
- lib/rager/config.rb
|
75
75
|
- lib/rager/context.rb
|
76
|
+
- lib/rager/embed.rb
|
77
|
+
- lib/rager/embed/options.rb
|
78
|
+
- lib/rager/embed/providers/abstract.rb
|
79
|
+
- lib/rager/embed/providers/openai.rb
|
76
80
|
- lib/rager/error.rb
|
77
81
|
- lib/rager/errors/http_error.rb
|
78
82
|
- lib/rager/errors/missing_credentials_error.rb
|
79
83
|
- lib/rager/errors/options_error.rb
|
80
84
|
- lib/rager/errors/parse_error.rb
|
85
|
+
- lib/rager/errors/template_error.rb
|
81
86
|
- lib/rager/errors/unknown_provider_error.rb
|
82
87
|
- lib/rager/http/adapters/abstract.rb
|
83
88
|
- lib/rager/http/adapters/async_http.rb
|
@@ -96,7 +101,23 @@ files:
|
|
96
101
|
- lib/rager/mesh_gen/providers/replicate.rb
|
97
102
|
- lib/rager/operation.rb
|
98
103
|
- lib/rager/options.rb
|
104
|
+
- lib/rager/rerank.rb
|
105
|
+
- lib/rager/rerank/options.rb
|
106
|
+
- lib/rager/rerank/providers/abstract.rb
|
107
|
+
- lib/rager/rerank/providers/cohere.rb
|
108
|
+
- lib/rager/rerank/query.rb
|
109
|
+
- lib/rager/rerank/result.rb
|
99
110
|
- lib/rager/result.rb
|
111
|
+
- lib/rager/search.rb
|
112
|
+
- lib/rager/search/options.rb
|
113
|
+
- lib/rager/search/providers/abstract.rb
|
114
|
+
- lib/rager/search/providers/brave.rb
|
115
|
+
- lib/rager/search/result.rb
|
116
|
+
- lib/rager/template.rb
|
117
|
+
- lib/rager/template/input.rb
|
118
|
+
- lib/rager/template/options.rb
|
119
|
+
- lib/rager/template/providers/abstract.rb
|
120
|
+
- lib/rager/template/providers/erb.rb
|
100
121
|
- lib/rager/types.rb
|
101
122
|
- lib/rager/version.rb
|
102
123
|
homepage: https://github.com/mvkvc/rager_ruby
|