--- language: - en license: apache-2.0 datasets: - cactus-needle/base metrics: [] model-index: [] pipeline_tag: text-generation base_model: Cactus-Compute/needle2 tags: - needle - cactus-needle - tool-calling - named-entity-extraction - lora --- # Get Name — addressee/given-name extraction for cactus-needle `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. It was trained to answer one question: *"which single person is this text about / addressed to, and what is that person's first name?"* — and to call a tool only when such a person exists. | 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)* | ## Behaviour - **Given name only.** Full names are collapsed to the first name on purpose (`John Snow` → `John`, `James Miller` → `James`). - **Single target.** In enumerations the person directly addressed (`you, Greg`) is preferred over names merely listed (`the team was Carl, Stephanie, and Greg` → no call). - **No call when there is no target:** group greetings, place names, brands, assistants (Siri/Alexa), generic salutations, and passive mentions. ## How to use The archive is a needle `.cact` weights file for `cactus-needle`. ```sh # pull the archive needle download Qrzysztof/get-name ``` ```python from needle import Needle tool = { "name": "extract_name", "parameters": { "type": "object", "properties": { "name": { "type": "string", "description": "The given (first) name of the intended person; never the surname.", } }, "required": ["name"], }, } system = ( "You extract the given (first) name of the intended person. " "If the text has no intended person, do not call the tool." ) agent = Needle(tools=[tool], weights="tuned.cact", system=system) print(agent.complete("Nice to meet you, Alex")) # {"name": "Alex"} ``` > **Note:** the `system` prompt above is mandatory for best results — the model > was trained with it in every example and the same string must be passed at > inference. ## Running in the browser (no server) The needle engine ships an **official WebAssembly build**, so this model runs entirely in the browser — no backend, no Python. Only three assets are needed: | 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 | Everything is fetchable from the Hugging Face CDN (CORS-enabled), so a purely static page works. Open the included **[`browser-demo.html`](./browser-demo.html)** to try it, or use the **live Space: ** (direct: `qrzysztof-get-name-demo.static.hf.space`), or wire up the same calls yourself: ```html ``` Browser specifics (verified against the WASM build): - **API is identical to the native engine** — `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). - Hosting: serve statically (GitHub Pages, Vercel, or just `python3 -m http.server`) — HF's CDN allows the cross-origin fetches. - Footprint: ~13.7 MB download, ~325 KB WASM, and ~150–200 MB process memory (measured via Node RSS while loading weights + running a completion; not the engine's `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). - One call per `complete()`; for batch processing run a fresh engine instance per text (same guidance as the Python API in Known limitations). ## Training - **Method:** LoRA adapters (rank 16, alpha 32) on the five attention projections of every layer of a frozen `Cactus-Compute/needle2` base; engine, tokenizer and confidence head untouched. Adapter merged into the weights at export. - **Data:** ~1,100 hand-curated, template-augmented examples in needle's tool-calling JSONL format (`data.jsonl` in this repo), 88 % positive / 12 % negative, covering: - greetings & welcomes, - vocative / direct address (incl. titled forms, `Dr. John Snow, …`), - documents issued to a person (birth certificates, passports, licences…), - enumerations with an addressed member (`…and you, Greg,…`), - message targets and relays (`Tell Maria…`, `Pass this note to Owen…`), - off-topic no-call examples (groups, places, brands, assistants, generic salutations). - **Hyper-parameters:** batch 16, lr 1e-4 with warmup + cosine decay, grad clip 1.0, epochs chosen so the held-out loss lands ~0.5 (see Known limitations), validation split 0.1, seq len 256. - **Recipe:** `needle finetune data.jsonl --epochs 9 --lora-rank 16` then `needle build checkpoints/needle2.pkl --lora adapter.pkl --out tuned.cact`. Training ran on a single Colab T4 and took a few minutes per run. ## Known limitations - **False-positive rejection is the weak point.** The tuning budget between *never calls the tool* and *calls a tool on everything* is narrow for this "is it really addressed to a person?" discrimination. This release is tuned on the extraction side (strong recall on intended targets). If you need stricter rejection, retrain with a higher negative share (25 %+) and stop a little earlier on the validation curve. - **Sequential calls in one process:** repeated `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 head is not tuned:** tuned weights report `confidence` as `None` and a warning is emitted at construction (expected with needle LoRA blends). - **Non-English input:** like the base model, out-of-domain text (and Spanish in particular) is not well calibrated. ## Files - `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.