Views
No views yet
get-name is a small LoRA fine-tune of the cactus-needle base model
(Cactus-Compute/needle2) that extracts the given (first) name of the
intended person in a piece of text.| Input | Output |
|---|---|
Nice to meet you, Alex | Alex |
By the way, Alice, if you don't know, how old am I? | Alice |
The birth certificate was issued to John Snow | John |
Right now, there are me, Carl, Stephanie, and you, Greg, in the room. | Greg |
Please let Maria know about the meeting. | Maria |
Give this package to Lucas. | Lucas |
Hi everyone, thanks for coming. | (no call) |
My brother Carl lives in Boston. | (no call — mention, not target) |
John Snow → John, James Miller → James).you, Greg) is preferred over names merely listed (the team was Carl, Stephanie, and Greg → no call)..cact weights file for cactus-needle.1# pull the archive
2needle download Qrzysztof/get-name1from needle import Needle
2
3tool = {
4 "name": "extract_name",
5 "parameters": {
6 "type": "object",
7 "properties": {
8 "name": {
9 "type": "string",
10 "description": "The given (first) name of the intended person; never the surname.",
11 }
12 },
13 "required": ["name"],
14 },
15}
16system = (
17 "You extract the given (first) name of the intended person. "
18 "If the text has no intended person, do not call the tool."
19)
20
21agent = Needle(tools=[tool], weights="tuned.cact", system=system)
22print(agent.complete("Nice to meet you, Alex"))
23# {"name": "Alex"}Note: thesystemprompt above is mandatory for best results — the model was trained with it in every example and the same string must be passed at inference.
| Asset | Source |
|---|---|
needle.js (62 KB, Emscripten glue) | Cactus-Compute/needle2/wasm/needle.js |
needle.wasm (325 KB, engine) | Cactus-Compute/needle2/wasm/needle.wasm |
tuned.cact (13.7 MB, this model) | this repo |
browser-demo.html
to try it, or use the live Space: https://huggingface.co/spaces/Qrzysztof/get-name-demo
(direct: qrzysztof-get-name-demo.static.hf.space), or wire up the same calls
yourself:1<script src="https://huggingface.co/Cactus-Compute/needle2/resolve/main/wasm/needle.js"></script>
2<script>
3const SYSTEM = "You extract the given (first) name of the intended person. If the text has no intended person, do not call the tool.";
4const TOOLS = [{ name: "extract_name", parameters: { type: "object", properties: { name: { type: "string" } }, required: ["name"] } }];
5
6let mod;
7const enc = s => { const b = new TextEncoder().encode(s + "\0"); const p = mod._malloc(b.length); mod.HEAPU8.set(b, p); return p; };
8
9async function init() {
10 const [wasm, cact] = await Promise.all([
11 fetch("https://huggingface.co/Cactus-Compute/needle2/resolve/main/wasm/needle.wasm").then(r => r.arrayBuffer()),
12 fetch("https://huggingface.co/Qrzysztof/get-name/resolve/main/tuned.cact").then(r => r.arrayBuffer()),
13 ]);
14 mod = await createNeedle({ wasmBinary: wasm });
15
16 const p = mod._malloc(cact.byteLength);
17 mod.HEAPU8.set(new Uint8Array(cact), p);
18 if (mod._needle_load(p, BigInt(cact.byteLength)) !== 0) throw new Error("needle_load failed");
19 mod._free(p);
20
21 if (mod._needle_init(enc(SYSTEM), enc(JSON.stringify(TOOLS)), 0) < 0) throw new Error("needle_init failed");
22}
23
24function complete(text) {
25 const qP = enc(text), cap = 1 << 20, outP = mod._malloc(cap);
26 const rc = mod._needle_complete(qP, 512, outP, cap);
27 const bytes = mod.HEAPU8.subarray(outP, outP + Math.min(rc, cap));
28 let end = bytes.indexOf(0); if (end < 0) end = bytes.length;
29 const response = JSON.parse(new TextDecoder().decode(bytes.subarray(0, end)));
30 mod._free(qP); mod._free(outP);
31 return response; // { type, function_calls: [{ name, arguments: { name } }], … }
32}
33
34await init();
35console.log(complete("Nice to meet you, Alex")); // function_calls[0].arguments.name === "Alex"
36console.log(complete("Hi everyone, thanks for coming.")); // function_calls === []
37</script>needle_load / needle_init /
needle_complete / needle_reset. Return codes follow the Python binding:
needle_load returns 0 on success; needle_init and needle_complete
return negative on error.needle_load takes the cact length as a 64-bit BigInt, and tools must
be a JSON array (like the Python binding sends).python3 -m http.server) — HF's CDN allows the cross-origin fetches.peak_ram_mb field, which proved unreliable in this build). Roughly
~50 tokens/s on recent Apple Silicon / desktop Chrome (2-bit/4-bit quantized
weights).complete(); for batch processing run a fresh engine instance
per text (same guidance as the Python API in Known limitations).Cactus-Compute/needle2 base; engine,
tokenizer and confidence head untouched. Adapter merged into the weights at
export.data.jsonl in this repo), 88 % positive /
12 % negative, covering:
Dr. John Snow, …),…and you, Greg,…),Tell Maria…, Pass this note to Owen…),needle finetune data.jsonl --epochs 9 --lora-rank 16 then
needle build checkpoints/needle2.pkl --lora adapter.pkl --out tuned.cact.complete() calls in the same
long-lived process showed degraded output on later calls. For batch work,
run one fresh process per text (one query each) or recreate the Needle
object between batches.confidence as
None and a warning is emitted at construction (expected with needle LoRA
blends).tuned.cact — merged, exported weights (13.7 MB) for Needle(weights=...).data.jsonl — the training dataset (browser-search friendly, one JSON
object per line).tool.json — the extract_name tool schema.browser-demo.html — self-contained, zero-server browser demo (WASM engine +
tuned weights fetched straight from Hugging Face).README.md — this card.