rubycanusellm 0.2.0 → 0.3.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/CHANGELOG.md +9 -1
- data/lib/rubycanusellm/embedding_response.rb +23 -0
- data/lib/rubycanusellm/providers/base.rb +4 -0
- data/lib/rubycanusellm/providers/openai.rb +38 -1
- data/lib/rubycanusellm/version.rb +1 -1
- data/lib/rubycanusellm.rb +5 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 76737cbccfa63deb73a8a13e57c7202d42eb0689595ddae1b1cedf122f262e91
|
|
4
|
+
data.tar.gz: 282fda500fb7f36bebcd7e4fc3683a25e264e483b63e264da5aeb21b5cf229ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ffb10c5216314c8ae733b3be09391197a8e785308c42555764e7bc0144e958638dfb8a253e5d818ed6ba77eb69ee07e1b9279f4a7aafd1aca6e7f0e26f8c1b1
|
|
7
|
+
data.tar.gz: de69c64ab2ee56df386974bd9f99ffbcbc374cd4661b6394ee3295338f02ecee6cab439fbcd0a6bd3b8d9e54b045ef065fda7a8e290d4f6c6a95cce69cdc7949
|
data/CHANGELOG.md
CHANGED
|
@@ -20,4 +20,12 @@
|
|
|
20
20
|
- CLI with generators:
|
|
21
21
|
- `generate:config` — scaffolds configuration file
|
|
22
22
|
- `generate:completion` — scaffolds completion service object
|
|
23
|
-
- Rails and plain Ruby project detection for generators
|
|
23
|
+
- Rails and plain Ruby project detection for generators
|
|
24
|
+
|
|
25
|
+
## [0.3.0] - 2025-04-03
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Embeddings support for OpenAI provider (text-embedding-3-small)
|
|
30
|
+
- EmbeddingResponse object with cosine similarity helper
|
|
31
|
+
- `RubyCanUseLLM.embed` method
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RubyCanUseLLM
|
|
4
|
+
class EmbeddingResponse
|
|
5
|
+
attr_reader :embedding, :model, :tokens, :raw
|
|
6
|
+
|
|
7
|
+
def initialize(embedding:, model:, tokens:, raw:)
|
|
8
|
+
@embedding = embedding
|
|
9
|
+
@model = model
|
|
10
|
+
@tokens = tokens
|
|
11
|
+
@raw = raw
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cosine_similarity(other)
|
|
15
|
+
dot = embedding.zip(other).sum { |a, b| a * b }
|
|
16
|
+
mag_a = Math.sqrt(embedding.sum { |a| a**2 })
|
|
17
|
+
mag_b = Math.sqrt(other.sum { |b| b**2 })
|
|
18
|
+
return 0.0 if mag_a.zero? || mag_b.zero?
|
|
19
|
+
|
|
20
|
+
dot / (mag_a * mag_b)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -20,6 +20,15 @@ module RubyCanUseLLM
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
def embed(text, **options)
|
|
24
|
+
body = {
|
|
25
|
+
model: options[:model] || "text-embedding-3-small",
|
|
26
|
+
input: text
|
|
27
|
+
}
|
|
28
|
+
response = embedding_request(body)
|
|
29
|
+
parse_embedding(response)
|
|
30
|
+
end
|
|
31
|
+
|
|
23
32
|
private
|
|
24
33
|
|
|
25
34
|
def build_body(messages, options)
|
|
@@ -118,6 +127,34 @@ module RubyCanUseLLM
|
|
|
118
127
|
raw: data
|
|
119
128
|
)
|
|
120
129
|
end
|
|
130
|
+
|
|
131
|
+
def embedding_request(body)
|
|
132
|
+
uri = URI("https://api.openai.com/v1/embeddings")
|
|
133
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
134
|
+
http.use_ssl = true
|
|
135
|
+
http.read_timeout = config.timeout
|
|
136
|
+
|
|
137
|
+
req = Net::HTTP::Post.new(uri)
|
|
138
|
+
req["Authorization"] = "Bearer #{config.api_key}"
|
|
139
|
+
req["Content-Type"] = "application/json"
|
|
140
|
+
req.body = body.to_json
|
|
141
|
+
|
|
142
|
+
handle_response(http.request(req))
|
|
143
|
+
rescue Net::ReadTimeout, Net::OpenTimeout
|
|
144
|
+
raise TimeoutError, "Request to OpenAI timed out after #{config.timeout}s"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def parse_embedding(data)
|
|
148
|
+
embedding = data.dig("data", 0, "embedding")
|
|
149
|
+
usage = data["usage"]
|
|
150
|
+
|
|
151
|
+
EmbeddingResponse.new(
|
|
152
|
+
embedding: embedding,
|
|
153
|
+
model: data["model"],
|
|
154
|
+
tokens: usage["total_tokens"],
|
|
155
|
+
raw: data
|
|
156
|
+
)
|
|
157
|
+
end
|
|
121
158
|
end
|
|
122
159
|
end
|
|
123
|
-
end
|
|
160
|
+
end
|
data/lib/rubycanusellm.rb
CHANGED
|
@@ -8,6 +8,7 @@ require_relative "rubycanusellm/chunk"
|
|
|
8
8
|
require_relative "rubycanusellm/providers/base"
|
|
9
9
|
require_relative "rubycanusellm/providers/openai"
|
|
10
10
|
require_relative "rubycanusellm/providers/anthropic"
|
|
11
|
+
require_relative "rubycanusellm/embedding_response"
|
|
11
12
|
|
|
12
13
|
module RubyCanUseLLM
|
|
13
14
|
PROVIDERS = {
|
|
@@ -39,5 +40,9 @@ module RubyCanUseLLM
|
|
|
39
40
|
def chat(messages, **options, &block)
|
|
40
41
|
client.chat(messages, **options, &block)
|
|
41
42
|
end
|
|
43
|
+
|
|
44
|
+
def embed(text, **options)
|
|
45
|
+
client.embed(text, **options)
|
|
46
|
+
end
|
|
42
47
|
end
|
|
43
48
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubycanusellm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Juan Manuel Guzman Nava
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: One interface, every LLM. Rubycanusellm provides a unified client for
|
|
14
14
|
OpenAI, Anthropic, and more, plus generators that scaffold the boilerplate so you
|
|
@@ -31,6 +31,7 @@ files:
|
|
|
31
31
|
- lib/rubycanusellm/chunk.rb
|
|
32
32
|
- lib/rubycanusellm/cli.rb
|
|
33
33
|
- lib/rubycanusellm/configuration.rb
|
|
34
|
+
- lib/rubycanusellm/embedding_response.rb
|
|
34
35
|
- lib/rubycanusellm/errors.rb
|
|
35
36
|
- lib/rubycanusellm/providers/anthropic.rb
|
|
36
37
|
- lib/rubycanusellm/providers/base.rb
|