Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

apiad/typus

Repository files navigation

Typus (typus-dsl)

Strict typing for loose models.

PyPI - Version PyPi - Python Version Github - Open Issues PyPi - Downloads (Monthly) Github - Commits

Typus is a Python library for Grammar Constrained Decoding (GCD).

Large Language Models (LLMs) are powerful but chaotic. They hallucinate invalid syntax, invent non-existent functions, and break JSON formatting. Typus solves this by generating strict Context-Free Grammars (CFGs) that constrain the LLM's token generation process.

Instead of writing complex EBNF strings by hand, you use a Pythonic Interface to define your constraintsβ€”from simple regex patterns to entire semantic domains.

🌟 Why Typus?

  • 🚫 No More Hallucinations: Force the LLM to output exactly what you need (valid JSON, SQL, Python, or CSV).
  • 🐍 Python-First: Define grammars using standard Python operators (|, +) and types (dataclasses, int, str).
  • 🧩 Universal: Define your grammar once and compile it for any target:
    • Llama.cpp / GGUF: Compiles to GBNF.
    • Validators: Compiles to Regex.
    • Parsers: Compiles to Lark (EBNF).
  • 🧠 Cognitive Control: Use Templates to force "Chain of Thought" reasoning before actions.

πŸ“¦ Installation

pip install typus-dsl
# or with uv
uv add typus-dsl

πŸ— The Stack: From Low-Level to High-Level

Typus offers three layers of abstraction depending on your needs.

1. The Grammar DSL (Low Level)

For when you need pixel-perfect control over every character.

Use standard Python operators to define rules.

from typus import Grammar
g = Grammar()
# Define primitives
g.digit = g.regex(r"[0-9]")
g.number = g.digit + g.maybe("." + g.some(g.digit))
# Define structure
g.coordinate = "(" + g.number + ", " + g.number + ")"
g.root = "Point: " + g.coordinate

2. Templates (Mid Level)

For when you want to structure the LLM's thought process.

Mix static prompts with dynamic grammar constraints using Python f-string syntax.

# Force the model to think before it answers
g.root = g.template(
 "Thought: {thought}\nAction: {action}",
 thought=g.some(g.regex(r"[^\n]+"), sep="\n"),
 action="SEARCH" | "CALCULATE"
)

3. The Domain Engine (High Level)

For when you want to project a "Problem Domain" into a target language.

Define your types and functions in Python, and Typus generates the grammar that enforces them in JSON, SQL, HTML, or Python.

# Define the domain once
@dataclass
class User: ...
# Generate a JSON Schema grammar
Json().build(Domain(User))
# Generate a SQL Query grammar
SQLQuery().build(Domain(User))

⚑ Use Cases & Examples

Use Case 1: Semantic Versioning (Regex Validation)

Ensure the model generates valid SemVer strings like v1.0.2 or v2.10.0-rc1.

from typus import Grammar
g = Grammar()
g.digits = g.regex(r"(0|[1-9][0-9]*)")
g.version = g.digits + "." + g.digits + "." + g.digits
g.tag = g.maybe("-" + g.regex(r"[0-9a-z-]+"))
g.root = "v" + g.version + g.tag
print(g.compile("gbnf"))

Use Case 2: Structured Reasoning (Templates)

Force an Agent to provide a reasoning trace before emitting a final JSON answer. This prevents "blind" answering.

from typus import Grammar
g = Grammar()
g.thought = g.some(g.regex(r"[^\n]+"), sep="\n")
g.json_blob = g.regex(r"\{.*\}") # Simplified JSON regex
# The template constrains the structure
g.root = g.template(
 "Reasoning:\n{steps}\n\nFinal Answer:\n{result}",
 steps=g.thought,
 result=g.json_blob
)

Use Case 3: Type-Safe JSON Generation (Domain + JSON)

Define your data schema using Pydantic or Dataclasses, and get a grammar that guarantees the output matches that schema.

from dataclasses import dataclass
from typing import List
from typus.languages import Json
@dataclass
class Product:
 id: int
 name: str
 tags: List[str]
# Generate a strict GBNF grammar for this schema
# The LLM cannot miss a comma, quote, or bracket.
g = Json().build(Product)
print(g.compile("gbnf"))

Use Case 4: Safe SQL Querying (Domain + SQL)

Expose a specific set of "Allowed Queries" to the LLM. The grammar ensures the model can only generate valid SELECT statements for your specific table columns, preventing SQL Injection and hallucinations.

from typus import Grammar, Domain
from typus.languages import SQLQuery
# 1. Define the Schema
@dataclass
class Users:
 name: str
 age: int
# 2. Define allowed access patterns
def get_users_by_name(name: str) -> Users: ...
def get_users_by_age(min_age: int) -> Users: ...
# 3. Build the Grammar
# The LLM can generate: "SELECT name, age FROM Users WHERE name = '...'"
# It CANNOT generate: "DROP TABLE Users"
g = SQLQuery().build(
 Domain(Users, entrypoints=[get_users_by_name, get_users_by_age])
)

πŸ”§ Supported Backends

Typus is compiler-agnostic. You build the AST once, and export it to:

Backend Command Use Case
GBNF g.compile("gbnf") Llama.cpp, llama-python, local GGUF models.
Regex g.compile("regex", max_depth=3) Guidance, Outlines, Standard API validators. Supports bounded recursion.
Lark g.compile("lark") Python Parsing. Use Typus to parse the string the LLM just generated.
JSON Schema (Via Json language) OpenAI / Anthropic structured output APIs.

πŸ›£ Roadmap

  • v0.1: Core DSL (Sequence, Choice, Regex), GBNF Compiler.
  • v0.2: Templates (g.template), Regex Compiler with unrolling.
  • v0.3: Lark Compiler (Round-trip parsing).
  • v0.4: The Domain Engine (typus.domain reflection).
  • v0.5: Language Strategies (Json, SQLQuery, Markdown, Python).

πŸ“„ License

MIT License. See LICENSE for details.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

No packages published

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /