omniai 2.4.0 → 2.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b888dff5046dce34b72c4e1e37cad2ed2ce0a9a5259b1a998cc85567dc3f202
4
- data.tar.gz: 14d100fd069b47cc0cd6a40794a0582639baf07384050d0e47a574a0062e01b9
3
+ metadata.gz: ab754f5c048f4d0e4c76e75f142f4e3d511e81a4f2a0585dd466e4b325ccdeb2
4
+ data.tar.gz: 815d97caf42308a0bfaf183383522c5e34ce08ecab30835390d4c22034b32779
5
5
  SHA512:
6
- metadata.gz: 3a11e8b75566c699dd7f3c5bf2ae97a004bfb4ff0479e671dd7665db09970627666cacca21d72d11016ab4b783256e96799d66ea65f063492531a5a0320c025a
7
- data.tar.gz: cc7e0e511676995ce72b092fd9238ba507f78bb371bc2eb6c1cff0d76ac27c3c28672f1ccd66da4360c4ff1294b6732301744bb4db06c97d51ac65580401dd60
6
+ metadata.gz: 3497bf2f884a273896d42271170a513462f180bf86ca561f9120a3b8d464485b42400828901ada0bfd3c47ff2f374eb57242149a3664b3b6208b42fcf4227425
7
+ data.tar.gz: d714671acf5e5c8dcfd3834bfbc529d2fede0967e8e7a3ddda4710588375eb65366c1067e1bcd00220764a6e9d30f583e7478e6e85881762fe005e43f8da3851
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gemspec
7
7
  gem "factory_bot"
8
8
  gem "irb"
9
9
  gem "rake"
10
+ gem "redcarpet"
10
11
  gem "rspec"
11
12
  gem "rspec_junit_formatter"
12
13
  gem "rubocop"
data/README.md CHANGED
@@ -119,7 +119,46 @@ end
119
119
  The weather is 24° Celsius in London and 42° Fahrenheit in Madrid.
120
120
  ```
121
121
 
122
- ### Example #5: [Chat w/ CLI](https://github.com/ksylvest/omniai/blob/main/examples/chat_with_cli)
122
+ ### Example #5: [Chat w/ History](https://github.com/ksylvest/omniai/blob/main/examples/chat_with_history)
123
+
124
+ Building a conversation history (e.g. multiple user and assistant messages) is especially helpful when building an agent like conversation experience. A prompt can be used to track this back and forth conversation:
125
+
126
+ ```ruby
127
+ require "omniai/openai"
128
+
129
+ puts("Type 'exit' or 'quit' to leave.")
130
+
131
+ client = OmniAI::OpenAI::Client.new
132
+
133
+ conversation = OmniAI::Chat::Prompt.build do |prompt|
134
+ prompt.system "You are a helpful assistant. Respond in both English and French."
135
+ end
136
+
137
+ loop do
138
+ print "> "
139
+ text = gets.chomp.strip
140
+ next if text.empty?
141
+ break if text.eql?("exit") || text.eql?("quit")
142
+
143
+ conversation.user(text)
144
+ response = client.chat(conversation, stream: $stdout)
145
+ conversation.assistant(response.text)
146
+ end
147
+ ```
148
+
149
+ ```
150
+ Type 'exit' or 'quit' to leave.
151
+
152
+ > What is the capital of France?
153
+ The capital of France is Paris.
154
+ La capitale de la France est Paris.
155
+
156
+ > How many people live there?
157
+ The population of Paris is approximately 2.1 million.
158
+ La population de Paris est d’environ 2,1 million.
159
+ ```
160
+
161
+ ### Example #6: [Chat w/ CLI](https://github.com/ksylvest/omniai/blob/main/examples/chat_with_cli)
123
162
 
124
163
  The `OmniAI` gem also ships with a CLI to simplify quick tests.
125
164
 
@@ -139,7 +178,7 @@ omniai chat --provider="google" --model="gemini-2.0-flash" "Who are you?"
139
178
  I am a large language model, trained by Google.
140
179
  ```
141
180
 
142
- ### Example #6: [Text-to-Speech](https://github.com/ksylvest/omniai/blob/main/examples/text_to_speech)
181
+ ### Example #7: [Text-to-Speech](https://github.com/ksylvest/omniai/blob/main/examples/text_to_speech)
143
182
 
144
183
  This example demonstrates using `OmniAI` with **OpenAI** to convert text to speech and save it to a file.
145
184
 
@@ -155,7 +194,7 @@ File.open(File.join(__dir__, 'audio.wav'), 'wb') do |file|
155
194
  end
