Create datasets - Braintrust
Upload CSV/JSON
The fastest way to create a dataset is uploading a CSV or JSON file:
- Go to Datasets.
- If there are existing datasets, click + Dataset. Otherwise, click Upload CSV/JSON.
- Drag and drop your file in the Upload dataset dialog.
- Columns automatically map to the
inputfield. Drag and drop them into different categories as needed:
- Input: Fields used as inputs for your task.
- Expected: Ground truth or ideal outputs for scoring.
- Metadata: Additional context for filtering and grouping.
- Tags: Labels for organizing and filtering individual records. When you categorize columns as tags, they’re automatically added to your project’s tag configuration. These are per-record tags, distinct from dataset-level tags that organize datasets in the list.
- Do not import: Exclude columns from the dataset.
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/Python: Use the high-level
initDataset()/init_dataset()method which automatically creates datasets and provides simpleinsert()operations. - Go/Ruby: Use lower-level API methods that require initializing an API client and explicitly managing dataset creation and record insertion.
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
- Go to Logs.
- Select the traces you want to add.
- 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:
- Filter logs by feedback scores using the Filter menu:
scores.user_rating > 0.8(SQL) orfilter: scores.user_rating > 0.8(BTQL) for highly-rated examplesmetadata.thumbs_up = falsefor negative feedbackcomment IS NOT NULL and scores.correctness < 0.5for low-scoring feedback with comments
- Select the traces you want to include.
- Select Add to dataset.
- 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:
- “Generate a dataset from the highest-scoring examples in this experiment”
- “Create a dataset with the most common inputs in the logs”
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:
- Image URLs - Keep datasets lightweight by referencing external images. Best for large images and fastest to sync.
- Base64 - Encode images directly in records. Self-contained but inflates dataset size.
- Attachments (easiest to manage) - Store files directly in Braintrust.
- External attachments - Reference files in your own object stores.
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
- Manage datasets — tag, snapshot, validate, and edit records.
- Use in evaluations with
Eval(). - Track performance across experiments.