Clayton BorgesDESENVOLVEDOR
← ← All Projects

EKO – Mystical AI Chatbot & Environmental Narrative Game

2025
AI Application / Narrative Game

Two-phase AI project developed within EKO – Residência Artística, funded by FAC – Fundo de Apoio à Cultura do Distrito Federal (GDF). A deployed mystical chatbot (Python + Streamlit + local Ollama) where users consult EKO — a sarcastic, timeless oracular entity — with full 78-card Tarot reading support; and Ekonsulta, a satirical narrative game that profiles players' environmental behavior across 50 dilemmas into 6 behavioral archetypes, using hidden scoring to prevent gaming the result.

Media
EKO – Mystical AI Chatbot & Environmental Narrative Game 1
EKO – Mystical AI Chatbot & Environmental Narrative Game 2
Overview

EKO is a two-phase AI project built by Clayton Borges and Raphael Palmer as part of EKO – Residência Artística, a cultural residency funded by FAC – Fundo de Apoio à Cultura do Distrito Federal, Secretaria de Cultura e Economia Criativa / GDF. The residency brought together artists, technologists, and environmental institutions — including ICMBio/Parque Nacional de Brasília, SesiLab, Ateliê Ecoarte, and Centro Tradicional de Invenção Cultural — to explore the intersection of AI, ecology, and culture in Brasília. Phase 1 is a production chatbot: users interact with EKO — a mystical, sarcastic oracular character — via a Streamlit web UI styled with a full-bleed mystical aesthetic. EKO answers questions, detects topic categories to shift tone, and draws from a full 78-card Tarot deck when requested. The LLM is a local Ollama instance (llama3.1:8b), with no external API keys. Phase 2 is Ekonsulta, a satirical narrative game about environmental behavior: players make binary choices across 50 dilemmas spanning food, fashion, transportation, water, and technology. Hidden scoring maps each choice to one of 6 behavioral archetypes — EKO delivers the final verdict with sarcastic precision.

Problem

Environmental awareness campaigns typically address users didactically — presenting facts and expecting behavioral change. This approach fails to reach people who already know what they should do but don't act on it. Ekonsulta targets a specific audience: people who engage in 'green performance' — virtue signaling about sustainability while their actual choices contradict their stated values. Sarcasm and uncomfortable self-recognition are more effective tools than information for this audience.

Goal

Phase 1: deploy a production-quality AI chatbot with a strong character persona, full Tarot support, and reliable connectivity to a self-hosted LLM despite VPN routing challenges. Phase 2: design and prototype a narrative game with 50 deep-researched dilemmas, 6 behavioral archetypes, and a hidden scoring system that prevents players from optimizing toward a desired outcome.

My Role
  • ◈Clayton Borges — UI, mobile optimization, context/persona tuning, project ownership
  • ◈Raphael Palmer — VPN bypass engineering, Ollama server integration, core backend logic
Stack
PythonStreamlitOllamallama3.1:8bTinyDBDockerngrokCloudflare TunnelReact 19TypeScriptVite
Technical Decisions
  1. 01No cloud LLM dependency — the entire system runs on a self-hosted Ollama instance (llama3.1:8b). No OpenAI/Anthropic API keys, no per-token costs, no user data leaving the infrastructure. Chosen for cost control and privacy; the tradeoff is that inference speed depends on local hardware.
  2. 02DNS monkey-patching in production code — socket.getaddrinfo is replaced at module load time to force 'localhost' → '127.0.0.1'. This is a production workaround for VPN DNS interception that prevented the app from resolving localhost to the loopback interface in the deployment environment.
  3. 03Dual tunnel strategy — the Docker image bundles ngrok for container deployments (starts ngrok inside the container to create a public tunnel to host.docker.internal:11434). The local dev script uses Cloudflare Tunnel as an alternative public endpoint. Multiple topologies were tested to find reliable connectivity through VPN.
  4. 04Two separate prompt paths — tarot requests use a short, focused prompt for card interpretation. Conversation requests use the full EKO persona context + conversation history window + tone instruction injected based on topic category detection (astrology keywords → cosmic tone; greetings → welcome tone).
  5. 05Response post-processing pipeline — the LLM (especially llama3.1:8b) tends to include <think> tags, EKO self-references, internal monologue, and leaked card names outside of tarot mode. The separate_thinking_and_response() function strips all of this with targeted regex patterns.
  6. 06Session isolation via UUID in TinyDB — each browser session gets a UUID stored in st.session_state; all DB queries are scoped to that UUID, enabling concurrent multi-user usage on a single TinyDB JSON file without cross-session contamination.
  7. 07Hidden scoring system in Ekonsulta — the game deliberately hides all point accumulation from the player. Each of the 50 dilemma choices secretly increments weights for one or more of 6 behavioral archetypes. The design philosophy: players should not be able to 'optimize' toward a desired archetype — the verdict should feel revelatory.
  8. 0850 deep-researched dilemmas across 5 themes — each theme (food, fashion, cars, water, technology) has a dedicated research document backing the scenario writing. Scenarios were designed to avoid obvious 'right answers,' forcing players to confront genuine tensions between convenience, cost, and environmental impact.
What I Learned
  • →Persona engineering for a local LLM requires significantly more iteration than for cloud models — llama3.1:8b at temperature 0.9 is creative but inconsistent, requiring an explicit response post-processing layer to enforce character consistency that a larger model would maintain on its own.
  • →The VPN connectivity problem produced the most creative engineering in the project: DNS monkey-patching, dual tunnel strategies, and prefer-127.0.0.1-over-localhost are each unusual solutions that worked precisely because we diagnosed the root cause (DNS interception) rather than treating symptoms.
  • →Hidden scoring is a game design decision, not just a technical one — making scores visible during the Ekonsulta flow would let players reverse-engineer the archetypes and pick answers strategically, completely defeating the game's purpose. The reveal-at-the-end structure is essential to the satirical effect.
  • →TinyDB (JSON file database) is adequate for a Streamlit prototype with low concurrent usage but would not scale to multi-user production deployment — the single-file structure creates write contention under any meaningful concurrency.
  • →Building a chatbot persona requires both system prompt engineering and output post-processing — the prompt defines how the model should respond, but a post-processing layer is needed to catch the cases where the model breaks character, especially for smaller models with less instruction-following reliability.
Status

Phase 1 deployed — Phase 2 (Ekonsulta) prototype complete, full game in design