Spaces:
Sleeping
title: Sidechat
emoji: π¬
colorFrom: yellow
colorTo: purple
sdk: gradio
sdk_version: 6.18.0
app_file: app.py
pinned: false
license: apache-2.0
short_description: Completely normal text assistant, with talking on the side
tags:
- track:wood
- sponsor:openbmb
- achievement:offgrid
- achievement:sharing
- achievement:fieldnotes
Side chat
A Gradio port of the browser steganacrostics app. A completely normal text
assistant β except every line of the answer secretly starts with the next
letter of a hidden secret word (an acrostic). It does this with
grammar-constrained decoding over a small local model (openbmb/MiniCPM5-1B by
default; set SIDECHAT_MODEL=LiquidAI/LFM2.5-350M for the smaller, faster
original), running on CPU via PyTorch transformers.
What's ported from the JavaScript original (../../src/):
- Grammar engine (
grammar.py) β a tiny NFA that pins each line to its forced first letter, with optional*bullets and a max line length. - Constrained generation (
logits.py+masking.py) β aLogitsProcessorthat masks every token that would break the acrostic; EOS only at an accept state. A state-keyed cache makes the per-step vocab scan cheap. - List-vs-prose classifier (
classifier.py) β an optimized prompt, grammar-constrained tolist./story., that auto-picks the render mode. The prompt is tuned per model: failure modes are model-specific, soeval_classifier.py(50 list + 50 prose prompts) andsweep_minicpm.pyre-optimize it for whatever model is in use. - Local-crossing search (
crossing_search.py) β the "extra attention at the constraint": generate each prose line greedily, then choose where to break it so a short window straddling the crossing (last k tokens + forced letter + next j tokens) reads best. Plus stealth lowercase casing and a minimum line length.
Run locally:
pip install -r requirements.txt
python app.py
Then open the printed URL, type a prompt, set a secret in βοΈ Settings, and click Generate. The list-vs-prose classifier runs automatically on each Generate (turn it off in βοΈ Settings to set the render mode by hand, or use π Detect to preview it). Because everything runs on CPU, generation takes seconds (more for the larger model); the crossing search trades extra time for smoother prose.
The model is downloaded from the Hugging Face Hub on first run. Custom logits processing requires the model to run in-process, so this app does not use the remote Inference API.