Files
Project_Velocity/.Agent Context/Bibels/dreamweaver_ios_integration_guide.md

8.7 KiB
Raw Permalink Blame History

Dream Weaver API v2 — iOS Integration Guide (Dynamic Keywords)

Version: 2.0-FINAL | Updated: 2026-03-09 | Server: 54.172.172.2 | Port: 8082

This document is for Sayan (iOS / Swift). Dream Weaver API v2 introduces a Dynamic Keyword to Local LLM Prompt Expansion system. The app no longer relies on 5 hardcoded styles. Users can pick ANY keywords, and a local LLM (Qwen 3.5 27B via Ollama) will generate a photorealistic interior design prompt based on the room type without sending data to the cloud.

Caution

PORT 8080 IS DEAD. Do not use port 8080 anymore. The old gateway process has been completely killed. If you try to send POST /dream-weaver or /docs to port 8080 you will get a 404. You MUST change your AppConfig.baseURL parameter to use port 8082.


1. Architecture Overview (API v2)

┌────────────────────┐       HTTP/S      ┌──────────────────────────────┐
│                    │ ── keywords ────► │  Dream Weaver Gateway v2     │
│  iPad App (Swift)  │                   │  FastAPI  port 8082          │
│                    │ ◄── PNG result ── │  dw_gateway_v2.py            │
└────────────────────┘                   └─────────────┬────────────────┘
                                                       │ LLM Prompt Expansion
                                                       │ (Local Ollama: Qwen 3.5 27B)
                                                       ▼
                                         ┌─────────────────────────┐
                                         │  ComfyUI Engine         │
                                         │  port 8188              │
                                         │  RealVisXL V5.0 Ltng    │
                                         └─────────────────────────┘

Key changes in v2:

  1. The API now runs on port 8082 to avoid conflicts.
  2. The style parameter is deprecated in favor of keywords (array of strings) and room_type.

2. Dynamic Keyword Expansion Flow

Instead of injecting keywords into a rigid template, the new backend reads the keywords and room_type, and asks a local LLM (Qwen 3.5 27B) to act as an interior designer:

  1. User input: keywords: ["blue marble", "gold veins", "renaissance"], room_type: "bathroom"
  2. Backend LLM Expansion: The LLM knows that a "bathroom" cannot have beds and needs wet-area materials. It creates a rich positive prompt: "renaissance revival luxury interior design, blue veined marble flooring, gold brass fixtures..."
  3. ComfyUI Generation: The expanded prompt is sent to ComfyUI for generation.

Supported Room Types: bedroom, living_room, bathroom, kitchen, dining_room, home_office, hallway, balcony.


3. API Reference — New v2 Endpoints

BASE URL

http://54.172.172.2:8082

3.1 GET /health — Liveness Check

Call this on app launch to confirm the v2 server is up. Response:

{
  "status": "ok",
  "comfyui": true,
  "gpu": "4x NVIDIA L4 (96GB VRAM)",
  "model": "RealVisXL V5.0 Lightning",
  "llm_expansion": true,
  "version": "2.0.0"
}

3.2 GET /room-types

Returns all supported room types and their required design context (useful if you want to build UI tooltips).

{
  "room_types": {
    "bedroom": {
      "description": "a private sleeping space",
      "key_elements": ["bed", "bedside tables", "wardrobe", "soft lighting", "textiles", "headboard"]
    },
    ...
  }
}

3.3 POST /dream-weaver/expand (Preview Prompt)

Use this if you want the user to preview the LLM's generated prompt before committing to a generation. Request (JSON):

{
    "keywords": ["blue marble", "gold veins", "renaissance"],
    "room_type": "bathroom"
}

Response:

{
    "style_name": "Renaissance Luxury",
    "positive_prompt": "renaissance revival luxury interior design, blue veined marble flooring...",
    "negative_prompt": "(worst quality, low quality...), extra windows...",
    "cfg": 7.5,
    "denoise": 0.72,
    "steps": 30,
    "source": "ollama_local"
}

3.4 POST /dream-weaver (Submit Generation)

Use this for the main generation flow. Request: multipart/form-data

Field Type Required Description
image File The room photo (JPEG/PNG)
keywords String Comma-separated user keywords e.g. "gold, marble, luxury"
room_type String e.g. "living_room", "bedroom"
additional_notes String (Optional) e.g. "make it feel like a luxury hotel"
denoise Float (Optional) 0.50.85. If omitted, LLM decides.

Response:

{
  "job_id": "a1b2c3d4-...",
  "status": "processing",
  "prompt_preview": "renaissance revival luxury interior design...",
  "poll_url": "/dream-weaver/status/a1b2c3d4-...",
  "result_url": "/dream-weaver/result/a1b2c3d4-..."
}

4. Polling & Downloading (Unchanged from v1)

Poll Job Status: GET /dream-weaver/status/{job_id} every 2 seconds until ready == true.

Download Result: GET /dream-weaver/result/{job_id} returns the raw PNG stream.


5. Updated Swift Example (v2)

func submitGenerationV2(image: UIImage, roomType: String, keywords: [String]) async throws -> GenerationJob {
    let url = URL(string: "\(AppConfig.baseURL)/dream-weaver")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"

    let boundary = UUID().uuidString
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    var body = Data()
    
    // 1. Image
    let imageData = image.jpegData(compressionQuality: 0.85)!
    body.appendMultipartForm(boundary: boundary, name: "image", filename: "room.jpg", contentType: "image/jpeg", data: imageData)

    // 2. Room Type
    body.appendMultipartForm(boundary: boundary, name: "room_type", value: roomType)

    // 3. Keywords
    let kwString = keywords.joined(separator: ", ")
    body.appendMultipartForm(boundary: boundary, name: "keywords", value: kwString)

    body.append("--\(boundary)--\r\n".data(using: .utf8)!)
    request.httpBody = body

    let (data, _) = try await URLSession.shared.data(for: request)
    return try JSONDecoder().decode(GenerationJob.self, from: data)
}

// Helper extension for building multipart forms cleanly
extension Data {
    mutating func appendMultipartForm(boundary: String, name: String, value: String) {
        self.append("--\(boundary)\r\n".data(using: .utf8)!)
        self.append("Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n".data(using: .utf8)!)
        self.append("\(value)\r\n".data(using: .utf8)!)
    }
    
    mutating func appendMultipartForm(boundary: String, name: String, filename: String, contentType: String, data: Data) {
        self.append("--\(boundary)\r\n".data(using: .utf8)!)
        self.append("Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(filename)\"\r\n".data(using: .utf8)!)
        self.append("Content-Type: \(contentType)\r\n\r\n".data(using: .utf8)!)
        self.append(data)
        self.append("\r\n".data(using: .utf8)!)
    }
}

6. Sayan's Action Checklist (v2)

  • Change AppConfig.baseURL port to 8082 (e.g., http://54.172.172.2:8082).
  • Add a UI element for the user to select the Room Type (bedroom, living_room, bathroom, etc.).
  • Change the POST /dream-weaver payload from {style} to {keywords, room_type}.
  • (Optional) Use the new GET /dream-weaver/expand endpoint to let the user preview and edit the AI-generated prompt before generating.