Data Format for Fine-Tuning Needle 2: JSONL Structure and Schema Requirements

Needle 2 requires a JSON Lines (JSONL) dataset where each line contains a single JSON object with required fields query, tools, and answers, plus optional reasoning and system fields for improved grounding and system message prepending.

The data format for fine-tuning Needle 2 follows a strict schema designed for LoRA adapter training on tool-calling tasks. According to the cactus-compute/needle source code, the pipeline expects training examples in JSONL format, processed by the load_jsonl function in needle/model/finetune.py to render prompt/target pairs for tokenization.

JSONL File Structure

Needle 2 training data uses JSON Lines format (.jsonl), meaning the file contains one JSON object per line with no trailing commas between records. This structure allows the fine-tuning pipeline to stream large datasets efficiently without loading the entire file into memory.

The parser in needle/model/finetune.py reads each line individually, validates the schema, and performs deduplication before feeding examples into the LoRA training loop.

Required Fields

Every training example must include three core fields:

  • query (string): The user request or passage that the model will process. This represents the input context that should trigger specific tool calls.

  • tools (array): A catalogue of tool objects available for the turn. Each object defines the tool name and JSON schema for its parameters. This field can be omitted only if the model already has access to the tools through other means.

  • answers (array): An array of call objects representing the exact tool calls the model should emit for the given query. Each object contains name and arguments keys mapping to the intended function call.

Optional Fields

Two additional fields improve model quality:

  • reasoning (string): A short explanation showing how each argument is derived from a specific span in the query. Including this field teaches the model to ground its arguments to source text, reducing hallucinations.

  • system (string): A system message that will be prepended to the prompt, equivalent to passing Needle(system=...) in the Python API.

Field Specifications and Schema

The answers array must contain only arguments that actually appear in the query text. According to the fine-tuning documentation in doc/finetuning.md, missing optional fields should be omitted entirely rather than filled with placeholder values.

Tool definitions in the tools array follow the JSON Schema format with type, properties, and required keys. The model uses these schemas to validate argument structure during inference.

Best Practices for Training Data

The documentation in doc/finetuning.md specifies several critical rules for dataset curation:

Include off-topic examples. Approximately one in eight examples (≈12.5%) should set "answers": [] to teach the model when not to call any tools. This prevents over-triggering on irrelevant queries.

Provide reasoning traces. While optional, the reasoning field significantly improves argument grounding. The training pipeline in needle/model/finetune.py uses these traces to align parameter values with their source spans in the query text.

Validate argument coverage. Ensure every parameter in answers appears verbatim in the query string. The fine-tuning renderer checks this consistency during prompt generation.

Fine-Tuning Pipeline Implementation

The actual training logic resides in needle/model/finetune.py, which implements the complete LoRA fine-tuning workflow:

  1. Loading: The load_jsonl function streams the dataset line-by-line, parsing each JSON object and filtering malformed entries.

  2. Rendering: Examples are converted to prompt/target pairs using the tokenizer defined in needle/model/tokenizer.py.

  3. Augmentation: The pipeline performs dataset augmentation and deduplication before training.

  4. Training: The finetune_local function handles the LoRA training loop, saving adapter weights for later merging with the base model.

Creating Your Training Dataset

Generate a valid JSONL file using Python's json module:

import json

example = {
    "query": "Bantilan, N. (2018). Themis. Journal of Technology in Human Services, 36(1).",
    "tools": [
        {
            "name": "extract_citation_data",
            "parameters": {
                "type": "object",
                "properties": {
                    "authors": {"type": "string"},
                    "title": {"type": "string"},
                    "publisher": {"type": "string"}
                },
                "required": ["authors", "title"]
            }
        }
    ],
    "answers": [
        {
            "name": "extract_citation_data",
            "arguments": {
                "authors": "Bantilan, N.",
                "title": "Themis",
                "publisher": "Journal of Technology in Human Services, 36(1)."
            }
        }
    ],
    "reasoning": "authors precede the year; title follows the year; publisher is the journal segment"
}

with open("data.jsonl", "w") as f:
    f.write(json.dumps(example) + "\n")

Running Fine-Tuning

Execute the LoRA training using the Needle CLI:


# Train LoRA adapter on custom dataset

needle finetune data.jsonl --epochs 10 --out adapter.pkl

# Merge adapter with base checkpoint to create deployable model

needle build checkpoints/needle2.pkl --lora adapter.pkl --out tuned.cact

The base model checkpoint loading logic in needle/model/run.py handles the initial weight loading before the LoRA adapter is merged during the build process.

Loading Tuned Models

Deploy the fine-tuned model in Python:

import needle

agent = needle.Needle(
    tools=[extract_citation_data], 
    weights="tuned.cact"
)
result = agent.process("Bantilan, N. (2018). Themis...")

Summary

  • Needle 2 requires JSON Lines format (.jsonl) with one JSON object per line, parsed by needle/model/finetune.py.
  • Required fields are query (input text), tools (available functions), and answers (target calls).
  • Optional reasoning fields improve grounding by explaining how arguments map to query spans.
  • Optional system fields prepend system messages to training prompts.
  • Include approximately 12.5% off-topic examples (empty answers arrays) to prevent false positives.
  • Use needle finetune to train LoRA adapters, then needle build to merge them into deployable .cact files.

Frequently Asked Questions

What file extension should I use for Needle 2 training data?

Use the .jsonl extension for JSON Lines format. The load_jsonl function in needle/model/finetune.py expects one valid JSON object per line with newline delimiters, not a JSON array containing multiple objects.

Does the tools field need to be repeated in every example?

No. If the model already knows the available tools through configuration, you can omit the tools field from individual examples. However, including it ensures the training context matches inference conditions exactly.

How should I handle optional parameters that are missing from the query?

Omit missing optional parameters from the arguments object entirely. According to doc/finetuning.md, you should never use placeholder values like "null" or "N/A" for missing optional fields. The model learns to exclude these keys when the information is absent from the query.

Can I mix multiple tool types in a single training file?

Yes. The JSONL format supports heterogeneous training examples. Each line can reference different tools in its tools array and answers array, allowing you to train a single LoRA adapter on diverse tool-calling scenarios.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →