cloudflare-ai 0.5.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9085ff95f730366db7b3261cc94935f782d719b8129dd1341796ee6d66fd373c
4
- data.tar.gz: 60b29886c88200aebdd1c46e743a28dd597540144494e8288098e05c6ddb8e04
3
+ metadata.gz: 2f16a1fd5c112fb69440d4d89b1f27d167e854c537ca952b91e1f3f673c0efb5
4
+ data.tar.gz: 59f999e994f5bd21071ee2f125b5e138ba353feb857912b1df472f35acc05006
5
5
  SHA512:
6
- metadata.gz: 3b95c01b2cab4dec4c0bdd476d99f5ab65183215a64e6c6711a50caed5874a51ff34b78b530b1877b13a1be8851fc527202a1b250f94d57a554ff46b25716136
7
- data.tar.gz: 86721eb5cf51bfd886a6f9e1a4be71c4b33492cd90e2a2adedbe2f6474c7e601b4e2f1bc52bfd315039a3b24ea202fd627dc032a2dda63e8ad6f04b0e01da08a
6
+ metadata.gz: 1d258b49887ca664f616aad4dbc74afc4bb8d49d0452933c2ee907306af56cf81da0bf084c260ddbe4db9d96f522812cc5abfb771c3d94757f12342334b16fd6
7
+ data.tar.gz: 133fcfd21cedbdb324604ec0e9bd4aacb0750b9f486df7bc217998e4dd117f4e6d482572ba1feee8b629e3362857cb8b8f28d2f1e3c6f1d89acddd18b73752e9
data/README.md CHANGED
@@ -23,8 +23,8 @@ It's still early days, and here are my immediate priorities:
23
23
  * [x] [Text Embeddings](https://developers.cloudflare.com/workers-ai/models/text-embeddings/)
24
24
  * [x] [Text Classification](https://developers.cloudflare.com/workers-ai/models/text-classification/)
25
25
  * [x] [Translation](https://developers.cloudflare.com/workers-ai/models/translation/)
26
- * [ ] [Image Classification](https://developers.cloudflare.com/workers-ai/models/image-classification/)
27
- * [ ] [Text-to-Image](https://developers.cloudflare.com/workers-ai/models/text-to-image/)
26
+ * [x] [Image Classification](https://developers.cloudflare.com/workers-ai/models/image-classification/)
27
+ * [x] [Text-to-Image](https://developers.cloudflare.com/workers-ai/models/text-to-image/)
28
28
  * [ ] [Automatic Speech Recognition](https://developers.cloudflare.com/workers-ai/models/speech-recognition/)
29
29
 
30
30
  # Table of Contents
@@ -75,7 +75,8 @@ The full list of supported models is available here: [models.rb](lib/cloudflare/
75
75
  More information is available [in the cloudflare documentation](https://developers.cloudflare.com/workers-ai/models/).
76
76
  The default model used is the first enumerated model in the applicable set in [models.rb](lib/cloudflare/ai/models.rb).
77
77
 
78
- ### Text generation (chat / scoped prompt)
78
+ ### Text generation
79
+ #### (chat / scoped prompt)
79
80
  ```ruby
80
81
  messages = [
81
82
  Cloudflare::AI::Message.new(role: "system", content: "You are a big fan of Cloudflare and Ruby."),
@@ -86,6 +87,11 @@ messages = [
86
87
  result = client.chat(messages: messages)
87
88
  puts result.response # => "Yes, I love Cloudflare!"
88
89
  ```
90
+ #### (string prompt)
91
+ ```ruby
92
+ result = client.complete(prompt: "What is your name?", max_tokens: 512)
93
+ puts result.response # => "My name is Jonas."
94
+ ```
89
95
 
90
96
  #### Streaming responses
91
97
  Responses will be streamed back to the client using Server Side Events (SSE) if a block is passed to the `chat` or `complete` method.
@@ -101,9 +107,6 @@ result = client.complete(prompt: "Hi!") { |data| puts data}
101
107
  ```
102
108
  #### Token limits
103
109
  Invocations of the `prompt` and `chat` can take an optional `max_tokens` argument that defaults to 256.
104
- ```ruby
105
- result = client.complete(prompt: "What is your name?", max_tokens: 512)
106
- ```
107
110
 
108
111
  #### Result object
109
112
  All invocations of the `prompt` and `chat` methods return a `Cloudflare::AI::Results::TextGeneration` object. This object's serializable JSON output is
@@ -149,6 +152,29 @@ p result.result # => [{"label"=>"NEGATIVE", "score"=>0.6647962927818298}, {"labe
149
152
  #### Result object
150
153
  All invocations of the `classify` methods return a `Cloudflare::AI::Results::TextClassification`.
151
154
 
155
+ ### Image classification
156
+ The image classification endpoint accepts either a path to a file or a file stream.
157
+
158
+ ```ruby
159
+ result = client.classify(image: "/path/to/cat.jpg")
160
+ p result.result # => {"result":[{"label":"TABBY","score":0.6159140467643738},{"label":"TIGER CAT","score":0.12016300112009048},{"label":"EGYPTIAN CAT","score":0.07523812353610992},{"label":"DOORMAT","score":0.018854796886444092},{"label":"ASHCAN","score":0.01314085815101862}],"success":true,"errors":[],"messages":[]}
161
+
162
+ result = client.classify(image: File.open("/path/to/cat.jpg"))
163
+ p result.result # => {"result":[{"label":"TABBY","score":0.6159140467643738},{"label":"TIGER CAT","score":0.12016300112009048},{"label":"EGYPTIAN CAT","score":0.07523812353610992},{"label":"DOORMAT","score":0.018854796886444092},{"label":"ASHCAN","score":0.01314085815101862}],"success":true,"errors":[],"messages":[]}
164
+ ```
165
+
166
+ #### Result object
167
+ All invocations of the `classify` method returns a `Cloudflare::AI::Results::TextClassification`.
168
+
169
+ ### Text to Image
170
+ ```ruby
171
+ result = client.draw(prompt: "robot with blue eyes")
172
+ p result.result # => File:0x0000000110deed68 (png tempfile)
173
+ ```
174
+
175
+ #### Result object
176
+ All invocations of the `draw` method returns a `Cloudflare::AI::Results::TextToImage`.
177
+
152
178
  ### Translation
153
179
  ```ruby
154
180
  result = client.translate(text: "Hello Jello", source_lang: "en", target_lang: "fr")
@@ -2,6 +2,7 @@ require "event_stream_parser"
2
2
  require "faraday"
3
3
 
4
4
  class Cloudflare::AI::Client
5
+ include Cloudflare::AI::Clients::ImageHelpers
5
6
  include Cloudflare::AI::Clients::TextGenerationHelpers
6
7
 
7
8
  attr_reader :url, :account_id, :api_token
@@ -18,11 +19,19 @@ class Cloudflare::AI::Client
18
19
  post_streamable_request(url, payload, &block)
19
20
  end
20
21
 
21
- def classify(text:, model_name: Cloudflare::AI::Models.text_classification.first)
22
+ def classify(text: nil, image: nil, model_name: nil)
23
+ raise ArgumentError, "Must provide either text or image (and not both)" if [text, image].compact.size != 1
24
+
25
+ model_name ||= text ? Cloudflare::AI::Models.text_classification.first : Cloudflare::AI::Models.image_classification.first
22
26
  url = service_url_for(account_id: account_id, model_name: model_name)
23
- payload = {text: text}.to_json
24
27
 
25
- Cloudflare::AI::Results::TextClassification.new(connection.post(url, payload).body)
28
+ if text
29
+ payload = {text: text}.to_json
30
+ Cloudflare::AI::Results::TextClassification.new(connection.post(url, payload).body)
31
+ else
32
+ image = File.open(image) if image.is_a?(String)
33
+ Cloudflare::AI::Results::ImageClassification.new(post_request_with_binary_file(url, image).body)
34
+ end
26
35
  end
27
36
 
28
37
  def complete(prompt:, model_name: default_text_generation_model_name, max_tokens: default_max_tokens, &block)
@@ -32,6 +41,17 @@ class Cloudflare::AI::Client
32
41
  post_streamable_request(url, payload, &block)
33
42
  end
34
43
 
44
+ def draw(prompt:, num_steps: 20, model_name: Cloudflare::AI::Models.text_to_image.first)
45
+ url = service_url_for(account_id: account_id, model_name: model_name)
46
+ payload = {prompt: prompt, num_steps: num_steps}.to_json
47
+
48
+ result = connection.post(url, payload).body
49
+ binary_data = result.split(",").map(&:to_i).pack("C*")
50
+ Cloudflare::AI::Results::TextToImage.new(
51
+ Tempfile.new(["cloudflare-ai", ".png"], binmode: true).tap { |result| result.write(binary_data) }
52
+ )
53
+ end
54
+
35
55
  def embed(text:, model_name: Cloudflare::AI::Models.text_embedding.first)
36
56
  url = service_url_for(account_id: account_id, model_name: model_name)
37
57
  payload = {text: text}.to_json
@@ -0,0 +1,20 @@
1
+ require "faraday/multipart"
2
+
3
+ module Cloudflare
4
+ module AI
5
+ module Clients
6
+ module ImageHelpers
7
+ private
8
+
9
+ def post_request_with_binary_file(url, file)
10
+ connection.post do |req|
11
+ req.url url
12
+ req.headers["Transfer-Encoding"] = "chunked"
13
+ req.headers["Content-Type"] = "multipart/form-data"
14
+ req.body = ::Faraday::UploadIO.new(file, "octet/stream")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -17,7 +17,7 @@ class Cloudflare::AI::Models
17
17
  end
18
18
 
19
19
  def image_classification
20
- %w[@cf/huggingface/distilbert-sst-2-int8]
20
+ %w[@cf/microsoft/resnet-50]
21
21
  end
22
22
 
23
23
  def text_to_image
@@ -30,7 +30,7 @@ class Cloudflare::AI::Result
30
30
  result_data.to_json
31
31
  end
32
32
 
33
- private
33
+ protected
34
34
 
35
35
  attr_reader :result_data
36
36
 
@@ -0,0 +1,3 @@
1
+ class Cloudflare::AI::Results::ImageClassification < Cloudflare::AI::Result
2
+ # Empty seam kept for consistency with other result objects that have more complexity.
3
+ end
@@ -0,0 +1,5 @@
1
+ class Cloudflare::AI::Results::TextToImage < Cloudflare::AI::Result
2
+ def initialize(file)
3
+ @result_data = {result: file, success: true, errors: [], messages: []}
4
+ end
5
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cloudflare
4
4
  module AI
5
- VERSION = "0.5.1"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloudflare-ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ajay Krishnan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-23 00:00:00.000000000 Z
11
+ date: 2024-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: faraday-multipart
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: zeitwerk
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -93,14 +107,17 @@ files:
93
107
  - README.md
94
108
  - lib/cloudflare/ai.rb
95
109
  - lib/cloudflare/ai/client.rb
110
+ - lib/cloudflare/ai/clients/image_helpers.rb
96
111
  - lib/cloudflare/ai/clients/text_generation_helpers.rb
97
112
  - lib/cloudflare/ai/contextual_logger.rb
98
113
  - lib/cloudflare/ai/message.rb
99
114
  - lib/cloudflare/ai/models.rb
100
115
  - lib/cloudflare/ai/result.rb
116
+ - lib/cloudflare/ai/results/image_classification.rb
101
117
  - lib/cloudflare/ai/results/text_classification.rb
102
118
  - lib/cloudflare/ai/results/text_embedding.rb
103
119
  - lib/cloudflare/ai/results/text_generation.rb
120
+ - lib/cloudflare/ai/results/text_to_image.rb
104
121
  - lib/cloudflare/ai/results/translation.rb
105
122
  - lib/cloudflare/ai/version.rb
106
123
  homepage: https://rubygems.org/gems/cloudflare-ai