156
195
  ```
157
196
 
158
- ### Example #7: [Speech-to-Text](https://github.com/ksylvest/omniai/blob/main/examples/speech_to_text)
197
+ ### Example #8: [Speech-to-Text](https://github.com/ksylvest/omniai/blob/main/examples/speech_to_text)
159
198
 
160
199
  This example demonstrates using `OmniAI` with **OpenAI** to convert speech to text.
161
200
 
@@ -170,7 +209,7 @@ File.open(File.join(__dir__, 'audio.wav'), 'rb') do |file|
170
209
  end
171
210
  ```
172
211
 
173
- ### Example #8: [Embeddings](https://github.com/ksylvest/omniai/blob/main/examples/embeddings)
212
+ ### Example #9: [Embeddings](https://github.com/ksylvest/omniai/blob/main/examples/embeddings)
174
213
 
175
214
  This example demonstrates using `OmniAI` with **Mistral** to generate embeddings for a dataset. It defines a set of entries (e.g. "George is a teacher." or "Ringo is a doctor.") and then compares the embeddings generated from a query (e.g. "What does George do?" or "Who is a doctor?") to rank the entries by relevance.
176
215
 
@@ -75,7 +75,7 @@ module OmniAI
75
75
  # @param index [Integer]
76
76
  #
77
77
  # @return [Boolean]
78
- def message?
78
+ def message?(index: 0)
79
79
  !message(index:).nil?
80
80
  end
81
81
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module OmniAI
4
4
  class CLI
5
- # A generic handler for CLI commands (e.g. 'omnia chat').
5
+ # A generic handler for CLI commands (e.g. 'omniai chat').
6
6
  class BaseHandler
7
7
  # @param stdin [IO] an optional stream for stdin
8
8
  # @param stdout [IO] an optional stream for stdout
@@ -2,7 +2,11 @@
2
2
 
3
3
  module OmniAI
4
4
  class CLI
5
- # Used for CLI usage of 'omnia chat'.
5
+ # Used by CLI to process commands like:
6
+ #
7
+ # omniai chat
8
+ # omniai chat "What is the capital of France?"
9
+ # omniai chat --provider="google" --model="gemini-2.0-flash" "Who are you?"
6
10
  class ChatHandler < BaseHandler
7
11
  # @param argv [Array<String>]
8
12
  def handle!(argv:)
@@ -20,14 +24,18 @@ module OmniAI
20
24
  def listen!
21
25
  @stdout.puts('Type "exit" or "quit" to leave.')
22
26
 
27
+ prompt = OmniAI::Chat::Prompt.new
28
+
23
29
  loop do
24
30
  @stdout.print("# ")
25
31
  @stdout.flush
26
- prompt = @stdin.gets&.chomp
32
+ text = @stdin.gets&.strip
27
33
 
28
- break if prompt.nil? || prompt.match?(/\A(exit|quit)\z/i)
34
+ break if text.nil? || text.match?(/\A(exit|quit)\z/i)
29
35
 
30
- chat(prompt:)
36
+ prompt.user(text)
37
+ response = chat(prompt:)
38
+ prompt.assistant(response.text)
31
39
  rescue Interrupt
32
40
  break
33
41
  end
@@ -48,12 +56,21 @@ module OmniAI
48
56
  exit
49
57
  end
50
58
 
51
- options.on("-p", "--provider=PROVIDER", "provider") { |provider| @provider = provider }
52
- options.on("-m", "--model=MODEL", "model") { |model| @args[:model] = model }
59
+ options.on("-p", "--provider=PROVIDER", "provider") do |provider|
60
+ @provider = provider
61
+ end
62
+
63
+ options.on("-m", "--model=MODEL", "model") do |model|
64
+ @args[:model] = model
65
+ end
66
+
53
67
  options.on("-t", "--temperature=TEMPERATURE", Float, "temperature") do |temperature|
54
68
  @args[:temperature] = temperature
55
69
  end
56
- options.on("-f", "--format=FORMAT", "format") { |format| @args[:format] = format.intern }
70
+
71
+ options.on("-f", "--format=FORMAT", "format") do |format|
72
+ @args[:format] = format.intern
73
+ end
57
74
  end
58
75
  end
59
76
  end
@@ -2,7 +2,9 @@
2
2
 
3
3
  module OmniAI
4
4
  class CLI
5
- # Used for CLI usage of 'omnia embed'.
5
+ # Used by CLI to process commands like:
6
+ #
7
+ # omniai embed "All cats are felidae."
6
8
  class EmbedHandler < BaseHandler
