How to Use Needle 2 for Structured Data Extraction: A Complete Guide
Needle 2 is a 45M-parameter on-device model that converts free-form text into JSON-structured tool calls using a schema-driven extraction pipeline with built-in validation.
Needle 2 from cactus-compute/needle provides on-device structured data extraction through a compact 45 million parameter architecture. This guide demonstrates how to leverage the extract() API to transform unstructured text into validated JSON outputs using either Pydantic models or raw JSON schemas according to the source implementation.
Understanding the Needle 2 Extraction Pipeline
The extraction workflow centers on needle/__init__.py, which orchestrates the conversion of free-form text into structured data through three distinct phases.
The Core Architecture
When you invoke needle.extract(), the library creates a temporary Needle agent that wraps your target schema as a single tool definition. According to the source code in needle/__init__.py (lines 30-55), this agent prepares the schema for ingestion by the native inference engine.
The agent then calls the native inference engine (libneedle.so) via agent._complete() (lines 61-73), which returns a JSON envelope containing a function_calls list. The first call's arguments field contains your extracted data structure.
Engine Selection and Loading
Needle 2 automatically selects the appropriate inference engine based on available resources. The _weight_generation() function reads a four-byte tag from any provided .cact weight file to determine whether to use the Needle 2 or Needle 3 engine (lines 29-38). When no weights are specified, the system loads the default generation 2 engine from a cached Hugging-Face binary (lines 43-73).
Implementing Structured Data Extraction
The practical implementation follows a three-step workflow: schema definition, invocation, and validation.
Defining Your Schema with Pydantic
The most robust approach uses Pydantic models to define expected data structures. The build_schema utilities in needle/agent/tools.py handle the conversion from Pydantic BaseModel classes to JSON schema definitions automatically.
import needle
from pydantic import BaseModel
# Define the expected structure
class Invoice(BaseModel):
vendor: str
total: float
due_date: str # ISO-8601 date string
# Run extraction on a free-form sentence
text = "Invoice from Acme Corp, $1,200.00, due 2026-09-01"
invoice = needle.extract(text, Invoice) # strict mode (default)
print(invoice.vendor) # → Acme Corp
print(invoice.total) # → 1200.0
print(invoice.due_date) # → 2026-09-01
Running the Extraction
When processing text, the extract() function handles the complete pipeline from text parsing to object instantiation. If you provide a Pydantic model as the schema parameter, the raw dictionary is automatically instantiated as a typed object; otherwise, the function returns the raw dictionary (lines 52-55).
# Using a raw JSON schema instead of Pydantic
schema = {
"type": "object",
"properties": {
"city": {"type": "string"},
"temp_c": {"type": "number"},
"sky": {"type": "string"},
},
"required": ["city", "temp_c", "sky"],
}
weather = needle.extract("Weather in Paris: 18°C, partly cloudy.", schema)
print(weather) # {'city': 'Paris', 'temp_c': 18, 'sky': 'partly cloudy'}
Validation and Strict Mode
By default, Needle 2 operates in strict mode (strict=True), which pipes results through _validate_extraction() (lines 15-27). This verification ensures that temporal values such as dates and years are grounded in the original source text and that the engine has not fabricated or negated values. If validation fails, the library raises ExtractionValidationError.
To disable strict validation and receive raw JSON even when validation fails, set strict=False:
invoice_raw = needle.extract(text, Invoice, strict=False)
print(invoice_raw) # {'vendor': 'Acme Corp', 'total': 1200.0, 'due_date': '2026-09-01'}
Summary
- Needle 2 uses a 45M-parameter on-device model to generate JSON-structured tool calls from unstructured text via
libneedle.so - The
extract()function inneedle/__init__.pyorchestrates the complete pipeline from schema wrapping to validation - Engine selection occurs automatically through
_weight_generation()based on.cactfile tags or defaults to the Hugging-Face cached generation 2 engine - Strict mode validates temporal grounding and prevents hallucination by default, throwing
ExtractionValidationErroron validation failures - Both Pydantic models and raw JSON schemas are supported as extraction targets, with automatic type instantiation for Pydantic inputs
Frequently Asked Questions
What makes Needle 2 different from other extraction libraries?
Unlike cloud-dependent solutions, Needle 2 operates entirely on-device through a compact 45 million parameter architecture. It produces structured JSON tool calls rather than raw text completions, and includes built-in validation in needle/__init__.py to ensure extracted values are grounded in source material rather than hallucinated.
How does strict validation work in Needle 2?
When strict=True (the default), the library passes extracted results through _validate_extraction() in needle/__init__.py (lines 15-27). This function specifically checks that temporal values like dates and years exist in the original input text, ensuring the model hasn't fabricated information. If validation fails, the library raises an ExtractionValidationError rather than returning invalid data.
Can I use Needle 2 without Pydantic models?
Yes. While Pydantic BaseModel classes provide the best developer experience with automatic type conversion via needle/agent/tools.py, you can pass raw JSON schema dictionaries directly to needle.extract(). The library will return a raw Python dictionary instead of a typed object when using this approach.
What happens when no weight files are provided?
If you don't specify a .cact weight file, Needle 2 automatically loads the default generation 2 engine from a cached Hugging-Face binary. The _weight_generation() function handles this fallback logic in needle/__init__.py (lines 43-73), ensuring the extraction pipeline works immediately after installation without manual model downloads.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →