Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(ingestion-service): skip tokenization for obs level ERROR
  • Loading branch information
hassiebp committed Sep 15, 2025
commit f6494e68f035e9667c40b5b64136600004f1913a
13 changes: 10 additions & 3 deletions worker/src/services/IngestionService/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { Cluster, Redis } from "ioredis";
import { v4 } from "uuid";
import { Model, Price, PrismaClient, Prompt } from "@langfuse/shared";
import {
Model,
ObservationLevel,
Price,
PrismaClient,
Prompt,
} from "@langfuse/shared";
import {
ClickhouseClientType,
convertDateToClickhouseDateTime,
Expand Down Expand Up @@ -841,9 +847,10 @@ export class IngestionService {
);

if (
// Manual tokenisation when no user provided usage
// Manual tokenisation when no user provided usage and generation has not status ERROR
model &&
Object.keys(providedUsageDetails).length === 0
Object.keys(providedUsageDetails).length === 0 &&
observationRecord.level !== ObservationLevel.ERROR
) {
let newInputCount: number | undefined;
let newOutputCount: number | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1201,4 +1201,61 @@ describe("Token Cost Calculation", () => {
expect(generation.usage_details.output).toBe(generationUsage1.usage.output);
expect(generation.usage_details.total).toBe(generationUsage1.usage.total);
});

it("should skip tokenization and cost calculation if generation status is ERROR", async () => {
const generationUsage1 = {
model: modelName,
input: "hello world",
output: "hey whassup",
usage: null,
level: "ERROR",
};

const events = [
{
id: uuidv4(),
type: "generation-create",
timestamp: new Date().toISOString(),
body: {
id: generationId,
startTime: new Date().toISOString(),
...generationUsage1,
},
},
];

await (mockIngestionService as any).processObservationEventList({
projectId,
entityId: generationId,
createdAtTimestamp: new Date(),
observationEventList: events,
});

expect(mockAddToClickhouseWriter).toHaveBeenCalled();
const args = mockAddToClickhouseWriter.mock.calls[0];
const tableName = args[0];
const generation = args[1];

expect(tableName).toBe("observations");
expect(generation).toBeDefined();
expect(generation.type).toBe("GENERATION");
expect(generation.level).toBe("ERROR");

// Model name should be matched
expect(generation.internal_model_id).toBe(tokenModelData.id);

// No user provided cost
expect(generation.provided_cost_details.input).toBeUndefined();
expect(generation.provided_cost_details.output).toBeUndefined();
expect(generation.provided_cost_details.total).toBeUndefined();

// No calculated cost
expect(generation.cost_details.input).toBeUndefined();
expect(generation.cost_details.output).toBeUndefined();
expect(generation.cost_details.total).toBeUndefined();

expect(generation.usage_details.input).toBeUndefined();
expect(generation.usage_details.output).toBeUndefined();
expect(generation.usage_details.total).toBeUndefined();
});
});
Loading