Skip to main content

Runtime semiformal system: @semiformal and semi() for semantically underspecified logic

Project description

semipy

Write Python logic in natural language. semipy generates, validates, and caches real Python functions from your specs — no boilerplate, no hardcoded rules.

from semipy import semiformal, semi, configure

configure(openai_api_key="sk-...")  # or set OPENAI_API_KEY in environment

@semiformal
def parse_log_line(line: str) -> dict:
    #> extract timestamp, level, and message from an Apache log line
    result = ...
    return result

# First call: agent generates a Python function and caches it.
# All later calls: load the cached implementation instantly.
row = parse_log_line('127.0.0.1 - - [10/Oct/2000:13:55:36] "GET /index.html" 200')

Install

pip install semipy

For Jupyter notebook display:

pip install "semipy[jupyter]"

For PDF input materialization:

pip install "semipy[pdf]"

API key

semipy uses the OpenAI API for code generation. Set your key in one of three ways:

Environment variable (recommended for scripts):

export OPENAI_API_KEY=sk-...

.env file at the project root (loaded automatically):

OPENAI_API_KEY=sk-...

In code (overrides env):

from semipy import configure
configure(openai_api_key="sk-...")

Configuration

from semipy import configure

configure(
    openai_api_key="sk-...",       # defaults to OPENAI_API_KEY env var
    openai_model="gpt-4o",         # generation model (default: gpt-5.4)
    verbose=True,                  # rich terminal output during generation (default: True)
    cache_dir=".semiformal",       # where portal JSON and dispatch modules are stored
    max_retries=3,                 # agent retry limit on validation failure
    session_source=None,           # pin portal identity (useful for Jupyter; see below)
)

All fields are optional — call configure() with only what you want to override.

Terminal output

When verbose=True (the default), semipy prints a live Rich panel showing the agent's reasoning, tool calls, and generated code as they stream in. This works in both terminal and Jupyter.

 Implementing code...
 ─────────────────────────────────────────────────
  Reasoning  The function needs to parse a standard Apache
             Combined Log Format line...
 ─────────────────────────────────────────────────
  Tool  build_and_run_gist  passed
 ─────────────────────────────────────────────────
  Reusing cached implementation; runtime verify passed.
  parse_log_line  GENERATE  a1b2c3d4  examples/logs.py:12

To silence all output: configure(verbose=False).

To see full prompt, decision, and tool-call dumps, set the environment variable:

export SEMIPY_PIPELINE_TRACE=1

Usage patterns

@semiformal with #> spec blocks

from semipy import semiformal

@semiformal
def extract_fields(record: str) -> dict:
    #> extract date, sender, and subject from an email header
    result = ...
    return result

The #> block is the spec. The result = ... is the slot anchor — the agent fills it in.

Inline semi() for expressions

from semipy import semiformal, semi

@semiformal
def classify_rows(rows):
    return [r for r in rows if semi(f"is {repr(r['status'])} a client error?")]

Standalone semi() in any function

from semipy import semi

def process(text):
    label = semi(f"classify '{text}' as positive, negative, or neutral")
    return label

Multiple slots in one function

from semipy import semiformal

@semiformal
def analyze(entry: str) -> dict:
    #> extract the IP address from the log entry
    ip = ...

    #> determine if the HTTP status code in the entry indicates an error
    is_error = ...

    return {"ip": ip, "error": is_error}

Caching and reuse

Generated functions are stored in .semiformal/ relative to your working directory:

  • .semiformal/<session>.portal.json — versioned DAG of all commits, branches, and decisions.
  • .semiformal/runtime/<module>.semi.py — compiled Python implementations for import.

On subsequent runs, semipy loads the cached implementation without calling the LLM. It re-verifies when it detects new input shapes, and runs ADAPT (re-generation from the prior commit) when verification fails.

To force regeneration, delete .semiformal/ or the relevant portal file.

Jupyter

In Jupyter notebooks, semipy detects the ipykernel environment automatically. The portal is keyed to os.getcwd() so one portal persists across kernel restarts.

Install the optional display extras for inline Rich output:

pip install "semipy[jupyter]"

If multiple notebooks share a working directory and need separate caches:

configure(session_source="/path/to/my_notebook.ipynb")

VS Code extension

The Semipy VS Code extension adds:

  • Syntax highlighting for #> spec lines (teal) and #< reasoning lines (green)
  • Slot history tree in the Explorer panel
  • Split-view to inspect generated .semi.py alongside your source
  • Inlay hints and CodeLens showing commit id and decision

Examples

See the examples/ directory:

  • examples/apache_log_semiformal_stages.py — staged walkthrough from simple extraction to INSTANTIATE
  • examples/use_contract_intelligence.py — contract field extraction from PDF
  • examples/use_sponsorship_canonicalizer.py — entity canonicalization pipeline

License

MIT

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

semiformal_py-0.1.2.tar.gz (134.8 kB view details)

Uploaded Source

Built Distribution

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

semiformal_py-0.1.2-py3-none-any.whl (163.2 kB view details)

Uploaded Python 3

File details

Details for the file semiformal_py-0.1.2.tar.gz.

File metadata

  • Download URL: semiformal_py-0.1.2.tar.gz
  • Upload date:
  • Size: 134.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for semiformal_py-0.1.2.tar.gz
Algorithm Hash digest
SHA256 089f9bd0bb546ebe9586249c8130156a01d5750f57df13983592989ae18344ad
MD5 4858dd68bd683562a4ce5d0a6f190b23
BLAKE2b-256 57ce06345380ccf80573959e707e043a841b073e2e331d821ddca4a5e1f9774d

See more details on using hashes here.

File details

Details for the file semiformal_py-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: semiformal_py-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 163.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for semiformal_py-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9df4fe42743c1ebec1a49168b2db48629e0b585e3e1ab82d6a8cb83c72568266
MD5 a3b3bf8e1c901f4afc5437f46f48a666
BLAKE2b-256 c1928f2243988f250352300a99bb719a66e6ff7a2e1cc88569c05b1e2e451b16

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