Skip to main content

Add your description here

Project description

Typus (typus-dsl)

Strict typing for loose models.

Typus is a Python library for defining Context-Free Grammars (CFGs) programmatically and compiling them into generation constraints for Large Language Models (LLMs).

It solves the Backend Fragmentation problem. Define your grammar once in Python, and compile it to GBNF (for Llama.cpp), JSON Schema, or Regex.

🚀 Features

  • 🐍 Pythonic DSL: Define grammars using standard Python operators (+, |) and attribute access (g.rule).
  • 📝 Structured Templates: Use standard Python format strings ("Reason: {thought}") to define rigid prompt structures.
  • 🛡️ Type-Safe Core: A robust AST (Symbol, Terminal, Sequence) that prevents invalid states by construction.
  • ⚡ Regex Support: First-class support for Regular Expressions using g.regex().
  • 🏗️ High-Level Builders: Helpers like maybe(), some(), and any() that handle recursion automatically.
  • 🏷️ Deterministic Naming: Rules generated by helpers use stable, readable names (e.g., some_item) or explicit names you provide.
  • ⚙️ GBNF Backend: Out-of-the-box support for llama.cpp grammars.
  • 🔌 Plugin Architecture: Easily register custom backends without modifying the core.

📦 Installation

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

⚡ Quick Start

1. Basic: Semantic Versioning (SemVer)

Define a grammar to validate version strings like v1.0.2 or v2.10.0-rc1.

from typus import Grammar

g = Grammar()

# 1. Define atomic components with Regex
# "0" or "1-9" followed by digits (no leading zeros allowed)
g.digits = g.regex(r"(0|[1-9][0-9]*)")

# 2. Structure the version core: X.Y.Z
g.version_core = g.digits + "." + g.digits + "." + g.digits

# 3. Handle optional pre-release tag (e.g. "-alpha", "-rc1")
# maybe(x) -> x | ε
g.prerelease = g.maybe("-" + g.regex(r"[0-9A-Za-z-]+"))

# 4. Assemble the root rule
g.root = "v" + g.version_core + g.prerelease

print(g.compile("gbnf"))

2. Intermediate: Reasoning & Action (Templates)

Force the LLM to follow a strict "Chain of Thought" structure using g.template().

from typus import Grammar

g = Grammar()

# 1. Define the dynamic components
g.thought = g.some(g.regex(r"[^\n]+"), sep="\n")  # One or more lines of text
g.action  = "SEARCH" | "CALCULATE" | "FINISH"
g.query   = '"' + g.regex(r"[^\"]+") + '"'

# 2. Use a Template to structure the interaction
# This mixes static text prompts with grammar rules ({thought}, {action}, {query})
g.root = g.template(
    "Thought: {thought}\n"
    "Action: {action}({query})",
    thought=g.thought,
    action=g.action,
    query=g.query
)

print(g.compile("gbnf"))

Output (GBNF):

root ::= "Thought: " some_regex_sep_newline "\nAction: " action "(" query ")"
thought ::= some_regex_sep_newline
some_regex_sep_newline ::= [^\n]+ | [^\n]+ "\n" some_regex_sep_newline
action ::= ( "SEARCH" | "CALCULATE" | "FINISH" )
query ::= "\"" [^"]+ "\""

3. Advanced: Structured Function Calling

Define a grammar for an Agent tool call, like search_tool(query="foo", limit=5). This demonstrates recursion, lists, and explicit naming.

from typus import Grammar

g = Grammar()

# 1. Define primitives
g.identifier = g.regex(r"[a-zA-Z_][a-zA-Z0-9_]*")
g.string_lit = '"' + g.regex(r'[^"]*') + '"'
g.number_lit = g.regex(r"[0-9]+")

# 2. Define a generic "Value" (String or Number)
g.value = g.string_lit | g.number_lit

# 3. Define a named argument: name=value
g.arg = g.identifier + "=" + g.value

# 4. Define the Argument List
# any(x, sep) -> (x (sep x)*)?
# We explicitly name the recursive rule "args" for cleaner GBNF.
g.arg_list = g.any(g.arg, sep=", ", name="args")

# 5. Root: name(args)
g.root = g.identifier + "(" + g.arg_list + ")"

print(g.compile("gbnf"))

Output (GBNF):

root ::= [a-zA-Z_][a-zA-Z0-9_]* "(" ( args | "" ) ")"
identifier ::= [a-zA-Z_][a-zA-Z0-9_]*
value ::= ( string-lit | number-lit )
string-lit ::= "\"" [^"]* "\""
number-lit ::= [0-9]+
arg ::= identifier "=" value
args ::= arg | arg ", " args

🏗 Architecture

Typus follows a strict Layered Architecture to ensure security and flexibility.

Layer 1: The Core (typus.core)

The atomic units of the grammar. These are pure data structures.

  • Terminal: A string literal or regex.
  • Sequence (+): A + B. Optimized to flatten automatically ((A+B)+C -> A+B+C).
  • Choice (|): A | B.
  • Epsilon: The empty string ($\epsilon$).
  • NonTerminal: A reference to another rule (allowing recursion).

Layer 2: The Engine (typus.grammar)

The Grammar class manages the state. It handles:

  • Lazy Evaluation: You can use g.my_rule before defining it.
  • Recursion Management: Generates stable recursive rules for some() and any().
  • Template Parsing: Converts Python format strings into grammar sequences.
  • Backend Dispatch: Delegates compilation to registered visitors.

Layer 3: The Backends (typus.backends)

Typus is agnostic to the output format.

  • GBNF: Included by default. Handles escaping and rule naming conventions.
  • (Planned) JSON Schema: For OpenAI/Anthropic structured outputs.
  • (Planned) Lark: For validation and parsing.

🛣 Roadmap

  • v0.1: Core AST, Operators, GBNF Backend.
  • v0.2: Regex support (g.regex("[0-9]+")) & Templates.
  • v0.3: JSON Schema Backend.
  • v0.4: typus.domain (Python Type Reflection).
  • v0.5: typus.languages (Python, HTML, SQL Generators).

📄 License

MIT License. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typus_dsl-0.3.1.tar.gz (28.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typus_dsl-0.3.1-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file typus_dsl-0.3.1.tar.gz.

File metadata

  • Download URL: typus_dsl-0.3.1.tar.gz
  • Upload date:
  • Size: 28.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for typus_dsl-0.3.1.tar.gz
Algorithm Hash digest
SHA256 549c2047eb30fba24861f2e9c03e0196d08888950a6332364ac5b842986d9bc6
MD5 0f540d2bc842a3ff23e79ea7ddc4d263
BLAKE2b-256 bc7df7f637bf3daa8a52890a26673c9d5b748f4f5b8d2f41a398b2741d8d1755

See more details on using hashes here.

File details

Details for the file typus_dsl-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: typus_dsl-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for typus_dsl-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ce66fa15f3f94e214345cd40c0fd46e9e7c7166ee0ae424dee522429d8c81a66
MD5 5a5163223078205362b09eace52dccec
BLAKE2b-256 94b2b59ce089056648c60828bdad108c17ea98a03e274c6aa0cc2cf5aac09cee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page