Savanty
Open source (MIT) · Skelf Research

Describe it in English.
Solve it with a guarantee.

Savanty is a natural-language to constraint solver. An LLM translates your problem into Answer Set Programming; the Clingo solver searches exhaustively for a valid answer set — or proves none exists. Not a guess: a proof.

$ pip install savanty
savanty — graph colouring
1 · English in
Colour 3 regions with 3 colours so no two adjacent regions share a colour.
↓  LLM translates
2 · Generated ASP
node(n1). node(n2). node(n3).
1 { assign(N,c1); assign(N,c2); assign(N,c3) } 1 :- node(N).
:- assign(n1,C), assign(n2,C).
:- assign(n2,C), assign(n3,C).
↓  Clingo solves
3 · Answer set (guaranteed)
assign(n1,c1)  assign(n2,c2)  assign(n3,c1)  SATISFIABLE

What is Savanty?

Savanty is an open-source Python package and FastAPI service that turns a plain-English description of a discrete constraint problem into a solved answer — by putting an LLM where LLMs are good (translation) and a solver where solvers are good (search), with a typed feedback loop between them.

The LLM

Translates English → ASP

A DSPy-orchestrated model (GPT-4o by default, or any OpenAI-compatible endpoint including Ollama Cloud) emits facts, choice rules, and integrity constraints over a canonical assign(Var, Value) contract. That is a language task, and LLMs do it well.

Clingo

Searches, soundly

Answer Set Programming is sound and complete over finite domains. If Clingo returns a model, every integrity constraint holds. If it returns UNSAT, no valid assignment exists. The guarantee lives here.

The loop

Repairs, with typed cores

When the solver rejects the program, Savanty classifies the failure and — on UNSAT — computes a minimal unsatisfiable core so the LLM revises exactly the constraints that conflict, instead of re-reading a raw error.

Read the full pipeline on how it works, or the honest scope on the FAQ.

The problems Savanty solves

Use each tool for what it is good at. English in, a guaranteed answer set out.

LLMs hallucinate solutions

The problem

Ask a model to schedule four nurses and it returns a plausible table. Plausible is not valid — nothing proved the schedule satisfies every constraint.

Savanty's approach

Savanty never lets the LLM answer. The LLM only translates; Clingo produces the assignment, and a returned assignment satisfies every integrity constraint by construction.

Why LLMs alone fail →

Solvers do not read English

The problem

ASP and CP-SAT are formal languages. Stakeholders do not type them, and hiring an OR modeller for a one-off scheduling question is expensive.

Savanty's approach

The LLM front-end does the "OR consultant" work automatically: picking the relation, the choice rule, and the integrity constraints that encode your policy.

The translation step →

Translation breaks silently

The problem

A mis-formalized constraint yields a wrong-but-consistent answer, or an UNSAT you cannot diagnose. The failure hides until someone checks by hand.

Savanty's approach

A typed self-repair loop classifies each failure and, on UNSAT, extracts a minimal unsatisfiable core so the exact conflicting constraints get revised — or infeasibility is reported faithfully.

Reading an unsat core →

Not every problem fits a solver

The problem

Point a constraint solver at a continuous or statistical problem and you get nonsense. Most tools try anyway.

Savanty's approach

The first LLM call is a suitability check. If your problem is continuous, statistical, or streaming, Savanty returns a suggested_tool (scipy, cvxpy, sklearn, pandas) and stops.

What Savanty is not for →

One canonical contract. Every decision is assign(Var, Value).

Requirements become integrity constraints (rules starting with :-). That uniform encoding is what makes the unsat-core repair loop possible — the solver reasons about your constraints.

1 English problem
Schedule 4 nurses (Alice, Bob, Carol, Dave) across morning / evening shifts over 3 days. Each shift needs exactly 1 nurse. No nurse works two shifts on the same day.
2 Generated ASP
% domains
nurse(alice; bob; carol; dave).
slot(d1_am; d1_pm; d2_am; d2_pm; d3_am; d3_pm).

% exactly one nurse per slot
1 { assign(S, N) : nurse(N) } 1 :- slot(S).

% no nurse works both shifts of a day
:- assign(d1_am, N), assign(d1_pm, N).
:- assign(d2_am, N), assign(d2_pm, N).
:- assign(d3_am, N), assign(d3_pm, N).

% harness appends automatically
#show assign/2.
3 Clingo answer set
assign(d1_am, alice) assign(d1_pm, bob) assign(d2_am, carol) assign(d2_pm, dave) assign(d3_am, bob) assign(d3_pm, alice) SATISFIABLE — every constraint holds

The generated encoding is returned as result.asp_code next to the solution, so you can audit it.

Translate, solve, repair

A small pipeline with a clear division of labour. Every part is inspectable.

Discrete constraint satisfaction. That is the whole job.

The suitability check is the first thing Savanty runs. If your problem does not fit ASP, it says so — honestly.

Good fit

  • Shift scheduling, rostering, timetabling
  • Task and resource assignment
  • Seating, team formation, allocation
  • Route planning over a small graph
  • Logic puzzles, graph colouring, n-queens

Wrong tool — Savanty redirects you

  • Continuous optimization cvxpy / scipy
  • Statistical / ML modelling sklearn / pytorch
  • Data analysis over large tables pandas
  • Simulation or streaming data
  • Pure arithmetic a calculator
Sound & complete
over finite domains (Clingo / ASP)
3
typed repair modes: syntax_error, unsat, empty
1
canonical relation — assign(Var, Value)
MIT
open source, on PyPI and GitHub

Bring us a problem you can describe but can't reliably solve

Savanty is open source (MIT). Install it from PyPI, describe your problem in English, and get a guaranteed answer set — or a faithful proof that none exists.

Part of Skelf Research

Savanty is one of Skelf Research's narrowly-scoped, open tools.

Explore Skelf Research →