About Creative Storyteller 🖋️✨

🕯️ Inspiration

The "Creative Storyteller" was born from a simple question: What if the stories we read could illustrate themselves in real-time? We wanted to move beyond static chatbots and create an experience that feels like a living, breathing editorial. Inspired by the nostalgia of classic adventure books and the raw power of Gemini 2.0 Flash, we aimed to build a system that doesn't just "answer" but "creates."

🏗️ How We Built It

The project is built on a modern, high-concurrency stack designed for seamless streaming:

  • The Brain (Gemini 2.0 Flash): We utilized system instructions to turn Gemini into a "Creative Director" that interleaves narrative text with visual markers.
  • The Artist (Imagen 3): Using imagegeneration@006 via Vertex AI, we generate high-quality cinematic illustrations based on prompts extracted dynamically from the story stream.
  • The Pipeline (FastAPI & SSE): We implemented a custom Server-Sent Events (SSE) manager. Instead of waiting for a full story or using separate polls, we use a unified stream:
    • Text chunks are streamed immediately for the "typewriter" effect.
    • Image markers trigger background workers that fetch illustrations without blocking the narrative flow.
  • The Interface: A "Noir-Editorial" UI built with vanilla HTML/CSS/JS for maximum performance and a premium, book-like aesthetic.

📐 Mathematical Foundation

To ensure the "typewriter" effect feels natural, we use a rhythm-based delay function. Instead of a linear delay, many characters follow a probability distribution to mimic human reading speeds. If $D$ is the base delay and $L$ is the length of the pending buffer, the catch-up delay $d$ is approximated by:

$$d = \begin{cases} D & \text{if } L < 200 \ \frac{D}{k} & \text{if } L \ge 200 \end{cases}$$

where $k$ is a catch-up coefficient (set to 3.6 in our implementation) to ensure the UI stays synchronized with the deep-learning model's high-throughput output.

🧠 What We Learned

  • Prompt Engineering as Architecture: We learned that Gemini 2.0 Flash is exceptionally good at following complex output rules (like markers) without sacrificing creative writing quality.
  • Concurrency is Key: Handling multiple async generators (text + images) taught us a lot about Python's asyncio and how to prevent "head-of-line blocking" in real-time streams.
  • UX of AI: We discovered that "shimmer" placeholders are vital. Letting the user see what is being drawn before it appears reduces perceived latency and increases engagement.

⚖️ Challenges We Faced

  • The Marker Split Problem: Sometimes a streaming chunk would end in the middle of a marker (e.g., [IMAG). We had to implement a robust buffer-and-regex parser to ensure markers are only processed when complete, preventing broken syntax from leaking into the UI.
  • Resource Management: Managing concurrent image generations (each taking 5-8 seconds) alongside a sub-second text stream required careful balancing of asyncio.Semaphore to stay within Vertex AI quotas.
  • State Synchronization: Correlating which image belongs to which part of the story in a stateless HTTP environment was solved by using a unique event ID system within the SSE protocol.

Creative Storyteller isn't just an app; it's a peek into the future of interactive entertainment.

Built With

  • docker
  • fastapi
  • gemini-2.0-flash
  • google-artifact-registry
  • google-cloud-build
  • google-cloud-platform-(gcp)
  • google-cloud-run
  • google-vertex-ai
  • imagen-3-(imagegeneration@006)
  • typewriter.js-logic
  • uvicorn
  • vanilla-html5/css3/javascript
Share this project:

Updates

Submission history