omniai 1.8.1 → 1.8.2

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: cca8dd5cc19989ca0a3fc89d1e8f2c5a56611378a202ea8da2fd49528454ea6c
4
- data.tar.gz: ee0abcf49b13df01ed5b63ed557de44d42d640fb966bcfb5c7592e19aff06f93
3
+ metadata.gz: fca0a46de30a2f54bfab6cc05b65c5fb78b2292c147928c5fe2781e3e5bd3c68
4
+ data.tar.gz: dd6fcf4d76afeca2ff6a289ddb4a4c1d4bed13e976dd03e34da369ab2b3308b0
5
5
  SHA512:
6
- metadata.gz: eb48e8f76d7cd1836ad8dc0ceb577362a3f289026749e2cc49044e31d25758a625ff66fe8003be12dc09585d9ee571671dd4f6d0b8c355cc7962eb4c136ec9f0
7
- data.tar.gz: 41cf6419a3cf3c1662e2f6c5925ae5a05e991f6f2e8f81bcf3d5dfb62ad029bf3d6c32565892ef81acc651a43533dc3a7e9efb2c75922bbdddf28bb29e18b3c2
6
+ metadata.gz: bead375cec92e44876ca250ec8d9ba7e9e98e9b847dd6d41b5633fa1a9de32f134474bfaea6b85cd5f4c522e4389e6e2aadd91287e35b175e66d441affdd697f
7
+ data.tar.gz: f6a7202e05bbdf3bbf994d721960e267e72ecf8846aececda62ae8ecceb34448470e3282818e747a4408177ec37165f0e937f945dc76943af07cf4caa930ad33
data/README.md CHANGED
@@ -2,14 +2,142 @@
2
2
 
