How Does LMQL Differ from Writing Plain Prompts for LLMs?

Updated

LMQL treats prompting as a program rather than a string. Instead of assembling one long prompt and hoping the model follows it, you write a Python function decorated with @lmql.query, put the prompt in top-level strings, mark generated text with bracketed variables like [ANSWER], and attach a where clause that the runtime enforces as a hard constraint. The result is returned to Python as an ordinary value. This matters most when you need guaranteed output format, bounded length, or reusable prompt components; for a one-off question where any reasonable answer will do, a plain prompt is simpler.

The core shift: prompts become functions with constraints

The site's front-page example shows the whole pattern:

@lmql.query
def meaning_of_life():
    '''lmql
    "Q: What is the answer to life, the universe and everything?"
    "A: [ANSWER]"
    where len(ANSWER) < 120 and STOPS_AT(ANSWER, ".")
    print("LLM returned", ANSWER)

    "The answer is [NUM: int]"
    return NUM
    '''

Three things are happening that a plain prompt cannot express:

  • Top-level strings are the prompt. Each string literal is appended to the context the model sees, so multi-part prompts are built by writing several strings in sequence.
  • Bracketed variables are generation sites. [ANSWER] is where the model writes; [NUM: int] additionally declares a type, so the runtime constrains decoding to an integer.
  • where is enforced, not requested. len(ANSWER) < 120 and STOPS_AT(ANSWER, ".") are hard constraints applied by the optimizing runtime during generation, not instructions the model may ignore.

The function then returns NUM directly, so the caller gets 42 rather than a paragraph to parse.

What plain prompting cannot do

Need Plain prompt LMQL
Output format guarantee Ask politely; validate and retry afterward Type and regex constraints in where
Length limit State it in the prompt; truncate after len(...) constraint enforced at decode time
Stop condition Hope the model stops STOPS_AT(...)
Reuse across calls Copy-paste and edit strings Functions, loops, nested queries
Switching model provider Rewrite integration code One line, per the site's backend list

The site names the supported backends as llama.cpp, OpenAI, and Hugging Face Transformers, and states that code is portable across them with a single line change.

Control flow replaces prompt templates

Because the query body is Python, repetition and composition are ordinary code. The packing-list example on the site loops four times, emitting - [THING]\n each iteration with where THING in ["Volleyball", "Sunscreen", ...], so each generated item is restricted to the allowed set. In a plain-prompt workflow this becomes a long enumerated instruction plus post-hoc filtering.

The site also highlights nested queries, described as bringing procedural programming to prompting: modular local instructions and reuse of prompt components. Its execution-trace demo shows a dateformat instruction applied to three separate questions, then a follow-up question — the kind of structure that is fragile when flattened into one prompt.

Where the difference actually shows up

Consider a task like extracting a date from free text in a fixed format. With a plain prompt you write "respond in DD/MM/YYYY", then check the output and retry on failure. With LMQL you constrain the variable and the runtime handles it during decoding. The site's own demo uses exactly this pattern across multiple questions before asking a comparative follow-up.

The trade-off is real: LMQL asks you to learn its syntax and run its runtime, and the constraints only pay off when output shape matters. For exploratory chatting or single free-form answers, the overhead is not justified.

Getting oriented

The site points to Get Started, Docs, a Playground, and a GitHub repository, and notes LMQL was created by the SRI Lab at ETH Zurich with contributors. The Playground is the lowest-commitment way to test whether constrained generation fits your task before wiring the runtime into an application.