Skip to main content

Ducktape Laya for Python

Local Laya GGUF decisions (choice, noul, ordinal score) from Python, backed by the shared libducktape_laya.so. Inference runs in-process: no server, network or model download. Linux x86-64 only; see the repository README for CPU and glibc requirements. Python 3.10+.

The package uses ctypes, so it needs no compiler. It loads the native library bundled in the wheel, or the system's libducktape_laya.so.1. Setting DUCKTAPE_LAYA_LIB_DIR selects a specific library instead; if that one cannot be loaded, the first Engine.open, Engine.open_router or runtime_info call raises OSError rather than falling back (loading is lazy, so import itself succeeds). Download the model separately and check its hash; see the repository README.

import ducktape_laya

with ducktape_laya.Engine.open("/path/to/Laya-Q8_0.gguf") as engine:
    result = engine.execute({
        "state": "Please refund the duplicate charge.",
        "questions": {
            "refund": {"type": "noul", "instructions": "Does the customer request a refund?"},
        },
    })
    print(result["answers"]["refund"]["noul"])

Requests are JSON values or JSON strings; a string is sent as is. execute accepts primitive and structured requests and lists of up to 32 requests under one strict contract. Optional per-request max_tokens, temperatures, overflow, max_windows and (with "model": "auto") lang are plain request keys. Results are parsed JSON.

Open options are keyword-only and omitted when unset: Engine.open(path, threads=0, context_tokens=None, temperatures=None, overflow=None). context_tokens is the prompt capacity (default 512, at most the model's trained length), temperatures maps calibration keys such as "choice" or "noul.2" to positive overrides, and overflow is the default policy for prompts over the limit ("reject" (default), "truncate_end", "truncate_start" or "scan"; a request's own overflow wins). The binding checks some values itself: threads (0..256) and overflow raise ValueError, a non-integer context_tokens raises TypeError, and non-finite numbers (such as a NaN temperature) or non-serializable configs raise ValueError/TypeError from JSON encoding. Other invalid values (for example a non-positive context_tokens or temperature, a NUL character or invalid Unicode in a path or config) raise LayaError with status 1. Engine.open_router(config, ...) takes the same options, applied to every route; a route may be "path.gguf" or {"path": ..., "config": {...}}, whose config overrides them key by key. Requests to a router name a route in "model". With "auto": {"english": "en", "default": "ml"} in the router config, "model": "auto" chooses the route by the state's language (optionally given as "lang"); "auto" cannot be a route ID.

Errors: native failures and invalid request text raise LayaError, whose status matches the C ABI (Status). Calls after close() raise EngineClosedError, a LayaError. Arguments the binding checks itself (threads, timeout, request_id) raise ValueError or TypeError, and a missing or incompatible library raises OSError.

Calls block and release the GIL. An engine is safe to share between threads; calls on one engine run one at a time, so open several engines for parallel inference. Per call, timeout (seconds; None or 0 means no deadline) sets a deadline (status 6), cancel takes a single CancelToken whose cancel() stops the call from any thread (status 5), and on_event receives start/end/error events on the thread running the call. execute_async runs the call on a worker thread (where on_event then runs), and cancelling the task cancels the native call. close() waits for running calls; called from an on_event callback, it returns at once and the model is released when the running call finishes. Engines not closed are released when garbage collected, but close them for prompt release. Engine.open_router opens a lazy registry of several local models; see the API guide.

From a checkout

The binding is not on PyPI yet. Build the native library first (see the repository README), then either point Python at the source and the built library:

export DUCKTAPE_LAYA_LIB_DIR=/path/to/ducktape-laya/build
export PYTHONPATH=/path/to/ducktape-laya/bindings/python/src
python3 -c 'import ducktape_laya; print(ducktape_laya.runtime_info()["abi_version"])'

or install the source directory into a virtual environment with pip install /path/to/ducktape-laya/bindings/python and keep DUCKTAPE_LAYA_LIB_DIR set when running. Either way the library comes from DUCKTAPE_LAYA_LIB_DIR: a wheel built from pyproject.toml alone does not contain it. scripts/package-linux.py builds the real wheel, which bundles the library and needs no environment variable. It packages every native artifact at once, so it needs a build configured with -DDUCKTAPE_BUILD_NODE=ON (the Node addon built), npm and Cargo: it runs npm pack and cargo package before building the wheel (see packaging). Then pip install build/packages-0.2.0/ducktape_laya-0.2.0-*.whl.

Metadata

Release files for ducktape-laya 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for ducktape-laya 0.2.0
File Interpreter ABI Platform
ducktape_laya-0.2.0-py3-none-manylinux_2_38_x86_64.whl Python 3 none Linux glibc 2.38+ x86-64 Details

Release files / ducktape_laya-0.2.0-py3-none-manylinux_2_38_x86_64.whl

Download URL ducktape_laya-0.2.0-py3-none-manylinux_2_38_x86_64.whl
Size 2.9 MB
Tags Linux glibc 2.38+ x86-64 Python 3
SHA-256 checksum
How to use checksums
41bfc20760f13f2f9e9ec27658e3f02293a578ca3a2e57007c42e6a6e9a27f72
BLAKE2b-256 checksum
How to use checksums
7c2a6c1eff71836de5dc98cefafbe0d88e28aadc2b7fecc66f7d7596927ba701
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for ducktape-laya 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 1 file in this release has been uploaded with provenance metadata.

Attestation for ducktape_laya-0.2.0-py3-none-manylinux_2_38_x86_64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.0 This release

1 release file Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page