Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Birch-san/eddad13648725d47c71799c39e8361b2 to your computer and use it in GitHub Desktop.
Save Birch-san/eddad13648725d47c71799c39e8361b2 to your computer and use it in GitHub Desktop.
Example API request for generating an image using a stored NAIv4 vibe. Uses vibe files created by https://gist.github.com/Birch-san/5eb62a4a5e4a1c4447a55e3a9faf8988
#!/usr/bin/env bash
set -eo pipefail
# https://stackoverflow.com/a/12194427/5257399
create() { # fd base [qualifier [suffix [max]]]
local fd="$1" base="$2" qualifier="${3-}" suffix="${4-.png}" max="${5-}"
local n=0 file
local - # ash-style local scoping of options in 4.4+
set -o noclobber
REPLY=
# Add a dot to qualifier if it's provided and doesn't already start with one
[[ -n "$qualifier" && "$qualifier" != .* ]] && qualifier=".$qualifier"
# First pass: find the highest existing index
while true; do
PAD=$(printf '%03d' "$n")
# Check for ANY file with this index (regardless of qualifier)
if ls "${base}_${PAD}"* &>/dev/null; then
((n++))
((max > 0 && n > max)) && return 1
else
break
fi
done
# Create the file with the next available index
file="${base}_${PAD}${qualifier}${suffix}"
eval 'command exec '"$fd"'> "$file"' 2>/dev/null || return 1
REPLY=$file
}
# closes file descriptor 3
cleanup() {
local exit_code=$1
# echo "Performing cleanup..." >&2
exec 3>&- 2>/dev/null || true # Close FD 3, suppress errors if already closed
# Add any other cleanup tasks here
# echo "Cleanup completed with exit code: $exit_code" >&2
exit $exit_code # Preserve the original exit code
}
: "${IN_VIBE:=mycoolvibe.nometa-naiv4vibe}"
VIBE_B64_IN="$(mktemp)"
base64 -w 0 -i "$IN_VIBE" >"$VIBE_B64_IN"
: "${API_TOKEN:=put yer token here}"
: "${ENDPOINT:=https://image.novelai.net/ai/generate-image}"
: "${MODEL:=nai-diffusion-4-curated-preview}"
: "${WIDTH:=832}"
: "${HEIGHT:=1216}"
: "${SAMPLER:=k_euler_ancestral}"
: "${NOISE_SCHEDULE:=karras}"
: "${SEED:=860501111}"
: "${OUT_DIR:=out}"
: "${QUAL:=}"
: "${STRENGTH:=0.7}"
: "${BASE_CAPTION:=1girl, wide sleeves}"
REQUEST_BODY_IN="$(mktemp)"
RESPONSE_HEADERS_OUT="$(mktemp)"
RESPONSE_BODY_OUT="$(mktemp)"
jq -rMn \
--arg model "$MODEL" \
--rawfile vibe_base64 "$VIBE_B64_IN" \
--argjson width "$WIDTH" \
--argjson height "$HEIGHT" \
--arg sampler "$SAMPLER" \
--arg noiseSched "$NOISE_SCHEDULE" \
--argjson seed "$SEED" \
--argjson strength "$STRENGTH" \
--arg baseCaption "$BASE_CAPTION" \
'{
"action": "generate",
"input": $baseCaption,
"model": $model,
"parameters": {
"reference_image_multiple": [$vibe_base64],
"reference_strength_multiple": [$strength],
"v4_prompt": {
"caption": {
"base_caption": $baseCaption,
"char_captions": [],
"base_caption_dropout": 0,
"is_nsfw": false,
"is_furry": false,
"is_photo": false,
"is_unsplash": false,
"is_tags": true,
"is_gel": true
},
"use_coords": false,
"use_order": true
},
"v4_negative_prompt": {
"caption": {
"base_caption": "very displeasing, lowres, bad, error, fewer, extra, missing, worst quality, jpeg artifacts, bad quality, watermark, unfinished, displeasing, chromatic aberration, signature, extra digits, artistic error, username, scan, abstract",
"char_captions": [],
"base_caption_dropout": 0,
"is_nsfw": false,
"is_furry": false,
"is_photo": false,
"is_unsplash": false,
"is_tags": false,
"is_gel": false
},
"use_coords": false,
"use_order": true
},
"steps": 23,
"height": $height,
"width": $width,
"scale": 3.0,
"seed": $seed,
"n_samples": 1,
"sampler": $sampler,
"noise_schedule": $noiseSched,
"cfg_rescale": 0.0,
"dynamic_thresholding": false,
"sm": false,
"sm_dyn": false
}
}' >"$REQUEST_BODY_IN"
curl -sX POST "$ENDPOINT" \
-H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/json' \
-d "@$REQUEST_BODY_IN" \
-D "$RESPONSE_HEADERS_OUT" \
-o "$RESPONSE_BODY_OUT"
STATUS="$(tac "$RESPONSE_HEADERS_OUT" | grep --line-buffered -m1 HTTP/1.1 | awk '$0 = $2')"
echo "Status: $STATUS" >&2
if [[ "$STATUS" =~ ^2[0-9]{2}$ ]]; then
mkdir -p "$OUT_DIR"
pushd "$OUT_DIR" > /dev/null
create 3 out "$QUAL" .png || exit
# EXIT includes normal exit (code 0), error exits (non-zero), and when terminated by signals like SIGINT (Ctrl+C)
# Track the exit code to preserve it through the trap
trap 'cleanup $?' EXIT
echo "Decompressing response to: $REPLY" >&2
funzip "$RESPONSE_BODY_OUT" >&3
echo "Saved $REPLY" >&2
code "$REPLY"
else
jq . <"$RESPONSE_BODY_OUT" 2>/dev/null || cat "$RESPONSE_BODY_OUT"
fi
# exec 3>&- # close the file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment