Create datasets - Braintrust

Upload CSV/JSON

The fastest way to create a dataset is uploading a CSV or JSON file:

  1. Go to Datasets.
  2. If there are existing datasets, click + Dataset. Otherwise, click Upload CSV/JSON.
  3. Drag and drop your file in the Upload dataset dialog.
  4. Columns automatically map to the input field. Drag and drop them into different categories as needed:

The preview table updates in real-time as you move columns between categories, showing exactly how your dataset will be structured. 5. Click Import.

If your data includes an id field, duplicate rows will be deduplicated, with only the last occurrence of each ID kept.

Create via SDK

Create datasets programmatically and populate them with records. The approach varies by language:

TypeScript

import { initDataset } from "braintrust";

async function main() {
  // Initialize dataset (creates it if it doesn't exist)
  const dataset = initDataset("My App", { dataset: "Customer Support" });

// Insert records with input, expected output, and metadata
  dataset.insert({
    input: { question: "How do I reset my password?" },
    expected: { answer: "Click 'Forgot Password' on the login page." },
    metadata: { category: "authentication", difficulty: "easy" },
  });

dataset.insert({
    input: { question: "What's your refund policy?" },
    expected: { answer: "Full refunds within 30 days of purchase." },
    metadata: { category: "billing", difficulty: "easy" },
  });

dataset.insert({
    input: { question: "How do I integrate your API with NextJS?" },
    expected: { answer: "Install the SDK and use our React hooks." },
    metadata: { category: "technical", difficulty: "medium" },
  });

// Flush to ensure all records are saved
  await dataset.flush();
  console.log("Dataset created with 3 records");
}

main();

Python

import braintrust

# Initialize dataset (creates it if it doesn't exist)
dataset = braintrust.init_dataset(project="My App", name="Customer Support")

# Insert records with input, expected output, and metadata
dataset.insert(
    input={"question": "How do I reset my password?"},
    expected={"answer": "Click 'Forgot Password' on the login page."},
    metadata={"category": "authentication", "difficulty": "easy"},
)

dataset.insert(
    input={"question": "What's your refund policy?"},
    expected={"answer": "Full refunds within 30 days of purchase."},
    metadata={"category": "billing", "difficulty": "easy"},
)

dataset.insert(
    input={"question": "How do I integrate your API with NextJS?"},
    expected={"answer": "Install the SDK and use our React hooks."},
    metadata={"category": "technical", "difficulty": "medium"},
)

# Flush to ensure all records are saved
dataset.flush()
print("Dataset created with 3 records")

Go

package main

import (
    "context"
    "fmt"
    "log"
    "os"

"github.com/braintrustdata/braintrust-sdk-go/api"
    "github.com/braintrustdata/braintrust-sdk-go/api/datasets"
    "github.com/braintrustdata/braintrust-sdk-go/api/projects"
)

func main() {
    ctx := context.Background()

// Initialize API client
    client := api.NewClient(os.Getenv("BRAINTRUST_API_KEY"))

// Get or create project
    project, err := client.Projects().Create(ctx, projects.CreateParams{
        Name: "My App",
    })
    if err != nil {
        log.Fatal(err)
    }

// Create dataset
    dataset, err := client.Datasets().Create(ctx, datasets.CreateParams{
        ProjectID: project.ID,
        Name: "Customer Support",
    })
    if err != nil {
        log.Fatal(err)
    }

// Insert records with input, expected output, and metadata
events := []datasets.Event{
    {
        Input: map[string]interface{}{
            "question": "How do I reset my password?",
        },
        Expected: map[string]interface{}{
            "answer": "Click 'Forgot Password' on the login page.",
        },
        Metadata: map[string]interface{}{
            "category": "authentication",
            "difficulty": "easy",
        },
    },
    {
        Input: map[string]interface{}{
            "question": "What's your refund policy?",
        },
        Expected: map[string]interface{}{
            "answer": "Full refunds within 30 days of purchase.",
        },
        Metadata: map[string]interface{}{
            "category": "billing",
            "difficulty": "easy",
        },
    },
    {
        Input: map[string]interface{}{
            "question": "How do I integrate your API with NextJS?",
        },
        Expected: map[string]interface{}{
            "answer": "Install the SDK and use our React hooks.",
        },
        Metadata: map[string]interface{}{
            "category": "technical",
            "difficulty": "medium",
        },
    },
    }

err = client.Datasets().InsertEvents(ctx, dataset.ID, events)
    if err != nil {
        log.Fatal(err)
    }

fmt.Println("Dataset created with 3 records")
}

CLI

