@tryhamster/gerbil 1.1.2 → 1.2.0
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.
- package/README.md +18 -16
- package/dist/{architectures-wan0swXu.mjs → architectures-Ol7yUmKf.mjs} +128 -68
- package/dist/architectures-Ol7yUmKf.mjs.map +1 -0
- package/dist/cli.mjs +8 -8
- package/dist/cli.mjs.map +1 -1
- package/dist/{defaults-9komdrbY.mjs → defaults-bJcmOaRG.mjs} +2 -2
- package/dist/defaults-bJcmOaRG.mjs.map +1 -0
- package/dist/frameworks/express.mjs +1 -1
- package/dist/frameworks/fastify.mjs +1 -1
- package/dist/frameworks/hono.mjs +1 -1
- package/dist/frameworks/next.d.mts +2 -2
- package/dist/frameworks/next.mjs +1 -1
- package/dist/frameworks/trpc.mjs +1 -1
- package/dist/gerbil-BjGA5L2E.mjs +4 -0
- package/dist/{gerbil-DZbWbIm2.d.mts → gerbil-CCVOEU-J.d.mts} +2 -2
- package/dist/{gerbil-DZbWbIm2.d.mts.map → gerbil-CCVOEU-J.d.mts.map} +1 -1
- package/dist/{gerbil-CQspp8fS.mjs → gerbil-Cv7rXGOV.mjs} +2 -2
- package/dist/{gerbil-CQspp8fS.mjs.map → gerbil-Cv7rXGOV.mjs.map} +1 -1
- package/dist/gpu/hooks.d.mts +27 -10
- package/dist/gpu/hooks.d.mts.map +1 -1
- package/dist/gpu/hooks.mjs +19 -12
- package/dist/gpu/hooks.mjs.map +1 -1
- package/dist/gpu/index.d.mts +2 -2
- package/dist/gpu/index.mjs +5 -5
- package/dist/{gpu-BYCQ5aTI.mjs → gpu-BWLMlkVW.mjs} +78 -21
- package/dist/gpu-BWLMlkVW.mjs.map +1 -0
- package/dist/{index-CKszv3lt.d.mts → index-CSLqgNu-.d.mts} +212 -133
- package/dist/index-CSLqgNu-.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +6 -6
- package/dist/integrations/ai-sdk.mjs +1 -1
- package/dist/integrations/langchain.mjs +1 -1
- package/dist/integrations/llamaindex.mjs +1 -1
- package/dist/integrations/mcp.d.mts +2 -2
- package/dist/integrations/mcp.mjs +4 -4
- package/dist/{mcp-CszII8GJ.mjs → mcp-C0yKaH39.mjs} +3 -3
- package/dist/{mcp-CszII8GJ.mjs.map → mcp-C0yKaH39.mjs.map} +1 -1
- package/dist/{moonshine-stt-DDUm5WfP.mjs → moonshine-stt-C4GKK-h5.mjs} +45 -5
- package/dist/{moonshine-stt-DDUm5WfP.mjs.map → moonshine-stt-C4GKK-h5.mjs.map} +1 -1
- package/dist/moonshine-stt-zJ9YEi1X.mjs +4 -0
- package/dist/{one-liner-DVche8Eg.mjs → one-liner-DfJh2O0X.mjs} +2 -2
- package/dist/{one-liner-DVche8Eg.mjs.map → one-liner-DfJh2O0X.mjs.map} +1 -1
- package/dist/repl-DTSxHD6t.mjs +9 -0
- package/dist/skills/index.d.mts +2 -2
- package/dist/skills/index.d.mts.map +1 -1
- package/dist/skills/index.mjs +3 -3
- package/dist/{skills-BQI-VSn2.mjs → skills-B5cDRVJ1.mjs} +2 -2
- package/dist/{skills-BQI-VSn2.mjs.map → skills-B5cDRVJ1.mjs.map} +1 -1
- package/package.json +1 -2
- package/dist/architectures-wan0swXu.mjs.map +0 -1
- package/dist/defaults-9komdrbY.mjs.map +0 -1
- package/dist/gerbil-tHnYb9nZ.mjs +0 -4
- package/dist/gpu-BYCQ5aTI.mjs.map +0 -1
- package/dist/index-CKszv3lt.d.mts.map +0 -1
- package/dist/moonshine-stt-BtR-KiSP.mjs +0 -4
- package/dist/repl-BYJA2U7t.mjs +0 -9
- package/docs/PROJECT-STATE.md +0 -321
- package/docs/adding-a-model-family.md +0 -280
- package/docs/ai-sdk.md +0 -205
- package/docs/architecture/README.md +0 -84
- package/docs/architecture/caching.md +0 -227
- package/docs/architecture/inference.md +0 -176
- package/docs/architecture/overview.md +0 -189
- package/docs/architecture/streaming.md +0 -261
- package/docs/architecture/webgpu.md +0 -213
- package/docs/browser.md +0 -762
- package/docs/cli.md +0 -155
- package/docs/embeddings.md +0 -156
- package/docs/frameworks.md +0 -90
- package/docs/gerbil-site-native-migration.md +0 -217
- package/docs/gpu-engine/architectures.md +0 -398
- package/docs/gpu-engine/ir.md +0 -372
- package/docs/gpu-engine/kernels.md +0 -718
- package/docs/gpu-engine/paper.html +0 -1759
- package/docs/gpu-engine/paper.md +0 -2109
- package/docs/gpu-engine/safetensors.md +0 -312
- package/docs/gpu-engine/tokenizer.md +0 -302
- package/docs/kernel-research-queue.md +0 -85
- package/docs/mcp-client.md +0 -224
- package/docs/mcp.md +0 -109
- package/docs/memory-rag.md +0 -91
- package/docs/memory.md +0 -301
- package/docs/metal-safari-intel.md +0 -190
- package/docs/mobile-failure-diagnosis.md +0 -124
- package/docs/mobile.md +0 -99
- package/docs/observability.md +0 -230
- package/docs/onnx-removal-plan.md +0 -339
- package/docs/repl.md +0 -473
- package/docs/research/autoresearch-portable.md +0 -933
- package/docs/research/dispatch-reduction-hivemind.md +0 -84
- package/docs/research/ios-safari-model-caching.md +0 -117
- package/docs/research/mobile-webgpu-speed-fusion.md +0 -135
- package/docs/research/native-stt-model-selection.md +0 -49
- package/docs/research/native-tts-model-selection.md +0 -90
- package/docs/research/native-vs-chromium-decision.md +0 -152
- package/docs/research/nemotron-mamba2-inference.md +0 -910
- package/docs/research/qwen35-multimodal.md +0 -293
- package/docs/research/qwen36-gemma4-targets.md +0 -337
- package/docs/research/sota-embedding-models.md +0 -179
- package/docs/research/sota-mobile-models-2026.md +0 -263
- package/docs/research/sota-modality-models.md +0 -202
- package/docs/research/tps-baselines.md +0 -71
- package/docs/research/webgpu-m4-reference.md +0 -104
- package/docs/site-update-plan.md +0 -155
- package/docs/skills.md +0 -261
- package/docs/structured-output.md +0 -123
- package/docs/stt.md +0 -111
- package/docs/tools.md +0 -304
- package/docs/tts.md +0 -147
- package/docs/vision.md +0 -158
package/docs/skills.md
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
# Gerbil Skills
|
|
2
|
-
|
|
3
|
-
Skills are reusable AI tasks with Zod-validated inputs and outputs.
|
|
4
|
-
|
|
5
|
-
## Built-in Skills
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
import {
|
|
9
|
-
commit, summarize, explain, review,
|
|
10
|
-
test, translate, extract, title
|
|
11
|
-
} from "@tryhamster/gerbil/skills";
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
### commit
|
|
15
|
-
|
|
16
|
-
Generate git commit messages from staged changes.
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
const msg = await commit({
|
|
20
|
-
type: "conventional", // "conventional" | "simple" | "detailed"
|
|
21
|
-
maxLength: 72
|
|
22
|
-
});
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### summarize
|
|
26
|
-
|
|
27
|
-
Summarize content.
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
const summary = await summarize({
|
|
31
|
-
content: document,
|
|
32
|
-
length: "short", // "short" | "medium" | "long"
|
|
33
|
-
format: "bullets", // "paragraph" | "bullets"
|
|
34
|
-
focus: ["key points"]
|
|
35
|
-
});
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
### explain
|
|
39
|
-
|
|
40
|
-
Explain code or concepts.
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
const explanation = await explain({
|
|
44
|
-
content: code,
|
|
45
|
-
level: "beginner", // "beginner" | "intermediate" | "expert"
|
|
46
|
-
language: "typescript"
|
|
47
|
-
});
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### review
|
|
51
|
-
|
|
52
|
-
Code review.
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
const feedback = await review({
|
|
56
|
-
code,
|
|
57
|
-
focus: ["security", "performance"], // "security" | "performance" | "style" | "bugs" | "all"
|
|
58
|
-
format: "detailed" // "inline" | "summary" | "detailed"
|
|
59
|
-
});
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### test
|
|
63
|
-
|
|
64
|
-
Generate tests.
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
const tests = await test({
|
|
68
|
-
code,
|
|
69
|
-
framework: "vitest", // "jest" | "vitest" | "mocha" | "playwright"
|
|
70
|
-
style: "unit" // "unit" | "integration" | "e2e"
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### translate
|
|
75
|
-
|
|
76
|
-
Translate text.
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
const spanish = await translate({
|
|
80
|
-
text,
|
|
81
|
-
to: "es",
|
|
82
|
-
from: "en", // optional, auto-detected
|
|
83
|
-
preserveFormatting: true
|
|
84
|
-
});
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### extract
|
|
88
|
-
|
|
89
|
-
Extract structured data.
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
const data = await extract({
|
|
93
|
-
content: "John is 32 and lives in NYC",
|
|
94
|
-
schema: z.object({ name: z.string(), age: z.number(), city: z.string() }),
|
|
95
|
-
context: "Extract person info"
|
|
96
|
-
});
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### title
|
|
100
|
-
|
|
101
|
-
Generate titles.
|
|
102
|
-
|
|
103
|
-
```typescript
|
|
104
|
-
const heading = await title({
|
|
105
|
-
content: article,
|
|
106
|
-
style: "seo", // "professional" | "clickbait" | "seo" | "simple"
|
|
107
|
-
maxLength: 60
|
|
108
|
-
});
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Custom Skills
|
|
112
|
-
|
|
113
|
-
### defineSkill
|
|
114
|
-
|
|
115
|
-
Create a custom skill:
|
|
116
|
-
|
|
117
|
-
```typescript
|
|
118
|
-
import { defineSkill } from "@tryhamster/gerbil/skills";
|
|
119
|
-
import { z } from "zod";
|
|
120
|
-
|
|
121
|
-
export const sentiment = defineSkill({
|
|
122
|
-
// Required
|
|
123
|
-
name: "sentiment", // kebab-case
|
|
124
|
-
description: "Analyze text sentiment",
|
|
125
|
-
|
|
126
|
-
// Input/Output validation
|
|
127
|
-
input: z.object({
|
|
128
|
-
text: z.string(),
|
|
129
|
-
detailed: z.boolean().default(false)
|
|
130
|
-
}),
|
|
131
|
-
output: z.object({
|
|
132
|
-
sentiment: z.enum(["positive", "negative", "neutral"]),
|
|
133
|
-
confidence: z.number(),
|
|
134
|
-
keywords: z.array(z.string()).optional()
|
|
135
|
-
}),
|
|
136
|
-
|
|
137
|
-
// Defaults
|
|
138
|
-
temperature: 0.3,
|
|
139
|
-
maxTokens: 100,
|
|
140
|
-
thinking: false,
|
|
141
|
-
|
|
142
|
-
// Model (skill loads this automatically if different from current)
|
|
143
|
-
model: "qwen2.5-coder-0.5b",
|
|
144
|
-
|
|
145
|
-
// Metadata
|
|
146
|
-
version: "1.0.0",
|
|
147
|
-
author: "your-name",
|
|
148
|
-
|
|
149
|
-
// Implementation - receives (input, gerbil)
|
|
150
|
-
async run(input, gerbil) {
|
|
151
|
-
const prompt = input.detailed
|
|
152
|
-
? `Analyze sentiment with keywords: ${input.text}`
|
|
153
|
-
: `What is the sentiment: ${input.text}`;
|
|
154
|
-
|
|
155
|
-
return gerbil.json(prompt, { schema: this.output });
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### File Convention
|
|
161
|
-
|
|
162
|
-
Skills can be loaded from files matching `*.skill.ts` or `*.skill.js`:
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
// skills/sentiment.skill.ts
|
|
166
|
-
import { defineSkill } from "@tryhamster/gerbil/skills";
|
|
167
|
-
|
|
168
|
-
export default defineSkill({
|
|
169
|
-
name: "sentiment",
|
|
170
|
-
// ...
|
|
171
|
-
});
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### Loading Skills
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
import { loadSkills, loadSkillPackage, useSkill } from "@tryhamster/gerbil/skills";
|
|
178
|
-
|
|
179
|
-
// Load from directory
|
|
180
|
-
await loadSkills("./skills"); // loads *.skill.ts files
|
|
181
|
-
|
|
182
|
-
// Load from npm package
|
|
183
|
-
await loadSkillPackage("gerbil-skills-extra");
|
|
184
|
-
|
|
185
|
-
// Use by name
|
|
186
|
-
const sentiment = useSkill("sentiment");
|
|
187
|
-
const result = await sentiment({ text: "I love this!" });
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### Skill-Specific Models
|
|
191
|
-
|
|
192
|
-
Skills can specify which model they prefer:
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
export const codeReview = defineSkill({
|
|
196
|
-
name: "code-review",
|
|
197
|
-
description: "Review code for issues",
|
|
198
|
-
model: "qwen2.5-coder-0.5b", // Uses coder model
|
|
199
|
-
|
|
200
|
-
async run(input, gerbil) {
|
|
201
|
-
// gerbil is already loaded with qwen2.5-coder-0.5b
|
|
202
|
-
return gerbil.generate(`Review this code: ${input.code}`);
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
When a skill specifies a different model than the currently loaded one, Gerbil automatically switches models. To avoid this overhead, you can pre-load the skill's model or pass your own Gerbil instance:
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
// Option 1: Let skill switch automatically (may incur loading time)
|
|
211
|
-
const result = await codeReview({ code: myCode });
|
|
212
|
-
|
|
213
|
-
// Option 2: Pass pre-loaded Gerbil instance
|
|
214
|
-
const g = new Gerbil();
|
|
215
|
-
await g.loadModel("qwen2.5-coder-0.5b");
|
|
216
|
-
const result = await codeReview.run({ code: myCode }, g);
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Registry API
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
import {
|
|
223
|
-
listSkills, // Get all skill names
|
|
224
|
-
getSkillInfo, // Get skill metadata
|
|
225
|
-
hasSkill, // Check if skill exists
|
|
226
|
-
removeSkill, // Unregister a skill
|
|
227
|
-
clearSkills // Clear all skills
|
|
228
|
-
} from "@tryhamster/gerbil/skills";
|
|
229
|
-
|
|
230
|
-
console.log(listSkills());
|
|
231
|
-
// ["commit", "summarize", "explain", "review", ...]
|
|
232
|
-
|
|
233
|
-
const info = getSkillInfo("commit");
|
|
234
|
-
// { name, description, version, author, builtin: true }
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## REPL Skills View
|
|
238
|
-
|
|
239
|
-
In the Gerbil REPL, press `2` or navigate to **Skills** to access all available skills.
|
|
240
|
-
|
|
241
|
-
**Controls:**
|
|
242
|
-
- **Up/Down** — Navigate skill list
|
|
243
|
-
- **Enter** — Select and run a skill
|
|
244
|
-
- **c** — Create a new skill (opens wizard)
|
|
245
|
-
- **Esc** — Back to menu
|
|
246
|
-
|
|
247
|
-
The first option **"+ Create new skill"** opens a guided wizard that helps you build a custom skill step-by-step.
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## MCP Integration
|
|
252
|
-
|
|
253
|
-
Skills are automatically exposed as MCP tools:
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
gerbil serve --mcp
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
Each skill becomes a tool: `gerbil_commit`, `gerbil_summarize`, etc.
|
|
260
|
-
|
|
261
|
-
Custom skills loaded via `loadSkills()` are also exposed.
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# Structured Output
|
|
2
|
-
|
|
3
|
-
Gerbil can make a model return a **JSON object** instead of free-form text. The engine
|
|
4
|
-
generates, extracts the JSON from the output, validates it, and — if it fails — retries with
|
|
5
|
-
a corrective nudge until the result is valid or the retry budget is exhausted.
|
|
6
|
-
|
|
7
|
-
This is available at three levels:
|
|
8
|
-
|
|
9
|
-
- **Engine** — `WebGPUEngine.generateObject()` (lowest level)
|
|
10
|
-
- **`Gerbil` class** — `g.generateObject()` (Node-facing wrapper)
|
|
11
|
-
- **One-liner** — `generateObject()` (zero-setup singleton)
|
|
12
|
-
- **React** — the `useObject` hook (`@tryhamster/gerbil/gpu/hooks`)
|
|
13
|
-
|
|
14
|
-
> `generateObject` is distinct from the Zod-driven `Gerbil.json()`. `json()` parses against a
|
|
15
|
-
> Zod schema; `generateObject()` validates with a predicate or a minimal
|
|
16
|
-
> `{ required: [...] }` schema and is the same code path the `useObject` hook uses.
|
|
17
|
-
|
|
18
|
-
## Validation
|
|
19
|
-
|
|
20
|
-
The `schema` option is an `ObjectValidator`, either:
|
|
21
|
-
|
|
22
|
-
- **A predicate** `(o: unknown) => boolean` — full control; return `true` when the parsed
|
|
23
|
-
value is acceptable.
|
|
24
|
-
- **A minimal schema object** `{ required: string[]; properties?: Record<string, unknown> }`
|
|
25
|
-
— only the `required` key set is enforced (every key must exist on the parsed object).
|
|
26
|
-
- **Omitted** — any syntactically valid JSON value (object or array) is accepted.
|
|
27
|
-
|
|
28
|
-
`maxRetries` (default `4`) is the number of retries **after** the first attempt, so up to
|
|
29
|
-
`maxRetries + 1` generations run. The result includes `attempts` (1 = first try).
|
|
30
|
-
|
|
31
|
-
## Engine
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
import { WebGPUEngine } from "@tryhamster/gerbil/gpu";
|
|
35
|
-
|
|
36
|
-
const engine = await WebGPUEngine.create({ repo: "mlx-community/Qwen3.5-0.8B-4bit" });
|
|
37
|
-
|
|
38
|
-
const { object, text, attempts } = await engine.generateObject(
|
|
39
|
-
'Extract {name, age} from: "I am Sarah, 28"',
|
|
40
|
-
{ schema: { required: ["name", "age"] }, maxRetries: 4 },
|
|
41
|
-
);
|
|
42
|
-
// object === { name: "Sarah", age: 28 }
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
`generateObject` extends the engine's `GenerateOptions`, so `maxTokens`, `systemPrompt`, and
|
|
46
|
-
`sampling` (e.g. `{ temperature: 0.2 }`) are all available.
|
|
47
|
-
|
|
48
|
-
## `Gerbil` class
|
|
49
|
-
|
|
50
|
-
```typescript
|
|
51
|
-
import { Gerbil } from "@tryhamster/gerbil";
|
|
52
|
-
|
|
53
|
-
const g = new Gerbil();
|
|
54
|
-
await g.loadModel("qwen3.5-0.8b");
|
|
55
|
-
|
|
56
|
-
const { object } = await g.generateObject<{ primes: number[] }>(
|
|
57
|
-
"List the first 3 primes as {primes: number[]}",
|
|
58
|
-
{ schema: (o) => Array.isArray((o as any).primes) },
|
|
59
|
-
);
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
## One-liner
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
import { generateObject } from "@tryhamster/gerbil";
|
|
66
|
-
|
|
67
|
-
const { object } = await generateObject(
|
|
68
|
-
"Return {ok: true}",
|
|
69
|
-
{ model: "qwen3.5-0.8b", schema: { required: ["ok"] } },
|
|
70
|
-
);
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## React (`useObject`)
|
|
74
|
-
|
|
75
|
-
```tsx
|
|
76
|
-
import { useObject } from "@tryhamster/gerbil/gpu/hooks";
|
|
77
|
-
|
|
78
|
-
function CityExtractor() {
|
|
79
|
-
const { generate, object, isGenerating, attempts } = useObject<{ city: string }>({
|
|
80
|
-
model: "mlx-community/Qwen3.5-0.8B-4bit",
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<div>
|
|
85
|
-
<button
|
|
86
|
-
disabled={isGenerating}
|
|
87
|
-
onClick={() =>
|
|
88
|
-
generate("Extract the city: I live in Paris", { schema: { required: ["city"] } })
|
|
89
|
-
}
|
|
90
|
-
>
|
|
91
|
-
Extract
|
|
92
|
-
</button>
|
|
93
|
-
{object && <pre>{JSON.stringify(object, null, 2)} ({attempts} attempts)</pre>}
|
|
94
|
-
</div>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## CLI
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
# Inline, no schema (any valid JSON accepted)
|
|
103
|
-
gerbil object "Return {ok: true} as JSON"
|
|
104
|
-
|
|
105
|
-
# With a schema file (a minimal { required: [...] } validator)
|
|
106
|
-
echo '{ "required": ["name", "age"] }' > person.json
|
|
107
|
-
gerbil object "Extract {name, age}: I am Sarah, 28" --schema person.json
|
|
108
|
-
|
|
109
|
-
# Flags: --model, --max-tokens, --temperature, --retries, --schema
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
The command prints the parsed object as pretty JSON followed by the attempt count.
|
|
113
|
-
|
|
114
|
-
## Types
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
import type {
|
|
118
|
-
GenerateObjectOptions,
|
|
119
|
-
GenerateObjectResult,
|
|
120
|
-
ObjectSchema,
|
|
121
|
-
ObjectValidator,
|
|
122
|
-
} from "@tryhamster/gerbil";
|
|
123
|
-
```
|
package/docs/stt.md
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Speech-to-Text (STT)
|
|
2
|
-
|
|
3
|
-
Gerbil transcribes audio with **Moonshine** — a native, raw-waveform encoder/decoder STT
|
|
4
|
-
model (no FFT, no log-mel) running on the WebGPU engine. It uses a Conv1d front-end over the
|
|
5
|
-
raw waveform, encodes once, then autoregressively decodes with cross-attention into the
|
|
6
|
-
frozen encoder K/V. No ONNX, no API keys.
|
|
7
|
-
|
|
8
|
-
> **Pre-1.0.** Moonshine is the only STT path. The old Whisper ONNX/transformers.js lane has
|
|
9
|
-
> been removed. The `Gerbil`-class `transcribe()` method still works but now runs native
|
|
10
|
-
> Moonshine under the hood (see [below](#gerbil-class-transcribe-native-wrapper)).
|
|
11
|
-
|
|
12
|
-
## Quick Start
|
|
13
|
-
|
|
14
|
-
Moonshine has its own engine class, `MoonshineSTT`. Feed it raw **16 kHz mono PCM**
|
|
15
|
-
(`Float32Array`).
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
import { MoonshineSTT } from "@tryhamster/gerbil/gpu";
|
|
19
|
-
|
|
20
|
-
const stt = await MoonshineSTT.create({ repo: "UsefulSensors/moonshine-base" });
|
|
21
|
-
|
|
22
|
-
// pcm: Float32Array, 16 kHz mono
|
|
23
|
-
const result = await stt.transcribe(pcm);
|
|
24
|
-
console.log(result.text);
|
|
25
|
-
|
|
26
|
-
stt.destroy();
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## API
|
|
30
|
-
|
|
31
|
-
### `MoonshineSTT.create(options?)`
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
interface MoonshineSTTOptions {
|
|
35
|
-
/** HF repo (default "UsefulSensors/moonshine-base"). */
|
|
36
|
-
repo?: string;
|
|
37
|
-
revision?: string;
|
|
38
|
-
hfToken?: string;
|
|
39
|
-
cacheDir?: string;
|
|
40
|
-
onProgress?: (loaded: number, total: number, message: string) => void;
|
|
41
|
-
}
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### `transcribe(pcm, options?)`
|
|
45
|
-
|
|
46
|
-
```typescript
|
|
47
|
-
interface TranscribeOptions {
|
|
48
|
-
/** Stop after this many decoded tokens (default 194). */
|
|
49
|
-
maxNewTokens?: number;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
interface TranscribeResult {
|
|
53
|
-
text: string;
|
|
54
|
-
/** Decoded token ids (excluding the start token, including trailing EOS). */
|
|
55
|
-
tokens: number[];
|
|
56
|
-
/** Encoder frames produced by the conv frontend. */
|
|
57
|
-
encoderFrames: number;
|
|
58
|
-
/** Audio duration in seconds (samples / 16000). */
|
|
59
|
-
audioSeconds: number;
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
`pcm` must be raw 16 kHz mono `Float32Array` samples. If your audio is a WAV file or at a
|
|
64
|
-
different sample rate, decode and resample it to 16 kHz first.
|
|
65
|
-
|
|
66
|
-
### Decoding / resampling helpers
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
// Reuse the audio utilities from the core package to get 16 kHz mono PCM.
|
|
70
|
-
import { decodeWav, resampleAudio } from "@tryhamster/gerbil/core/stt";
|
|
71
|
-
|
|
72
|
-
const { audio, sampleRate } = decodeWav(wavUint8Array);
|
|
73
|
-
const pcm16k = sampleRate === 16000 ? audio : resampleAudio(audio, sampleRate, 16000);
|
|
74
|
-
|
|
75
|
-
const { text } = await stt.transcribe(pcm16k);
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Model
|
|
79
|
-
|
|
80
|
-
### Moonshine
|
|
81
|
-
|
|
82
|
-
- **Architecture:** `MoonshineForConditionalGeneration` (encoder-decoder)
|
|
83
|
-
- **Front-end:** raw-waveform Conv1d (no FFT / log-mel)
|
|
84
|
-
- **Default repo:** `UsefulSensors/moonshine-base`
|
|
85
|
-
- **Sample rate:** 16 kHz mono
|
|
86
|
-
- **Language:** English (the native engine is English-only; multilingual Whisper has been removed).
|
|
87
|
-
|
|
88
|
-
---
|
|
89
|
-
|
|
90
|
-
## `Gerbil`-class `transcribe()` (native wrapper)
|
|
91
|
-
|
|
92
|
-
> The Whisper ONNX/transformers.js lane (and its multilingual support) has been removed. The
|
|
93
|
-
> `Gerbil`-class `transcribe()` method now runs native Moonshine: it requires WebGPU,
|
|
94
|
-
> accepts 16 kHz mono `Float32Array` PCM (not WAV bytes), is English-only, and does not
|
|
95
|
-
> produce timestamps. The browser `useVoiceInput` hook is gone — use `useSTT` from
|
|
96
|
-
> `@tryhamster/gerbil/gpu/hooks`. The AI SDK `gerbil.transcription()` provider also routes
|
|
97
|
-
> through this native path.
|
|
98
|
-
|
|
99
|
-
```typescript
|
|
100
|
-
import { Gerbil } from "@tryhamster/gerbil";
|
|
101
|
-
|
|
102
|
-
const g = new Gerbil();
|
|
103
|
-
const pcm16kMono = /* Float32Array @ 16 kHz */;
|
|
104
|
-
const result = await g.transcribe(pcm16kMono);
|
|
105
|
-
console.log(result.text);
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## See Also
|
|
109
|
-
|
|
110
|
-
- [Text-to-Speech (TTS)](./tts.md) — native Kani-TTS-2
|
|
111
|
-
- [Browser Hooks](./browser.md) — React hooks
|