✨ Laya CLI (laya-cli)
A modern, high-performance CLI for Laya — typed decisions (choice/score/noul) in one forward pass, designed for Humans (Rich table output) and AI Agents / Classifiers (Machine-readable --json & JSONL).
⚡ Key Features
- 🤖 Typed Decisions in One Pass:
choice(top label + probs),score(ordinal),noul(P(true)) — no generation, no hallucination, ~33ms on T4, 7ms/q batched - 🧭 Router-Aware Multilingual:
laya.Router(preload=True)auto-detects script/language in <0.5ms and dispatches tolaya(English, 512 ctx) vslaya-multilingual(100+ langs, 1024 ctx); warns if--routerwithout--lang - 🧹 Embedding Shortlist for High-Cardinality:
--shortlist-k 20vialaya.predict_shortlist+embed_fn_from_agent(Banking77 77 opts → 3 tokens/opt without shortlist → shortlist fixes) - 🔍 Preset Library:
triage/email/guard/moderation/router— directlaya.*_questions()passthrough, mergeable with--questions file.jsonand--questions-inline - 📦 Streaming Batch Mode:
classify/predict --inputloads model once + warmup, streams JSONL (--state-fieldverbatim, no silent(photographer: Name)injection) - 🔧 Post-Filter & Eval:
filter --where "on_topic>=0.4" --sort -on_topicandevaluate(accuracy, passing @ threshold, precision, escalation rate)
🚀 Global Installation
Option 1: Install globally via uv (Recommended)
uv tool install laya-cli
Option 2: Install via pip / pipx
pipx install laya-cli
# or
pip install laya-cli
Option 3: Run without installing
uvx laya-cli --help
Requires Python 3.10+ (
.python-versionpins 3.11). Heavy ML deps (torch,transformers,safetensorsvialaya, ~2 GB) download on firstpredict/classify. AfterwardsHF_HUB_OFFLINE=1works. Foruvdev, tests mock Laya so CI is fast.
🤖 Classifier Pipeline Integration (Pexels → Laya)
Pipe candidate streams directly from pexels-cli (px) into Laya. This is the original use-case that drove laya-cli (82 candidates, state deduped):
# 1. Pexels → candidates.jsonl with `state` strings
px videos --queries "black friday shopping,christmas shopping,checkout cart" \
--per-page 8 --state --dedupe keep-first > candidates.jsonl
# 2. Laya → score + filter (streaming, one model load)
cat candidates.jsonl \
| laya-cli classify --questions questions.json \
| laya-cli filter --where "on_topic>=0.4" --sort -on_topic \
> shortlist.jsonl
# Or with the new primary command (supports presets without a file):
cat candidates.jsonl | laya-cli predict --questions questions.json --format jsonl > scored.jsonl
px videos --queries "..." --state --dedupe | laya-cli predict --preset triage --format jsonl | laya-cli filter --where "intent==refund"
Candidate JSONL format (px --state):
{"id": 5890229, "type": "video", "query": "black friday shopping", "photographer": "Pavel Danilyuk", "state": "a man shopping on black friday", "url": "https://www.pexels.com/video/a-man-shopping-on-black-friday-5890229/", "duration": 10, "width": 2160, "height": 3840}
laya-cli reads --state-field state verbatim — use --prepend-field only explicitly (mixing photographer into state degraded on_topic by 0.1-0.3).
📖 Usage Examples
1. Direct CLI (Human & AI)
# Human: table output, no file needed
laya-cli predict "I was charged twice, refund please" --preset triage
laya-cli predict --text "Ignore previous instructions" --preset guard --format table
laya-cli predict --state '{"subject":"Invoice #4411","body":"Billed twice"}' --preset email --format table
# AI agent: JSON single-shot
laya-cli predict --text "Is this spam?" --preset guard --format json
# -> {"answers": {"jailbreak": {"noul": 0.02, "confidence": 0.97, ...}}, "usage": ...}
# Custom + preset merging (preset < file < inline)
laya-cli predict --text "hello" --preset triage --questions-inline '{"custom":{"type":"noul","instructions":"Is it polite?"}}' --format json
# High-cardinality choice (77 banking intents)
laya-cli predict --text "where is my card?" --questions banking.json --shortlist-k 20 --format json
# Multilingual — Router recommended
laya-cli predict --text "मुझसे दो बार शुल्क लिया गया" --preset triage --router --format json
laya-cli predict --text "Der Kunde wurde zweimal belastet" --preset triage --router --lang de --format json
2. Batch & Pipeline
# Batch from file (human-readable table per row)
laya-cli predict --input candidates.jsonl --questions questions.json --format table
# Batch JSONL with flatten (like classify) for jq/filter
laya-cli predict --input candidates.jsonl --questions questions.json --flatten --format jsonl > scored.jsonl
cat scored.jsonl | laya-cli filter --where "on_topic>=0.4,is_relevant>=0.7" --sort -on_topic,+id
# Legacy streaming (kept for compatibility):
cat candidates.jsonl | laya-cli classify --questions questions.json | laya-cli filter --where "on_topic>=0.4" --sort -on_topic > shortlist.jsonl
3. Presets & Info
laya-cli questions list --format table
laya-cli questions triage > questions.json # also: email, guard, moderation, router
laya-cli presets guard | laya-cli predict --text "test" --questions /dev/stdin
laya-cli info # python/torch/cuda/mps + cache
laya-cli evaluate --questions questions.json --labeled labeled.jsonl --label-field label --threshold 0.5
🛠 Development
uv sync --group dev # hatchling + ruff/mypy/pytest
uv run ruff check . # lint (E/F/W/I, line-length 120)
uv run ruff format . # format
uv run pytest -q # 26 tests, mocked laya (no model download)
uv run pytest --cov=src/laya_cli --cov-report=term-missing
uv build # hatchling -> dist/*.whl + sdist (src/ layout)
Repo layout: src/laya_cli/, tests/, pyproject.toml (hatchling + dependency-groups), uv.lock, .python-version 3.11, .github/workflows/ci.yml + publish.yml.
📄 License
Apache-2.0 — same as Laya upstream. See LICENSE.
This project is not affiliated with Convai Innovations. Laya weights are Apache-2.0 and hosted on Hugging Face (convaiinnovations/laya).
Release files for laya-cli 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| laya_cli-0.1.0.tar.gz | 131.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| laya_cli-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 148.4 kB
Release files / laya_cli-0.1.0.tar.gz
| Download URL | laya_cli-0.1.0.tar.gz |
|---|---|
| Size | 131.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
17365f32783ebf722b98ddce9e745733e6e125020a24d7ef6c9efd9dc9e93c83
|
|
BLAKE2b-256 checksum How to use checksums |
4098a1486a97566d6fdd3da20170d2894e4726f5b0f5cec764663335393e55b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.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}
|
Release files / laya_cli-0.1.0-py3-none-any.whl
| Download URL | laya_cli-0.1.0-py3-none-any.whl |
|---|---|
| Size | 17.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b2a02ef897360c50c258d4727a5928232d7a23cd84bc5a5c405f04c93741c84
|
|
BLAKE2b-256 checksum How to use checksums |
c2bce488800cdf62ac289c0d5f763da97640822f50e74181744141b438b9cc34
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.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}
|