getimg_client 0.1.3 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -8
- data/lib/endpoints.json +1 -0
- data/lib/getimg_client.rb +36 -19
- data/test/integration/getimg_client_integration_test.rb +37 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49df7df20de9d97f5bc96e06eb517c007f55101e61b56c6d33d4878687f13249
|
4
|
+
data.tar.gz: 4dc36a54730384489acb5068e24e55fd272186f1c6cafb610272f05b777e522c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2a3a252131ecfca467e4ca97704a6d1d86d3ac4d0f8840a9f18c03a2686b5bdff4322ddf09e697d6cc765e5cd743579580c6be70c2b6a6a0df0c1c51aa9781d
|
7
|
+
data.tar.gz: 586153f30ac2646900cd7e0ad87d531ec1151ea53c5a7dd3271f0120774531f1df2f6ad1ee608a47ab8020a9e223ed42171932a0e66f3845725dfff1e790271e
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# GetimgClient
|
1
|
+
# GetimgClient [![Gem Version](https://badge.fury.io/rb/getimg_client.svg)](https://badge.fury.io/rb/getimg_client)
|
2
2
|
|
3
3
|
## Introduction
|
4
4
|
GetimgClient is a Ruby gem designed to interact with the Getimg.ai API, enabling users to generate, manipulate, and enhance images using various AI models. This gem simplifies the process of making API requests to Getimg.ai, allowing for seamless integration of image generation and manipulation capabilities into your Ruby applications.
|
@@ -46,14 +46,14 @@ Fetch and cache the list of available models from the API.
|
|
46
46
|
### `models`
|
47
47
|
Retrieve cached models or fetch them if not already retrieved.
|
48
48
|
|
49
|
-
### `generate_image(prompt, model
|
50
|
-
Generate an image based on a text prompt and specified model. Supports various image manipulation methods such as image-to-image, inpainting, controlnet, face fixing, instruct and upscaling.
|
49
|
+
### `generate_image(prompt, model: :essential, **options)`
|
50
|
+
Generate an image based on a text prompt and specified model. Supports various image manipulation methods such as image-to-image, inpainting, controlnet, face fixing, instruct, and upscaling. Specifying a model is optional; by default, it will invoke the Essential V1 endpoint.
|
51
51
|
|
52
52
|
### `get_balance`
|
53
53
|
Retrieve the current account balance from the Getimg.ai API.
|
54
54
|
|
55
55
|
## Request Routing
|
56
|
-
The `generate_image` method routes requests based on the provided options and the model's supported pipelines, sending it to its respective pipeline whether that's SD1.5, SDXL or LCM based:
|
56
|
+
The `generate_image` method routes requests based on the provided options and the model's supported pipelines, sending it to its respective pipeline whether that's SD1.5, SDXL, Essential, or LCM based:
|
57
57
|
- **text-to-image**: Default if no images are provided.
|
58
58
|
- **image-to-image**: Triggered if a base image is provided.
|
59
59
|
- **inpaint**: Triggered if a mask image is provided.
|
@@ -82,8 +82,12 @@ If an HTTP error occurs, the error message will include both the HTTP status and
|
|
82
82
|
## Models
|
83
83
|
The provided `model` option will determine the model use, and contribute to the client's inference of the desired endpoint. Models can be the string `id` listed online at [the GetImg dashboard](https://dashboard.getimg.ai/models) or retrieved using the `GetimgClient.models` method. Equally, you can use symbols instead. For example, `:realistic_vision_v5_1` will translate to `'realistic-vision-v5-1'`
|
84
84
|
|
85
|
+
## Essential
|
86
|
+
Getimg offers the "essential" checkpoints, which perform more abstract Stable Diffusion operations based on the provided prompt. Note that *:essential* and *:essential_v2* will *not* be listed in the model listing, as these are not in fact actual models, nor valid "model" values at the API's end.
|
87
|
+
In order to route a request to Essential or Essential V2 however, you can provide *:essential* or *:essential_v2* as a model argument in *#generate_image*.
|
88
|
+
|
85
89
|
## Latent Consistency Models (LCM)
|
86
|
-
Latent
|
90
|
+
Latent Consistency Models (LCM) are optimized for faster image generation and lower costs by avoiding the repetitive steps of traditional diffusion methods. They work in a lower-dimensional space, resulting in quicker outputs but with slightly less detail compared to standard models.
|
87
91
|
|
88
92
|
## Base Image Options
|
89
93
|
The `base_image` option can be provided, which will automatically set the "image" property for image-to-image, controlnet, face-fix, upscale, inpaint and instruct calls, and can be either a file path or a base64 encoded string of the file contents.
|
@@ -98,7 +102,13 @@ If all went well and no errors were reported, the response will be equal to the
|
|
98
102
|
GetimgClient.set_api_key('your_api_key')
|
99
103
|
```
|
100
104
|
|
101
|
-
### Generate Text-to-Image
|
105
|
+
### Generate Text-to-Image using Essential V1 with default options
|
106
|
+
```ruby
|
107
|
+
result = GetimgClient.generate_image("A city skyline at night")
|
108
|
+
puts result["image"]
|
109
|
+
```
|
110
|
+
|
111
|
+
### Generate Text-to-Image using Stable Diffusion 1.5
|
102
112
|
```ruby
|
103
113
|
result = GetimgClient.generate_image("A scenic landscape", model: :stable_diffusion_v1_5, width: 512, height: 512)
|
104
114
|
puts result["image"]
|
@@ -114,7 +124,7 @@ puts result["image"]
|
|
114
124
|
### Generate an image using Controlnet
|
115
125
|
```ruby
|
116
126
|
base_image = "path/to/base_image.jpg"
|
117
|
-
result = GetimgClient.generate_image("Enhance the scene", model: :stable_diffusion_v1_5, base_image:, strength: 0.7, controlnet: canny-1.1)
|
127
|
+
result = GetimgClient.generate_image("Enhance the scene", model: :stable_diffusion_v1_5, base_image:, strength: 0.7, controlnet: 'canny-1.1')
|
118
128
|
puts result["image"]
|
119
129
|
```
|
120
130
|
|
@@ -148,7 +158,21 @@ puts result["image"]
|
|
148
158
|
```
|
149
159
|
|
150
160
|
## Logging
|
151
|
-
|
161
|
+
GetimgClient supports logging request details for debugging and development purposes. The logging behavior depends on the environment and configuration:
|
162
|
+
|
163
|
+
Rails Development Environment: If the **RAILS_ENV** environment variable is set to "development" and Rails is defined, logs will be sent to the Rails logger.
|
164
|
+
|
165
|
+
**GETIMG_LOG** Environment Variable: If the GETIMG_LOG environment variable is set, logs will be printed to the standard output.
|
166
|
+
|
167
|
+
#### Log output example
|
168
|
+
```text
|
169
|
+
Generating image with the following details:
|
170
|
+
Prompt: A scenic landscape
|
171
|
+
Model: stable-diffusion-v1-5
|
172
|
+
Requested Pipeline: text-to-image
|
173
|
+
Endpoint URI: https://api.getimg.ai/v1/stable-diffusion/text-to-image
|
174
|
+
Options: {width: 512, height: 512}
|
175
|
+
```
|
152
176
|
|
153
177
|
## Unit Testing
|
154
178
|
The gem includes unit tests using Minitest. Integration tests make real API calls and will incur usage fees. Ensure your API key is set in the environment before running tests.
|
data/lib/endpoints.json
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
"lcm_text_to_image": "https://api.getimg.ai/v1/latent-consistency/text-to-image",
|
11
11
|
"lcm_image_to_image": "https://api.getimg.ai/v1/latent-consistency/image-to-image",
|
12
12
|
"essential_text_to_image": "https://api.getimg.ai/v1/essential/text-to-image",
|
13
|
+
"essentialv2_text_to_image": "https://api.getimg.ai/v1/essential-v2/text-to-image",
|
13
14
|
"face_fix": "https://api.getimg.ai/v1/enhancements/face-fix",
|
14
15
|
"upscale": "https://api.getimg.ai/v1/enhancements/upscale",
|
15
16
|
"models": "https://api.getimg.ai/v1/models",
|
data/lib/getimg_client.rb
CHANGED
@@ -32,7 +32,7 @@ class GetimgClient
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# Generate an image based on the prompt and model
|
35
|
-
def self.generate_image(prompt, model
|
35
|
+
def self.generate_image(prompt, model: :essential, **options)
|
36
36
|
# Validate the prompt
|
37
37
|
raise ArgumentError, 'Prompt is required' unless prompt.is_a?(String) && !prompt.strip.empty?
|
38
38
|
|
@@ -43,7 +43,11 @@ class GetimgClient
|
|
43
43
|
|
44
44
|
# Convert model to appropriate ID format
|
45
45
|
model_id = model.to_s.gsub('_', '-')
|
46
|
-
|
46
|
+
if %w[essential essential-v2].include?(model_id)
|
47
|
+
model_info = models[model_id] || { name: model_id, pipelines: ['text-to-image'] }
|
48
|
+
else
|
49
|
+
model_info = models[model_id] || raise(ArgumentError, "Unknown model: #{model}")
|
50
|
+
end
|
47
51
|
|
48
52
|
# Determine the requested pipeline
|
49
53
|
requested_pipeline = method_requested(base_image, mask_image_path, controlnet, model_info).to_s.gsub('_', '-')
|
@@ -54,7 +58,7 @@ class GetimgClient
|
|
54
58
|
end
|
55
59
|
|
56
60
|
# Determine the endpoint key based on the model family and pipeline
|
57
|
-
endpoint_key = determine_endpoint_key(model_info, requested_pipeline)
|
61
|
+
endpoint_key = determine_endpoint_key(model_info, requested_pipeline, model_id)
|
58
62
|
uri = URI(API_ENDPOINTS[endpoint_key.to_s])
|
59
63
|
|
60
64
|
# Handle image to image, controlnet, instruct, inpaint, face-fix, and upscale pipelines
|
@@ -71,16 +75,8 @@ class GetimgClient
|
|
71
75
|
# Ensure scale is an integer if present
|
72
76
|
options[:scale] = options[:scale].to_i if options[:scale]
|
73
77
|
|
74
|
-
#
|
75
|
-
|
76
|
-
puts "Generating image with the following details:"
|
77
|
-
puts "Prompt: #{prompt}"
|
78
|
-
puts "Model: #{model_id}"
|
79
|
-
puts "Requested Pipeline: #{requested_pipeline}"
|
80
|
-
puts "Endpoint URI: #{uri}"
|
81
|
-
truncated_options = options.transform_values { |v| v.is_a?(String) && v.length > 50 ? "#{v[0, 50]}..." : v }
|
82
|
-
puts "Options: #{truncated_options}"
|
83
|
-
end
|
78
|
+
# Log the request details
|
79
|
+
log_request_details(prompt, model_id, requested_pipeline, uri, options)
|
84
80
|
|
85
81
|
# Create and send the request
|
86
82
|
request = create_request(uri, prompt, model: model_id, **options)
|
@@ -101,6 +97,25 @@ class GetimgClient
|
|
101
97
|
|
102
98
|
private
|
103
99
|
|
100
|
+
# Log request details
|
101
|
+
def self.log_request_details(prompt, model_id, requested_pipeline, uri, options)
|
102
|
+
log_message = <<~LOG
|
103
|
+
Generating image with the following details:
|
104
|
+
Prompt: #{prompt}
|
105
|
+
Model: #{model_id}
|
106
|
+
Requested Pipeline: #{requested_pipeline}
|
107
|
+
Endpoint URI: #{uri}
|
108
|
+
Options: #{options.transform_values { |v| v.is_a?(String) && v.length > 50 ? "#{v[0, 50]}..." : v }}
|
109
|
+
LOG
|
110
|
+
|
111
|
+
if ENV['RAILS_ENV'] === 'development' && defined?(Rails) && Rails.logger
|
112
|
+
Rails.logger.info(log_message)
|
113
|
+
end
|
114
|
+
if ENV['GETIMG_LOG']
|
115
|
+
puts log_message
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
104
119
|
# Determine the requested method based on provided image paths, controlnet, and model_info
|
105
120
|
def self.method_requested(base_image, mask_image_path, controlnet, model_info)
|
106
121
|
return :controlnet if controlnet
|
@@ -113,8 +128,12 @@ class GetimgClient
|
|
113
128
|
end
|
114
129
|
|
115
130
|
# Determine the appropriate endpoint key based on the model family and pipeline
|
116
|
-
def self.determine_endpoint_key(model_info, requested_pipeline)
|
117
|
-
if
|
131
|
+
def self.determine_endpoint_key(model_info, requested_pipeline, model_id)
|
132
|
+
if model_id == 'essential'
|
133
|
+
return :essential_text_to_image
|
134
|
+
elsif model_id == 'essential-v2'
|
135
|
+
return :essentialv2_text_to_image
|
136
|
+
elsif model_info[:family] == 'stable-diffusion-xl'
|
118
137
|
return :sdxl_image_to_image if requested_pipeline == 'image-to-image'
|
119
138
|
return :sdxl_inpaint if requested_pipeline == 'inpaint'
|
120
139
|
return :sdxl_text_to_image
|
@@ -133,10 +152,8 @@ class GetimgClient
|
|
133
152
|
request['accept'] = 'application/json'
|
134
153
|
request['content-type'] = 'application/json'
|
135
154
|
|
136
|
-
body = {
|
137
|
-
|
138
|
-
model: model
|
139
|
-
}.merge(options)
|
155
|
+
body = { prompt: prompt }.merge(options)
|
156
|
+
body[:model] = model unless %w[essential essential-v2].include?(model)
|
140
157
|
|
141
158
|
request.body = body.to_json
|
142
159
|
request
|
@@ -1,11 +1,10 @@
|
|
1
1
|
require_relative "../test_helper"
|
2
|
+
require 'stringio'
|
2
3
|
|
3
4
|
class GetimgClientIntegrationTest < Minitest::Test
|
4
5
|
def setup
|
5
6
|
@base_image = Base64.strict_encode64(File.read(File.join(__dir__, "sample_image.jpeg")))
|
6
|
-
|
7
7
|
@small_image = Base64.strict_encode64(File.read(File.join(__dir__, "small_sample_image.jpeg")))
|
8
|
-
|
9
8
|
@mask_image = Base64.strict_encode64(File.read(File.join(__dir__, "mask_image.jpeg")))
|
10
9
|
end
|
11
10
|
|
@@ -58,6 +57,42 @@ class GetimgClientIntegrationTest < Minitest::Test
|
|
58
57
|
save_image(result["image"], "test_upscale")
|
59
58
|
end
|
60
59
|
|
60
|
+
def test_generate_text_to_image_essential
|
61
|
+
puts "-- Running test_generate_text_to_image_essential..."
|
62
|
+
result = GetimgClient.generate_image("A modern cityscape")
|
63
|
+
assert result["image"]
|
64
|
+
save_image(result["image"], "test_generate_text_to_image_essential")
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_logging_to_rails_logger
|
68
|
+
skip "Rails not defined, skipping Rails logger test" unless defined?(Rails) && ENV['RAILS_ENV'] === 'development'
|
69
|
+
|
70
|
+
original_logger = Rails.logger
|
71
|
+
log_output = StringIO.new
|
72
|
+
Rails.logger = Logger.new(log_output)
|
73
|
+
|
74
|
+
GetimgClient.generate_image("A scenic landscape", model: :stable_diffusion_v1_5, width: 512, height: 512)
|
75
|
+
|
76
|
+
assert_includes log_output.string, "Generating image with the following details:"
|
77
|
+
assert_includes log_output.string, "Prompt: A scenic landscape"
|
78
|
+
|
79
|
+
Rails.logger = original_logger
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_logging_to_puts
|
83
|
+
ENV['GETIMG_LOG'] = '1'
|
84
|
+
log_output = StringIO.new
|
85
|
+
$stdout = log_output
|
86
|
+
|
87
|
+
GetimgClient.generate_image("A scenic landscape", model: :stable_diffusion_v1_5, width: 512, height: 512)
|
88
|
+
|
89
|
+
assert_includes log_output.string, "Generating image with the following details:"
|
90
|
+
assert_includes log_output.string, "Prompt: A scenic landscape"
|
91
|
+
|
92
|
+
$stdout = STDOUT
|
93
|
+
ENV.delete('GETIMG_LOG')
|
94
|
+
end
|
95
|
+
|
61
96
|
private
|
62
97
|
|
63
98
|
def save_image(base64_image, filename)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: getimg_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Melvin Sommer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|