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.pyalongside 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 INSTANTIATEexamples/use_contract_intelligence.py— contract field extraction from PDFexamples/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
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 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
089f9bd0bb546ebe9586249c8130156a01d5750f57df13983592989ae18344ad
|
|
| MD5 |
4858dd68bd683562a4ce5d0a6f190b23
|
|
| BLAKE2b-256 |
57ce06345380ccf80573959e707e043a841b073e2e331d821ddca4a5e1f9774d
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9df4fe42743c1ebec1a49168b2db48629e0b585e3e1ab82d6a8cb83c72568266
|
|
| MD5 |
a3b3bf8e1c901f4afc5437f46f48a666
|
|
| BLAKE2b-256 |
c1928f2243988f250352300a99bb719a66e6ff7a2e1cc88569c05b1e2e451b16
|