AI Parser
ShowParser converts a natural language description directly into a Show object using a local language model via Ollama. No exec() is involved — the model returns structured JSON that flaight safely converts into drone actions.
Two modes
| Mode | What you provide | What the model does |
|---|---|---|
Direct (parse) |
Explicit choreography instructions | Follows them literally — no added creativity |
Thematic (parse_thematic) |
A theme, mood, or emotion | Freely designs formations, movement, and a colour palette to express it |
Setup
from flaight import ShowParser
parser = ShowParser(
host="http://localhost:11434", # Ollama server URL
model="llama3.2", # model name
)
Mode 1 — direct choreography
Describe exactly what the drones should do.
from flaight import DryRunRunner, ShowParser
parser = ShowParser(host="http://localhost:11434", model="llama3.2")
show = parser.parse(
"Two drones take off, fly apart to opposite sides, alternate red and blue, then land.",
uris=["radio://0/80/2M/E7E7E7E701", "radio://0/80/2M/E7E7E7E702"],
)
DryRunRunner(show).run()
The model follows instructions literally. If you don't mention flying, no Takeoff/Land actions are generated — only color actions.
Mode 2 — thematic / emotional
Provide a theme or feeling. The model acts as a creative choreographer and designs the entire show.
show = parser.parse_thematic(
"Melancholy — a lone farewell slowly fading into darkness.",
uris=["radio://0/80/2M/E7E7E7E701", "radio://0/80/2M/E7E7E7E702",
"radio://0/80/2M/E7E7E7E703"],
)
DryRunRunner(show, realtime=True).run()
Thematic prompts in any language work:
"Euphoria — an explosion of energy and colour""Aufbruch — ein Neuanfang voller Hoffnung""A thunderstorm building and breaking""Sunrise over the mountains""Tense standoff, then sudden release"
Preview before generating
Ask the model for a plain-text summary first — useful to check that it understood the description before committing to a full generation:
# Mode 1 — summarizes the explicit instructions
summary = parser.summarize(description, uris=uris)
# Mode 2 — describes the creative concept the model would build
summary = parser.summarize_thematic(description, uris=uris)
print(summary)
Interactive REPL
run_interactive runs a loop: describe → confirm summary → generate → simulate or fly → repeat.
parser.run_interactive(
uris=["radio://0/80/2M/E7E7E7E701", "radio://0/80/2M/E7E7E7E702"],
fly=False, # True → real hardware instead of dry-run
realtime=True,
)
Tip
The same loop is available from the command line via flaight — no Python script needed. See CLI — flaight.
For a self-contained code example of both modes without the REPL, see examples/ai_show.py.
Saving generated shows
Any AI-generated show can be exported as a standalone Python script:
See Exporting for details.
Error handling
from flaight import ParseError
try:
show = parser.parse(description, uris=uris)
except ParseError as exc:
print(f"Could not parse show: {exc}")
ParseError is raised when the model returns invalid JSON or a response that cannot be mapped to flaight actions (e.g. because the model timed out or returned an unexpected format).