Implementation:Langfuse Langfuse Scores Repository
| Knowledge Sources | |
|---|---|
| Domains | Tracing, Scores, ClickHouse |
| Last Updated | 2026-02-14 00:00 GMT |
Overview
The Scores Repository provides a comprehensive data-access layer for reading, writing, querying, and aggregating score records in ClickHouse, supporting the Langfuse tracing and evaluation system.
Description
This repository module is the primary interface for all score-related database operations against ClickHouse. Scores in Langfuse represent evaluations attached to traces, observations, sessions, or dataset runs. They can originate from annotations (human reviewers), automated evaluators, or API submissions.
The module exports over 30 functions that cover:
- CRUD operations -
upsertScore,getScoreById,getScoresByIds,deleteScore,deleteScoresByTraceIds - Batch retrieval -
getScoresForTraces,getScoresForSessions,getScoresForDatasetRunswith configurable metadata inclusion - Annotation search -
searchExistingAnnotationScorefor finding previously created manual annotations - Table listing with filters -
getScoresTableWithAggregatedScores,getScoresCountForTablefor paginated UI tables - Aggregation and analytics -
getScoresGroupedByName,getScoresGroupedByNameForDashboard,getScoreCountsByProjectAndDay - Streaming -
getScoresStream,getScoresStreamForExportfor large data export - Metadata retrieval -
getScoreMetadataById - Score configuration helpers -
getDistinctScoreNames,getScoreNames
The module uses parameterized ClickHouse SQL queries with proper deduplication via LIMIT 1 BY id, project_id and ORDER BY event_ts DESC patterns. It integrates with the shared filter system (FilterList, createFilterFromFilterState) to support dynamic, user-driven filtering from the UI.
Usage
Use this module when you need to:
- Retrieve scores for display in the traces table, sessions table, or score detail views.
- Upsert scores received via the ingestion API or annotation UI.
- Query aggregated score data for dashboards and analytics.
- Stream score data for CSV or JSON export workflows.
- Search for existing annotation scores before creating duplicates.
- Delete scores as part of trace or project cleanup operations.
Code Reference
Source Location
- Repository: Langfuse
- File: packages/shared/src/server/repositories/scores.ts
- Lines: 1-1818
Signature
export const searchExistingAnnotationScore = async (
projectId: string,
observationId: string | null,
traceId: string | null,
sessionId: string | null,
name: string | undefined,
configId: string | undefined,
dataType: ScoreDataTypeType,
) => ScoreDomain | undefined;
export const getScoreById = async (params: {
projectId: string;
scoreId: string;
source?: ScoreSourceType;
}) => Promise<ScoreDomain | undefined>;
export const getScoresByIds = async (
projectId: string,
scoreId: string[],
source?: ScoreSourceType,
) => Promise<ScoreDomain[]>;
export const upsertScore = async (score: Partial<ScoreRecordReadType>) => Promise<void>;
export const getScoresForTraces = async <ExcludeMetadata extends boolean, IncludeHasMetadata extends boolean>(
props: GetScoresForTracesProps<ExcludeMetadata, IncludeHasMetadata>,
) => ScoreDomain[];
export const getScoresForSessions = async <ExcludeMetadata extends boolean, IncludeHasMetadata extends boolean>(
props: GetScoresForSessionsProps<ExcludeMetadata, IncludeHasMetadata>,
) => ScoreDomain[];
export const getScoresForDatasetRuns = async <ExcludeMetadata extends boolean, IncludeHasMetadata extends boolean>(
props: GetScoresForDatasetRunsProps<ExcludeMetadata, IncludeHasMetadata>,
) => ScoreDomain[];
export const getScoreCountsByProjectAndDay = async (params: {
startDate: Date;
endDate: Date;
}) => Array<{ count: number; projectId: string; date: string }>;
Import
import {
searchExistingAnnotationScore,
getScoreById,
getScoresByIds,
upsertScore,
getScoresForTraces,
getScoresForSessions,
getScoresForDatasetRuns,
getScoreCountsByProjectAndDay,
} from "@langfuse/shared/src/server/repositories/scores";
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| projectId | string | Yes | The project ID scoping all queries |
| scoreId | string | Yes (for single get) | The unique identifier of the score record |
| traceIds | string[] | Yes (for trace scores) | Array of trace IDs to fetch scores for |
| sessionIds | string[] | Yes (for session scores) | Array of session IDs to fetch scores for |
| source | ScoreSourceType | No | Filter by score source (ANNOTATION, API, EVAL) |
| filter | FilterState | No | Dynamic filter conditions from the UI filter bar |
| orderBy | OrderByState | No | Column and direction for sorting results |
| limit / offset | number | No | Pagination parameters |
| excludeMetadata | boolean | No | When true, omits the metadata map from results for performance |
| includeHasMetadata | boolean | No | When true, adds a boolean flag indicating metadata presence |
Outputs
| Name | Type | Description |
|---|---|---|
| ScoreDomain | object | Domain model representing a score with id, name, value, source, traceId, observationId, comment, metadata, etc. |
| ScoreAggregation | object | Aggregated score data grouped by name, with average values and counts |
| count | number | Row counts for paginated table queries |
| stream | ReadableStream | Streaming interface for large data exports |
Usage Examples
// Retrieve a single score by ID
const score = await getScoreById({
projectId: "proj-123",
scoreId: "score-456",
source: "ANNOTATION",
});
// Fetch all scores for a set of traces, excluding metadata for performance
const scores = await getScoresForTraces({
projectId: "proj-123",
traceIds: ["trace-1", "trace-2"],
excludeMetadata: true,
includeHasMetadata: true,
});
// Upsert a score from the ingestion pipeline
await upsertScore({
id: "score-789",
project_id: "proj-123",
name: "accuracy",
timestamp: new Date().toISOString(),
value: 0.95,
source: "API",
data_type: "NUMERIC",
});
// Get aggregated score counts per project per day
const counts = await getScoreCountsByProjectAndDay({
startDate: new Date("2024-03-01"),
endDate: new Date("2024-03-03"),
});