7
9
  # @param argv [Array<String>]
8
10
  def handle!(argv:)
data/lib/omniai/client.rb CHANGED
@@ -16,71 +16,94 @@ module OmniAI
16
16
  # end
17
17
  # end
18
18
  class Client
19
- # @return [String, nil]
19
+ # @!attribute [rw] api_key
20
+ # @return [String, nil]
20
21
  attr_accessor :api_key
21
22
 
22
- # @return [Logger, nil]
23
+ # @!attribute [rw] logger
24
+ # @return [Logger, nil]
23
25
  attr_accessor :logger
24
26
 
25
- # @return [String, nil]
27
+ # @!attribute [rw] host
28
+ # @return [String, nil]
26
29
  attr_accessor :host
27
30
 
28
- # @return [Integer, nil]
31
+ # @!attribute [rw] timeout
32
+ # @return [Integer, nil]
29
33
  attr_accessor :timeout
30
34
 
31
35
  # Initialize a client for Anthropic. This method requires the provider if it is undefined.
32
36
  #
33
37
  # @raise [OmniAI::Error] if the provider is not defined and the gem is not installed
38
+ #
34
39
  # @return [Class<OmniAI::Client>]
35
40
  def self.anthropic
36
41
  require "omniai/anthropic" unless defined?(OmniAI::Anthropic::Client)
37
42
  OmniAI::Anthropic::Client
38
- rescue LoadError
43
+ rescue ::LoadError
39
44
  raise Error, "requires 'omniai-anthropic': `gem install omniai-anthropic`"
40
45
  end
41
46
 
47
+ # Initialize a client for DeepSeek. This method requires the provider if it is undefined.
48
+ #
49
+ # @raise [OmniAI::Error] if the provider is not defined and the gem is not installed
50
+ #
51
+ # @return [Class<OmniAI::Client>]
52
+ def self.deepseek
53
+ require "omniai/deepseek" unless defined?(OmniAI::DeepSeek::Client)
54
+ OmniAI::DeepSeek::Client
55
+ rescue ::LoadError
56
+ raise Error, "requires 'omniai-deepseek': `gem install omniai-deepseek`"
57
+ end
58
+
42
59
  # Lookup the `OmniAI::Google::Client``. This method requires the provider if it is undefined.
43
60
  #
44
61
  # @raise [OmniAI::Error] if the provider is not defined and the gem is not installed
62
+ #
45
63
  # @return [Class<OmniAI::Client>]
46
64
  def self.google
47
65
  require "omniai/google" unless defined?(OmniAI::Google::Client)
48
66
  OmniAI::Google::Client
49
- rescue LoadError
67
+ rescue ::LoadError
50
68
  raise Error, "requires 'omniai-google': `gem install omniai-google`"
51
69
  end
52
70
 
53
71
  # Initialize a client for Mistral. This method requires the provider if it is undefined.
54
72
  #
55
73
  # @raise [OmniAI::Error] if the provider is not defined and the gem is not installed
74
+ #
56
75
  # @return [Class<OmniAI::Client>]
57
76
  def self.mistral
58
77
  require "omniai/mistral" unless defined?(OmniAI::Mistral::Client)
59
78
  OmniAI::Mistral::Client
60
- rescue LoadError
79
+ rescue ::LoadError
61
80
  raise Error, "requires 'omniai-mistral': `gem install omniai-mistral`"
62
81
  end
63
82
 
64
83
  # Initialize a client for OpenAI. This method requires the provider if it is undefined.
65
84
  #
66
85
  # @raise [OmniAI::Error] if the provider is not defined and the gem is not installed
86
+ #
67
87
  # @return [Class<OmniAI::Client>]
68
88
  def self.openai
69
89
  require "omniai/openai" unless defined?(OmniAI::OpenAI::Client)
70
90
  OmniAI::OpenAI::Client
71
- rescue LoadError
91
+ rescue ::LoadError
72
92
  raise Error, "requires 'omniai-openai': `gem install omniai-openai`"
73
93
  end
74
94
 
75
95
  # Initialize a client by provider (e.g. 'openai'). This method attempts to require the provider.
76
96
  #
97
+ # @param provider [String, Symbol] required (e.g. 'anthropic', 'deepsek', 'google', 'mistral', 'openai', etc)
98
+ #
77
99
  # @raise [OmniAI::Error] if the provider is not defined and the gem is not installed
