Needle JSONL Training Data Format: How to Structure Queries, Tools, and Answers
Needle uses a JSON Lines (JSONL) format where each line is a JSON object containing a query string, optional tools array with JSON Schema definitions, and an answers array with tool calls that fulfill the request.
The Needle framework from cactus-compute expects training examples in a strict JSONL structure. This format enables fine-tuning of small language models to call tools accurately, with explicit schemas that constrain generation. Each training example represents one turn of user interaction and the correct tool invocation sequence.
Core JSONL Schema for Needle Training Data
Every line in your training file must be a valid JSON object with these fields:
| Field | Required | Description |
|---|---|---|
query |
Yes | Natural language request or passage to process |
tools |
No | Array of JSON Schema objects describing available tools |
answers |
Yes | Array of tool call objects with name and arguments |
reasoning |
No | Human-readable explanation of argument derivation |
A minimal valid example:
{
"query": "dim the kitchen to 10",
"answers": [
{"name": "set_lights", "arguments": {"room": "kitchen", "brightness": 10}}
]
}
A complete example with all optional fields:
{
"query": "dim the kitchen to 10",
"tools": [
{
"name": "set_lights",
"parameters": {
"type": "object",
"properties": {
"room": {"type": "string"},
"brightness": {"type": "integer"}
},
"required": ["room", "brightness"]
},
"description": "Set the brightness of a room's lights."
}
],
"answers": [
{"name": "set_lights", "arguments": {"room": "kitchen", "brightness": 10}}
],
"reasoning": "'kitchen' → room; 'dim to 10' → brightness 10"
}
Understanding Each Field in the Needle JSONL Format
The query Field
The query contains the raw user input. Its content varies by tool type:
- Action tools: Short commands like
"send email to alice"or"what's the weather in Tokyo?" - Extraction tools: Longer passages containing data to extract, such as product descriptions or log files
In needle/model/finetune.py, the load_jsonl function silently skips any line missing the query key.
The tools Array
The tools field holds JSON Schema objects describing each function the model may call. These schemas are auto-generated from Python functions decorated with @needle.tool in needle/agent/tools.py.
The tool decorator uses build_schema to introspect type hints and docstrings, producing schemas like:
{
"name": "function_name",
"parameters": {
"type": "object",
"properties": {...},
"required": [...]
},
"description": "Function docstring"
}
Including tools in training examples teaches the model the available function signatures and argument constraints.
The answers Array
The answers field contains the ground-truth tool calls that solve the query. Each object requires:
name: Must exactly match a tool name in thetoolslistarguments: Object with keys matching the schema'sproperties, values of correct types
Multiple tool calls are supported for multi-step reasoning:
{
"query": "Turn off the lights and lock the front door",
"answers": [
{"name": "set_lights", "arguments": {"room": "all", "state": "off"}},
{"name": "lock_door", "arguments": {"location": "front"}}
]
}
The reasoning Field
The optional reasoning string provides a human-readable trace linking query segments to arguments. The training pipeline ignores this field, but it aids debugging and dataset inspection. Example: "user mentioned 'tomorrow' → date param is 2024-01-15".
Defining Tools and Auto-Generating Schemas
The @needle.tool decorator in needle/agent/tools.py eliminates manual schema writing. Define your function with Python type hints:
import needle
@needle.tool
def set_lights(room: str, brightness: int):
"""Set the brightness of a room's lights."""
return {"room": room, "brightness": brightness}
@needle.tool
def get_weather(city: str, units: str = "metric"):
"""Fetch current weather for a city."""
return {"city": city, "units": units}
The decorator registers each function and builds its schema automatically. The generated tools JSON matches OpenAI's function-calling format, ensuring compatibility with standard tool-use datasets.
Loading JSONL Data for Training
In needle/model/finetune.py, the load_jsonl function converts your JSONL file into NumPy arrays for JAX training:
from needle.model.finetune import load_jsonl
from needle.model.tokenizer import get_tokenizer
tokenizer = get_tokenizer()
# Returns padded/truncated token IDs and attention masks
sequences, attention_masks = load_jsonl(
"training_data.jsonl",
tokenizer,
max_len=1024
)
print(sequences.shape) # (num_examples, 1024)
print(attention_masks.shape) # (num_examples, 1024)
The function handles:
- Tokenization of queries, tools, and answers into the model's prompt format
- Padding or truncation to
max_len - Generation of attention masks for variable-length sequences
Lines without a query key are skipped without error.
Generating Synthetic Training Data
Needle provides needle generate-data to synthesize examples from tool schemas using the OpenRouter API. This augments small hand-written datasets.
Step 1: Export your tool schemas to JSON:
from needle.agent.tools import export_schemas
export_schemas([set_lights, get_weather], "my_tools.json")
Step 2: Generate synthetic examples:
export OPENROUTER_API_KEY=sk-...
needle generate-data \
--tools my_tools.json \
--num-samples 500 \
--output data.jsonl
The generate_examples and generate_dataset functions in needle/model/finetune.py handle API calls, schema validation, and JSONL formatting.
Augmenting Existing Datasets
To add generated examples to an existing training file, use augment_jsonl from needle/model/finetune.py:
from needle.model.finetune import augment_jsonl
augment_jsonl(
original_path="existing_data.jsonl",
new_examples=generated_examples,
output_path="combined_data.jsonl"
)
This appends new rows without parsing the entire file into memory, supporting incremental dataset growth.
Complete Workflow Example
# 1. Define tools with auto-generated schemas
import needle
@needle.tool
def search_products(query: str, max_results: int = 10):
"""Search product catalog by query string."""
pass
# 2. Export schemas for data generation
from needle.agent.tools import export_schemas
export_schemas([search_products], "schemas.json")
# 3. Generate synthetic training data (CLI)
# needle generate-data --tools schemas.json --num-samples 1000 --output train.jsonl
# 4. Load for fine-tuning
from needle.model.finetune import load_jsonl
from needle.model.tokenizer import get_tokenizer
tokenizer = get_tokenizer()
seqs, masks = load_jsonl("train.jsonl", tokenizer, max_len=512)
# 5. Start training via CLI
# needle finetune --data train.jsonl --model gpt2 --epochs 3
Summary
- Needle training data uses JSONL format with one JSON object per line
- Required fields:
query(user input) andanswers(tool calls) - Optional fields:
tools(JSON Schemas) andreasoning(debugging notes) - Tool schemas are auto-generated via
@needle.tooldecorator inneedle/agent/tools.py load_jsonlinneedle/model/finetune.pyconverts JSONL to NumPy arrays for training- Use
needle generate-datato synthesize examples from schemas via OpenRouter API
Frequently Asked Questions
What happens if a JSONL line is missing the query field?
Lines without a query key are silently skipped by load_jsonl in needle/model/finetune.py. No error is raised, and processing continues with valid lines. This allows mixed files with metadata headers or incomplete examples.
Can I include multiple tool calls in one training example?
Yes. The answers array supports multiple objects when a query requires sequential or parallel tool execution. Each object needs a name matching a tool in the tools array and valid arguments per that tool's schema.
How do I validate my JSONL file before training?
Needle does not include a standalone validator, but you can verify structure by attempting to load with load_jsonl. For schema validation, check that tool name values in answers exist in the tools list and that arguments match the declared parameters structure.
Is the reasoning field used during model training?
No. The reasoning field is ignored by the training pipeline in needle/model/finetune.py. It exists for human dataset curation and debugging. The model learns only from the structured relationship between query, tools, and answers.
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 →