Use the bt datasets create CLI command to create datasets directly from the terminal. Accepts JSONL files, stdin, or inline JSON rows.

# Create an empty dataset
bt datasets create my-dataset

# Seed from a JSONL file
bt datasets create my-dataset --file records.jsonl

# Seed from stdin
cat records.jsonl | bt datasets create my-dataset

# Seed with inline JSON rows
bt datasets create my-dataset --rows '[{"id":"case-1","input":{"text":"hi"},"expected":"hello"}]'

Rows that omit an id field get auto-generated stable IDs. Accepted top-level record fields are id, input, expected, metadata, tags, and origin.

Promote traces from logs

You can add a trace to a dataset by mapping fields from a production log span into dataset row format. The span’s input maps to the dataset row’s input, and the span’s output typically becomes the row’s expected value. This is useful when you see a notably good or bad response in production and want to capture it as a test case. You can add traces to datasets with the Braintrust UI or programmatically with the Braintrust API.

To promote logs in bulk, define the mapping once and re-run it as a dataset pipeline.

UI

  1. Go to Logs.
  2. Select the traces you want to add.
  3. Select + Dataset and then the dataset you want to add to.

API

Use the BTQL endpoint to fetch an existing span from your production logs, then insert it into a dataset using the dataset insert API. The origin field links the dataset row back to the source span, creating a Log button in the Origin column.

Curate from topics

Topic classifications turn logs into structured signals you can filter by, such as task type, sentiment, or error category. Filter logs by classification, then promote the matching traces to a dataset for targeted evaluation.See Build datasets from topics for the full workflow.

Curate from user feedback

User feedback from production provides valuable test cases that reflect real user interactions. Use feedback to create datasets from highly-rated examples or problematic cases.See Capture user feedback for implementation details on logging feedback programmatically.To build datasets from feedback:

  1. Filter logs by feedback scores using the Filter menu:
    • scores.user_rating > 0.8 (SQL) or filter: scores.user_rating > 0.8 (BTQL) for highly-rated examples
    • metadata.thumbs_up = false for negative feedback
    • comment IS NOT NULL and scores.correctness < 0.5 for low-scoring feedback with comments
  2. Select the traces you want to include.
  3. Select Add to dataset.
  4. Choose an existing dataset or create a new one.

You can also ask Loop to create datasets based on feedback patterns, such as “Create a dataset from logs with positive feedback” or “Build a dataset from cases where users clicked thumbs down.”

Generate with Loop

Ask Loop to create a dataset based on your logs or specific criteria.Example queries:

Log from production

Track user feedback from your application:

TypeScript

import { initDataset, Dataset } from "braintrust";

class MyApplication {
  private dataset: Dataset | undefined = undefined;

async initApp() {
    this.dataset = await initDataset("My App", { dataset: "logs" });
  }

async logUserExample(
    input: any,
    expected: any,
    userId: string,
    thumbsUp: boolean,
  ) {
    if (this.dataset) {
      this.dataset.insert({
        input,
        expected,
        metadata: { userId, thumbsUp },
      });
    }
  }
}

Python

import braintrust

class MyApplication:
    def init_app(self):
        self.dataset = braintrust.init_dataset(project="My App", name="logs")

def log_user_example(self, input, expected, user_id, thumbs_up):
        if self.dataset:
            self.dataset.insert(
                input=input,
                expected=expected,
                metadata={"user_id": user_id, "thumbs_up": thumbs_up},
            )

Multimodal datasets

You can store and process images and other file types in your datasets. There are several ways to use files in Braintrust:

For large images, use image URLs to keep datasets lightweight. To keep all data within Braintrust, use attachments. Attachments support any file type including images, audio, and PDFs.

TypeScript

import { Attachment, initDataset } from "braintrust";
import path from "node:path";

async function createPdfDataset(): Promise<void> {
  const dataset = initDataset({
    project: "Project with PDFs",
    dataset: "My PDF Dataset",
  });
  for (const filename of ["example.pdf"]) {
    dataset.insert({
      input: {
        file: new Attachment({
          filename,
          contentType: "application/pdf",
          data: path.join("files", filename),
        }),
      },
    });
  }
  await dataset.flush();
}

createPdfDataset();

Python

import os
from braintrust import Attachment, init_dataset

def create_pdf_dataset() -> None:
    dataset = init_dataset("Project with PDFs", "My PDF Dataset")
    for filename in ["example.pdf"]:
        dataset.insert(
            input={
                "file": Attachment(
                    filename=filename,
                    content_type="application/pdf",
                    data=os.path.join("files", filename),
                )
            },
        )
    dataset.flush()

create_pdf_dataset()

Next steps