A control layer for LLM-in-the-loop reliability: wrap an unreliable generator in a verify-and-refuse feedback loop with a pluggable controller (deterministic checks, a model critic, or compositions) and composable 'circuits'. Keep one exact element in the loop and outputs are checked, corrected, or honestly refused. Zero runtime dependencies; runs with no model at all.
Project description
LLM Feedback Control
A control layer for LLM-in-the-loop reliability: wrap an unreliable generator in a verify-and-refuse feedback loop, so what comes out is checked, corrected, or honestly refused — never a confident guess.
What it does
Language models are fluent but they make things up — and they sound just as sure when they're wrong. The moment an LLM's output feeds a decision that has to be right — a form parsed, a process mapped, a config validated, one model's answer judged by another — "usually correct, and never tells you when it isn't" becomes a real problem.
LLM Feedback Control borrows the fix from control engineering: don't try to make the generator cleverer, close a loop around it. You pair the model with a reference — something that can check its output — and the loop:
- verifies the answer against that reference,
- fills in / corrects what's wrong by re-asking with the specific gaps pointed out,
- refuses — says "I can't vouch for this" — when it can't verify the result, instead of guessing.
The controller seat is pluggable. The reference can be deterministic code (a schema, graph checks — an exact guarantee), a low-power model acting as a critic (for fuzzy quality no rule captures), or a composition of several — and the feedback blocks wire into "circuits": a summing junction, an instrumentation amp (independent critics, common-mode rejection), a multi-stage cascade, a hysteresis gate. One rule holds it together: keep at least one exact element in the loop.
Because the loop does the work — not the model's size — a small model you run for free on a laptop becomes reliable enough to use in earnest: in our tests a 3.8B model inside the loop matched one about seven times larger. That is now a proof point, not the whole story.
Use cases
| If you need to… | Use | Circuit |
|---|---|---|
| Turn a process described in prose into a verified state machine (dead ends, unreachable steps, loops) | run_audit |
— |
| Pull form fields from a document, each checked against the source, refusing on a missing required field | extract_form |
— |
| Extract your own structure (records, entities, configs) with a schema and a check you supply | feedback_loop |
— |
| Get trustworthy output from a small / local model instead of paying for a large one | any target — the loop does the work | closed loop |
| Decide whether a task is exactly checkable at all, and refuse the fuzzy ones | regime_gate |
comparator |
| Catch fuzzy quality no rule expresses (relevance, coherence, "did it answer the question?") | llm_critic_reference + llm_critic_repair |
model controller |
| Keep an exact guarantee but add a critic's breadth on top | combine_references |
summing junction |
| Avoid a single critic's false alarms / same-model rubber-stamping | quorum_reference (independent critics) |
instrumentation amp |
| Run a multi-step pipeline (extract → normalise → enrich), each step checked, stopping if one can't be trusted | cascade / loop_stage |
multi-stage amp |
| Stop a borderline accept/refuse decision from flip-flopping run to run | schmitt_gate |
Schmitt trigger |
The rows below the line are covered in Controllers and circuits; the first three are the built-in targets, detailed next.
What you can extract
It's one engine pointed at different targets. A target is anything you can pair with a schema and a deterministic check — two ship today, more are a small addition (the loop is public and injectable):
- workflows / processes → state machines (
run_audit) — states, transitions, dead ends, unreachable steps, loops; - form fields (invoices, applications, claims) against a field schema
(
extract_form) — verifies each value against the source, recovers ones the model hallucinated, refuses on missing required fields; - records / tables, entities & relations, configs / specs — bring a
schema + a reference and call
feedback_loop.
It helps on the structured, verifiable slice — where a deterministic reference exists. For open-ended generation (summaries, sentiment) there's nothing to check against, so it refuses to claim exactness, by design.
Beyond the built-in targets, the controller seat is pluggable and the feedback blocks compose into circuits — see Controllers and circuits.
Documentation
The full user manual is in docs/:
| chapter | contents |
|---|---|
| Getting started | install, the API, the lfc CLI, choosing/bringing a model, configuration |
| How it works | the op-amp model: negative/positive feedback, refusal-as-stabilizer, the general engine |
| API reference | every public function |
| Results | measured numbers, method, honest scope |
| Worked examples | actual run transcripts |
| FAQ | GPU? models? offline? why did it refuse? |
| Controllers and circuits | a model in the controller seat; combining independent critics; the op-amp "circuits" (summing junction, instrumentation amp, cascade, hysteresis gate) |
| Changelog | release history |
Install
pip install llm-feedback-control # zero dependencies
Then follow Getting started. The deterministic parts run with no model at all; a model (local Ollama, OpenAI, or your own callable) is a pure upgrade.
License
MIT with an attribution clause — see LICENSE.
Built with llm-feedback-control by Edward Chalk (sapientronic.ai).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llm_feedback_control-0.3.0.tar.gz.
File metadata
- Download URL: llm_feedback_control-0.3.0.tar.gz
- Upload date:
- Size: 41.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52fde108d1bba1b9815522896f518547f1b63306a40da68fbdc2a9557f3b0a96
|
|
| MD5 |
df556494faeb4506407c35af3da7a760
|
|
| BLAKE2b-256 |
75bb27d93ed9d4f455f3857c22afe5c54a3331c687dceb7bbcfc597ae5384dac
|
File details
Details for the file llm_feedback_control-0.3.0-py3-none-any.whl.
File metadata
- Download URL: llm_feedback_control-0.3.0-py3-none-any.whl
- Upload date:
- Size: 37.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
45f9ba7d98755646f128a811d8ec68eb9671c0a9fd1c24aaf8de194c7a979486
|
|
| MD5 |
9997cecf79684c29a67b3c52b65a3d82
|
|
| BLAKE2b-256 |
8a10cd3c8d67708e75b1d4fc9df85d4dba361c130736534ab40ed4877a51e8eb
|