Quickstart
Make your first Seer log — measure retrieval quality from unlabeled traffic.
Seer is in private beta. Email ben@seersearch.com to request an API key.
Prefer zero-friction integration? Use the @seer_trace decorator (Python) or wrapWithSeerTrace (TypeScript) to wrap your retrieval function and auto-log query+context.
Quick Start
- Python
- TypeScript
- cURL
Step 1. Install the Seer SDK:
pip install seer-sdk
Step 2. Get an API key from the Seer Console and export it:
export SEER_API_KEY="seer_live_your_key_here"
Step 3. Create quickstart.py and paste:
from seer import SeerClient
client = SeerClient() # reads SEER_API_KEY from env
# Your retrieval step
def retrieve(query: str) -> list[dict]:
# Replace with your real retriever
return [
{"text": "Christopher Nolan directed Inception.", "score": 0.95},
{"text": "Nolan is British-American.", "score": 0.89}
]
query = "Who directed Inception and what is their nationality?"
context = retrieve(query)
client.log(
task=query, # the user query
context=context, # list of passage dicts
metadata={
"env": "prod", # environment tag
"feature_flag": "retrieval-v1", # for A/B testing
},
)
print("Logged to Seer!")
# Events are auto-flushed when the process exits
Step 4. Run it:
python quickstart.py
Step 1. Install the Seer SDK:
npm install @seer/sdk
Step 2. Get an API key from the Seer Console and export it:
export SEER_API_KEY="seer_live_your_key_here"
Step 3. Create quickstart.ts and paste:
import { SeerClient } from '@seer/sdk';
const client = new SeerClient(); // reads SEER_API_KEY from env
// Your retrieval step
function retrieve(query: string) {
// Replace with your real retriever
return [
{ text: "Christopher Nolan directed Inception.", score: 0.95 },
{ text: "Nolan is British-American.", score: 0.89 }
];
}
const query = "Who directed Inception and what is their nationality?";
const context = retrieve(query);
// No await needed! Fire-and-forget by default
client.log({
task: query, // the user query
context: context, // list of passage objects
metadata: {
env: "prod", // environment tag
feature_flag: "retrieval-v1", // for A/B testing
},
});
console.log("Logged to Seer!");
// Events are auto-flushed when the process exits
Step 4. Run it:
npx ts-node quickstart.ts
Step 1. Get an API key from the Seer Console:
export SEER_API_KEY="seer_live_your_key_here"
Step 2. Send a log:
curl -X POST "https://api.seersearch.com/v1/log" \
-H "Authorization: Bearer $SEER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"task": "Who directed Inception and what is their nationality?",
"context": [
{"text": "Christopher Nolan directed Inception.", "score": 0.95},
{"text": "Nolan is British-American.", "score": 0.89}
],
"metadata": {
"env": "prod",
"feature_flag": "retrieval-v1"
}
}'
Using the Decorator / Wrapper
Add logging around your retrieval function without changing call sites:
- Python
- TypeScript
from seer import seer_trace
@seer_trace(
task_arg="query", # which arg is the query
context_from_return=True, # return value is the context
)
def retrieve(query: str) -> list[dict]:
# Your retriever
return [
{"text": "Christopher Nolan directed Inception.", "score": 0.95},
{"text": "Nolan is British-American.", "score": 0.89}
]
# Decorator logs automatically when function is called
results = retrieve("Who directed Inception and what is their nationality?")
print("Decorated call logged to Seer!")
import { wrapWithSeerTrace, SeerClient } from '@seer/sdk';
const client = new SeerClient();
const retrieve = wrapWithSeerTrace(
async (query: string) => {
// Your retriever
return [
{ text: "Christopher Nolan directed Inception.", score: 0.95 },
{ text: "Nolan is British-American.", score: 0.89 }
];
},
{
taskArgIndex: 0, // index of the query argument
contextFromReturn: true, // return value is the context
client,
}
);
// Wrapper logs automatically when function is called
const results = await retrieve("Who directed Inception and what is their nationality?");
console.log("Wrapped call logged to Seer!");
What Happens Next
As logs arrive, Seer evaluates each retrieval to compute metrics:
- Recall: An evaluator model enumerates the minimal disjoint requirements (K) required to answer the question and checks which are supported by your retrieved context.
recall = covered_requirements / K. Seer flags queries with recall < 1.0. - Precision: what proportion of retrieved documents in context are useful to answer the question/task.
unique docs judged "supporting" / docs in context - F1, nDCG: Derived from the recall + precision signals (and optional scores if provided in
contextitems).
Use the Seer dashboard to:
- Compare variants (change testing): Filter by
feature_flagto see A/B impacts. - Monitor production: Filter by
envor anymetadatafield.
Context Format
The context parameter accepts either:
- Simple strings:
["passage 1", "passage 2"] - Passage objects:
[{"text": "passage 1", "score": 0.9}, ...]
When using objects, include at least the text field. Optional fields like score, id, and source enable richer analytics.
See Context & Event Schema for the full specification.
Fire-and-Forget Mode
By default, the SDK operates in fire-and-forget mode:
log()returns immediately (non-blocking)- Events are queued and sent asynchronously
- Events auto-flush when your process exits normally
You only need to call client.flush() if:
- Using
os._exit()(Python) orprocess.exit()(Node.js) - Running a short-lived script that exits too quickly
- You need to ensure events are sent before a specific point
- Python
- TypeScript
# Only needed in special cases
client.flush() # block until all queued events are sent
// Only needed in special cases
await client.flush(); // block until all queued events are sent
Next Steps
- SDK Reference: Python | TypeScript
- Understand Metrics: /metrics
- Set up Change Testing (A/B): /change-testing
- Enable Production Monitoring: /production-monitoring