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@006via 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
asyncioand 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.Semaphoreto 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
Log in or sign up for Devpost to join the conversation.