Skip to main content
Version: 0.14

Godot API Reference

AtelicoEngineNode​

The main Godot node for the Atelico AI Engine.

Add as a child node in your scene tree and call initialize_engine to configure backends before using any LLM, embedding, or image generation methods.

Signals emitted by this node:

  • inference_token_generated(job_id: int, chunk_json: String) -- a new token chunk arrived during streaming chat/text completion.
  • inference_completed(job_id: int, success: bool) -- a streaming LLM request finished (success=true) or failed (success=false).
  • image_generation_chunk(job_id: int, response_json: String) -- a progress chunk from streaming image generation.
  • image_generation_completed(job_id: int, success: bool) -- streaming image generation finished.
  • model_loading_completed(success: bool) -- engine initialization done.
  • async_request_completed(job_id: int, response_json: String) -- a non-blocking (async) request completed. On failure response_json is {"error":{"message":...,"type":"engine_error"}}.

Signals​

inference_token_generated​

Emitted once per token during a streaming LLM request (llm_chat_stream or llm_respond_stream).

  • job_id: matches the return value of the streaming method.
  • chunk_json: a ChatCompletionChunk or ResponseStreamDelta JSON string.

inference_completed​

Emitted when a streaming LLM request finishes.

  • job_id: matches the return value of the streaming method.
  • success: true if generation completed normally, false on error.

image_generation_chunk​

Emitted for each progress update during streaming image generation (image_generate_stream).

  • job_id: matches the return value of image_generate_stream.
  • response_json: an ImageGenerationResponse JSON string with partial or complete image data.

image_generation_completed​

Emitted when streaming image generation finishes.

  • job_id: matches the return value of image_generate_stream.
  • success: true if generation completed normally, false on error.

audio_synthesis_chunk​

Emitted for each chunk during streaming TTS synthesis (audio_synthesize_stream).

  • job_id: matches the return value of audio_synthesize_stream.
  • chunk_json: an AudioSpeechChunk JSON string with fields sequence, audio (base64 WAV), duration_seconds, text.

audio_synthesis_completed​

Emitted when streaming TTS synthesis finishes.

  • job_id: matches the return value of audio_synthesize_stream.
  • success: true on normal completion, false on error.

model_loading_completed​

Emitted when initialize_engine finishes configuring backends.

  • success: true if at least one backend was configured successfully.

async_request_completed​

Emitted when a non-blocking (async) request completes. Fired by llm_chat_async and embed_async.

  • job_id: matches the return value of the async method.
  • response_json: the full JSON response string, or {"error":{"message":...,"type":"engine_error"}} on failure.

model_download_manifest​

Fires once per download job, before any model_download_progress events, with the full file list. Each entry is a Dictionary {"path": String, "size": int}. Skipped when the engine can't probe the store (offline / HF-only models).

model_download_progress​

Per-event signal for an async download (model_download_async, adapter_download_async). job_id matches the return value of the async method; kind is "model" or "adapter".

file_* params describe the file currently in progress (reset on each new file); job_* params describe the whole job (cumulative, never reset). Drive a unified bar off job_bytes_done / job_total_bytes; use the file_* params for a detail label.

Any _total_bytes param is -1 when the store didn't advertise a size, and file_count is 0 until the engine's preflight LIST has been observed.

model_download_completed​

Emitted when an async model or adapter download finishes.

  • job_id: matches the return value of the async method.
  • success: true if all files downloaded successfully.
  • error: error message on failure, empty string on success.

Methods​

set_data_logging(config_json: GString) -> bool​

Configure model input/output capture before calling initialize_engine.

config_json is the same data_logging object accepted by the SDK and C FFI engine configuration. The logger starts automatically during initialization and does not block Godot's render or inference threads.

disable_data_logging()​

Disable capture before engine initialization.

set_env_var(key: GString, value: GString)​

Set a process environment variable.

Useful for configuring RUST_LOG, HF_TOKEN, or OPENAI_API_KEY from GDScript before initializing the engine.

Inputs

  • key -- environment variable name (e.g. "RUST_LOG", "HF_TOKEN").
  • value -- value to set.

Outputs

No return value.

Example

Input: key="RUST_LOG", value="debug"
Output: (none -- environment variable is set for the process)

phys_footprint_mb() -> f64​

Sample the process's current physical memory footprint in megabytes.

Returns the Mach TASK_VM_INFO phys_footprint — the exact metric iOS jetsam uses to decide when to kill the app. On non-Apple platforms this returns 0.0. Callers (e.g. the on-device Anima bench) poll this while a generation is in flight to track peak RSS directly, with no env-var flag or session-log scraping in the loop.

Outputs

The current physical footprint in MB (f64).

last_gen_peak_footprint_mb() -> f64​

Peak physical footprint (MB) sampled DURING the most recent Anima generate().

A background thread inside the engine polls this process's Mach phys_footprint every ~5 ms for the whole duration of the generate call and records the max. This is the true in-place high-water mark — the one number GDScript cannot obtain by polling phys_footprint_mb around the call, because the caller is blocked inside the native generate while it runs (e.g. the VAE-decode transient lands and is freed before control returns). Works identically on macOS and iOS.

Outputs

The peak footprint in MB (f64), or 0.0 if no generation has run this process (or on non-Apple platforms).

last_gen_stage_profile() -> VarDictionary​

Per-stage GPU wall-clock (ms) of the most recent Anima generate().

Returns a Dictionary with text_encode_ms, denoise_total_ms, denoise_per_step_ms, vae_ms, te_reload_ms, vae_reload_ms and dit_reload_ms (all f64). The three *_reload_ms are the paging costs of the low-memory policy: text encoder paged in at the start of the generate, VAE paged in right before the decode, DiT paged in at the start (after the previous generate dropped it before its decode); each is 0.0 when the component was already resident. The values come from the engine's device-synced stage timers (the same numbers the [stage-timing] INFO logs carry), read from a process-wide slot rather than the session log — the RELEASE deploy build filters INFO logs on device, so the log-scrape path yields nothing there.

Stage timing is always computed by generate(), so this reflects the most recent generation. If no generation has run this process, every field is -1.0.

Outputs

A Dictionary of the seven stage timings in milliseconds.

initialize_engine(backends_config: Array<VarDictionary>)​

Configure the engine router with an array of backend definitions.

GPU scheduling configuration is read from the AtelicoSingleton at init time. Call AtelicoSingleton.set_gpu_scheduling_mode() etc. before calling this method to configure GPU sharing behavior.

Inputs

  • backends_config -- Array of Dictionaries, each with:
    • "name" (string, required) -- logical name for the backend (e.g. "in-memory").
    • "type" (string, required) -- "in-memory" (local inference) or "proxy" (remote API).
    • "config" (Dictionary, required) -- backend-specific settings:
      • For "proxy": {"base_url": "...", "api_key": "..."}.
      • For "in-memory": empty dictionary {} is valid.

Outputs

No return value. Emits model_loading_completed(true) signal on success.

Example

Input: [{"name":"in-memory","type":"in-memory","config":{}}]
Output: (signal) model_loading_completed(true)

llm_chat(request_str: GString) -> GString​

Synchronous (blocking) chat completion.

