FaceID
BETA
See example prompts in the gallery
Overview
FaceID is a model adapter allowing to generate image while preserving a person identity without fine-tuning. Input images can be as few as just one image. The adapter was trained on human faces and cannot be used for pets or other subjects.
Usage
- Generate a placeholder fine-tune dataset which will contain the person images. The fine-tune will not go through training and will be immediately ready.
- Generate the image using the FaceID adapter using a syntax similar to LoRA -
<faceid:ID:1>
Notes
- Use
cfg_scale=3
- FaceID can work nicely together with Face Swap to improve similarity.
- Disable Face-Swap in case your prompt is animation style. Additionally, make sure to select an animated model from the gallery.
- For fast generation use the LCM schedulers.
- For realistic images, please consider enabling face-correct to improve facial features.
- When creating a fine-tune: Base-model is only used as a default for UI generation but does not affect FaceID.
- When creating a fine-tune:
steps
andtraining_face_correct
are not used for FaceID.
API
FaceID is an adapter loaded on top of a base model. As such the inference needs to take place on a model from the gallery.
The fine-tune's trained_at
is set upon creation and there is no training time. As such no callback is needed.
If you are receiving 422
error model_type=faceid is not supported. Use a checkpoint instead
- Change the request URL to https://api.astria.ai/tunes/690204/prompts with 690204
as a hard-coded tune_id of Realistic Vision v5.1 from the gallery. See explanation above.
Step 1: Create fine-tune
POST /tunes
- cURL
- Node.js
- Python
# With images as multipart/form-data
# Hard coded tune id of Realistic Vision v5.1 from the gallery - https://www.astria.ai/gallery/tunes
# https://www.astria.ai/gallery/tunes/690204/prompts
curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes \
-F tune[title]="John Doe - UUID - 1234-6789-1234-56789" \
-F tune[name]=man \
-F tune[model_type]="faceid" \
-F tune[callback]="https://optional-callback-url.com/webhooks/astria?user_id=1&tune_id=1" \
-F tune[base_tune_id]=690204 \
-F "tune[images][][email protected]" \
-F "tune[images][][email protected]" \
-F "tune[images][][email protected]" \
-F "tune[images][][email protected]"
# With image_urls as form-data
curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes \
-F tune[title]="John Doe - UUID - 1234-6789-1234-56789" \
-F tune[name]=man \
-F tune[model_type]="faceid" \
-F tune[callback]="https://optional-callback-url.com/to-your-service-when-ready?user_id=1&tune_id=1" \
-F tune[base_tune_id]=690204 \
-F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg" \
-F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg" \
-F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg" \
-F "tune[image_urls][]=https://i.imgur.com/HLHBnl9.jpeg"
# As JSON
cat > data.json <<- EOM
{
"tune": {
"title": "John Doe - UUID - 1234-6789-1234-56789",
"name": "man",
"model_type": "faceid",
"callback": "https://optional-callback-url.com/to-your-service-when-ready?user_id=1&tune_id=1",
"image_urls": [
"https://i.imgur.com/HLHBnl9.jpeg",
"https://i.imgur.com/HLHBnl9.jpeg",
"https://i.imgur.com/HLHBnl9.jpeg",
"https://i.imgur.com/HLHBnl9.jpeg"
]
}
}
EOM
curl -X POST -H"Content-Type: application/json" -H "Authorization: Bearer $API_KEY" --data @data.json https://api.astria.ai/tunes
// NodeJS 16
// With image_urls and fetch()
// For NodeJS 18 - do NOT import the below as it is built-in
import fetch from "node-fetch";
const API_KEY = 'sd_XXXXXX';
const DOMAIN = 'https://api.astria.ai';
function createTune() {
let options = {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({
tune: {
"title": 'John Doe - UUID - 1234-6789-1234-56789',
// Hard coded tune id of Realistic Vision v5.1 from the gallery - https://www.astria.ai/gallery/tunes
// https://www.astria.ai/gallery/tunes/690204/prompts
"base_tune_id": 690204,
"name": "man",
"model_type": "faceid",
"image_urls": [
"https://i.imgur.com/HLHBnl9.jpeg",
"https://i.imgur.com/HLHBnl9.jpeg",
"https://i.imgur.com/HLHBnl9.jpeg",
"https://i.imgur.com/HLHBnl9.jpeg"
]
}
})
};
return fetch(DOMAIN + '/tunes', options)
.then(r => r.json())
.then(r => console.log(r))
}
createTune()
/// With form-data, fetch()
// For NodeJS 18 - do NOT import the two below as they are built-in
import fetch from "node-fetch";
import FormData from 'form-data';
import fs from 'fs';
const API_KEY = 'sd_XXXX';
const DOMAIN = 'https://api.astria.ai';
function createTune() {
let formData = new FormData();
formData.append('tune[title]', 'John Doe - UUID - 1234-6789-1234-56789');
formData.append('tune[model_type]', 'faceid');
// Hard coded tune id of Realistic Vision v5.1 from the gallery - https://www.astria.ai/gallery/tunes
// https://www.astria.ai/gallery/tunes/690204/prompts
formData.append('tune[base_tune_id]', 690204);
formData.append('tune[name]', 'man');
// Load all JPGs from ./samples directory and append to FormData
let files = fs.readdirSync('./samples');
files.forEach(file => {
if(file.endsWith('.jpg')) {
formData.append('tune[images][]', fs.createReadStream(`./samples/${file}`), file);
}
});
formData.append('tune[callback]', 'https://optional-callback-url.com/to-your-service-when-ready?user_id=1&tune_id=1');
let options = {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + API_KEY
},
body: formData
};
return fetch(DOMAIN + '/tunes', options)
.then(r => r.json())
.then(r => console.log(r));
}
createTune();
import requests
headers = {'Authorization': f'Bearer {API_KEY}'}
def load_image(file_path):
with open(file_path, "rb") as f:
return f.read()
# Assuming `tune.images` are already defined in your context
# If not, you should define them before the below code
image_data = load_image("assets/image.jpeg")
data = {
"tune[title]": "John Doe - UUID - 1234-6789-1234-56789",
"tune[name]": "man",
"tune[base_tune_id]": 690204,
"tune[model_type]": "faceid",
"tune[token]": "ohwx"
}
files = []
for image in tune.images:
image_data = load_image(image) # Assuming image is a file path
files.append(("tune[images][]", image_data))
API_URL = 'https://api.astria.ai/tunes'
response = requests.post(API_URL, data=data, files=files, headers=headers)
response.raise_for_status()
Response
[
{
"id": 1,
"title": "John Doe",
"name": "woman",
"token": "ohwx",
"base_tune_id": null,
"args": null,
"steps": null,
"face_crop": null,
"training_face_correct": false,
"ckpt_url": null,
"ckpt_urls": [],
"eta": "2023-10-02T14:32:40.363Z",
"trained_at": "2023-10-02T14:32:40.363Z",
"started_training_at": "2023-10-02T14:32:05.229Z",
"expires_at": "2023-11-01T14:32:40.363Z",
"created_at": "2023-10-02T14:32:05.067Z",
"branch": "sd15",
"model_type": "faceid",
"updated_at": "2023-10-02T14:32:40.363Z",
"url": "https://www.astria.ai/tunes/788416.json",
"orig_images": [
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock"
]
},
{
"id": 775459,
"title": "Marry Jane",
"name": null,
"is_api": false,
"token": "ohwx",
"base_tune_id": null,
"args": null,
"steps": null,
"face_crop": null,
"training_face_correct": null,
"ckpt_url": "https://sdbooth2-production.s3.amazonaws.com/mock",
"ckpt_urls": [
"https://sdbooth2-production.s3.amazonaws.com/mock"
],
"eta": "2023-09-23T16:07:49.137Z",
"trained_at": "2023-09-23T16:07:49.137Z",
"started_training_at": "2023-09-23T16:07:37.334Z",
"expires_at": "2023-10-23T16:07:49.137Z",
"created_at": "2023-09-23T16:07:36.606Z",
"branch": "sd15",
"model_type": "faceid",
"updated_at": "2023-09-23T16:07:49.138Z",
"url": "https://www.astria.ai/tunes/775459.json",
"orig_images": [
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock",
"https://sdbooth2-production.s3.amazonaws.com/mock"
]
}
]
Step 2: Create prompts
POST /tunes/:id/prompts
- cURL
- Node.js
- Python
# Note the hard-coded 690204 which is the tune_id of Realistic Vision v5.1 from the gallery
curl -X POST -H "Authorization: Bearer $API_KEY" https://api.astria.ai/tunes/690204/prompts \
-F prompt[text]="<faceid:tune_id:strength> woman trekking in the alps" \
-F prompt[negative_prompt]="" \
-F prompt[super_resolution]=true \
-F prompt[face_correct]=true \
-F prompt[face_swap]=true \
-F prompt[callback]="https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1"
const fetch = require('node-fetch');
const FormData = require('form-data');
// Note the hard-coded 690204 which is the tune_id of Realistic Vision v5.1 from the gallery
const API_URL = 'https://api.astria.ai/tunes/690204/prompts';
const API_KEY = 'YOUR_API_KEY'; // Replace with your actual API key
const headers = { Authorization: `Bearer ${API_KEY}` }
const form = new FormData();
form.append('prompt[text]', '<faceid:tune_id:strength> woman trekking in the alps');
form.append('prompt[negative_prompt]', '');
form.append('prompt[super_resolution]', true);
form.append('prompt[face_correct]', true);
form.append('prompt[face_swap]', true);
form.append('prompt[callback]', 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1');
fetch(API_URL, {
method: 'POST',
headers: headers,
body: form
}).then(response => response.json())
import requests
# Note the hard-coded 690204 which is the tune_id of Realistic Vision v5.1 from the gallery
API_URL = 'https://api.astria.ai/tunes/690204/prompts'
API_KEY = 'YOUR_API_KEY' # Replace with your actual API key
headers = {
'Authorization': f'Bearer {API_KEY}'
}
data = {
'prompt[text]': '<faceid:tune_id:strength> woman trekking in the alps',
'prompt[negative_prompt]': '',
'prompt[super_resolution]': True,
'prompt[face_correct]': True,
'prompt[face_swap]': True,
'prompt[callback]': 'https://optional-callback-url.com/to-your-service-when-ready?prompt_id=1'
}
files = []
files.append((f"tune[prompts_attributes][{i}][input_image]", load_image(prompt['input_image'])))
response = requests.post(API_URL, headers=headers, data=data)