Skip to content

AI Core & Tasks

The ai_core app is the central nervous system of the Apptork Root System. It abstracts the chaotic world of third-party AI providers into a clean, unified, asynchronous interface.


🧠 The AI Model Orchestration Matrix

Instead of hardcoding models in your frontend, the Root System uses a dynamic orchestration matrix.

Your frontend hits the /api/v1/ai/{task-type}/models/ endpoint and receives exactly what it needs to render a rich model-selection UI:

{
  "alias": "sd3-turbo",
  "display_name": "Stable Diffusion 3 Turbo",
  "description": "High-quality, fast image generation.",
  "cost": 5.0,
  "estimated_seconds": 12,
  "is_default": true,
  "requires_subscription": false,
  "has_access": true,
  "capabilities": {
    "speed": 5,
    "photorealism": 4,
    "prompt_adherence": 4
  },
  "traits": [
    {"slug": "fast", "type": "PRO", "name": "Lightning Fast"},
    {"slug": "expensive", "type": "CON", "name": "High Cost"},
    {"slug": "beta", "type": "INFO", "name": "Beta Version"}
  ],
  "supported_parameters": ["aspect_ratio", "negative_prompt", "seed"]
}

Model Tiering & Reusability: The ProviderModelConfig architecture is extremely flexible. You can reuse the exact same underlying AI model across multiple configurations. For example, you can offer a "Standard" tier and a "Pro" tier of the same model: the Pro tier can cost more credits, require an active subscription, and utilize a different Transformer that automatically injects enhanced negative prompts and uses more inference stepsβ€”all dynamically controlled from the Django Admin.


The Transformer Architecture

To achieve this unified API, we use a Transformer Registry pattern.

Mobile clients send a single, standardized payload to our API. The BasePayloadTransformer maps this unified payload into the specific format expected by the chosen AI provider.

  1. API Request & Deduction: The client hits the endpoint. The system validates the payload, calculates the cost, atomically deducts the credits, and creates a Task record with a PENDING status.
  2. Celery Orchestration: The API immediately returns a 202 Accepted alongside a Task ID, offloading the work to a Celery Worker.
  3. Transformation: The worker looks up the correct transformer in the TRANSFORMER_REGISTRY, which maps the prompt and parameters for the specific vendor (e.g., Replicate, OpenAI, or a custom GPU).
  4. Storage & Webhooks: Upon completion, the worker downloads the generated asset, uploads it directly to MinIO (or AWS S3) via the SmartFileField, links the secure URL to the Task, and marks it COMPLETED.

(To learn how to add a new model via a Transformer in 15 minutes, see Extending the System).


πŸ”Œ The Provider Registry

If you need to integrate a completely new AI API (like Anthropic, fal.ai, or a custom GPU cluster), you use the Provider Registry.

By subclassing BaseProviderClient and registering it in PROVIDER_REGISTRY, you get an instant integration point that handles API key injection and request routing. You write the HTTP request; the Root System handles the rest.


✨ Automated Prompt Improver

Users often write terrible, single-word prompts in their native language. To guarantee high-quality outputs, we built an automated prompt enhancement pipeline natively into the image editing tasks.

graph TD
    UserPrompt["User Prompt (e.g., 'kΔ±rmΔ±zΔ± elma')"] --> LangDetect{langdetect}
    LangDetect -->|English| Skip[Use As-Is]
    LangDetect -->|Non-English| GPT[OpenAI Translation]
    LangDetect -->|Mixed Content| SmartPreserve[Intelligent Preservation]
    GPT --> EnhancedPrompt["Enhanced English Prompt"]
    SmartPreserve --> EnhancedPrompt
    Skip --> Generate[Image Generation Task]
    EnhancedPrompt --> Generate

Intelligent Preservation: If a user requests text to be rendered on an image (e.g., "A t-shirt with 'BENΔ° YIKA' text on it"), the system is intelligent enough to translate the context but preserve the quoted text exactly as written.

Prompt Leak Protection: The pipeline automatically appends our PROMPT_LEAK_PROTECTION constant to image generation instructions, preventing the AI from rendering the system instructions into the final output image.


Real-Time Task Streaming

Real-Time Updates without Polling

Long-polling is inefficient. Root System pushes updates directly to the client.

By listening to the Server-Sent Events (SSE) endpoint at /api/v1/ai/stream/, clients receive real-time streams of their task statuses (PROCESSING, COMPLETED, FAILED).

This is handled natively by the Gunicorn + Uvicorn workers, scaling to thousands of concurrent connections.

Ownership-Based Authorization: The stream is protected by the AICoreChannelManager. Users cannot intercept events meant for other users. The system automatically multiplexes events only to the authenticated owner of the specific task.


API Key Security Gap

API Keys are stored in plain text

Currently, the AIProvider model stores third-party API keys (e.g., Replicate, OpenAI) as plain text in the PostgreSQL database.

If your database is compromised, these keys could be exposed. For a production deployment, it is strongly recommended to implement at-rest encryption for the api_key field.

Recommended Solutions:

  1. Django-Cryptography: Use a package like django-cryptography to seamlessly encrypt the api_key field at the ORM level.
  2. External Secrets Manager: Migrate the API keys out of the database entirely and fetch them at runtime from a secure vault (e.g., AWS Secrets Manager, HashiCorp Vault, Doppler).