└── docs
└── api
├── 0-overview.md
├── 0-tune
├── 0-tune.md
├── 1-create.md
├── 2-retrieve.md
├── 4-list.md
├── 5-delete.md
└── _category_.json
├── 05-flux-api.md
├── 1-prompt
├── 0-prompt.md
├── 1-create.md
├── 2-retrieve.md
├── 4-list.md
├── 5-delete.md
└── _category_.json
├── 2-pack
├── 0-pack.md
├── 1-list.md
├── 2-tunes
│ ├── 0-create.md
│ └── _category_.json
├── _category_.json
├── assign_prompts.png
└── create_pack.png
├── 20-sdxl-api.md
├── 3-like
├── 0-create.md
├── 1-delete.md
└── _category_.json
├── 4-images
├── 1-inspect.md
└── _category_.json
├── 5-themes
├── 1-create.md
└── _category_.json
└── _category_.json
/docs/api/0-overview.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Overview
3 | ---
4 |
5 | # Astria Fine-tuning API - Overview
6 |
7 | ## Billing
8 | The API uses account balance just like the web interface. See the [pricing](https://www.astria.ai/pricing) page for more details.
9 |
10 | ## Mock testing
11 | The API allows creating a mock `Tune` object with attribute `branch=fast`. See [Create a tune documentation](https://docs.astria.ai/docs/api/tune/create#branch-optional). API call for creating `fast` tune is free, and subsequent prompt calls will return mock images without incurring any charges. This is useful for testing your integration with the API.
12 | Once you're ready for production, you can [purchase credits](https://www.astria.ai/users/edit#billing) and adjust the quantity on the checkout page to how much you need.
13 |
14 | ## Beta features
15 | Astria maintains backward compatability and avoid making changes that could alter the behavior of the API. However, features marked as BETA are subject to change as we try to improve the product.
16 |
17 | ## Auto top off
18 | To allow your account to work without disruption, top-off feature can be enabled to refill account each time account balance reaches zero. Auto top-off can be enabled in the [billing page](https://www.astria.ai/users/edit#billing).
19 | It is recommended to set the top-off amount to at least a week worth of API calls to avoid hitting the rate limit on top-off - Frequent top-offs can cause credit card charges to fail or bank declines.
20 |
21 | ## Storage
22 | Generated images, training pictures and models, will be automatically deleted 30 days after the training has ended. You may delete the fine-tune object including the trained model, training images, and generated images at any time before using the delete API calls. You may opt-in to automatically [extend model storage](https://www.astria.ai/users/edit#billing) or set the `auto_extend` for [tune](/docs/api/tune/create/).
23 |
24 |
25 | ## Authorization
26 | The API uses bearer `Authorization` headers scheme. API calls should include the header:
27 |
28 | ```text
29 | Authorization: Bearer sd_XXXXXX
30 | ```
31 |
32 | Find your API key on the [API settings](https://www.astria.ai/users/edit#api) under your account settings.
33 |
34 |
35 | ## REST API
36 | Astria API is built as a REST API. Main resources are `tune` and `prompt` and each one has all the CRUD operations. Prompts are usually used as a nested resource on top of tunes (i.e: `/tunes/:id/prompts`).
37 |
38 | ## Error Codes
39 |
40 | :::tip
41 | Pay attention to 504 error below and turn on idempotency for your account to avoid duplicate objects.
42 | :::
43 |
44 | `422` - Validation error - Log these errors, specifically the response body, and use an exception tracking system such as Rollbar or Sentry to get notified. Do not retry these requests.
45 |
46 | `429` - Rate limiting - This error might show when using polling. Use callbacks to avoid this.
47 |
48 | `500` - Internal server error - Such requests should be retried with exponential backoff and wait start time of 30 seconds.
49 |
50 | `504` - Gateway timeout - This error indicates that the request processing took more than the 30 seconds which is set as the max request timeout. In most cases the request would probably have been processed and you should avoid retrying it. In order to get the response see Idempotency section
51 |
52 |
53 | ## Idempotency
54 |
55 | Idempotency is a principle in programming which means that the same operation (a request in our case) can be made multiple times without changing the result. This can be useful when a request is interrupted and you want to make sure it is processed only once, and avoid duplicate objects.
56 |
57 | Idempotency can be enabled for the account in the [API settings](https://www.astria.ai/users/edit#api).
58 |
59 | For tunes request with the same `title`, idempotency will return the existing tune object and will not create a new one. This is useful for cases where you want to make sure you don't create duplicate tunes. In this case set the tune title to a unique value such as a UUID which identifies the transaction.
60 |
61 | For prompts request with the same attributes, idempotency will return the existing prompt object and will not create a new one. Prompt attributes considered for the idempotency are `text, tune_id, cfg_scale, steps, seed, callback, negative_prompt, super_resolution, face_correct, ar, num_images, controlnet, denoising_strength, use_lpw, controlnet_conditioning_scale, w, h, hires_fix, scheduler, controlnet_txt2img, inpaint_faces`
62 |
63 | When retrying a 504 error, and idempotency is enabled, make sure to wait 60 seconds before retrying the request to allow the previous request to finish processing.
64 |
65 | ## Callbacks
66 |
67 | Callbacks for prompts and tunes are `POST` requests containing the entity object in the request body. Callbacks work in test mode with `branch=fast`. Callbacks are currently not retried if they fail. To test your callbacks, we recommend a local tunnel tool like [ngrok](https://ngrok.com/). If you need your backend server to receive some context arguments/metadata for the callback, like internal user-id or transaction id, we recommend adding those to the callback query string.
68 |
--------------------------------------------------------------------------------
/docs/api/0-tune/0-tune.md:
--------------------------------------------------------------------------------
1 | # The tune object
2 | Tune (or Fine-tune) represents a model that is created using training images to learn a new concept or subject. At its core a fine-tune is a neural-network weights file (usually weights 2GB) and contains the information of the trained images.
3 | A fine-tune model can be of various types (checkpoint or lora) and can be used to create prompts which will in turn generate images.
4 |
--------------------------------------------------------------------------------
/docs/api/0-tune/1-create.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Create a tune
3 | hide_table_of_contents: true
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 |
10 |
11 |
12 | Creates a new fine-tune model from training images which in turn will be used to create prompts and generate images.
13 |
14 | ### Parameters
15 |
16 | #### `name` (required)
17 | A class name the describes the fine-tune. e.g: `man`, `woman`, `cat`, `dog`, `boy`, `girl`, `style`
18 |
19 | #### `title` (required)
20 | Describes the fine-tune. Ideally a UUID related to the transaction. See [idempotency](/docs/api/overview) for more information.
21 |
22 | #### `images` (required)
23 | An array of images to train the fine-tune with. The images can be uploaded as multipart/form-data or as image_urls.
24 |
25 | #### `image_urls` (required)
26 | An array of images to train the fine-tune with. The images can be uploaded as multipart/form-data or as image_urls.
27 |
28 | #### `callback` (optional)
29 | A webhook URL to be called when the tune is finished training. The webhook will receive a POST request with the tune object. See [more on callbacks](/docs/api/overview#callbacks).
30 |
31 | #### `branch` (optional)
32 | Enum: `sd15`, `sdxl1`, `fast`. Will default to the `base_tune` branch if not specified, or to `sd15` if `base_tune` is not specified.
33 |
34 | :::info
35 | Use `branch=fast` for [mock testing](https://docs.astria.ai/docs/api/overview#mock-testing)
36 | :::
37 |
38 | #### `steps` (optional)
39 | Training steps. Recommended leaving blank in order to allow better defaults set by the system.
40 |
41 | #### `token` (optional)
42 | Unique short text to which the features will be embedded into. Default `ohwx` for SDXL and `sks` for SD15.
43 |
44 | #### `face_crop` (optional)
45 | Detects faces in training images and augments training set with cropped faces. Defaults to [account setting](https://www.astria.ai/users/edit)
46 |
47 | #### `training_face_correct` (optional)
48 | Enhance training images using GFPGAN. Consider enabling if input image are low quality or low resolution. May result in over-smoothing.
49 |
50 | #### `base_tune_id` (optional)
51 | Training on top of former fine-tune or a different baseline model from the [gallery](https://www.astria.ai/gallery/tunes) (id in the URL). e.g: `690204` - Realistic Vision v5.1
52 |
53 | #### `model_type` (optional)
54 | Enum: `lora`, `pti`, `faceid`, `null` for checkpoint.
55 | For SDXL1 - API will default to `pti` and will ignore `model_type` parameter.
56 |
57 | #### `auto_extend` (optional)
58 | Boolean: `true`, `false`. If `true`, the tune will be automatically extended when it expires. Default is `false`. See [pricing](https://www.astria.ai/pricing).
59 |
60 | #### `preset` (optional)
61 | Enum: `flux-lora-focus`, `flux-lora-portrait`, `flux-lora-fast` see details in the GUI, `null`. See [Flux lora training](/docs/use-cases/flux-finetuning/) for more information.
62 |
63 | #### `characteristics` (optional)
64 | A free-form object that can be used to templatize the prompts text. e.g: `{"eye_color": "blue eyes"}` would than be used in the prompt text as `ohwx woman, {{eye_color}}, holding flowers`.
65 |
66 | #### `prompts_attributes` (optional)
67 | Array of prompts entities with all attributes. See [create prompt](/docs/api/prompt/create) for more information.
68 |
69 | ### Returns
70 |
71 | Returns a tune object if successful which will start training immediately and call callback once training is complete.
72 |
73 |
11 |
12 | ### Parameters
13 |
14 | #### `offset` (optional)
15 | Starting offset for the list of prompts. Default: 0. Current page size is 20.
16 |
17 | ### Returns
18 |
19 | An array of all fine-tunes owned by the authenticated user
20 |
11 |
12 | Deletes a specific tune by its ID, and associated prompts in case of a checkpoint.
13 |
14 | ### Parameters
15 |
16 | #### `id` (required)
17 | The ID of the tune to be deleted.
18 |
19 | ### Returns
20 |
21 | Returns 200 OK if the prompt was successfully deleted.
22 |
23 |
62 |
--------------------------------------------------------------------------------
/docs/api/05-flux-api.md:
--------------------------------------------------------------------------------
1 | ---
2 | hide_table_of_contents: true
3 | tags: ["flux", "api", "training", "fine-tuning", "lora"]
4 | image: ../use-cases/img/ai-photoshoot-output.jpg
5 | ---
6 |
7 | import Tabs from '@theme/Tabs';
8 | import TabItem from '@theme/TabItem';
9 |
10 |
11 | # Flux API usage
12 |
13 | For an overview of Flux fine-tuning, see [Flux fine-tuning](/docs/use-cases/flux-finetuning/)
14 |
15 |
16 |
17 |
18 | * Unlike SD15 checkpoint training, Flux is trained as a LoRA model type. As such, inference is taking place on a base model such as Flux1.dev and `prompt.text` should specify the loaded lora such as `` - will load lora with id=123456 and strength=1
19 | * Flux1.Dev requires commercial license which Astria provides to its customers, and as such LoRA downloading is not available for API usage.
20 |
21 | See [LoRA docs](/docs/features/lora) on lora syntax
22 |
23 |
24 | :::info
25 | To avoid cloning inference details of different model types such as Flux LoRA vs SD1.5 checkpoint, please consider using the [Packs API](/docs/api/pack/pack/). Packs will help you abstract the inference logic so that you do not have to hard-code prompts and parameters such as `w,h, cfg_scale` in your backend. Moreover this will allow the creative department to launch packs, make modifications and even track likes, without needing to touch the backend code.
26 | :::
27 |
28 |
29 |
30 |
31 | ### Step 1: Fine-tune a lora model
32 | #### POST /tunes
33 |
34 |
35 |
36 |
37 | ```bash showLineNumbers
38 | # With images as multipart/form-data
39 | # Hard coded tune id of Flux1.dev from the gallery - https://www.astria.ai/gallery/tunes
40 | # https://www.astria.ai/gallery/tunes/1504944/prompts
41 | curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes \
42 | -F tune[title]="John Doe - UUID - 1234-6789-1234-56789" \
43 | -F tune[name]=man \
44 | -F tune[preset]=flux-lora-portrait \
45 | -F tune[callback]="https://optional-callback-url.com/webhooks/astria?user_id=1&tune_id=1" \
46 | -F tune[base_tune_id]=1504944 \
47 | -F tune[model_type]="lora" \
48 | -F "tune[images][]=@1.jpg" \
49 | -F "tune[images][]=@2.jpg" \
50 | -F "tune[images][]=@3.jpg" \
51 | -F "tune[images][]=@4.jpg"
52 |
53 | # With image_urls as form-data
54 | curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes \
55 | -F tune[title]="Grumpy cat - UUID - 1234-6789-1234-56789" \
56 | -F tune[name]=cat \
57 | -F tune[preset]=flux-lora-portrait \
58 | -F tune[callback]="https://optional-callback-url.com/to-your-service-when-ready?user_id=1&tune_id=1" \
59 | -F tune[base_tune_id]=1504944 \
60 | -F tune[model_type]="lora" \
61 | -F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg" \
62 | -F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg" \
63 | -F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg" \
64 | -F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg"
65 |
66 | # As JSON
67 | cat > data.json <<- EOM
68 | {
69 | "tune": {
70 | "title": "Grumpy Cat - UUID - 1234-6789-1234-56789",
71 | "name": "cat",
72 | "base_tune_id": 1504944,
73 | "model_type": "lora",
74 | "callback": "https://optional-callback-url.com/to-your-service-when-ready?user_id=1&tune_id=1",
75 | "image_urls": [
76 | "https://i.imgur.com/HLHBnl9.jpeg",
77 | "https://i.imgur.com/HLHBnl9.jpeg",
78 | "https://i.imgur.com/HLHBnl9.jpeg",
79 | "https://i.imgur.com/HLHBnl9.jpeg"
80 | ]
81 | }
82 | }
83 | EOM
84 |
85 | curl -X POST -H"Content-Type: application/json" -H "Authorization: Bearer $API_KEY" --data @data.json https://api.astria.ai/tunes
86 | ```
87 |
88 |
89 |
90 | ```javascript
91 | // NodeJS 16
92 | // With image_urls and fetch()
93 | // For NodeJS 18 - do NOT import the below as it is built-in
94 | import fetch from "node-fetch";
95 |
96 | const API_KEY = 'sd_XXXXXX';
97 | const DOMAIN = 'https://api.astria.ai';
98 |
99 | function createTune() {
100 | let options = {
101 | method: 'POST',
102 | headers: { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json' },
103 | body: JSON.stringify({
104 | tune: {
105 | "title": 'John Doe - UUID - 1234-6789-1234-56789',
106 | // Hard coded tune id of Flux1.dev from the gallery - https://www.astria.ai/gallery/tunes
107 | // https://www.astria.ai/gallery/tunes/1504944/prompts
108 | "base_tune_id": 1504944,
109 | "model_type": "lora",
110 | "name": "cat",
111 | "preset": "flux-lora-portrait",
112 | "image_urls": [
113 | "https://i.imgur.com/HLHBnl9.jpeg",
114 | "https://i.imgur.com/HLHBnl9.jpeg",
115 | "https://i.imgur.com/HLHBnl9.jpeg",
116 | "https://i.imgur.com/HLHBnl9.jpeg"
117 | ],
118 | }
119 | })
120 | };
121 | return fetch(DOMAIN + '/tunes', options)
122 | .then(r => r.json())
123 | .then(r => console.log(r))
124 | }
125 |
126 | createTune()
127 |
128 |
129 | /// With form-data, fetch() and nested prompts
130 | // For NodeJS 18 - do NOT import the two below as they are built-in
131 | import fetch from "node-fetch";
132 | import FormData from 'form-data';
133 | import fs from 'fs';
134 |
135 | const API_KEY = 'sd_XXXX';
136 | const DOMAIN = 'https://api.astria.ai';
137 | function createTune() {
138 | let formData = new FormData();
139 | formData.append('tune[title]', 'John Doe - UUID - 1234-6789-1234-56789');
140 | // Hard coded tune id of Flux1.dev from the gallery - https://www.astria.ai/gallery/tunes
141 | // https://www.astria.ai/gallery/tunes/1504944/prompts
142 | formData.append('tune[base_tune_id]', 1504944);
143 | formData.append('tune[model_type]', 'lora');
144 | formData.append('tune[name]', 'man');
145 | formData.append('tune[preset]', 'flux-lora-portrait');
146 | // Load all JPGs from ./samples directory and append to FormData
147 | let files = fs.readdirSync('./samples');
148 | files.forEach(file => {
149 | if(file.endsWith('.jpg')) {
150 | formData.append('tune[images][]', fs.createReadStream(`./samples/${file}`), file);
151 | }
152 | });
153 | formData.append('tune[callback]', 'https://optional-callback-url.com/to-your-service-when-ready?user_id=1&tune_id=1');
154 |
155 | let options = {
156 | method: 'POST',
157 | headers: {
158 | 'Authorization': 'Bearer ' + API_KEY
159 | },
160 | body: formData
161 | };
162 | return fetch(DOMAIN + '/tunes', options)
163 | .then(r => r.json())
164 | .then(r => console.log(r));
165 | }
166 |
167 | createTune();
168 |
169 | ```
170 |
171 |
172 |
173 | ```python
174 | import requests
175 | headers = {'Authorization': f'Bearer {API_KEY}'}
176 |
177 | def load_image(file_path):
178 | with open(file_path, "rb") as f:
179 | return f.read()
180 |
181 | # Assuming `prompts` and `tune.images` are already defined in your context
182 |
183 | image_data = load_image("assets/image.jpeg")
184 |
185 | data = {
186 | "tune[title]": "John Doe - UUID - 1234-6789-1234-56789",
187 | "tune[name]": "man",
188 | "tune[preset]": "flux-lora-portrait",
189 | "tune[base_tune_id]": 1504944,
190 | "tune[model_type]": "lora",
191 | }
192 | files = []
193 |
194 | for image in tune.images:
195 | image_data = load_image(image) # Assuming image is a file path
196 | files.append(("tune[images][]", image_data))
197 |
198 | API_URL = 'https://api.astria.ai/tunes'
199 | response = requests.post(API_URL, data=data, files=files, headers=headers)
200 | response.raise_for_status()
201 |
202 | ```
203 |
204 |
205 |
206 |
207 | ### Step 2: Generate images using the fine-tuned model
208 | #### POST /tunes/:id/prompts
209 |
210 |
211 |
212 |
213 | ```bash showLineNumbers
214 | # Note the hard-coded 1504944 which is the tune_id of Flux1.dev from the gallery
215 | curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes/1504944/prompts \
216 | -F prompt[text]=" a painting of ohwx man in the style of Van Gogh" \
217 | -F prompt[callback]="https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1"
218 | ```
219 |
220 |
221 |
222 | ```javascript
223 | const fetch = require('node-fetch');
224 | const FormData = require('form-data');
225 |
226 | // Note the hard-coded 1504944 which is the tune_id of Flux1.dev from the gallery
227 | const API_URL = 'https://api.astria.ai/tunes/1504944/prompts';
228 | const API_KEY = 'YOUR_API_KEY'; // Replace with your actual API key
229 | const headers = { Authorization: `Bearer ${API_KEY}` }
230 |
231 | const form = new FormData();
232 | form.append('prompt[text]', ' a painting of ohwx man in the style of Van Gogh');
233 | form.append('prompt[callback]', 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1');
234 |
235 | fetch(API_URL, {
236 | method: 'POST',
237 | headers: headers,
238 | body: form
239 | }).then(response => response.json())
240 |
241 |
242 | ```
243 |
244 |
245 |
246 | ```python
247 | import requests
248 |
249 | # Note the hard-coded 1504944 which is the tune_id of Flux1.dev from the gallery
250 | API_URL = 'https://api.astria.ai/tunes/1504944/prompts'
251 | API_KEY = 'YOUR_API_KEY' # Replace with your actual API key
252 |
253 | headers = {
254 | 'Authorization': f'Bearer {API_KEY}'
255 | }
256 |
257 | data = {
258 | 'prompt[text]': ' a painting of ohwx man in the style of Van Gogh',
259 | 'prompt[callback]': 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1'
260 | }
261 | files = []
262 |
263 | response = requests.post(API_URL, headers=headers, data=data)
264 | ```
265 |
266 |
267 |
268 |
269 |
270 |
--------------------------------------------------------------------------------
/docs/api/1-prompt/0-prompt.md:
--------------------------------------------------------------------------------
1 | # The prompt object
2 | The prompt object is usually used as a nested resource of tune as prompts are generated using a fine-tune model. A prompt is a text that is used to generate images using a fine-tune model. The prompt object contains the generated images.
3 |
--------------------------------------------------------------------------------
/docs/api/1-prompt/1-create.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Create a prompt
3 | hide_table_of_contents: true
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 |
10 |
11 |
12 | Creates a new fine-tune model from training images which in turn will be used to create prompts and generate images.
13 |
14 | ### Parameters
15 |
16 | #### `text` (required)
17 | Description of the image.
18 |
19 | #### `negative_prompt` (optional)
20 | A comma separated list of words that should not appear in the image.
21 |
22 | #### `callback` (optional)
23 | a URL that will be called when the prompt is done processing. The callback is a POST request where the body contains the prompt object. See [more](/docs/api/overview#callbacks).
24 |
25 | #### `num_images` (optional)
26 | Number of images to generate. Range: 1-8.
27 |
28 | #### `seed` (optional)
29 | Random number to create consistent results. Range: 0 to 2^32.
30 |
31 | #### `super_resolution` (optional)
32 | Boolean. X4 super-resolution.
33 |
34 | #### `inpaint_faces` (optional)
35 | Boolean. Requires super-resolution on. Inpaints faces.
36 |
37 | #### `hires_fix` (optional)
38 | Boolean. Super resolution details. Available only when super_resolution is true. Adds details.
39 |
40 | #### `face_correct` (optional)
41 | Boolean. Runs another AI model on top to correct the face in the image.
42 |
43 | #### `face_swap` (optional)
44 | Boolean. Uses training images to swap face and enhance resemblance.
45 |
46 | #### `cfg_scale` (optional)
47 | Float. How strictly the diffusion process adheres to the prompt text (higher values keep your image closer to your prompt). Range 0-15
48 |
49 | #### `steps` (optional)
50 | Integer. Number of diffusion steps to run . Range 0-50
51 |
52 | #### `use_lpw` (optional)
53 | Boolean. Use weighted prompts.
54 |
55 | #### `w` (optional)
56 | width - In multiples of 8.
57 |
58 | #### `h` (optional)
59 | height - In multiples of 8.
60 |
61 | #### `scheduler` (optional)
62 | enum: `euler`, `euler_a`, `dpm++2m_karras`, `dpm++sde_karras`, `dpm++2m`, `dpm++sde`, `lcm`, `tcd`. If not specified the default [account scheduler](https://www.astria.ai/users/edit) will be used.
63 |
64 | #### `backend_version` (optional)
65 | enum: null, `1`, If not specified will default to the [account version](https://www.astria.ai/users/edit) will be used.
66 |
67 | #### `style` (optional)
68 | enum: null, `Cinematic`, `Animated`, `Digital Art`, `Photographic`, `Fantasy art`, `Neonpunk`, `Enhance`, `Comic book`, `Lowpoly`, `Line art`. See [more](/docs/features/styles).
69 |
70 | #### `color_grading` (optional)
71 | enum: `Film Velvia`, `Film Portra`, `Ektar`.
72 |
73 | #### `film_grain` (optional)
74 | boolean - Adds noise to the image to make it look more realistic.
75 |
76 | ## Img2Img / ControlNet
77 |
78 | #### `controlnet` (optional)
79 | Requires input_image. Possible values: composition, reference, segroom, ipadapter, lineart, canny, depth, mlsd, hed, pose, tile, qr.
80 |
81 | #### `denoising_strength` (optional)
82 | For img2img. 1.0 - Take prompt. 0.0 - Take image. Range: 0.0-1.0. Default: 0.8
83 |
84 | #### `controlnet_conditioning_scale` (optional)
85 | Strength of controlnet conditioning. 0.0-1.0
86 |
87 | #### `controlnet_txt2img` (optional)
88 | Boolean toggle. True for text to image controlnet. False for image to image controlnet.
89 |
90 | #### `input_image` (optional)
91 | Binary multi-part request with the image. Used in conjunction with controlnet parameter.
92 |
93 | #### `input_image_url` (optional)
94 | URL to an image. Used in conjunction with controlnet parameter.
95 |
96 | #### `mask_image` (optional)
97 | Binary multi-part request with one channel mask image. Used in conjunction with input_image parameter for inpainting
98 |
99 | #### `mask_image_url` (optional)
100 | URL to a one channel mask image. Used in conjunction with input_image_url parameter for inpainting.
101 |
102 | #### `lora_scale` (optional)
103 | Available only when used as `prompts_attributes` in `POST /tunes` request to override the default scale of the LoRA model.
104 |
105 | ### Returns
106 |
107 | Returns a prompt object if successful which will start processing if tune is processed.
108 |
109 |
110 |
111 |
112 |
113 | #### POST /tunes/:id/prompts
114 |
115 |
116 |
117 |
118 | ```bash showLineNumbers
119 | curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes/1/prompts \
120 | -F prompt[text]="a painting of ohwx man in the style of Van Gogh" \
121 | -F prompt[negative_prompt]="old, blemish, wrin" \
122 | -F prompt[super_resolution]=true \
123 | -F prompt[face_correct]=true \
124 | -F prompt[callback]="https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1"
125 | ```
126 |
127 |
128 |
129 | ```javascript
130 | const fetch = require(`node-fetch');
131 | const FormData = require('form-data');
132 |
133 | const API_URL = 'https://api.astria.ai/tunes/1/prompts';
134 | const API_KEY = 'YOUR_API_KEY'; // Replace with your actual API key
135 | const headers = { Authorization: `Bearer ${API_KEY}` }
136 |
137 | const form = new FormData();
138 | form.append('prompt[text]', 'a painting of ohwx man in the style of Van Gogh');
139 | form.append('prompt[negative_prompt]', 'old, blemish, wrin');
140 | form.append('prompt[super_resolution]', true);
141 | form.append('prompt[face_correct]', true);
142 | form.append('prompt[callback]', 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1');
143 |
144 | fetch(API_URL, {
145 | method: 'POST',
146 | headers: headers,
147 | body: form
148 | }).then(response => response.json())
149 |
150 |
151 | ```
152 |
153 |
154 |
155 | ```python
156 | import requests
157 |
158 | API_URL = 'https://api.astria.ai/tunes/1/prompts'
159 | API_KEY = 'YOUR_API_KEY' # Replace with your actual API key
160 |
161 | headers = {
162 | 'Authorization': f'Bearer {API_KEY}'
163 | }
164 |
165 | data = {
166 | 'prompt[text]': 'a painting of ohwx man in the style of Van Gogh',
167 | 'prompt[negative_prompt]': 'old, blemish, wrin',
168 | 'prompt[super_resolution]': True,
169 | 'prompt[face_correct]': True,
170 | 'prompt[callback]': 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1'
171 | }
172 | files = []
173 | files.append((f"prompt[input_image]", load_image(prompt['input_image'])))
174 |
175 | response = requests.post(API_URL, headers=headers, files=files, data=data)
176 | ```
177 |
178 |
179 |
180 | #### Response
181 |
182 | ```json
183 | {
184 | "id": 1,
185 | "callback": "https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1",
186 | "text": "a painting of ohwx man in the style of Van Gogh",
187 | "negative_prompt": "old, blemish, wrinkles, mole",
188 | "cfg_scale": null,
189 | "steps": null,
190 | "seed": null,
191 | "trained_at": null,
192 | "started_training_at": null,
193 | "created_at": "2022-10-06T16:12:54.505Z",
194 | "updated_at": "2022-10-06T16:12:54.505Z",
195 | "tune_id": 1,
196 | "url": "http://api.astria.ai/tunes/1/prompts/1.json"
197 | }
198 | ```
199 |
11 |
12 | ### Parameters
13 |
14 | #### `offset` (optional)
15 | Starting offset for the list of prompts. Default: 0. Current page size is 20.
16 |
17 | ### Returns
18 |
19 | An array of prompts owned by the authenticated user. If used as a nested resource (in the url), will return prompts owned by the tune.
20 |
11 |
12 | Deletes a specific prompt associated with a tune.
13 |
14 | ### Parameters
15 |
16 | #### `id` (required)
17 | The ID of the prompt to be deleted.
18 |
19 | ### Returns
20 |
21 | Returns 200 OK if the prompt was successfully deleted.
22 |
23 |
81 |
--------------------------------------------------------------------------------
/docs/api/2-pack/0-pack.md:
--------------------------------------------------------------------------------
1 | # The pack object
2 |
3 |
4 |
5 | A pack is a collection of prompts. A pack also contains the configuration for fine-tuning such as using LoRA/FaceID/Checkpoint, base model and preset.
6 |
7 | :::info
8 | The [headshot-starter](https://github.com/astriaai/headshots-starter?tab=readme-ov-file#incoming-changes) open-source project now supports packs.
9 | :::
10 |
11 | ## Advantages
12 | 1. Test new prompts, ideas and themes on a bulk of models quickly to assure consistent high-quality results.
13 | 1. Move fast from the creative process of creating prompts to the deployment of new themes in production.
14 | 2. Avoid mismatch between hard-coded JSONs and the actual prompts.
15 | 3. Decouple the creative process from your code and avoid mirroring inference API details in your codebase.
16 | 3. Run user tests in production for new prompts and quickly iterate.
17 | 4. Aggregate likes for prompts to improve the quality of the generated images and tighten the feedback loop.
18 | 5. Sort packs by aggregated likes to present the best packs to the user.
19 |
20 | ## Example user flow
21 | 1. `GET /packs` Display a list of packs to the user. See [docs](/docs/api/pack/list/)
22 | 2. User selects a pack, a class name (man/woman) and training images
23 | 3. Call `POST /p/:id/tunes` with title, (training) images, and class name - to create a new fine-tune model using a pack. See [docs](/docs/api/pack/tunes/create/)
24 | 4. `GET /tunes/:id/prompts` to get a list of prompts and their status
25 | 5. `POST /prompts/:id/likes` to send feedback to the API. See [docs](/docs/api/like/create/)
26 | 6. Sort prompts by likes
27 | 7. Present packs sorted by aggregated likes
28 |
29 | ## Getting started
30 | 1. Click your email in the header to access [my packs](https://www.astria.ai/packs), and create your first pack. 
31 | 2. Assign prompts to the pack from the [prompts tab](https://www.astria.ai/prompts).
32 | 3. Once a pack is assigned a new tag shows next to the prompt indicating that it is assigned to the pack.
33 |
--------------------------------------------------------------------------------
/docs/api/2-pack/1-list.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: List all packs
3 | hide_table_of_contents: true
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 |
10 |
11 |
12 | ### Parameters
13 |
14 |
15 | ### Returns
16 |
17 | An array of packs owned by the authenticated user or gallery packs for `GET /gallery/packs`
18 |
81 |
82 |
--------------------------------------------------------------------------------
/docs/api/2-pack/2-tunes/0-create.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Create a tune from a pack
3 | hide_table_of_contents: true
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 |
10 |
11 |
12 | Creates a new fine-tune model from training images according to the pack base tune id, model type and adds prompts to generate images.
13 |
14 | ### Parameters
15 |
16 | #### `name` (required)
17 | A class name the describes the fine-tune. e.g: `man`, `woman`, `cat`, `dog`, `boy`, `girl`, `style`. Class name must be supported by pack.
18 |
19 | #### `title` (required)
20 | Describes the fine-tune. Ideally a UUID related to the transaction. See [idempotency](/docs/api/overview) for more information.
21 |
22 | #### `images` (required)
23 | An array of images to train the fine-tune with. The images can be uploaded as multipart/form-data or as image_urls.
24 |
25 | #### `image_urls` (required)
26 | An array of images to train the fine-tune with. The images can be uploaded as multipart/form-data or as image_urls.
27 |
28 | #### `callback` (optional)
29 | A webhook URL to be called when the tune is finished training. The webhook will receive a POST request with the tune object. See [more on callbacks](/docs/api/overview#callbacks).
30 |
31 | #### `characteristics` (optional)
32 | A free-form object that can be used to templatize the prompts text. e.g: `{"eye_color": "blue eyes"}` would than be used in the prompt text as `ohwx woman, {{eye_color}}, holding flowers`.
33 |
34 | #### `prompt_attributes.callback` (optional)
35 | A webhook URL to be called when each prompt is finished inference. The webhook will receive a POST request with the prompt object. See [more on callbacks](/docs/api/overview#callbacks).
36 |
37 | #### `prompts_callback` (optional)
38 | A webhook URL to be called when all the prompts are finished training. The webhook will receive a POST request with an array of prompts objects.
39 |
40 | #### `tune_ids` (optional)
41 | Array of tune ids. If provided, will be used instead of the above attributes to create pack prompts only.
42 |
43 |
44 | ### Returns
45 |
46 | Returns a tune object if successful which will start training immediately and call callback once training is complete.
47 |
48 |
280 |
281 |
--------------------------------------------------------------------------------
/docs/api/2-pack/assign_prompts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/astriaai/astria-docs/e50fe870d4d131ebfd10dabb604ef00a64873595/docs/api/2-pack/assign_prompts.png
--------------------------------------------------------------------------------
/docs/api/2-pack/create_pack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/astriaai/astria-docs/e50fe870d4d131ebfd10dabb604ef00a64873595/docs/api/2-pack/create_pack.png
--------------------------------------------------------------------------------
/docs/api/20-sdxl-api.md:
--------------------------------------------------------------------------------
1 | ---
2 | hide_table_of_contents: true
3 | image: ../use-cases/img/sdxl-output.jpg
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 |
10 | # SDXL API usage
11 |
12 | For general tips on SDXL training and inference, see [SDXL training](/docs/use-cases/sdxl-training)
13 |
14 |
15 |
16 |
17 | Unlike SD15 checkpoint training, SDXL on Astria is trained as a LoRA+text-embedding. As such, inference is taking place a on a base line model such as SDXL 1.0 and `prompt.text` should specify the loaded lora such as `` - will load lora with id=123456 and strength=0.83
18 |
19 | See [LoRA docs](/docs/features/lora) on lora syntax
20 |
21 | With SDXL you cannot combine multiple LoRAs.
22 |
23 | Use any SDXL model from [the gallery](https://www.astria.ai/gallery/tunes?branch=sdxl1) to do inference.
24 |
25 | :::warning
26 | If you are receiving `422` error `model_type=pti is not supported. Use a checkpoint instead` - Change the request URL to https://api.astria.ai/tunes/666678/prompts with `666678` as a hard-coded tune_id of SDXL 1.0 from the gallery. See explanation above.
27 | :::
28 |
29 |
30 |
31 |
32 | #### POST /tunes/:id/prompts
33 |
34 |
35 |
36 |
37 | ```bash showLineNumbers
38 | # Note the hard-coded 666678 which is the tune_id of SDXL 1.0 from the gallery
39 | curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes/666678/prompts \
40 | -F prompt[text]=" a painting of ohwx man in the style of Van Gogh" \
41 | -F prompt[negative_prompt]="old, blemish, wrin" \
42 | -F prompt[super_resolution]=true \
43 | -F prompt[face_correct]=true \
44 | -F prompt[callback]="https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1"
45 | ```
46 |
47 |
48 |
49 | ```javascript
50 | const fetch = require('node-fetch');
51 | const FormData = require('form-data');
52 |
53 | // Note the hard-coded 666678 which is the tune_id of SDXL 1.0 from the gallery
54 | const API_URL = 'https://api.astria.ai/tunes/666678/prompts';
55 | const API_KEY = 'YOUR_API_KEY'; // Replace with your actual API key
56 | const headers = { Authorization: `Bearer ${API_KEY}` }
57 |
58 | const form = new FormData();
59 | form.append('prompt[text]', ' a painting of ohwx man in the style of Van Gogh');
60 | form.append('prompt[negative_prompt]', 'old, blemish, wrin');
61 | form.append('prompt[super_resolution]', true);
62 | form.append('prompt[face_correct]', true);
63 | form.append('prompt[callback]', 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1');
64 |
65 | fetch(API_URL, {
66 | method: 'POST',
67 | headers: headers,
68 | body: form
69 | }).then(response => response.json())
70 |
71 |
72 | ```
73 |
74 |
75 |
76 | ```python
77 | import requests
78 |
79 | # Note the hard-coded 666678 which is the tune_id of SDXL 1.0 from the gallery
80 | API_URL = 'https://api.astria.ai/tunes/666678/prompts'
81 | API_KEY = 'YOUR_API_KEY' # Replace with your actual API key
82 |
83 | headers = {
84 | 'Authorization': f'Bearer {API_KEY}'
85 | }
86 |
87 | data = {
88 | 'prompt[text]': ' a painting of ohwx man in the style of Van Gogh',
89 | 'prompt[negative_prompt]': 'old, blemish, wrin',
90 | 'prompt[super_resolution]': True,
91 | 'prompt[face_correct]': True,
92 | 'prompt[callback]': 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1'
93 | }
94 | files = []
95 | files.append((f"tune[prompts_attributes][{i}][input_image]", load_image(prompt['input_image'])))
96 |
97 | response = requests.post(API_URL, headers=headers, data=data)
98 | ```
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/docs/api/3-like/0-create.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Create a like
3 | hide_table_of_contents: true
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 |
10 |
11 |
12 | Adds a like to a prompt.
13 | If the prompt was created using a pack (i.e: `orig_prompt_id` is set) - a like will be added to the original prompt as well.
14 |
15 | ### Parameters
16 |
17 |
18 | ### Returns
19 |
20 | Returns status code 201 if successful and no content.
21 |
22 |
191 |
192 |
193 |
194 | ### Example implementation
195 |
196 | The images inspect API is meant to be used by the client-side of your app. The /images/inspect needs to be proxied by your server to avoid exposing your API key to the client.
197 |
198 | The example below implements two behaviors
199 | 1. `createWarning` notifies the user about an attribute is true such as `funny_face` or `wearing_sunglasses`. The function expects a form input element containing the class `name` selected by the user.
200 | 2. `aggregateCharacteristics` aggregates the most common values for each key in the characteristics object and sets the `characteristicsInputTarget` value to the aggregated characteristics.
201 |
202 | ```javascript
203 | async inspect(previewEl, file) {
204 | const form = document.getElementById('new_tune');
205 | const formValues = Object.fromEntries(new FormData(form));
206 | const name = formValues['tune[name]'];
207 | const csrfToken = document.querySelector("[name='csrf-token']").content;
208 | const formData = new FormData();
209 | formData.append('authenticity_token', csrfToken);
210 | formData.append('name', name);
211 |
212 | // Check if file is an image and readable
213 | if (file.type.startsWith('image/')) {
214 | try {
215 | const resizedFile = await this.resizeImage(file);
216 | formData.append('file', resizedFile || file);
217 | } catch (error) {
218 | console.warn('Image resizing failed, uploading original file:', error);
219 | formData.append('file', file);
220 | }
221 | } else {
222 | formData.append('file', file);
223 | }
224 |
225 | const response = await fetch('/images/inspect', {
226 | method: 'POST',
227 | body: formData,
228 | });
229 | const data = await response.json();
230 | if (!data['name']) {
231 | this.createWarning(previewEl, `Could not detect image`);
232 | }
233 |
234 | // Iterate over hash and add warning messages for each true value
235 | Object.keys(data).forEach((key) => {
236 | if (key === 'name') {
237 | if (data[key] === '') {
238 | this.createWarning(previewEl, `Could not detect ${name} in the image`);
239 | } else if (data[key] && data[key] !== name) {
240 | this.createWarning(previewEl, `Could not detect ${name} in the image (2)`);
241 | }
242 | } else if (data[key] === true) {
243 | const warning = capitalizeFirstLetter(key.replace(/_/g, " "));
244 | this.createWarning(previewEl, warning);
245 | }
246 | });
247 |
248 | this.characteristics.push(data);
249 | this.aggregateCharacteristics();
250 | previewEl.querySelector('.loading').classList.add('d-none');
251 | previewEl.querySelector('.remove-btn').classList.remove('d-none');
252 | }
253 |
254 | // Helper function to resize the image
255 | async resizeImage(file) {
256 | return new Promise((resolve, reject) => {
257 | const img = new Image();
258 | const reader = new FileReader();
259 |
260 | reader.onload = (e) => {
261 | img.onload = () => {
262 | const canvas = document.createElement('canvas');
263 | const maxDimension = 512; // Set max dimension for resizing
264 | let width = img.width;
265 | let height = img.height;
266 |
267 | if (width <= maxDimension && height <= maxDimension) {
268 | console.log(`Image is already smaller than ${maxDimension}x${maxDimension}`)
269 | resolve(file);
270 | return;
271 | }
272 | // Calculate new dimensions while maintaining aspect ratio
273 | if (width > height) {
274 | if (width > maxDimension) {
275 | height = Math.round(height * maxDimension / width);
276 | width = maxDimension;
277 | }
278 | } else {
279 | if (height > maxDimension) {
280 | width = Math.round(width * maxDimension / height);
281 | height = maxDimension;
282 | }
283 | }
284 | console.log(`Resizing image to ${width}x${height} from ${img.width}x${img.height}`)
285 |
286 | canvas.width = width;
287 | canvas.height = height;
288 | const ctx = canvas.getContext('2d');
289 | ctx.drawImage(img, 0, 0, width, height);
290 |
291 | canvas.toBlob((blob) => {
292 | resolve(blob ? new File([blob], file.name, { type: file.type }) : null);
293 | }, file.type, 0.9); // Adjust quality if needed
294 | };
295 |
296 | img.onerror = reject;
297 | img.src = e.target.result;
298 | };
299 |
300 | reader.onerror = reject;
301 | reader.readAsDataURL(file);
302 | });
303 | }
304 |
305 |
306 | aggregateCharacteristics() {
307 | const aggregated = {};
308 | // Iterate over this.characteristics and select value which is more common into this.aggregatedCharacteristics
309 | // use only the characeteristics that are string
310 | this.characteristics.forEach((characteristic) => {
311 | Object.keys(characteristic).forEach((key) => {
312 | if (typeof characteristic[key] === 'string') {
313 | if (aggregated[key]) {
314 | aggregated[key].push(characteristic[key]);
315 | } else {
316 | aggregated[key] = [characteristic[key]];
317 | }
318 | }
319 | });
320 | });
321 | console.log('aggregated', aggregated);
322 |
323 | const commonValues = {};
324 | // find most common value for each key and set aggregatedCharacteristics to that value
325 | Object.keys(aggregated).forEach((key) => {
326 | const values = aggregated[key];
327 | const mostCommonValue = values.sort((a, b) =>
328 | values.filter(v => v === a).length - values.filter(v => v === b).length
329 | ).pop();
330 | commonValues[key] = mostCommonValue;
331 | });
332 | console.log('commonValues', commonValues);
333 | this.characteristicsInputTarget.value = JSON.stringify(commonValues);
334 | }
335 |
336 | ```
337 |
--------------------------------------------------------------------------------
/docs/api/5-themes/1-create.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Create a theme
3 | hide_table_of_contents: true
4 | ---
5 |
6 | import Tabs from '@theme/Tabs';
7 | import TabItem from '@theme/TabItem';
8 |
9 |
10 |
11 |
12 | Themes API leverages a LLM (Large Language Models) to generate a variety of prompts based on a theme. The theme can be a short description of a concept, a mood, or a style. The API call will create 10 prompts which will start processing and generating images.
13 |
14 | ### Parameters
15 |
16 | #### `theme` (required)
17 | Class name of the object to be inspected in the image. Currently only `man`, `woman` are supported.
18 |
19 | #### `tuen_ids` (requires)
20 | A list of tune ids to be used for the theme. For each tune, 10 prompts will be generated.
21 |
22 | #### `prompt_attributes` (optional)
23 | `num_images, w, h` can be overridden
24 |
25 |
26 | ### Returns
27 | Returns empty response with status code 201. The themes are created in the background and can be pulled using `GET /tunes/:id/prompts`.
28 |
29 |
30 |