laya-cli 0.2.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {laya_cli-0.2.0 → laya_cli-0.2.1}/PKG-INFO +55 -18
- {laya_cli-0.2.0 → laya_cli-0.2.1}/README.md +54 -17
- {laya_cli-0.2.0 → laya_cli-0.2.1}/pyproject.toml +1 -1
- {laya_cli-0.2.0 → laya_cli-0.2.1}/src/laya_cli/__init__.py +1 -1
- {laya_cli-0.2.0 → laya_cli-0.2.1}/src/laya_cli/cli.py +51 -16
- {laya_cli-0.2.0 → laya_cli-0.2.1}/uv.lock +1 -1
- {laya_cli-0.2.0 → laya_cli-0.2.1}/.github/workflows/ci.yml +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/.github/workflows/publish.yml +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/.gitignore +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/.python-version +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/LICENSE +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/TASK.md +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/src/laya_cli/daemon.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/__init__.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/conftest.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/test_classify.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/test_cli.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/test_daemon.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/test_evaluate.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/test_filter.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/test_predict.py +0 -0
- {laya_cli-0.2.0 → laya_cli-0.2.1}/tests/test_questions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: laya-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Ergonomic CLI for Laya — typed decisions for humans and AI agents (predict, batch, presets, shortlist, router)
|
|
5
5
|
Project-URL: Homepage, https://github.com/MIt9/laya-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/MIt9/laya-cli.git
|
|
@@ -51,6 +51,7 @@ A modern, high-performance CLI for [Laya](https://github.com/NandhaKishorM/laya)
|
|
|
51
51
|
* 🔍 **Preset Library**: `triage` / `email` / `guard` / `moderation` / `router` — direct `laya.*_questions()` passthrough, mergeable with `--questions file.json` and `--questions-inline`
|
|
52
52
|
* 📦 **Streaming Batch Mode**: `classify`/`predict --input` loads model **once** + warmup, streams JSONL (`--state-field` verbatim, no silent `(photographer: Name)` injection)
|
|
53
53
|
* 🔧 **Post-Filter & Eval**: `filter --where "on_topic>=0.4" --sort -on_topic` and `evaluate` (accuracy, passing @ threshold, precision, escalation rate)
|
|
54
|
+
* ⚡ **Resident Daemon (optional)**: `laya-cli serve` keeps model in RAM — `predict`/`classify`/`evaluate` auto-hit `127.0.0.1` and skip 10-35s `laya.load()` on repeated calls (hash → `~/.cache/laya-cli/daemons/<hash>.json`, idle-timeout 1800s)
|
|
54
55
|
|
|
55
56
|
---
|
|
56
57
|
|
|
@@ -160,32 +161,68 @@ laya-cli evaluate --questions questions.json --labeled labeled.jsonl --label-fie
|
|
|
160
161
|
|
|
161
162
|
### 4. Resident Daemon Mode (optional, speeds up repeated calls)
|
|
162
163
|
|
|
163
|
-
|
|
164
|
+
**Виміряний факт (сесія 2026-09-22, 82 кандидати, MPS):**
|
|
165
|
+
|
|
166
|
+
| етап | час |
|
|
167
|
+
|------|-----|
|
|
168
|
+
| `px` (мережа, 12 запитів) | 9.3s |
|
|
169
|
+
| `laya.load()` (модель у пам'ять) | 10–35s |
|
|
170
|
+
| inference, 82 кандидати | ~10s (~120ms/шт) |
|
|
171
|
+
| `filter` | 0.08s |
|
|
172
|
+
|
|
173
|
+
Для одного пайплайну `px → classify → filter` 35–50s норм. Проблема — коли за сесію кілька разів викликаєш `predict`/`classify`/`evaluate` (підбір `questions.json`: прогнав → подивився → поправив → знову), кожен раз платиш 10–35s за ту саму модель. `laya-cli serve` тримає модель в RAM, наступні виклики летять на `127.0.0.1` (<1ms overhead).
|
|
174
|
+
|
|
175
|
+
#### Транспорт (як у `~/.claude/skills/laya-integration/SKILL.md` "Anything else... HTTP sidecar")
|
|
176
|
+
|
|
177
|
+
HTTP на loopback `127.0.0.1` (не `0.0.0.0`), один потік з `threading.Lock` (SKILL.md: "one GPU serves one forward pass at a time"):
|
|
178
|
+
|
|
179
|
+
- `POST /predict` → `{"state": ..., "questions": {...}, "lang": "...", "shortlist_k": 20}` → те саме що `agent.predict()` (той самий JSON що `laya-cli predict --format json`)
|
|
180
|
+
- `GET /status` → `{"model": "...", "subfolder": "...", "device": "...", "loaded_at": 123..., "idle_seconds": 42, "requests_served": 17, "pid": 12345, "port": 8765}`
|
|
181
|
+
- `POST /shutdown` → graceful stop (лише з localhost, також `serve stop` шле сигнал за pid-файлом)
|
|
182
|
+
|
|
183
|
+
#### Lifecycle
|
|
164
184
|
|
|
165
185
|
```bash
|
|
166
|
-
#
|
|
186
|
+
# Старт (без --foreground — форк у фон, пише pid+port в ~/.cache/laya-cli/daemons/<hash>.json)
|
|
167
187
|
laya-cli serve --model convaiinnovations/laya --device mps
|
|
168
|
-
laya-cli serve --model convaiinnovations/laya --subfolder multilingual --device cpu --idle-timeout 60
|
|
169
|
-
laya-cli serve --router --foreground --idle-timeout 0 #
|
|
188
|
+
laya-cli serve --model convaiinnovations/laya --subfolder multilingual --device cpu --idle-timeout 60
|
|
189
|
+
laya-cli serve --router --foreground --idle-timeout 0 --port 8765 # форграунд для логів, 0=disabled idle
|
|
190
|
+
|
|
191
|
+
# Один daemon = один конфіг (hash(model|subfolder|device|router|lang)), інший конфіг — окремий файл/порт
|
|
192
|
+
laya-cli serve status # дефолтний конфіг (як у predict без прапорців)
|
|
193
|
+
laya-cli serve status --model convaiinnovations/laya --subfolder multilingual --device cpu
|
|
194
|
+
laya-cli serve stop # graceful (POST /shutdown → pid файл видаляється)
|
|
195
|
+
laya-cli serve stop --all # всі daemon-и
|
|
196
|
+
# Також: curl http://127.0.0.1:<port>/status
|
|
197
|
+
```
|
|
170
198
|
|
|
171
|
-
|
|
172
|
-
laya-cli serve status
|
|
173
|
-
laya-cli serve status --model convaiinnovations/laya --subfolder multilingual
|
|
199
|
+
Перед прийомом запитів — прогрів throwaway `predict` (як у `TASK.md`). `idle-timeout 1800s` дефолт, `--idle-timeout 5` для тесту → daemon сам виходить через 5s без запитів і `serve status` каже `not running`.
|
|
174
200
|
|
|
175
|
-
|
|
176
|
-
laya-cli predict "hello" --preset guard --format json # -> via daemon, no 10s load
|
|
177
|
-
laya-cli predict "hello" --preset guard --no-daemon --format json # force in-process, ignore daemon
|
|
201
|
+
#### Клієнт (`predict`/`classify`/`evaluate`)
|
|
178
202
|
|
|
179
|
-
|
|
180
|
-
cat candidates.jsonl | laya-cli classify --questions q.json | laya-cli filter --where "on_topic>=0.4" --sort -on_topic
|
|
203
|
+
Перед `laya.load()` перевіряє `~/.cache/laya-cli/daemons/<hash>.json` для поточного конфігу; якщо файл є і daemon відповідає на `/status` — шле туди, інакше мовчки падає назад на in-process (поведінка `v1` без змін). `--no-daemon` форсує in-process (для відтворюваності/дебагу). Для батчу (`classify`/`predict --input`) — кожен рядок окремий `POST /predict` в циклі (loopback мілісекунди, batch-ендпоінт не потрібен).
|
|
181
204
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
laya-cli serve
|
|
185
|
-
|
|
205
|
+
```bash
|
|
206
|
+
# AI workflow (повністю автоматичний):
|
|
207
|
+
laya-cli serve --device mps & # один раз на сесію
|
|
208
|
+
laya-cli predict "hello" --preset guard --format json # -> via daemon, без 10s
|
|
209
|
+
laya-cli predict "hello2" --preset guard --format json # -> знову via daemon
|
|
210
|
+
laya-cli serve status # {"loaded_at":..., "requests_served": 2}
|
|
211
|
+
laya-cli predict "hello" --preset guard --no-daemon # форс in-process (знову 10s, для ізоляції)
|
|
212
|
+
laya-cli serve stop
|
|
213
|
+
|
|
214
|
+
# Human tuning loop (типовий):
|
|
215
|
+
laya-cli serve & # фон
|
|
216
|
+
cat candidates.jsonl | laya-cli classify --questions q.json | laya-cli filter --where "on_topic>=0.4" --sort -on_topic # via daemon
|
|
217
|
+
# ...поправив q.json...
|
|
218
|
+
cat candidates.jsonl | laya-cli classify --questions q.json | laya-cli filter ... # знову via daemon, без перезавантаження
|
|
219
|
+
laya-cli serve stop
|
|
220
|
+
|
|
221
|
+
# 5 паралельних predict — не падають, результати не плутаються (серіалізація Lock)
|
|
222
|
+
seq 1 5 | xargs -P5 -I{} laya-cli predict "text {}" --preset guard --format json
|
|
186
223
|
```
|
|
187
224
|
|
|
188
|
-
|
|
225
|
+
**Безпека/межі:** лише `127.0.0.1`, без auth (однокористувацька машина, як у SKILL.md), один потік, stateless крім моделі.
|
|
189
226
|
|
|
190
227
|
---
|
|
191
228
|
|
|
@@ -16,6 +16,7 @@ A modern, high-performance CLI for [Laya](https://github.com/NandhaKishorM/laya)
|
|
|
16
16
|
* 🔍 **Preset Library**: `triage` / `email` / `guard` / `moderation` / `router` — direct `laya.*_questions()` passthrough, mergeable with `--questions file.json` and `--questions-inline`
|
|
17
17
|
* 📦 **Streaming Batch Mode**: `classify`/`predict --input` loads model **once** + warmup, streams JSONL (`--state-field` verbatim, no silent `(photographer: Name)` injection)
|
|
18
18
|
* 🔧 **Post-Filter & Eval**: `filter --where "on_topic>=0.4" --sort -on_topic` and `evaluate` (accuracy, passing @ threshold, precision, escalation rate)
|
|
19
|
+
* ⚡ **Resident Daemon (optional)**: `laya-cli serve` keeps model in RAM — `predict`/`classify`/`evaluate` auto-hit `127.0.0.1` and skip 10-35s `laya.load()` on repeated calls (hash → `~/.cache/laya-cli/daemons/<hash>.json`, idle-timeout 1800s)
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
@@ -125,32 +126,68 @@ laya-cli evaluate --questions questions.json --labeled labeled.jsonl --label-fie
|
|
|
125
126
|
|
|
126
127
|
### 4. Resident Daemon Mode (optional, speeds up repeated calls)
|
|
127
128
|
|
|
128
|
-
|
|
129
|
+
**Виміряний факт (сесія 2026-09-22, 82 кандидати, MPS):**
|
|
130
|
+
|
|
131
|
+
| етап | час |
|
|
132
|
+
|------|-----|
|
|
133
|
+
| `px` (мережа, 12 запитів) | 9.3s |
|
|
134
|
+
| `laya.load()` (модель у пам'ять) | 10–35s |
|
|
135
|
+
| inference, 82 кандидати | ~10s (~120ms/шт) |
|
|
136
|
+
| `filter` | 0.08s |
|
|
137
|
+
|
|
138
|
+
Для одного пайплайну `px → classify → filter` 35–50s норм. Проблема — коли за сесію кілька разів викликаєш `predict`/`classify`/`evaluate` (підбір `questions.json`: прогнав → подивився → поправив → знову), кожен раз платиш 10–35s за ту саму модель. `laya-cli serve` тримає модель в RAM, наступні виклики летять на `127.0.0.1` (<1ms overhead).
|
|
139
|
+
|
|
140
|
+
#### Транспорт (як у `~/.claude/skills/laya-integration/SKILL.md` "Anything else... HTTP sidecar")
|
|
141
|
+
|
|
142
|
+
HTTP на loopback `127.0.0.1` (не `0.0.0.0`), один потік з `threading.Lock` (SKILL.md: "one GPU serves one forward pass at a time"):
|
|
143
|
+
|
|
144
|
+
- `POST /predict` → `{"state": ..., "questions": {...}, "lang": "...", "shortlist_k": 20}` → те саме що `agent.predict()` (той самий JSON що `laya-cli predict --format json`)
|
|
145
|
+
- `GET /status` → `{"model": "...", "subfolder": "...", "device": "...", "loaded_at": 123..., "idle_seconds": 42, "requests_served": 17, "pid": 12345, "port": 8765}`
|
|
146
|
+
- `POST /shutdown` → graceful stop (лише з localhost, також `serve stop` шле сигнал за pid-файлом)
|
|
147
|
+
|
|
148
|
+
#### Lifecycle
|
|
129
149
|
|
|
130
150
|
```bash
|
|
131
|
-
#
|
|
151
|
+
# Старт (без --foreground — форк у фон, пише pid+port в ~/.cache/laya-cli/daemons/<hash>.json)
|
|
132
152
|
laya-cli serve --model convaiinnovations/laya --device mps
|
|
133
|
-
laya-cli serve --model convaiinnovations/laya --subfolder multilingual --device cpu --idle-timeout 60
|
|
134
|
-
laya-cli serve --router --foreground --idle-timeout 0 #
|
|
153
|
+
laya-cli serve --model convaiinnovations/laya --subfolder multilingual --device cpu --idle-timeout 60
|
|
154
|
+
laya-cli serve --router --foreground --idle-timeout 0 --port 8765 # форграунд для логів, 0=disabled idle
|
|
155
|
+
|
|
156
|
+
# Один daemon = один конфіг (hash(model|subfolder|device|router|lang)), інший конфіг — окремий файл/порт
|
|
157
|
+
laya-cli serve status # дефолтний конфіг (як у predict без прапорців)
|
|
158
|
+
laya-cli serve status --model convaiinnovations/laya --subfolder multilingual --device cpu
|
|
159
|
+
laya-cli serve stop # graceful (POST /shutdown → pid файл видаляється)
|
|
160
|
+
laya-cli serve stop --all # всі daemon-и
|
|
161
|
+
# Також: curl http://127.0.0.1:<port>/status
|
|
162
|
+
```
|
|
135
163
|
|
|
136
|
-
|
|
137
|
-
laya-cli serve status
|
|
138
|
-
laya-cli serve status --model convaiinnovations/laya --subfolder multilingual
|
|
164
|
+
Перед прийомом запитів — прогрів throwaway `predict` (як у `TASK.md`). `idle-timeout 1800s` дефолт, `--idle-timeout 5` для тесту → daemon сам виходить через 5s без запитів і `serve status` каже `not running`.
|
|
139
165
|
|
|
140
|
-
|
|
141
|
-
laya-cli predict "hello" --preset guard --format json # -> via daemon, no 10s load
|
|
142
|
-
laya-cli predict "hello" --preset guard --no-daemon --format json # force in-process, ignore daemon
|
|
166
|
+
#### Клієнт (`predict`/`classify`/`evaluate`)
|
|
143
167
|
|
|
144
|
-
|
|
145
|
-
cat candidates.jsonl | laya-cli classify --questions q.json | laya-cli filter --where "on_topic>=0.4" --sort -on_topic
|
|
168
|
+
Перед `laya.load()` перевіряє `~/.cache/laya-cli/daemons/<hash>.json` для поточного конфігу; якщо файл є і daemon відповідає на `/status` — шле туди, інакше мовчки падає назад на in-process (поведінка `v1` без змін). `--no-daemon` форсує in-process (для відтворюваності/дебагу). Для батчу (`classify`/`predict --input`) — кожен рядок окремий `POST /predict` в циклі (loopback мілісекунди, batch-ендпоінт не потрібен).
|
|
146
169
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
laya-cli serve
|
|
150
|
-
|
|
170
|
+
```bash
|
|
171
|
+
# AI workflow (повністю автоматичний):
|
|
172
|
+
laya-cli serve --device mps & # один раз на сесію
|
|
173
|
+
laya-cli predict "hello" --preset guard --format json # -> via daemon, без 10s
|
|
174
|
+
laya-cli predict "hello2" --preset guard --format json # -> знову via daemon
|
|
175
|
+
laya-cli serve status # {"loaded_at":..., "requests_served": 2}
|
|
176
|
+
laya-cli predict "hello" --preset guard --no-daemon # форс in-process (знову 10s, для ізоляції)
|
|
177
|
+
laya-cli serve stop
|
|
178
|
+
|
|
179
|
+
# Human tuning loop (типовий):
|
|
180
|
+
laya-cli serve & # фон
|
|
181
|
+
cat candidates.jsonl | laya-cli classify --questions q.json | laya-cli filter --where "on_topic>=0.4" --sort -on_topic # via daemon
|
|
182
|
+
# ...поправив q.json...
|
|
183
|
+
cat candidates.jsonl | laya-cli classify --questions q.json | laya-cli filter ... # знову via daemon, без перезавантаження
|
|
184
|
+
laya-cli serve stop
|
|
185
|
+
|
|
186
|
+
# 5 паралельних predict — не падають, результати не плутаються (серіалізація Lock)
|
|
187
|
+
seq 1 5 | xargs -P5 -I{} laya-cli predict "text {}" --preset guard --format json
|
|
151
188
|
```
|
|
152
189
|
|
|
153
|
-
|
|
190
|
+
**Безпека/межі:** лише `127.0.0.1`, без auth (однокористувацька машина, як у SKILL.md), один потік, stateless крім моделі.
|
|
154
191
|
|
|
155
192
|
---
|
|
156
193
|
|
|
@@ -53,7 +53,11 @@ except ImportError:
|
|
|
53
53
|
def _build_parser() -> argparse.ArgumentParser:
|
|
54
54
|
p = argparse.ArgumentParser(
|
|
55
55
|
prog="laya-cli",
|
|
56
|
-
description=
|
|
56
|
+
description=(
|
|
57
|
+
"Ergonomic CLI for Laya — typed decisions (choice/score/noul) in one forward pass. "
|
|
58
|
+
"Works for humans (table) and agents (JSON/JSONL). "
|
|
59
|
+
"Optional resident daemon (laya-cli serve) keeps model in RAM to avoid 10-35s laya.load() on repeated predict/classify/evaluate (same model|subfolder|device|router|lang → ~/.cache/laya-cli/daemons/<hash>.json, 127.0.0.1 only, auto fallback if not running)."
|
|
60
|
+
),
|
|
57
61
|
)
|
|
58
62
|
p.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
|
|
59
63
|
sub = p.add_subparsers(dest="cmd", required=True)
|
|
@@ -61,8 +65,11 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
61
65
|
# ---- predict (primary, human+AI friendly) -----------------------------
|
|
62
66
|
pr = sub.add_parser(
|
|
63
67
|
"predict",
|
|
64
|
-
help="Run Laya on one text/JSON state or a batch (JSONL). Human-friendly & agent-friendly.",
|
|
65
|
-
description=
|
|
68
|
+
help="Run Laya on one text/JSON state or a batch (JSONL). Human-friendly & agent-friendly. Auto-uses daemon if live.",
|
|
69
|
+
description=(
|
|
70
|
+
"Predict with Laya on a single state or a batch. Supports plain text, JSON state, presets, shortlist for high-cardinality choices, and table/JSON output. "
|
|
71
|
+
"If a daemon is live for the same --model/--subfolder/--device/--router/--lang (hash → ~/.cache/laya-cli/daemons/<hash>.json), predict hits 127.0.0.1:<port>/predict and skips 10-35s laya.load(); otherwise it loads in-process. Use --no-daemon to force in-process."
|
|
72
|
+
),
|
|
66
73
|
epilog=(
|
|
67
74
|
"Examples (human):\n"
|
|
68
75
|
' laya-cli predict "I was charged twice, refund please" --preset triage\n'
|
|
@@ -74,6 +81,13 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
74
81
|
" cat candidates.jsonl | laya-cli predict --questions q.json --state-field state --format jsonl > scored.jsonl\n"
|
|
75
82
|
" laya-cli predict --input candidates.jsonl --questions q.json --shortlist-k 20 --format jsonl\n"
|
|
76
83
|
' laya-cli predict --preset triage --text "my payment failed" --model convaiinnovations/laya --device cpu --full-probs\n'
|
|
84
|
+
"\n"
|
|
85
|
+
"Daemon (optional, speeds up repeated calls):\n"
|
|
86
|
+
" laya-cli serve --model convaiinnovations/laya --device mps # start daemon (background, writes ~/.cache/laya-cli/daemons/<hash>.json)\n"
|
|
87
|
+
" laya-cli serve status # check live daemon (GET /status)\n"
|
|
88
|
+
' laya-cli predict "hello" --preset guard --format json # auto-uses daemon (<1ms overhead), no 10s load\n'
|
|
89
|
+
' laya-cli predict "hello" --preset guard --no-daemon # force in-process, ignore daemon\n'
|
|
90
|
+
" laya-cli serve stop # graceful shutdown (POST /shutdown)\n"
|
|
77
91
|
),
|
|
78
92
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
79
93
|
)
|
|
@@ -190,14 +204,19 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
190
204
|
# ---- classify (legacy batch, kept for TASK.md compat) -----------------
|
|
191
205
|
c = sub.add_parser(
|
|
192
206
|
"classify",
|
|
193
|
-
help="Batch classify JSONL from stdin via Laya (legacy, use predict for new code).",
|
|
194
|
-
description=
|
|
207
|
+
help="Batch classify JSONL from stdin via Laya (legacy, use predict for new code). Auto-uses daemon if live.",
|
|
208
|
+
description=(
|
|
209
|
+
"Classify JSONL from stdin via Laya; append flattened answers. Kept for pipeline compatibility (px | laya-cli classify). "
|
|
210
|
+
"For new code prefer `predict`. If a daemon is live for the same config (hash → ~/.cache/laya-cli/daemons/<hash>.json), classify hits 127.0.0.1 and skips load; else in-process. Use --no-daemon to force."
|
|
211
|
+
),
|
|
195
212
|
epilog=(
|
|
196
213
|
"Examples:\n"
|
|
197
214
|
" cat candidates.jsonl | laya-cli classify --questions questions.json > scored.jsonl\n"
|
|
198
215
|
' px videos --queries "..." --state --dedupe keep-first \\\n'
|
|
199
216
|
" | laya-cli classify --questions questions.json \\\n"
|
|
200
217
|
' | laya-cli filter --where "on_topic>=0.4" --sort -on_topic > shortlist.jsonl\n'
|
|
218
|
+
" # with daemon (start once, then all classify hit daemon):\n"
|
|
219
|
+
" laya-cli serve --model convaiinnovations/laya & laya-cli classify --questions q.json < candidates.jsonl\n"
|
|
201
220
|
),
|
|
202
221
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
203
222
|
)
|
|
@@ -279,12 +298,16 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
279
298
|
# ---- evaluate ---------------------------------------------------------
|
|
280
299
|
e = sub.add_parser(
|
|
281
300
|
"evaluate",
|
|
282
|
-
help="Evaluate on a labelled JSONL set and print accuracy / threshold report.",
|
|
283
|
-
description=
|
|
301
|
+
help="Evaluate on a labelled JSONL set and print accuracy / threshold report. Auto-uses daemon if live.",
|
|
302
|
+
description=(
|
|
303
|
+
"Evaluate before shipping: run classify on a labelled set and report accuracy per question, pass rate at threshold, and precision @ threshold. "
|
|
304
|
+
"If a daemon is live for the same --model/--device/--router, evaluate hits it and skips load; else in-process. Use --no-daemon to force."
|
|
305
|
+
),
|
|
284
306
|
epilog=(
|
|
285
307
|
"Examples:\n"
|
|
286
308
|
" laya-cli evaluate --questions questions.json --labeled labeled.jsonl --label-field label --threshold 0.5\n"
|
|
287
309
|
" laya-cli evaluate --questions q.json --labeled dev.jsonl --field on_topic --state-field state\n"
|
|
310
|
+
" laya-cli serve & laya-cli evaluate --questions q.json --labeled dev.jsonl # via daemon\n"
|
|
288
311
|
),
|
|
289
312
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
290
313
|
)
|
|
@@ -314,16 +337,28 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
314
337
|
s = sub.add_parser(
|
|
315
338
|
"serve",
|
|
316
339
|
help="Resident daemon that keeps model in memory (optional, speeds up repeated predict).",
|
|
317
|
-
description=
|
|
340
|
+
description=(
|
|
341
|
+
"Start a resident daemon that holds the Laya model in RAM (10-35s laya.load() once). "
|
|
342
|
+
"Subsequent `predict`/`classify`/`evaluate` with the SAME config (--model/--subfolder/--device/--router/--lang → hash → ~/.cache/laya-cli/daemons/<hash>.json) "
|
|
343
|
+
"automatically hit 127.0.0.1:<port>/predict and skip the load (<1ms overhead). If no daemon, they fall back to in-process load — no pipeline change. "
|
|
344
|
+
"Daemon binds only 127.0.0.1 (SKILL.md: Bind to 127.0.0.1), single-threaded lock (one GPU = one forward pass), idle-timeout auto-exit (default 1800s, 0=disabled), warmup throwaway predict on start."
|
|
345
|
+
),
|
|
318
346
|
epilog=(
|
|
319
|
-
"
|
|
320
|
-
" laya-cli serve --model convaiinnovations/laya --device mps
|
|
321
|
-
" laya-cli serve
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
" laya-cli
|
|
326
|
-
|
|
347
|
+
"Workflow for AI/human (typical tuning loop):\n"
|
|
348
|
+
" laya-cli serve --model convaiinnovations/laya --device mps # start once (background, writes ~/.cache/laya-cli/daemons/<hash>.json)\n"
|
|
349
|
+
" laya-cli serve status # GET /status → {model,device,loaded_at,idle_seconds,requests_served,pid,port}\n"
|
|
350
|
+
' laya-cli predict "test" --preset triage --format json # auto via daemon (no 10s load)\n'
|
|
351
|
+
' laya-cli predict "test2" --preset triage --format json # still via daemon\n'
|
|
352
|
+
' laya-cli predict "test" --preset triage --no-daemon --format json # force in-process (ignore daemon)\n'
|
|
353
|
+
" cat candidates.jsonl | laya-cli classify --questions q.json # batch: each line POST /predict (serialized)\n"
|
|
354
|
+
" laya-cli serve stop # POST /shutdown or SIGTERM, removes pid file\n"
|
|
355
|
+
" laya-cli serve stop --all # stop all configs\n"
|
|
356
|
+
"\n"
|
|
357
|
+
"Other examples:\n"
|
|
358
|
+
" laya-cli serve --foreground --idle-timeout 5 --port 0 # foreground for logs, 5s idle test\n"
|
|
359
|
+
" laya-cli serve --model convaiinnovations/laya --subfolder multilingual --device cpu\n"
|
|
360
|
+
" laya-cli serve status --model convaiinnovations/laya --subfolder multilingual # check that config\n"
|
|
361
|
+
' curl http://127.0.0.1:<port>/status ; curl -X POST http://127.0.0.1:<port>/predict -d \'{"state":"hi","questions":{...}}\'\n'
|
|
327
362
|
),
|
|
328
363
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
329
364
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|