3
3
  [![CircleCI](https://circleci.com/gh/ksylvest/omniai.svg?style=svg)](https://circleci.com/gh/ksylvest/omniai)
4
4
 
5
- OmniAI is a flexible AI library that standardizes the APIs of many different AIs:
5
+ OmniAI standardizes the APIs of various AI / LLM companies such as Anthropic, Google, Mistral and OpenAI for the generation of text, the conversion of text-to-speech, the conversion of speech-to-text, the generation of embeddings, and more. It offers a unified API regardless of the provider and task.
6
6
 
7
7
  - [OmniAI::Anthropic](https://github.com/ksylvest/omniai-anthropic)
8
8
  - [OmniAI::Google](https://github.com/ksylvest/omniai-google)
9
9
  - [OmniAI::Mistral](https://github.com/ksylvest/omniai-mistral)
10
10
  - [OmniAI::OpenAI](https://github.com/ksylvest/omniai-openai)
11
11
 
12
- All libraries are community maintained.
12
+ ## Examples
13
+
14
+ ### Example #1: [Chat](https://github.com/ksylvest/omniai/blob/main/examples/chat)
15
+
16
+ ```ruby
17
+ require 'omniai/anthropic'
18
+
19
+ CLIENT = OmniAI::Anthropic::Client.new
20
+
21
+ CAT_URL = 'https://images.unsplash.com/photo-1472491235688-bdc81a63246e?q=80&w=1024&h=1024&fit=crop&fm=jpg'
22
+ DOG_URL = 'https://images.unsplash.com/photo-1517849845537-4d257902454a?q=80&w=1024&h=1024&fit=crop&fm=jpg'
23
+
24
+ CLIENT.chat(stream: $stdout) do |prompt|
25
+ prompt.system('You are a helpful biologist with an expertise in animals that responds with the latin names.')
26
+ prompt.user do |message|
27
+ message.text('What animals are in the attached photos?')
28
+ message.url(CAT_URL, 'image/jpeg')
29
+ message.url(DOG_URL, 'image/jpeg')
30
+ end
31
+ end
32
+ ```
33
+
34
+ ```
35
+ The animals in the photos are:
36
+
37
+ 1. A cat (*Felis catus*).
38
+ 2. A dog (*Canis familiaris*).
39
+ ```
40
+
41
+ ### Example #2: [Text-to-Speech](https://github.com/ksylvest/omniai/blob/main/examples/text_to_speech)
42
+
43
+ ```ruby
44
+ require 'omniai/openai'
45
+
46
+ CLIENT = OmniAI::OpenAI::Client.new
47
+
48
+ File.open(File.join(__dir__, 'audio.wav'), 'wb') do |file|
49
+ CLIENT.speak('Sally sells seashells by the seashore.', format: OmniAI::Speak::Format::WAV) do |chunk|
50
+ file << chunk
51
+ end
52
+ end
53
+ ```
54
+
55
+ ### Example #3: [Speech-to-Text](https://github.com/ksylvest/omniai/blob/main/examples/speech_to_text)
56
+
57
+ ```ruby
58
+ require 'omniai/openai'
59
+
60
+ CLIENT = OmniAI::OpenAI::Client.new
61
+
62
+ File.open(File.join(__dir__, 'audio.wav'), 'rb') do |file|
63
+ transcription = CLIENT.transcribe(file)
64
+ puts(transcription.text)
65
+ end
66
+ ```
67
+
68
+ ### Example #4: [Tools](https://github.com/ksylvest/omniai/blob/main/examples/tools)
69
+
70
+ ```ruby
71
+ require 'omniai/google'
72
+
73
+ CLIENT = OmniAI::Google::Client.new
74
+
75
+ TOOL = OmniAI::Tool.new(
76
+ proc { |location:, unit: 'celsius'| "#{rand(20..50)}° #{unit} in #{location}" },
77
+ name: 'Weather',
78
+ description: 'Lookup the weather in a location',
79
+ parameters: OmniAI::Tool::Parameters.new(
80
+ properties: {
81
+ location: OmniAI::Tool::Property.string(description: 'e.g. Toronto'),
82
+ unit: OmniAI::Tool::Property.string(enum: %w[celcius fahrenheit]),
83
+ },
84
+ required: %i[location]
85
+ )
86
+ )
87
+
88
+ completion = CLIENT.chat(tools: [TOOL]) do |prompt|
89
+ prompt.user do |message|
90
+ message.text('What is the weather in "London" in celcius and "Seattle" in fahrenheit?')
91
+ end
92
+ end
93
+
94
+ puts(completion.text)
95
+ ```
96
+
97
+ ```
98
+ The weather is 24° celcius in London and 42° fahrenheit in Seattle.
99
+ ```
100
+
101
+ ### Example #5: [Embeddings](https://github.com/ksylvest/omniai/blob/main/examples/embeddings)
102
+
103
+ ```ruby
104
+ require 'omniai/mistral'
105
+
106
+ CLIENT = OmniAI::Mistral::Client.new
107
+
108
+ Entry = Data.define(:text, :embedding) do
109
+ def initialize(text:)
110
+ super(text:, embedding: CLIENT.embed(text).embedding)
111
+ end
112
+ end
113
+
114
+ ENTRIES = [
115
+ Entry.new(text: 'John is a musician.'),
116
+ Entry.new(text: 'Paul is a plumber.'),
117
+ Entry.new(text: 'George is a teacher.'),
118
+ Entry.new(text: 'Ringo is a doctor.'),
119
+ ].freeze
120
+
121
+ def search(query)
122
+ embedding = CLIENT.embed(query).embedding
123
+
124
+ results = ENTRIES.sort_by do |data|
125
+ Math.sqrt(data.embedding.zip(embedding).map { |a, b| (a - b)**2 }.reduce(:+))
126
+ end
127
+
128
+ puts "'#{query}': '#{results.first.text}'"
129
+ end
130
+
131
+ search('What does George do?')
132
+ search('Who is a doctor?')
133
+ search('Who do you call to fix a toilet?')
134
+ ```
135
+
136
+ ```
137
+ 'What does George do?': 'George is a teacher.'
138
+ 'Who is a doctor?': 'Ringo is a doctor.'
139
+ 'Who do you call to fix a toilet?': 'Paul is a plumber.'
140
+ ```
13
141
 
14
142
  ## Installation
15
143
 
@@ -83,7 +211,7 @@ require 'omniai/openai'
83
211
  require 'logger'
84
212
 
85
213
  logger = Logger.new(STDOUT)
86
- client = OmniAI::Example::Client.new(logger:)
214
+ client = OmniAI::OpenAI::Client.new(logger:)
87
215
  ```
88
216
 
89
217
  ```
@@ -2,7 +2,8 @@
2
2
 
3
3
  module OmniAI
4
4
  class Chat
5
- # For for.
5
+ # A choice wraps a message and index returned by an LLM. The default is to generate a single choice. Some LLMs
6
+ # support generating multiple choices at once (e.g. giving you multiple options to choose from).
6
7
  class Choice
7
8
  # @return [Integer]
8
9
  attr_accessor :index
@@ -12,7 +13,6 @@ module OmniAI
12
13
 
13
14
  # @param message [Message]
14
15
  # @param index [Integer]
15
- # @param tool_call_list [Array<ToolCall>]
16
16
  def initialize(message:, index: 0)
17
17
  @message = message
18
18
  @index = index
@@ -59,7 +59,7 @@ module OmniAI
59
59
  message.content
60
60
  end
61
61
 
62
- # @return [Array<ToolCall, nil]
62
+ # @return [Array<ToolCall>, nil]
63
63
  def tool_call_list
64
64
  message.tool_call_list
65
65
  end
@@ -11,7 +11,7 @@ module OmniAI
11
11
  attr_accessor :tool_call_id
12
12
 
13
13
  # @param content [Object]
14
- # @param tool_call [ToolCall]
14
+ # @param tool_call_id [String]
15
15
  def initialize(content:, tool_call_id:)
16
16
  @content = content
17
17
  @tool_call_id = tool_call_id
data/lib/omniai/client.rb CHANGED
@@ -75,15 +75,15 @@ module OmniAI
75
75
  # Initialize a client by provider (e.g. 'openai'). This method attempts to require the provider.
76
76
  #
77
77
  # @raise [OmniAI::Error] if the provider is not defined and the gem is not installed
78
- # @param provider [String] required (e.g. 'anthropic', 'google', 'mistral', 'openai', etc)
78
+ # @param provider [String, Symbol] required (e.g. 'anthropic', 'google', 'mistral', 'openai', etc)
79
79
  # @return [OmniAI::Client]
80
80
  def self.find(provider:, **)
81
81
  klass =
82
82
  case provider
83
- when 'anthropic' then anthropic
84
- when 'google' then google
85
- when 'mistral' then mistral
86
- when 'openai' then openai
83
+ when :anthropic, 'anthropic' then anthropic
84
+ when :google, 'google' then google
85
+ when :mistral, 'mistral' then mistral
86
+ when :openai, 'openai' then openai
87
87
  else raise Error, "unknown provider=#{provider.inspect}"
88
88
  end
89
89
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OmniAI
4
- VERSION = '1.8.1'
4
+ VERSION = '1.8.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.1
4
+ version: 1.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-17 00:00:00.000000000 Z
11
+ date: 2024-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser
@@ -125,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
125
  - !ruby/object:Gem::Version
126
126
  version: '0'
127
127
  requirements: []
128
- rubygems_version: 3.5.14
128
+ rubygems_version: 3.5.18
129
129
  signing_key:
130
130
  specification_version: 4
131
131
  summary: A generalized framework for interacting with many AI services