Inputs

  • request_str -- JSON ChatCompletionRequest:
    • model (string, required) -- model ID in "backend::org/model" format.
    • messages (array, required) -- conversation messages:
      • role (string) -- "system", "user", or "assistant".
      • content (string) -- message text.
    • max_tokens (int) -- maximum tokens to generate.
    • temperature (float) -- controls randomness; lower is more focused and repeatable, higher more varied. 0 = greedy.
    • top_k (int) -- only consider the K most-likely next tokens.
    • top_p (float) -- nucleus sampling: only consider the smallest set of tokens whose probabilities sum to p.
    • min_p (float) -- ignore tokens less likely than this fraction of the most-likely token.
    • repetition_penalty (float) -- discourage repeating words/phrases.
    • seed (int) -- set for reproducible output (same seed + params + prompt -> same result). Omitting it does not randomise: the engine uses one fixed default seed.
    • adapter_scale (float) -- strength of the LoRA adapter this request runs with (from the model::adapter suffix, or the model's default set by lora_load): 1.0 as trained, 0.0 the base model, values between blend. Omitted uses the model's default scale, else 1.0.
    • priority (string) -- "interactive", "normal" (default) or "background": how this request is scheduled against everything else competing for the GPU. A long generation hands the GPU over at token boundaries, so an "interactive" request does not wait for a "background" one to finish. All sampling parameters are optional: each model has recommended defaults, applied automatically when a request omits them.
    • response_format (object) -- structured output schema.
    • speculative (object) -- optional { proposer, k } for multi-token (speculative) decoding to speed up generation. Off by default. proposer is "prompt_lookup" (recommended for grounded prompts — RAG / summary / code edit; 1.5–2.5× AR speedup) or "lookahead" (general repetitive output; ~1.3× AR). Greedy output is bit-identical to plain AR. See docs/docs/guide/speculative-decoding.mdx for which proposer to use on which workload.

Outputs

JSON ChatCompletionResponse (on failure: {"error":{"message":...,"type":"engine_error"}}):

  • id (string) -- unique response ID.
  • choices (array) -- generated completions:
    • message (object) -- { role, content }.
    • finish_reason (string) -- "stop" or "length".
  • usage (object) -- { prompt_tokens, completion_tokens, total_tokens }.

Example

Input: {"model":"in-memory::meta-llama/Llama-3.2-1B-Instruct","messages":[{"role":"user","content":"Hello"}],"max_tokens":100}
Output: {"id":"chatcmpl-xxx","choices":[{"message":{"role":"assistant","content":"Hi!"},"finish_reason":"stop"}],"usage":{"prompt_tokens":5,"completion_tokens":3,"total_tokens":8}}

llm_chat_async(request_str: GString) -> i64​

Non-blocking chat completion. Runs on a background thread.

Inputs

  • request_str -- same JSON ChatCompletionRequest schema as llm_chat.

Outputs

int: a job_id. When inference finishes, the async_request_completed(job_id, response_json) signal is emitted with the full ChatCompletionResponse JSON (or {"error":{"message":...}} on failure).

Example

Input: {"model":"in-memory::llama","messages":[{"role":"user","content":"Hi"}]}
Output: 0 (job_id; then signal async_request_completed(0, "{...}") is emitted)

llm_chat_stream(request_str: GString) -> i64​

Streaming chat completion. Tokens arrive via signals.

Inputs

  • request_str -- same JSON ChatCompletionRequest schema as llm_chat. The stream field is set automatically.

Outputs

int: a job_id. For each generated token, the inference_token_generated(job_id, chunk_json) signal is emitted where chunk_json is a ChatCompletionChunk:

  • id (string) -- chunk ID.
  • choices (array) -- [{"delta": {"content": "token"}, "finish_reason": null}]

When generation finishes, inference_completed(job_id, success) is emitted.

Example

Input: {"model":"in-memory::llama","messages":[{"role":"user","content":"Hi"}]}
Output: 0 (job_id; then signals: inference_token_generated(0, "{...}") per token, inference_completed(0, true))

llm_text_complete(request_str: GString) -> GString​

Synchronous (blocking) text completion. Continues a raw prompt without chat template formatting.

Inputs

  • request_str -- JSON TextCompletionRequest:
    • model (string, required) -- backend-prefixed model ID.
    • prompt (string, required) -- raw text prompt (no chat template).
    • max_tokens (int) -- maximum tokens to generate.
    • temperature, top_k, top_p, min_p, repetition_penalty, seed, priority -- optional (same meanings as async_chat_completions). Each model supplies recommended defaults for any you omit. seed omitted does not randomise: the engine uses one fixed default seed.
    • priority (string) -- "interactive", "normal" (default) or "background": how this request is scheduled against everything else competing for the GPU. Use "interactive" for a line the player is waiting on, "background" for a pre-generation nobody is watching.

Outputs

JSON TextCompletionResponse (on failure: {"error":{"message":...,"type":"engine_error"}}):

  • id (string) -- unique completion ID.
  • choices (array) -- [{"text": "...", "index": 0, "finish_reason": "stop"}]
  • usage (object) -- { prompt_tokens, completion_tokens, total_tokens }

Example

Input: {"model":"in-memory::llama","prompt":"Once upon a time","max_tokens":50}
Output: {"id":"cmpl-xxx","choices":[{"text":" there was a...","index":0,"finish_reason":"stop"}],"usage":{"prompt_tokens":4,"completion_tokens":50,"total_tokens":54}}

llm_respond(request_str: GString) -> GString​

Synchronous (blocking) Responses API call. A higher-level conversational interface that manages conversation state internally.

Inputs

  • request_str -- JSON ResponseRequest:
    • model (string, required) -- backend-prefixed model ID.
    • input (string or array) -- user input text or message list.
    • instructions (string) -- system prompt / instructions.
    • max_output_tokens (int) -- maximum tokens to generate.
    • temperature, top_k, top_p, min_p, repetition_penalty, seed, priority -- optional (same meanings as async_chat_completions). Each model supplies recommended defaults for any sampling parameter you omit.

Outputs

JSON ResponseResponse (on failure: {"error":{"message":...,"type":"engine_error"}}):

  • id (string) -- unique response ID.
  • output (array) -- [{"type": "message", "content": [...]}]
  • usage (object) -- { input_tokens, output_tokens }

Example

Input: {"model":"in-memory::llama","input":"What is 2+2?"}
Output: {"id":"resp-xxx","output":[{"type":"message","content":[{"type":"output_text","text":"4"}]}],"usage":{"input_tokens":5,"output_tokens":1}}

llm_respond_stream(request_str: GString) -> i64​

Streaming Responses API request. Tokens arrive via signals.

Inputs

  • request_str -- same JSON ResponseRequest schema as llm_respond. The stream field is set automatically.

Outputs

int: a job_id. Tokens arrive via inference_token_generated(job_id, chunk_json), and completion is signaled by inference_completed(job_id, success).

Example

Input: {"model":"in-memory::llama","input":"Hello"}
Output: 0 (job_id; then signals: inference_token_generated(0, "{...}") per token, inference_completed(0, true))

llm_tokenize(model_id: GString, text: GString) -> GString​

Encode text into token IDs using a loaded model's tokenizer.

Loads the model on demand if it isn't already resident. Useful for budgeting prompt length against the context window before submitting a request, or for pre-tokenising prefixes that will be reused.

Inputs

  • model_id -- model identifier in "backend::model" format (e.g. "in-memory::meta-llama/Llama-3.2-3B-Instruct-Q4_K_M").
  • text -- UTF-8 text to tokenise.

Outputs

JSON TokenizeResponse (on failure: {"error":{"message":...,"type":"engine_error"}}):

{"model_id": "in-memory::meta-llama/...", "tokens": [128000, 9906, 11, 1917, 0]}

Example

Input: model_id="in-memory::meta-llama/Llama-3.2-3B-Instruct-Q4_K_M", text="Hello, world!"
Output: {"model_id":"in-memory::meta-llama/Llama-3.2-3B-Instruct-Q4_K_M","tokens":[128000,9906,11,1917,0]}

llm_detokenize(request_str: GString) -> GString​

Decode a token ID sequence back into text using a loaded model's tokenizer.

Inputs

  • request_str -- JSON detokenise request:

    {
    "model_id": "in-memory::meta-llama/Llama-3.2-3B-Instruct-Q4_K_M",
    "tokens": [128000, 9906, 11, 1917, 0],
    "skip_special_tokens": true
    }

    skip_special_tokens defaults to true when omitted.

Outputs

JSON DetokenizeResponse (on failure: {"error":{"message":...,"type":"engine_error"}}):

{"text": "Hello, world!"}

llm_model_capabilities(model_id: GString) -> GString​

Inspect a loaded model's static capabilities (vocab size, context window, dtype, active backend).

Inputs

  • model_id -- model identifier in "backend::model" format.

Outputs

JSON ModelCapabilities (on failure: {"error":{"message":...,"type":"engine_error"}}):

{
"model_id": "in-memory::meta-llama/Llama-3.2-3B-Instruct-Q4_K_M",
"vocab_size": 128256,
"max_position_embeddings": 131072,
"dtype": "Q4_K_M",
"device": "Cuda(0)",
"backend_kind": "metal",
"thinking_style": "native",
"native_tool_format": "gemma4",
"recommended_sampling": { "temperature": 1.0, "top_p": 0.95 }
}

device defaults to an empty string on older engines. thinking_style is one of "unsupported"/"thinktags"/"native". native_tool_format and the individual recommended_sampling knobs are omitted when absent. See [Self::llm_model_capabilities_dict] for a typed Godot Dictionary.

llm_model_capabilities_dict(model_id: GString) -> VarDictionary​

Inspect a loaded model's static capabilities as a typed Godot Dictionary (no JSON parsing on the GDScript side).

Same backend call as [Self::llm_model_capabilities]; returns an EMPTY dictionary on error. Keys:

  • model_id (String), vocab_size (int), max_position_embeddings (int), dtype (String), device (String), backend_kind (String) — always present.
  • thinking_style (String) — "unsupported"/"thinktags"/"native".
  • native_tool_format (String) — the format tag (e.g. "gemma4"), or an empty string when the model has no native tool block.
  • recommended_sampling (Dictionary) — nested; holds temperature, top_p, and/or repetition_penalty (float), and/or top_k (int) only for the knobs the model declares. Empty when the model recommends nothing.

image_generate(request_str: GString) -> GString​

Synchronous (blocking) image generation from a text prompt.

Inputs

  • request_str -- JSON ImageGenerationRequest:
    • model (string, required) -- backend-prefixed model ID.
    • prompt (string, required) -- text description of the image.
    • n (int) -- number of images to generate (default 1).
    • size (string) -- image dimensions (e.g. "512x512").
    • response_format (string) -- "b64_json" or "url".

Outputs

JSON ImageGenerationResponse on success:

  • created (int) -- Unix timestamp of generation.
  • data (array) -- [{"b64_json": "...", "revised_prompt": "..."}]

On failure: {"error": "..."} with the reason (also logged), so a GDScript caller can surface WHY generation failed instead of guessing from an empty string. (The streaming path, image_generate_stream, reports failures by logging and emitting image_generation_completed(job_id, false) -- same log idiom, this is the blocking equivalent with the reason in-band.)

Example

Input: {"model":"in-memory::PixArt-alpha/PixArt-Sigma-XL-2-512-MS","prompt":"A sunset","size":"512x512"}
Output: {"created":1234567890,"data":[{"b64_json":"iVBORw0KGgo...","revised_prompt":"A sunset"}]}

image_denoise_session(request_str: GString) -> GString​

Drive a resumable, externally-driven denoise session (blocking, JSON in / JSON out) so the game can render partial previews and refine step by step.

The request is an ImageSessionRequest JSON: a model (e.g. "image-generation::anima") plus a flattened op:

  • \{"model": "...", "op": "begin", "prompt": "...", "seed": 42, "size": "512x512", "pipeline_config": \{...\}\} -> {"kind":"begun","session_id":N,"n_steps":K,"width":W,"height":H}
  • {"model": "...", "op": "step", "session_id": N, "steps": 1} -> {"kind":"stepped","steps_done":..,"step_index":..,"n_steps":..,"done":bool}
  • {"model": "...", "op": "preview", "session_id": N} -> {"kind":"preview", ...ImageGenerationResponse...} (base64 PNG in data[0].b64_json, exactly like image_generate)
  • {"model": "...", "op": "cancel"|"end", "session_id": N} -> {"kind":"ended","session_id":N,"freed":bool}

Each step is one bounded block_on; control returns to Godot between steps so the app can paint a preview and stay responsive. A single step is atomic (cannot be interrupted mid-step); pause by simply not calling step, cancel with the cancel op. Returns an {"error": ...} JSON on any transport-level failure (router not ready, JSON parse error, stale or unknown session, model error).

video_generate(request_str: GString) -> GString​

Generate a video (blocking, JSON in / JSON out).

Mirrors image_generate. The OpenAI-shaped VideoGenerationRequest JSON (model, prompt, optional width/height/num_frames/fps/seed/ response_format) is forwarded through the engine router; the returned JSON is a VideoGenerationResponse. Returns an empty GString on any transport-level failure (router not ready, JSON parse error, model error).

audio_synthesize(request_str: GString) -> GString​

Synthesize speech from text (blocking).

Inputs

  • request_str -- JSON AudioSpeechRequest:
    • model (string, required) -- e.g. "in-memory::tts", "in-memory::kokoro-82m", "in-memory::pocket-tts". Bare ids accepted after the prefix: tts (default → kokoro-82m), kokoro, kokoro-82m, pocket, pocket-tts.
    • input (string, required) -- text to synthesize.
    • voice (string) -- voice id (default "af_heart"). Pocket TTS ships 31 built-in English voices (alba, ian, morgan, kate, ...).
    • speed (float) -- 0.25–4.0 multiplier (default 1.0).

Outputs

JSON object (on failure: {"error":{"message":...,"type":"engine_error"}}):

  • audio_b64 (string) -- base64-encoded WAV bytes (RIFF + PCM).
  • duration_seconds (float)
  • format (string) -- "wav"
  • sample_rate (int) -- typically 24000.

Example

Input: {"model":"in-memory::tts","input":"Hello!","voice":"af_heart"}
Output: {"audio_b64":"UklGRn...","duration_seconds":1.42,"format":"wav","sample_rate":24000}

audio_transcribe(request_str: GString) -> GString​

Transcribe audio to text (blocking).

Inputs

  • request_str -- JSON object:
    • model (string, required) -- e.g. "in-memory::whisper" (default → whisper-base.en), "in-memory::whisper-large-v3-turbo", "in-memory::distil-large-v3".
    • audio_b64 (string, required) -- base64-encoded WAV file (RIFF + PCM). Sample rate is read from the WAV header.
    • language (string) -- ISO 639-1 code ("en", "ja", ...) or omit for auto-detect.
    • response_format (string) -- "json" (default) or "verbose_json" (adds segments).
    • temperature (float) -- decoder sampling temperature (0.0 = greedy).
    • timestamp_granularities (array) -- ["segment"] and/or ["word"].

Outputs

JSON AudioTranscriptionResponse (on failure: {"error":{"message":...,"type":"engine_error"}}):

  • text (string)
  • language (string, optional)
  • duration (float, optional)
  • segments, words (optional, depending on response_format and granularities).

Example

Input: {"model":"in-memory::whisper","audio_b64":"UklGRn..."}
Output: {"text":"Hello from Atelico.","language":"en","duration":1.4}

audio_synthesize_stream(request_str: GString) -> i64​

Streaming TTS synthesis. Chunks arrive via signals.

Inputs

  • request_str -- JSON AudioSpeechRequest (same schema as audio_synthesize). The stream field is set automatically.

Outputs

int: a job_id. Per-chunk signals fire as audio_synthesis_chunk(job_id, chunk_json), and completion is signaled by audio_synthesis_completed(job_id, success).

Example

Input: {"model":"in-memory::pocket-tts","input":"First. Second.","voice":"alba"}
Output: 7 (job_id; then signals: audio_synthesis_chunk(7, "{...}"), audio_synthesis_completed(7, true))

image_generate_stream(request_str: GString) -> i64​

Streaming image generation. Progress chunks arrive via signals.

Inputs

  • request_str -- same JSON ImageGenerationRequest schema as image_generate. The stream field is set automatically.

Outputs

int: a job_id. Progress chunks arrive via image_generation_chunk(job_id, response_json), and completion is signaled by image_generation_completed(job_id, success).

Example

Input: {"model":"in-memory::PixArt","prompt":"A cat"}
Output: 0 (job_id; then signals: image_generation_chunk(0, "{...}"), image_generation_completed(0, true))

image_remove_background(request_str: GString) -> GString​

Synchronous (blocking) background removal from an image.

Inputs

  • request_str -- JSON BackgroundRemovalRequest:
    • model (string, required) -- backend-prefixed model ID.
    • image (string, required) -- base64-encoded image data or URL.

Outputs

JSON response (on failure: {"error":{"message":...,"type":"engine_error"}}):

  • data (array) -- [{"b64_json": "..."}] -- image with background removed.

Example

Input: {"model":"in-memory::briaai/RMBG-1.4","image":"iVBORw0KGgo..."}
Output: {"data":[{"b64_json":"iVBORw0KGgo..."}]}

embed(request_str: GString) -> GString​

Synchronous (blocking) text embedding.

Inputs

  • request_str -- JSON EmbeddingRequest:
    • model (string, required) -- backend-prefixed embedding model ID.
    • input (string or array of strings) -- text(s) to embed.

Outputs

JSON EmbeddingResponse (on failure: {"error":{"message":...,"type":"engine_error"}}):

  • object (string) -- always "list".
  • model (string) -- model used.
  • data (array) -- [{"object": "embedding", "index": 0, "embedding": [0.1, ...]}]
  • usage (object) -- { prompt_tokens, total_tokens }

Example

Input: {"model":"in-memory::sentence-transformers/all-MiniLM-L6-v2","input":"Hello world"}
Output: {"object":"list","data":[{"object":"embedding","index":0,"embedding":[0.1,0.2,...]}],"usage":{"prompt_tokens":2,"total_tokens":2}}

embed_async(request_str: GString) -> i64​

Non-blocking embedding. Runs on a background thread.

Inputs

  • request_str -- same JSON EmbeddingRequest schema as embed.

Outputs

int: a job_id. When embedding finishes, the async_request_completed(job_id, response_json) signal is emitted with the full EmbeddingResponse JSON (or {"error":{"message":...}} on failure).

Example

Input: {"model":"in-memory::all-MiniLM-L6-v2","input":"Hello"}
Output: 0 (job_id; then signal async_request_completed(0, "{...}") is emitted)

embed_image(request_str: GString) -> GString​

Synchronous (blocking) image embedding. Embeds a single image into a fixed-dimensional vector via a vision embedder (DINOv2).

Inputs

  • request_str -- JSON ImageEmbeddingRequest:
    • model (string, required) -- backend-prefixed vision embedding model ID (e.g. "in-memory::dinov2-small").
    • image (string, required) -- base64-encoded PNG/JPEG image bytes.

Outputs

JSON EmbeddingResponse (same shape as embed; on failure: {"error":{"message":...}}):

  • object (string) -- always "list".
  • model (string) -- model used.
  • data (array) -- [{"object": "embedding", "index": 0, "embedding": [0.1, ...]}]
  • usage (object) -- { prompt_tokens, total_tokens }

Example

Input: {"model":"in-memory::dinov2-small","image":"iVBORw0KGgo..."}
Output: {"object":"list","data":[{"object":"embedding","index":0,"embedding":[0.1,0.2,...]}],"usage":{"prompt_tokens":0,"total_tokens":0}}

embed_image_async(request_str: GString) -> i64​

Non-blocking image embedding. Runs on a background thread.

Inputs

  • request_str -- same JSON ImageEmbeddingRequest schema as embed_image.

Outputs

int: a job_id. When embedding finishes, the async_request_completed(job_id, response_json) signal is emitted with the full EmbeddingResponse JSON (or {"error":{"message":...}} on failure).

Example

Input: {"model":"in-memory::dinov2-small","image":"iVBORw0KGgo..."}
Output: 0 (job_id; then signal async_request_completed(0, "{...}") is emitted)

embed_audio(request_str: GString) -> GString​

Synchronous (blocking) audio embedding. Embeds a single audio clip into a fixed-dimensional vector via an audio embedder (CLAP). The resulting vector lives in CLAP's shared text/audio space, so it is directly comparable to a text query embedded by the same model.

Inputs

  • request_str -- JSON AudioEmbeddingRequest:
    • model (string, required) -- backend-prefixed audio embedding model ID (e.g. "in-memory::clap-htsat-unfused").
    • audio (string, required) -- base64-encoded RIFF/WAVE bytes (16-bit PCM or 32-bit float, mono/stereo). Downmixed and resampled internally.

Outputs

JSON EmbeddingResponse (same shape as embed; on failure: {"error":{"message":...}}):

  • object (string) -- always "list".
  • model (string) -- model used.
  • data (array) -- [{"object": "embedding", "index": 0, "embedding": [0.1, ...]}]
  • usage (object) -- { prompt_tokens, total_tokens }

Example

Input: {"model":"in-memory::clap-htsat-unfused","audio":"UklGRn..."}
Output: {"object":"list","data":[{"object":"embedding","index":0,"embedding":[0.1,0.2,...]}],"usage":{"prompt_tokens":0,"total_tokens":0}}

embed_audio_async(request_str: GString) -> i64​

Non-blocking audio embedding. Runs on a background thread.

Inputs

  • request_str -- same JSON AudioEmbeddingRequest schema as embed_audio.

Outputs

int: a job_id. When embedding finishes, the async_request_completed(job_id, response_json) signal is emitted with the full EmbeddingResponse JSON (or {"error":{"message":...}} on failure).

Example

Input: {"model":"in-memory::clap-htsat-unfused","audio":"UklGRn..."}
Output: 0 (job_id; then signal async_request_completed(0, "{...}") is emitted)

model_load(model_id: GString) -> bool​

Pre-load a model (blocking). Call during loading screens to avoid latency on the first inference request.

Inputs

  • model_id -- model ID in "backend::org/model" format (e.g. "in-memory::meta-llama/Llama-3.2-1B-Instruct").

Outputs

bool: true on success, false if the backend is not found or loading fails.

Example

Input: "in-memory::meta-llama/Llama-3.2-1B-Instruct"
Output: true

is_model_cached(model_id: GString, pipeline_config_json: GString) -> bool​

Returns true if the model's weights are already in the local Atelico cache (in either safetensors or GGUF form).

Pure filesystem check — does not touch the network and does not block on the model thread. Use this to decide whether to show a "this will download X MB" confirmation before calling model_download.

Inputs

  • model_id -- model ID in "backend::org/model" format. Same format as model_load / model_download.
  • pipeline_config_json -- OPTIONAL pipeline-config JSON, the SAME string model_download takes (and the same pipeline_config the game sends when generating). The cache answer validates against that config's file plan, so a device that downloaded with {"dit_precision": "svdq4"} reports cached for that config and not-cached for ""/"full" — never a needs-download loop, and likewise per model_asset (a cache holding only models/anima-rcm-x/ is cached for that asset and not for the default). "" or "{}" keeps the default (dense, anima-rcm) plan; unknown fields are ignored. Ignored for every model id that is not anima-rcm.

Outputs

bool: true if cached, false if missing, the backend is not found, or an anima-rcm config blob does not parse (logged as an error by the model's own cache check — this layer never reads the blob).

image_model_unload(model_id: GString) -> bool​

Unload an image-generation model (blocking), freeing its DiT, text encoder and VAE weights and any denoise session bound to it, then sweeping the device buffer pool so the memory leaves the process footprint before this returns. For the on-device anima-rcm bundle that is about 2.3 GB (svdq4 DiT 1.3 GB, Q8 text encoder 0.74 GB, VAE 0.25 GB). Every variant of the model is removed, whatever dit_precision or model_asset it was generated with.

The next image_generate for that model reloads it from the local cache (no download), paying the load time again. Call this when the game is done generating for a while, or before loading an LLM that needs the memory.

Inputs

  • model_id -- the model id as sent when generating, e.g. "in-memory::anima-rcm" or bare "anima-rcm"; a ::adapter suffix is accepted and ignored.

Outputs

bool: true if the model was resident and has been unloaded, false if it was not loaded or the backend is not found.

Example

Input: "in-memory::anima-rcm"
Output: true

language_model_unload() -> VarDictionary​

Drop every loaded language model (weights, KV cache, prefix cache) on every in-memory backend and return once the memory has left the process. Blocking: one round-trip to each backend's model thread, where the models are dropped and the device buffer pool is swept before the reply. A model thread mid-request finishes that request first.

Use this before freeing the node when another engine node will be created in the same frame (sequential creature generation on device: deck LLM out, image model in). queue_free releases the model too, but only at the end of the frame, and an engine created before that inherits this node's device through the shared registry and keeps the dead model's buffers in an idle pool for as long as it lives; on the 2026-09-18 phone soak every second and later creature rendered on top of about 900 MB of released deck LLM. Desktop hosts that never free the engine node need not call this.

Outputs

A Dictionary: unloaded (int, models that were resident, summed over backends), footprint_before_mb and footprint_after_mb (float, the process footprint around the call; 0.0 off Apple), elapsed_ms (int) and error (String, empty on success; a backend that failed leaves its message here and the others still run).

Example

Output: {"unloaded":1,"footprint_before_mb":2086.6,"footprint_after_mb":1012.4,"elapsed_ms":38,"error":""}

image_model_is_loaded(model_id: GString) -> bool​

Whether an image-generation model is currently resident in memory (blocking; one round-trip to the image model thread, so it waits for an in-flight generation to finish).

Inputs

Outputs

bool: true if any variant of the model is loaded.

memory_pressure(level: GString) -> VarDictionary​

Tell the engine the OS reported memory pressure. Returns at once: the report is queued to the image model thread and never waits for a generation in flight, so it is safe from the main thread's memory-warning hook (applicationDidReceiveMemoryWarning on iOS, Godot's NOTIFICATION_OS_MEMORY_WARNING) while image_generate_stream is running. A running generation sheds its text encoder and VAE at its next denoise step and applies the full level when it finishes; an idle engine applies it immediately.

  • "warning" -- every loaded Anima model drops its text encoder (~0.74 GB) and VAE (~0.25 GB) and keeps its DiT, so the next generation pays two small reloads instead of the full one.
  • "critical" -- every image model is unloaded outright; the next generation reloads from the local cache.

Both levels drop live denoise sessions and sweep the device buffer pool. Applies to every configured in-memory backend.

Inputs

  • level -- "warning" or "critical" (case-insensitive).

Outputs

A Dictionary: level (string), queued (bool, always true on success: the shed happens on the model thread after this returns, so models_paged, models_unloaded and sessions_dropped (int) are 0 here and the engine log line image: memory pressure '&lt;level&gt;' handled: ... carries the real counts), footprint_before_mb and footprint_after_mb (f64, both the process footprint at the call; 0.0 off Apple platforms), and error (string, empty on success).

Example

Input: "warning"
Output: {"level":"warning","queued":true,"footprint_before_mb":3120.5,"footprint_after_mb":3120.5,"models_paged":0,"models_unloaded":0,"sessions_dropped":0,"error":""}

is_adapter_cached(adapter_id: GString) -> bool​

Returns true if the adapter's files are already in the local Atelico cache.

Pure filesystem check; same caveats as is_model_cached.

Inputs

  • adapter_id -- bare adapter id (no backend prefix), e.g. "deckgen_latest_bonsai".

Outputs

bool: true if cached, false if missing or no backend is configured.

adapter_download(adapter_id: GString, auth_token: GString) -> VarDictionary​

Download an adapter (LoRA) into the local Atelico cache (blocking).

Downloads adapter_config.json and adapter_model.safetensors for the given adapter id from the configured object store. The adapter is NOT bound to any base model and is NOT loaded onto the GPU — that still happens lazily on the first inference request that names it.

Use this during a loading screen to avoid the network cost on the first inference that names this adapter.

Inputs

  • adapter_id -- bare adapter id (no backend prefix), e.g. "deckgen_latest_bonsai". Adapter operations don't take a backend:: prefix; if multiple in-memory backends are configured, pick_adapter_backend picks the lexicographically smallest one.

Outputs

VarDictionary { "ok": bool, "error": String }. Same shape as model_download — see there for details.

Example

Input: "deckgen_latest_bonsai"
Output: {"ok": true, "error": ""}

total_size(namespace: GString, id: GString) -> i64​

Sum the size of every remote object under <namespace>/<id>/ in the configured object store. Returns -1 when the store is unreachable or the asset is absent.

Blocking — issues a synchronous LIST against the bucket.

Inputs

  • namespace -- "models" or "adapters".
  • id -- the asset id (without any "backend::" prefix).

total_size_with_auth(namespace: GString, id: GString, auth_token: GString) -> i64​

Like [total_size] but threads an OPTIONAL per-request bearer token (a rotating Supabase JWT) to the store probe. Required when the store is an authenticated http(s) read-through, whose size probe (HEAD) rejects anonymous requests exactly like its GETs. Pass "" for no auth header (identical to total_size).

Inputs

  • namespace -- "models" or "adapters".
  • id -- the asset id (without any "backend::" prefix).
  • auth_token -- OPTIONAL bearer token, "" for none.

adapter_download_async(adapter_id: GString, auth_token: GString) -> i64​

Download an adapter (LoRA) asynchronously, streaming progress events via signals. Symmetric with [model_download_async].

model_download_progress fires with kind = "adapter" for events emitted by this call.

auth_token is an OPTIONAL per-request bearer token (a rotating Supabase JWT) attached to the http(s) asset-store GETs as Authorization: Bearer &lt;token&gt;. Pass "" for no auth header (unchanged behavior). Never read from the process environment.

lora_load(model_id: GString, adapter: GString) -> bool​

Make an adapter the default for a model: requests for model_id without a ::adapter suffix run with it from the next request on.

Inputs

  • model_id -- the base model, e.g. "in-memory::llama".
  • adapter -- an asset-store adapter id ("pirate"), or a local adapter directory written as a path: absolute (ProjectSettings.globalize_path("res://lora/pirate")) or starting with ./. It holds adapter_config.json and adapter_model.safetensors.

Outputs

bool: true once it is the default; false (logged) if the adapter cannot be resolved. For a model on a non-local backend the call is accepted without effect.

Example

Input: model_id="in-memory::llama", adapter="pirate"
Output: true

lora_unload(model_id: GString) -> bool​

Clear a model's default adapter and strength: requests without a suffix run on the base weights again.

Inputs

  • model_id -- the base model.

Outputs

bool: true on success.

Example

Input: "in-memory::llama"
Output: true

lora_set_scale(model_id: GString, scale: f64) -> bool​

Set the strength a model's adapter runs at, for requests without their own adapter_scale: 1.0 as trained, 0.0 the base model, values between blend. Applies to the default adapter and to one a request picks by suffix.

Inputs

  • model_id -- the base model.
  • scale -- finite and non-negative.

Outputs

bool: true on success, false (logged) for an invalid scale.

Example

Input: model_id="in-memory::llama", scale=0.5
Output: true

lora_list_active() -> GString​

Models this node has given a default adapter, as JSON.

Outputs

JSON array (empty string on error): [{"model_id": ..., "adapter": ...}], [] when no model has one.

Example

Input: (no arguments)
Output: [{"model_id":"in-memory::llama","adapter":"pirate"}]

Deprecated Methods​

chat_completions(request_str: GString) -> GString​

DEPRECATED: Use llm_chat instead.

Synchronous chat completion (old API name). Delegates to llm_chat.

Inputs

  • request_str -- same as llm_chat.

Outputs

Same as llm_chat.

Example

Input: {"model":"in-memory::llama","messages":[{"role":"user","content":"Hi"}]}
Output: (same as llm_chat -- use llm_chat instead)

async_chat_completions(request_str: GString) -> i64​

DEPRECATED: Use llm_chat_async instead.

Non-blocking chat completion (old API name). Delegates to llm_chat_async.

Inputs

  • request_str -- same as llm_chat_async.

Outputs

Same as llm_chat_async.

Example

Input: {"model":"in-memory::llama","messages":[{"role":"user","content":"Hi"}]}
Output: (same as llm_chat_async -- use llm_chat_async instead)

stream_chat_completions(request_str: GString) -> i64​

DEPRECATED: Use llm_chat_stream instead.

Streaming chat completion (old API name). Delegates to llm_chat_stream.

Inputs

  • request_str -- same as llm_chat_stream.

Outputs

Same as llm_chat_stream.

Example

Input: {"model":"in-memory::llama","messages":[{"role":"user","content":"Hi"}]}
Output: (same as llm_chat_stream -- use llm_chat_stream instead)

responses(request_str: GString) -> GString​

DEPRECATED: Use llm_respond instead.

Synchronous Responses API call (old API name). Delegates to llm_respond.

Inputs

  • request_str -- same as llm_respond.

Outputs

Same as llm_respond.

Example

Input: {"model":"in-memory::llama","input":"Hello"}
Output: (same as llm_respond -- use llm_respond instead)

stream_responses(request_str: GString) -> i64​

DEPRECATED: Use llm_respond_stream instead.

Streaming Responses API (old API name). Delegates to llm_respond_stream.

Inputs

  • request_str -- same as llm_respond_stream.

Outputs

Same as llm_respond_stream.

Example

Input: {"model":"in-memory::llama","input":"Hello"}
Output: (same as llm_respond_stream -- use llm_respond_stream instead)

embeddings(request_str: GString) -> GString​

DEPRECATED: Use embed instead.

Synchronous embedding (old API name). Delegates to embed.

Inputs

  • request_str -- same as embed.

Outputs

Same as embed.

Example

Input: {"model":"in-memory::all-MiniLM-L6-v2","input":"Hello"}
Output: (same as embed -- use embed instead)

async_embeddings(request_str: GString) -> i64​

DEPRECATED: Use embed_async instead.

Non-blocking embedding (old API name). Delegates to embed_async.

Inputs

  • request_str -- same as embed_async.

Outputs

Same as embed_async.

Example

Input: {"model":"in-memory::all-MiniLM-L6-v2","input":"Hello"}
Output: (same as embed_async -- use embed_async instead)

stream_image_generation(request_str: GString) -> i64​

DEPRECATED: Use image_generate_stream instead.

Streaming image generation (old API name). Delegates to image_generate_stream.

Inputs

  • request_str -- same as image_generate_stream.

Outputs

Same as image_generate_stream.

Example

Input: {"model":"in-memory::PixArt","prompt":"A cat"}
Output: (same as image_generate_stream -- use image_generate_stream instead)

AtelicoSingleton​

Engine-level singleton for GPU scheduling and inference configuration.

Registered as AtelicoSingleton and accessible from GDScript via Engine.get_singleton("AtelicoSingleton"). Configure GPU scheduling mode, VRAM budgets, token rate limiting, and frame budgets before calling AtelicoEngineNode.initialize_engine().

Settings configured here are read once at engine initialization time. Changing them after initialize_engine() has no effect.

Methods​

set_gpu_scheduling_mode(mode: i32)​

Set the GPU scheduling mode to control how GPU time is shared between inference and rendering.

  • mode: one of PRIORITIZE_COMPUTE (0), BALANCE (1), or PRIORITIZE_GRAPHICS (2). Invalid values default to BALANCE.

get_gpu_scheduling_mode() -> i32​

Get the current GPU scheduling mode as an integer constant.

Returns: one of PRIORITIZE_COMPUTE (0), BALANCE (1), or PRIORITIZE_GRAPHICS (2).

repair_json(input: GString, default_json: GString) -> GString​

Repair a possibly-truncated or malformed JSON string.

The common case is a structured-generation response cut off by a token limit (finish_reason == "length"), e.g. {"a": 1, "b": "hel — valid up to the cut but unparseable as a whole. Completes it best-effort: keeps complete fields, closes and keeps a truncated string value, drops a dangling key with no value, and closes open objects/arrays.

  • input: the JSON string to repair.
  • default_json: optional JSON string whose fields fill any missing/null fields in the result (fields present in input win). Pass an empty string for no default.

Returns: the repaired JSON string.

Caveat: a value truncated mid-token is kept as-is. Repair is a safety net — prefer checking finish_reason and raising max_tokens.

set_vram_budget_mb(budget_mb: i32)​

Set the maximum VRAM (in megabytes) that inference may use. When exceeded, model loading will be rejected.

  • budget_mb: VRAM cap in MB. Set to 0 for unlimited (default). Negative values are clamped to 0.

get_vram_budget_mb() -> i32​

Get the configured VRAM budget in MB.

Returns: VRAM budget in megabytes, or 0 if unlimited.

set_max_kv_tokens(tokens: i32)​

Cap the LLM KV cache at tokens (prompt + generation) per request.

The KV cache is the LLM's largest allocation after its weights: at the engine default of 2048 tokens a 28-layer model holds ~450 MB of F32 K/V whether or not a request ever needs that many. A game whose prompts stay well under that can set a ceiling and get the memory back -- the cache is (re)allocated within it. A request that needs more than the ceiling fails with a context-exceeds-ceiling error instead of growing the cache, so set it above your longest prompt plus max_tokens.

  • tokens: ceiling in tokens. 0 (the default) means no ceiling beyond the model's own context limit. Negative values are treated as 0.

get_max_kv_tokens() -> i32​

Get the configured KV-cache ceiling in tokens.

Returns: the ceiling, or 0 if none is set.

set_target_tokens_per_second(tps: i32)​

Set the maximum tokens per second for inference. The inference loop sleeps between tokens to stay under this rate, freeing GPU time for rendering.

  • tps: target tokens per second. Set to 0 for unlimited (default). Negative values are clamped to 0.

get_target_tokens_per_second() -> i32​

Get the configured token rate limit.

Returns: target tokens per second, or 0 if unlimited.

set_frame_time_ms(ms: i32)​

Set the target frame time in milliseconds, used as a hint for adaptive inference throttling. For example, pass 16 for a 60 FPS target or 33 for 30 FPS.

  • ms: frame budget in milliseconds. Set to 0 for no frame budget (default). Negative values are clamped to 0.

get_frame_time_ms() -> i32​

Get the configured frame time budget in milliseconds.

Returns: frame time in milliseconds, or 0 if no budget is set.

set_lora_pre_merge(enabled: bool)​

Configure whether LoRA adapters are pre-merged into base weights at load time.

Pre-merging (the default) bakes the LoRA delta into the base weight, giving zero per-token overhead during inference. This temporarily uses ~2× the base weight's memory during the merge and clones the base weight to support adapter unload.

Disable on memory-constrained devices (iPhone, low-RAM iPads) — A/B matrices are kept and the delta is applied at runtime in forward(). Lower peak memory, small per-token cost.

  • enabled: true to pre-merge (default), false for runtime delta.

Must be called BEFORE AtelicoEngineNode.initialize_engine(). Settings change after init has no effect on already-loaded adapters.

get_lora_pre_merge() -> bool​

Get the configured LoRA pre-merge policy. Returns the engine default (true) if set_lora_pre_merge has not been called.

is_cig_d3d12_supported() -> bool​

Check whether the GPU supports CiG (Compute-in-Graphics) with D3D12. Requires an NVIDIA Ada Lovelace+ GPU with HAGS enabled and R570+ driver.

Returns: true if D3D12 CiG is supported, false otherwise. Always returns false on non-CUDA builds (macOS, CPU-only).

is_cig_vulkan_supported() -> bool​

Check whether the GPU supports CiG (Compute-in-Graphics) with Vulkan. Requires an NVIDIA Ada Lovelace+ GPU with CUDA 12.9+ driver.

Returns: true if Vulkan CiG is supported, false otherwise. Always returns false on non-CUDA builds (macOS, CPU-only).

get_gpu_scheduling_mode_raw() -> i32​

set_gpu_scheduling_mode_raw(value: i32)​

NaturalTime​

Natural-language time parsing against the game clock.

Methods​

parse_instant(text: GString, now_iso: GString) -> GString​

The instant text names, resolved against now_iso ("YYYY-MM-DDTHH:MM:SS"), as ISO; "" when the text names no time.

parse_detail(text: GString, now_iso: GString) -> VarDictionary​

Full parse: {"resolved": iso, "kind": "instant"|"date"|"duration", "alternative": iso or "", "ambiguity": ""|"meridiem"|"date_order", "dated": whether the expression named a day rather than a bare clock time}. Empty dictionary when the text names no time.

AtelicoClassifierNode​

Godot node for text, image and audio classification.

Loads pre-trained classifier models (centroid, KNN/HNSW, SetFit, or the embedder-free n-gram perceptron) and predicts the class of input text, images, or audio. Useful for intent detection, sentiment analysis, or content routing in games.

Usage: Add as a child node, call initialize(), then load_classifier() with a classifier ID and directory path, then predict_text() / predict_image() / predict_audio() to classify by modality.

The embedding-backed kinds need their encoder weights present, so pair is_model_cached() / download_classifier() with load_classifier(). The ngram_perceptron kind has no embedder: point load_classifier() at a directory of files shipped with the game and it loads offline, with no download and no warm-up.

Methods​

initialize() -> bool​

Initialize the classifier engine. Must be called before load_classifier or any predict_* call.

Inputs

(none)

Outputs

bool: true on success, false if initialization fails.

Example

Input: (no arguments)
Output: true

load_classifier(classifier_id: GString, directory: GString) -> bool​

Load a classifier from a directory on disk.

Inputs

  • classifier_id -- logical name to reference this classifier in predict_*.
  • directory -- filesystem path to the classifier directory containing model weights and metadata files.

Outputs

bool: true on success, false on error (logged).

Example

Input: classifier_id="sentiment", directory="/models/sentiment_v1"
Output: true

download_classifier(classifier_id: GString) -> GString​

Download a classifier's files from the asset store into the local cache and return the directory holding them.

Fetches from the classifiers/<classifier_id>/ namespace using the process-environment asset-store config (set via AtelicoEngineNode.set_env_var), pulling exactly the files the on-disk loader needs. Pair with load_classifier, which takes the returned directory. Classifier assets are small, so this is synchronous.

Inputs

  • classifier_id -- store id of the classifier, e.g. "bb-creature-facing-v1".

Outputs

String: absolute path to the local classifier directory, or "" on failure (logged).

is_model_cached(model_id: GString) -> bool​

Whether an embedding model is already present in the on-device cache.

Lets a caller gate work that would otherwise trigger a blocking download — loading a classifier builds its embedder, fetching it if absent. Probe first, and skip (or offer a download) when this returns false.

Inputs

  • model_id -- the embedder's <org>/<model> id, e.g. "sentence-transformers/all-MiniLM-L6-v2".

Outputs

bool: true if cached, false if missing or the engine is not initialized.

Example

Input: model_id="sentence-transformers/all-MiniLM-L6-v2"
Output: true

predict_text(classifier_id: GString, text: GString, top_k: i32) -> GString​

Predict the class of input text using a loaded classifier.

Inputs

  • classifier_id -- the ID passed to load_classifier.
  • text -- the input text string to classify.
  • top_k -- number of top predictions to include (minimum 1).

Outputs

JSON prediction result (empty string on error):

  • label (string) -- predicted class name.
  • probability (float) -- confidence score for the top prediction.
  • top (array) -- top-k predictions as [label, probability] PAIRS, not objects: [["positive", 0.95], ["negative", 0.05]]. Read top[i][0] for the label and top[i][1] for the score.

Example

Input: classifier_id="sentiment", text="I love this game!", top_k=3
Output: {"label":"positive","probability":0.95,"top":[["positive",0.95],["neutral",0.04],["negative",0.01]]}

predict_image(classifier_id: GString, image_path: GString, top_k: i32) -> GString​

Predict the class of an image using a multi-modal classifier.

The classifier referenced by classifier_id must have been trained with an image embedder (e.g. DINOv2). Calling this against a text-only classifier returns an empty string and logs an error.

Inputs

  • classifier_id -- the ID passed to load_classifier.
  • image_path -- absolute filesystem path to the image file (PNG / JPEG).
  • top_k -- number of top predictions to include (minimum 1).

Outputs

JSON prediction result (empty string on error), same schema as predict_text:

  • label (string) -- predicted class name.
  • probability (float) -- confidence score for the top prediction.
  • top (array) -- top-k predictions.

Example

Input: classifier_id="animals", image_path="/abs/path/cat.jpg", top_k=3
Output: {"label":"cat","probability":0.91,"top":[{"label":"cat","probability":0.91},{"label":"dog","probability":0.07},{"label":"bird","probability":0.02}]}

predict_audio(classifier_id: GString, audio_path: GString, top_k: i32) -> GString​

Predict the class of an audio clip using a multi-modal classifier.

The classifier referenced by classifier_id must have been trained with an audio embedder (e.g. CLAP). Calling this against a text- or image-only classifier returns an empty string and logs an error.

Inputs

  • classifier_id -- the ID passed to load_classifier.
  • audio_path -- absolute filesystem path to the audio file (WAV).
  • top_k -- number of top predictions to include (minimum 1).

Outputs

JSON prediction result (empty string on error), same schema as predict_text / predict_image:

  • label (string) -- predicted class name.
  • probability (float) -- confidence score for the top prediction.
  • top (array) -- top-k predictions.

Example

Input: classifier_id="sounds", audio_path="/abs/path/bark.wav", top_k=3
Output: {"label":"dog","probability":0.88,"top":[{"label":"dog","probability":0.88},{"label":"cat","probability":0.09},{"label":"bird","probability":0.03}]}

create_classifier(classifier_id: GString, config_json: GString) -> bool​

Create an empty classifier to teach during play with train_incremental_text.

The classifier starts with no labels; each label is created by its first example. Persist it with save_classifier and bring it back with load_classifier.

Inputs

  • classifier_id -- logical name for later calls; must not already exist.
  • config_json -- JSON object:
    • kind (string) -- "centroid" (recommended), "knn", or "ngram_perceptron".
    • embedder (string) -- embedding model id, the same one embed_text takes ("all-MiniLM-L6-v2"). Required for centroid/knn, absent for ngram_perceptron. Its weights must be cached (is_model_cached).
    • multilabel (bool, optional) -- independent per-label scores. Default false.
    • k_neighbors (int, optional) -- knn only. Default 7.

Outputs

bool: true on success, false on error (logged).

Example

Input: classifier_id="dragon_cues", config_json={"kind":"centroid","embedder":"all-MiniLM-L6-v2"}
Output: true

remove_label(classifier_id: GString, label: GString) -> bool​

Forget a label and everything learned for it.

Inputs

  • classifier_id -- a created or loaded classifier.
  • label -- the label to remove.

Outputs

bool: true on success, false on error (logged), e.g. an unknown label.

Example

Input: classifier_id="dragon_cues", label="spin"
Output: true

get_classifier_info(classifier_id: GString) -> GString​

Describe a classifier for a debug panel: kind, labels and examples per label.

Inputs

  • classifier_id -- a created or loaded classifier.

Outputs

JSON object (empty string on error):

  • classifier_id, kind (string), modality (string)
  • embedding_dim (int or null) -- vector length *_embedding methods take.
  • supports_incremental_training (bool)
  • labels (array) -- {"label": string, "example_count": int or null}; the count is null for classifiers saved before counts were recorded.

Example

Input: classifier_id="dragon_cues"
Output: {"classifier_id":"dragon_cues","kind":"centroid","modality":"text","embedding_dim":384,
"supports_incremental_training":true,
"labels":[{"label":"come","example_count":6},{"label":"sit","example_count":6}]}

save_classifier(classifier_id: GString, directory: GString) -> bool​

Save a classifier to a directory (for example inside the player's save slot), in the format load_classifier reads back.

Inputs

  • classifier_id -- a created or loaded classifier.
  • directory -- filesystem path; created if missing. Use ProjectSettings.globalize_path("user://...") for a user:// path.

Outputs

bool: true on success, false on error (logged).

Example

Input: classifier_id="dragon_cues", directory="/Users/me/.../save1/dragon_cues"
Output: true

AtelicoKvStoreNode​

Godot node for semantic key-value storage with vector similarity search.

Backed by LanceDB. Store text entries with embeddings, then query by vector similarity to find semantically related content. Useful for game dialogue recall, lore lookup, or dynamic context retrieval.

Usage: Add as a child node, call kvstore_create() with a config JSON, then kvstore_query() to search by embedding similarity.

Methods​

kvstore_create(config_json: GString) -> bool​

Create a new KV store backed by LanceDB.

Inputs

  • config_json -- JSON configuration object:
    • store_id (string) -- unique identifier for this store (default "default").
    • db_path (string) -- filesystem path for the database (default "./data").
    • table_name (string) -- database table name (default "entries").
    • embed_dim (int) -- embedding vector dimensionality (default 384).
    • facet_names (array of string) -- exact-match filter columns every inserted entry must fill (default none).
    • value_fields (array) -- the payload columns, each {"name": string, "field_type": "Utf8" | "Int32" | "Float32", "nullable": bool} (default none).
    • has_priority (bool) -- enable priority scoring (default false).
    • similarity_weight (float) -- weight for similarity in combined score (default 0.5).
    • priority_weight (float) -- weight for priority in combined score (default 0.5).

Outputs

bool: true on success, false on error.

Example

Input: {"store_id":"episodes","db_path":"./data/episodes","embed_dim":384,
"facet_names":["creature"],
"value_fields":[{"name":"summary","field_type":"Utf8","nullable":false}]}
Output: true

kvstore_insert(store_id: GString, entries_json: GString) -> bool​

Insert one entry or a batch into a KV store at runtime.

Inputs

  • store_id -- the store to insert into (from kvstore_create).
  • entries_json -- one entry object, or an array of them. Each entry mirrors KvEntry:
    • id (string, required) -- unique identifier.
    • key_text (string, required) -- the text the entry is found by.
    • key_embedding (array of float, required) -- embedding of key_text, embed_dim long (e.g. from AtelicoEmbedderNode.embed_text).
    • facets (object of string, optional) -- one value per configured facet.
    • values (object, optional) -- payload, each value tagged with its column type: {"summary": {"Utf8": "fed a fish"}, "mood": {"Int32": 2}}.
    • priority (float, optional) -- ranking priority in 0..1.

Outputs

bool: true if every entry was inserted, false on error (logged). A batch is written in one call.

Example

Input: store_id="episodes",
entries_json={"id":"ep-17","key_text":"the player fed Stormfly a fish",
"key_embedding":[0.01,...],"facets":{"creature":"stormfly"},
"values":{"summary":{"Utf8":"fed a fish"}}}
Output: true

kvstore_query(store_id: GString, query_json: GString) -> GString​

Query a KV store using vector similarity search.

Inputs

  • store_id -- the store to query (must match a previous kvstore_create call).
  • query_json -- JSON query object:
    • query_embedding (array of float, required) -- the query vector.
    • query_text (string) -- text for display/debug.
    • vector_search_limit (int) -- ANN candidate pool size (default 20).
    • limit (int) -- number of results to return (default 5).
    • use_prefilter (bool) -- apply facet filters before ANN (default true).

Outputs

JSON array of result objects ("[]" on error):

  • id (string) -- entry identifier.
  • key_text (string) -- entry key text.
  • similarity (float) -- cosine similarity score.
  • priority (float) -- priority value (if enabled).
  • combined_score (float) -- weighted combination of similarity and priority.

Example

Input: store_id="lore", query_json={"query_embedding":[0.1,0.2,...],"limit":3}
Output: [{"id":"1","key_text":"dragon lore","similarity":0.95,"priority":1.0,"combined_score":0.95}]

kvstore_count(store_id: GString, filter: GString) -> i64​

Count entries in a KV store, optionally filtered.

Inputs

  • store_id -- the store to count entries in.
  • filter -- SQL-like filter expression (empty string = no filter, count all).

Outputs

int: the entry count, or -1 if the store is not found or an error occurs.

Example

Input: store_id="lore", filter=""
Output: 42

kvstore_destroy(store_id: GString) -> bool​

Delete a KV store and remove it from memory.

Inputs

  • store_id -- the store to destroy.

Outputs

bool: true if the store existed and was removed, false if not found.

Example

Input: "lore"
Output: true

kvstore_create_fts_index(store_id: GString, column: GString) -> bool​

Create a full-text-search (FTS) index on a string column of a KV store.

Required before calling kvstore_lexical_query or kvstore_hybrid_query. Typical column choices are "key_text" (the search keys) or any string-typed value column.

Inputs

  • store_id -- the store to index.
  • column -- column name to index.

Outputs

bool: true on success, false if the store is missing or the indexing call fails.

kvstore_lexical_query(store_id: GString, query_json: GString) -> GString​

Lexical (full-text) query against an FTS-indexed column.

The target column must have an FTS index — see kvstore_create_fts_index.

Inputs

  • store_id -- the store to query.

  • query_json -- JSON LexicalSearchQuery:

    {"text": "dragon attack", "column": "key_text", "filter": null, "limit": 10}

Outputs

JSON array of KvResult rows ("[]" on error). The combined_score field carries the BM25 score.

kvstore_hybrid_query(store_id: GString, query_json: GString) -> GString​

Hybrid (vector + lexical) query with weighted-sum reranking.

Each branch returns up to effective_per_branch_limit candidates; scores are min-max normalised independently and combined with the configured weights. The FTS column must have an FTS index.

Inputs

  • store_id -- the store to query.

  • query_json -- JSON HybridSearchQuery:

    {
    "embeddings": [0.0, 0.1, 0.2],
    "text": "dragon attack",
    "fts_column": "key_text",
    "filter": null,
    "limit": 5,
    "per_branch_limit": 0,
    "vector_weight": 0.5,
    "lexical_weight": 0.5
    }

Outputs

JSON object on success (empty string on error):

{
"results": [{ ...KvResult... }],
"scores": [{"vector_score": 0.8, "lexical_score": 0.6, "merged_score": 0.7}]
}

AtelicoGuardrailsNode​

Godot node for content safety checking (guardrails).

Configure with a preset ("game-safe", "child-safe", or "developer-sdk") and use check_input/check_output/check_image_prompt to validate user or model content against safety policies.

Usage: Add as a child node, call initialize("game-safe"), then pass text through check_input() before sending to the LLM or check_output() before displaying model responses to the player.

Methods​

initialize(preset: GString) -> bool​

Initialize guardrails with a safety preset.

Inputs

  • preset -- one of "game-safe" (default), "child-safe", or "developer-sdk". Each preset configures different thresholds for violence, sexual content, hate speech, etc.

Outputs

bool: true on success, false on error.

Example

Input: "game-safe"
Output: true

check_input(text: GString) -> GString​

Check user input text against safety guardrails.

Inputs

  • text -- the user-provided input text to validate.

Outputs

JSON SafetyVerdict (empty string on error):

  • action -- "Allow", or an object naming the decision: {"Block": {"reason": string}} or {"Rewrite": {"original": string, "rewritten": string, "reason": string}}. Test typeof(v.action) == TYPE_STRING (allowed) vs a Dictionary (acted on).
  • checker_name (string) -- the checker that blocked, or "composite" when the whole cascade allowed it.
  • score (float or null) -- the checker's confidence, when it reports one.

Example

Input: "Tell me a joke about dragons"
Output: {"action":"Allow","checker_name":"composite","score":null}

check_output(text: GString) -> GString​

Check model-generated output against safety guardrails.

Inputs

  • text -- the model output to validate before displaying to the player.

Outputs

Use this, not check_input, for text the game generated (NPC dialogue, a narrator's notebook): the cascade applies its output-side checks here.

JSON SafetyVerdict, same schema as check_input (empty string on error).

Example

Input: "The dragon breathes fire at the castle."
Output: {"action":"Allow","checker_name":"composite","score":null}

check_image_prompt(prompt: GString) -> GString​

Check an image generation prompt against safety guardrails.

Inputs

  • prompt -- the image generation prompt to validate.

Outputs

JSON SafetyVerdict, same schema as check_input (empty string on error).

Example

Input: "A peaceful sunset over mountains"
Output: {"action":"Allow","checker_name":"composite","score":null}

AtelicoAnnIndexNode​

Godot node for approximate nearest neighbor (ANN) vector search.

A pure data structure backed by HNSW (Hierarchical Navigable Small World) graph -- no GPU or ML models required. Insert vectors with label IDs, build the index, then search for nearest neighbors by cosine distance.

Usage: Add as a child node, call create(dim, max_elements), then insert() vectors, call build(), and finally search() to find nearest neighbors.

Methods​

create(dim: i32, max_elements: i32) -> bool​

Create a new empty ANN index.

Inputs

  • dim -- dimensionality of vectors (must match vectors inserted later).
  • max_elements -- maximum number of vectors the index can hold.

Outputs

bool: true on success.

Example

Input: dim=384, max_elements=1000
Output: true

insert(vector: Array<f32>, label_id: i64) -> bool​

Insert a vector with an associated label ID.

Call build() after all insertions are complete before searching.

Inputs

  • vector -- array of floats with length matching dim from create().
  • label_id -- integer label to identify this vector in search results.

Outputs

bool: true on success, false if the index has not been created.

Example

Input: vector=[0.1, 0.2, 0.3], label_id=42
Output: true

build() -> bool​

Build the HNSW index graph. Must be called after all insertions and before any search() calls.

Inputs

(none)

Outputs

bool: true on success, false if the index has not been created.

Example

Input: (no arguments)
Output: true

search(query: Array<f32>, k: i32) -> GString​

Search for the k nearest neighbors of a query vector.

Inputs

  • query -- query vector (array of floats with length matching dim).
  • k -- number of nearest neighbors to return.

Outputs

JSON array of result objects sorted by ascending distance ("[]" if index not created):

  • label_id (int) -- the label assigned during insert().
  • distance (float) -- cosine distance (lower = more similar).

Example

Input: query=[0.1, 0.2, 0.3], k=3
Output: [{"label_id":42,"distance":0.05},{"label_id":17,"distance":0.12},{"label_id":8,"distance":0.34}]

AtelicoEmbedderNode​

Godot node for direct multimodal embedding (text, image, audio).

Wraps the SDK embedding subsystem to turn a string, an image file, or an audio file into a dense vector. The three modalities can share one space when a cross-modal model embeds them, so a text query can retrieve images or audio by cosine similarity (feed the vectors into [AtelicoAnnIndexNode]).

Model id convention

Pass the embedder model id (optionally "in-memory::"-prefixed) for the modality you are embedding:

  • Text — a BERT-family encoder, e.g. "bge-small-en" / "in-memory::bge-small-en" (384-dim).
  • Image — a vision encoder or cross-modal image tower, e.g. "dinov2-small" (the DINOv2-Small vision embedder, 384-dim), "dinov2-large", "clip", "siglip".
  • Audio — the CLAP audio tower, "clap".

Gating

Each embed_* call resolves the model from the on-device cache and never triggers a blocking download: if the weights are absent it logs an error and returns an empty PackedFloat32Array. Gate first with AtelicoEngineNode.is_model_cached(model) and, if missing, fetch via AtelicoEngineNode.model_download_async(model, token) before embedding.

Usage: Add as a child node, call initialize(), then embed_text() / embed_image() / embed_audio().

Methods​

initialize() -> bool​

Initialize the embedding engine. Must be called before any embed_*.

Inputs

(none)

Outputs

bool: true on success, false if initialization fails.

embed_text(model: GString, text: GString) -> PackedFloat32Array​

Embed a text string into a dense vector.

Inputs

  • model -- text embedder model id (e.g. "bge-small-en").
  • text -- the text to embed.

Outputs

PackedFloat32Array: the embedding vector, or empty on error or when the model is not cached (see the node-level gating contract).

Example

Input: model="bge-small-en", text="a friendly dragon"
Output: [0.012, -0.034, 0.056, ...] (384 floats)

AtelicoCacheNode​

Godot node for prompt result caching.

Methods​

initialize() -> bool​

cache_get(key_json: GString, policy_json: GString) -> GString​

Look up a cached result. Returns JSON or empty string on miss.

cache_put(key_json: GString, policy_json: GString, response_json: GString) -> bool​

Store a result in the cache.

cache_clear()​

cache_size() -> i32​

AtelicoMatcherNode​

Godot node for ranking candidates against a query.

Methods​

initialize() -> bool​

match_one(matcher_id: GString, query: GString, elements_json: GString) -> GString​

Match the single best candidate. Returns JSON or empty string.

AtelicoSpeechListenerNode​

Listens to the microphone (or to audio you feed it) and reports speech as it is decided.

Setup: enable Project Settings > Audio > Driver > Enable Input (audio/driver/enable_input), without which Godot delivers silence; set engine to your initialised AtelicoEngineNode; connect the signals; call start_listening().

@onready var listener: AtelicoSpeechListenerNode = $SpeechListener
func _ready():
listener.engine = $AtelicoEngine
listener.endpointing = "command"
listener.transcription_received.connect(_on_heard)
listener.start_listening()
func _on_heard(text: String, is_final: bool, _start: float, _end: float):
if is_final:
dragon.hear(text)

While the scene tree is paused the node stops processing like any other; set its process_mode to PROCESS_MODE_ALWAYS to keep listening through a pause menu.

Signals (times are seconds since start_listening):

  • speech_started(start_time) -- the player began talking.
  • speech_ended(start_time, end_time) -- they stopped; the final text follows.
  • transcription_received(text, is_final, start_time, end_time) -- provisional text while they talk (only with partial_interval_ms > 0), then the final text.
  • transcription_failed(message) -- one utterance could not be transcribed; the listener keeps listening.
  • listening_stopped() -- after stop_listening(), once the last utterance has been reported.

Signals​

speech_started​

speech_ended​

transcription_received​

transcription_failed​

listening_stopped​

Methods​

start_listening() -> bool​

Start listening with the current settings.

Outputs

bool: true once listening, false on error (logged) -- no engine, an engine not yet initialised, bad settings, or already listening.

Example

listener.start_listening() # -> true

stop_listening()​

Stop listening. An utterance in progress is still transcribed and reported; listening_stopped fires after it.

Example

listener.stop_listening()

is_listening() -> bool​

Whether the listener is running (from start_listening until listening_stopped).

feed_audio(samples: PackedFloat32Array, sample_rate: i32) -> bool​

Supply audio yourself, with use_microphone off: mono samples at sample_rate Hz, any chunk size. Keep the rate constant while listening. Refused while the microphone is being captured — two sources on one timeline would interleave into garbage.

Outputs

bool: false (logged) if not listening or sample_rate is not positive.

Example

listener.feed_audio(samples, 48000) # -> true

VectorMemoryStore​

Godot node for vector memory storage backed by LanceDB.

Stores character memories and metadata as vector-embedded records and supports similarity-based retrieval. Useful for NPC memory recall, narrative context, and character persona management.

Usage: Add as a child node, set db_name and embed_dim exports, then call connect_to_db() and get_or_create_table() before reading or writing records.

Methods​

connect_to_db(db_name: GString) -> bool​

Open (or create) a LanceDB database at user://database/ followed by db_name. Does not create tables -- call get_or_create_table afterwards to set up tables with the desired schema.

  • db_name: database directory name (e.g. "npc_memories").

Returns: true on success, false if the connection fails or the database is already connected with the same name.

get_or_create_table(table_name: GString, table_schema: GString) -> bool​

Open or create a table with the given schema name. If the table already exists, it is opened; otherwise a new table is created with the specified schema.

  • table_name: logical table name (e.g. "npc_observations").
  • table_schema: schema preset name. Composable convention: "memory", "memory+emotion", "character", "character+emotion".

Returns: true on success, false if not connected or on error.

write_memory(_table_name: GString, node: VarDictionary) -> bool​

Write a single memory record to the store.

  • _table_name: reserved for future multi-table support (currently unused).
  • node: a Dictionary containing all Memory fields. Required keys: uuid, observer, counter, node_count, type_count, depth, poignancy, node_type, embedding_key, location, created, expiration, subject, predicate, object, description, filling (Array of String), and vector (Array of float with length matching embed_dim). Optional: emotion_at_encoding (String), and the recall state query_memory returns -- last_accessed (int, Unix seconds), recall_count (int), stability (float), cited_memories (Array of String) -- which default to "never recalled".

Writing appends: writing a memory whose uuid is already stored adds a second row (both are returned by queries). To update recall state on a stored memory, use record_recall, not a re-write.

Returns: true on success, false if not connected or the dictionary is missing required fields.

write_character(_table_name: GString, character: VarDictionary) -> bool​

Write a single character/persona metadata record to the store.

  • _table_name: reserved for future multi-table support (currently unused).
  • character: a Dictionary containing character fields. Required keys: uuid, uuid_int, persona_name, age, personality, background, story, daily_plan, home, lifestyle, usual_wake_up_time, activity, reflectiveness. Optional: emotional_baseline (String, defaults to "neutral").

Returns: true on success, false if not connected or the dictionary is missing required fields.

record_recall(uuids: PackedStringArray, now: i64) -> i64​

Record that memories were recalled, so the reinforcement survives a reload.

Call it with the uuids a retrieval actually used. Each memory's recall_count goes up by one, its stability (Ebbinghaus S, in game-hours) grows by the engine's reinforcement rule, and last_accessed becomes now. The new values come back in query_memory results, and in this session's scoring as well as the next.

  • uuids: memory uuids to reinforce; unknown ones are skipped.
  • now: the time of the recall, in the same units as the memories' created field (retrieval scoring compares the two). Use Unix seconds (int(Time.get_unix_time_from_system())) if created is Unix seconds.

Returns: the number of memories updated, or -1 if not connected or on error.

Input: uuids=["ep-17", "ep-3"], now=1758463200
Output: 2

get_table_row_count(_table_name: GString, filter: GString) -> i64​

Count rows in the memory store, optionally filtered.

  • _table_name: reserved for future multi-table support (currently unused).
  • filter: SQL-like filter expression (empty string means count all rows).

Returns: the number of matching rows, or -1 if not connected or on error.