78
- # @param provider [String, Symbol] required (e.g. 'anthropic', 'google', 'mistral', 'openai', etc)
100
+ #
79
101
  # @return [OmniAI::Client]
80
102
  def self.find(provider:, **)
81
103
  klass =
82
104
  case provider
83
105
  when :anthropic, "anthropic" then anthropic
106
+ when :deepseek, "deepseek" then deepseek
84
107
  when :google, "google" then google
85
108
  when :mistral, "mistral" then mistral
86
109
  when :openai, "openai" then openai
@@ -169,7 +192,7 @@ module OmniAI
169
192
  #
170
193
  # @yield [output] optional
171
194
  #
172
- # @return [Tempfile``]
195
+ # @return [Tempfile]
173
196
  def speak(input, model:, voice:, speed: nil, format: nil, &stream)
174
197
  raise NotImplementedError, "#{self.class.name}#speak undefined"
175
198
  end
data/lib/omniai/config.rb CHANGED
@@ -15,28 +15,35 @@ module OmniAI
15
15
  # config.speak_options = { ... }
16
16
  # end
17
17
  class Config
18
- # @return [String, nil]
18
+ # @!attribute [rw] api_key
19
+ # @return [String, nil]
19
20
  attr_accessor :api_key
20
21
 
21
- # @return [String, nil]
22
+ # @!attribute [rw] host
23
+ # @return [String, nil]
22
24
  attr_accessor :host
23
25
 
24
- # @return [Logger, nil]
26
+ # @!attribute [rw] logger
27
+ # @return [Logger, nil]
25
28
  attr_accessor :logger
26
29
 
27
- # @return [Integer, Hash{Symbol => Integer}, nil]
28
- # @option timeout [Integer] :read
29
- # @option timeout [Integer] :write
30
- # @option timeout [Integer] :connect
30
+ # @!attribute [rw] timeout
31
+ # @return [Integer, Hash{Symbol => Integer}, nil]
32
+ # @option timeout [Integer] :read
33
+ # @option timeout [Integer] :write
34
+ # @option timeout [Integer] :connect
31
35
  attr_accessor :timeout
32
36
 
33
- # @return [Hash]
37
+ # @!attribute [rw] chat_options
38
+ # @return [Hash]
34
39
  attr_accessor :chat_options
35
40
 
36
- # @return [Hash]
41
+ # @!attribute [rw] transcribe_options
42
+ # @return [Hash]
37
43
  attr_accessor :transcribe_options
38
44
 
39
- # @return [Hash]
45
+ # @!attribute [rw] speak_options
46
+ # @return [Hash]
40
47
  attr_accessor :speak_options
41
48
 
42
49
  # @param api_key [String] optional
data/lib/omniai/speak.rb CHANGED
@@ -5,7 +5,7 @@ module OmniAI
5
5
  #
6
6
  # Usage:
7
7
  #
8
- # class OmniAI::OpenAI::Speak < OmniAI::Speakw
8
+ # class OmniAI::OpenAI::Speak < OmniAI::Speak
9
9
  # module Model
10
10
  # WHISPER_1 = "whisper-1"
11
11
  # end
data/lib/omniai/tool.rb CHANGED
@@ -17,6 +17,8 @@ module OmniAI
17
17
  class Tool
18
18
  class << self
19
19
  # @param description [String]
20
+ #
21
+ # @return [String]
20
22
  def description(description = nil)
21
23
  return @description if description.nil?
22
24
 
@@ -61,11 +63,11 @@ module OmniAI
61
63
  # @return [String]
62
64
  attr_accessor :name
63
65
 
64
- # @!attribute [description]
66
+ # @!attribute [rw] description
65
67
  # @return [String, nil]
66
68
  attr_accessor :description
67
69
 
68
- # @!attribute[parameters]
70
+ # @!attribute [rw] parameters
69
71
  # @return [Hash, nil]
70
72
  attr_accessor :parameters
71
73
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OmniAI
4
- VERSION = "2.4.0"
4
+ VERSION = "2.4.1"
5
5
  end
data/lib/omniai.rb CHANGED
@@ -19,7 +19,8 @@ module OmniAI
19
19
 
20
20
  # An error that wraps an HTTP::Response for non-OK requests.
21
21
  class HTTPError < Error
22
- # @return [HTTP::Response]
22
+ # @!attribute [rw] response
23
+ # @return [HTTP::Response]
23
24
  attr_accessor :response
24
25
 
25
26
  # @param response [HTTP::Response]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-08 00:00:00.000000000 Z
10
+ date: 2025-04-23 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: event_stream_parser