Skip to content
Open
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
3 changes: 0 additions & 3 deletions valhalla/jawn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
"@anthropic-ai/tokenizer": "^0.0.4",
"@aws-sdk/client-s3": "^3.678.0",
"@aws-sdk/client-sqs": "^3.799.0",
"@aws-sdk/s3-request-presigner": "^3.537.0",
Expand Down Expand Up @@ -52,7 +51,6 @@
"generate-api-key": "^1.0.2",
"gpt-tokenizer": "^2.1.2",
"ioredis": "^5.3.2",
"js-tiktoken": "^1.0.8",
"kafkajs": "^2.2.4",
"lastmile": "^0.4.0",
"llama-api-client": "^0.1.2",
Expand All @@ -71,7 +69,6 @@
"sorted-btree": "^1.8.1",
"stripe": "17.7.0",
"swagger-ui-express": "^5.0.0",
"tiktoken": "^1.0.15",
"typescript": "^5.2.2",
"uuid": "^9.0.1",
"uuidv4": "^6.2.13",
Expand Down
31 changes: 0 additions & 31 deletions valhalla/jawn/src/lib/routers/tokenRouter.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,67 +1,41 @@
import {
calculateModel,
getModelFromResponse,
} from "../../../utils/modelMapper";
import { getTokenCountAnthropic } from "../../tokens/tokenCounter";
import { PromiseGenericResult, ok } from "../../../packages/common/result";
import { IBodyProcessor, ParseInput, ParseOutput } from "./IBodyProcessor";

export class AnthropicBodyProcessor implements IBodyProcessor {
public async parse(
parseInput: ParseInput
): PromiseGenericResult<ParseOutput> {
const { responseBody, requestModel, modelOverride } = parseInput;
const { responseBody } = parseInput;
const parsedResponseBody = JSON.parse(responseBody);
const responseModel = getModelFromResponse(parsedResponseBody);
const model = calculateModel(requestModel, responseModel, modelOverride);

if (
model?.includes("claude-3") ||
model?.includes("claude-sonnet-4") ||
model?.includes("claude-opus-4") ||
// for AI SDK
model?.includes("claude-4")
!parsedResponseBody?.usage?.output_tokens ||
!parsedResponseBody?.usage?.input_tokens
) {
if (
!parsedResponseBody?.usage?.output_tokens ||
!parsedResponseBody?.usage?.input_tokens
) {
return ok({
processedBody: parsedResponseBody,
});
} else {
return ok({
processedBody: parsedResponseBody,
usage: {
totalTokens:
parsedResponseBody?.usage?.input_tokens +
parsedResponseBody?.usage?.output_tokens +
parsedResponseBody?.usage?.cache_creation_input_tokens +
parsedResponseBody?.usage?.cache_read_input_tokens,
promptTokens: parsedResponseBody?.usage?.input_tokens,
promptCacheWriteTokens:
parsedResponseBody?.usage?.cache_creation_input_tokens,
promptCacheReadTokens:
parsedResponseBody?.usage?.cache_read_input_tokens,
completionTokens: parsedResponseBody?.usage?.output_tokens,
promptCacheWrite5m:
parsedResponseBody?.usage?.cache_creation?.ephemeral_5m_input_tokens,
promptCacheWrite1h:
parsedResponseBody?.usage?.cache_creation?.ephemeral_1h_input_tokens,
heliconeCalculated: true,
},
});
}
return ok({
processedBody: parsedResponseBody,
});
} else {
const prompt = parsedResponseBody?.prompt ?? "";
const completion = parsedResponseBody?.completion ?? "";
const completionTokens = await getTokenCountAnthropic(completion);
const promptTokens = await getTokenCountAnthropic(prompt);
return ok({
processedBody: parsedResponseBody,
usage: {
totalTokens: promptTokens + completionTokens,
promptTokens: promptTokens,
completionTokens: completionTokens,
totalTokens:
parsedResponseBody?.usage?.input_tokens +
parsedResponseBody?.usage?.output_tokens +
parsedResponseBody?.usage?.cache_creation_input_tokens +
parsedResponseBody?.usage?.cache_read_input_tokens,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider using nullish coalescing (?? 0) for cache token values to handle undefined values safely in the addition

Prompt To Fix With AI
This is a comment left during a code review.
Path: valhalla/jawn/src/lib/shared/bodyProcessors/anthropicBodyProcessor.ts
Line: 22:26

Comment:
**style:** Consider using nullish coalescing (`?? 0`) for cache token values to handle undefined values safely in the addition

How can I resolve this? If you propose a fix, please make it concise.

promptTokens: parsedResponseBody?.usage?.input_tokens,
promptCacheWriteTokens:
parsedResponseBody?.usage?.cache_creation_input_tokens,
promptCacheReadTokens:
parsedResponseBody?.usage?.cache_read_input_tokens,
completionTokens: parsedResponseBody?.usage?.output_tokens,
promptCacheWrite5m:
parsedResponseBody?.usage?.cache_creation
?.ephemeral_5m_input_tokens,
promptCacheWrite1h:
parsedResponseBody?.usage?.cache_creation
?.ephemeral_1h_input_tokens,
heliconeCalculated: true,
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { calculateModel } from "../../../utils/modelMapper";
import { consolidateTextFields } from "../../../utils/streamParser";
import { getTokenCountAnthropic } from "../../tokens/tokenCounter";
import { PromiseGenericResult, ok } from "../../../packages/common/result";
import { IBodyProcessor, ParseInput, ParseOutput } from "./IBodyProcessor";
import { isParseInputJson } from "./helpers";
Expand All @@ -25,9 +22,7 @@ export class AnthropicStreamBodyProcessor implements IBodyProcessor {
});
}

const { responseBody, requestBody, requestModel, modelOverride } =
parseInput;
const model = calculateModel(requestModel, undefined, modelOverride);
const { responseBody } = parseInput;

// Store the original response body for later use
const originalResponseBody = responseBody;
Expand Down Expand Up @@ -110,69 +105,38 @@ export class AnthropicStreamBodyProcessor implements IBodyProcessor {
}

try {
const processedBody = {
...processConsolidatedJsonForClaude3(processedLines),
// Store the original response body
streamed_data: originalResponseBody,
};

if (
model?.includes("claude-3") ||
model?.includes("claude-sonnet-4") ||
model?.includes("claude-opus-4") ||
// for AI SDK
model?.includes("claude-4")
!processedBody?.usage?.output_tokens ||
!processedBody?.usage?.input_tokens
) {
const processedBody = {
...processConsolidatedJsonForClaude3(processedLines),
// Store the original response body
streamed_data: originalResponseBody,
};

if (
!processedBody?.usage?.output_tokens ||
!processedBody?.usage?.input_tokens
) {
return ok({
processedBody: processedBody,
});
} else {
return ok({
processedBody: processedBody,
usage: {
totalTokens:
processedBody?.usage?.input_tokens +
processedBody?.usage?.output_tokens +
processedBody?.usage?.cache_creation_input_tokens +
processedBody?.usage?.cache_read_input_tokens,
promptTokens: processedBody?.usage?.input_tokens,
promptCacheWriteTokens:
processedBody?.usage?.cache_creation_input_tokens,
promptCacheReadTokens:
processedBody?.usage?.cache_read_input_tokens,
completionTokens: processedBody?.usage?.output_tokens,
promptCacheWrite5m:
processedBody?.usage?.cache_creation?.ephemeral_5m_input_tokens,
promptCacheWrite1h:
processedBody?.usage?.cache_creation?.ephemeral_1h_input_tokens,
heliconeCalculated: true,
},
});
}
return ok({
processedBody: processedBody,
});
} else {
const claudeData = {
...processedLines[processedLines.length - 1],
completion: processedLines.map((d) => d.completion).join(""),
};
const completionTokens = await getTokenCountAnthropic(
claudeData.completion
);
const promptTokens = await getTokenCountAnthropic(
JSON.parse(requestBody ?? "{}")?.prompt ?? ""
);
return ok({
processedBody: {
...consolidateTextFields(processedLines),
streamed_data: originalResponseBody,
},
processedBody: processedBody,
usage: {
totalTokens: completionTokens + promptTokens,
promptTokens: promptTokens,
completionTokens: completionTokens,
totalTokens:
processedBody?.usage?.input_tokens +
processedBody?.usage?.output_tokens +
processedBody?.usage?.cache_creation_input_tokens +
processedBody?.usage?.cache_read_input_tokens,
promptTokens: processedBody?.usage?.input_tokens,
promptCacheWriteTokens:
processedBody?.usage?.cache_creation_input_tokens,
promptCacheReadTokens:
processedBody?.usage?.cache_read_input_tokens,
completionTokens: processedBody?.usage?.output_tokens,
promptCacheWrite5m:
processedBody?.usage?.cache_creation?.ephemeral_5m_input_tokens,
promptCacheWrite1h:
processedBody?.usage?.cache_creation?.ephemeral_1h_input_tokens,
heliconeCalculated: true,
},
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { calculateModel } from "../../../utils/modelMapper";
import { getTokenCountAnthropic } from "../../tokens/tokenCounter";
import { PromiseGenericResult, ok } from "../../../packages/common/result";
import { IBodyProcessor, ParseInput, ParseOutput } from "./IBodyProcessor";
import { isParseInputJson } from "./helpers";
Expand All @@ -14,9 +12,7 @@ export class LlamaStreamBodyProcessor implements IBodyProcessor {
});
}

const { responseBody, requestBody, requestModel, modelOverride } =
parseInput;
const model = calculateModel(requestModel, undefined, modelOverride);
const { responseBody } = parseInput;

const originalResponseBody = responseBody;
const eventLines = responseBody.split("\n");
Expand Down Expand Up @@ -157,20 +153,6 @@ export class LlamaStreamBodyProcessor implements IBodyProcessor {
}
}

if (!usage) {
const completionTokens = await getTokenCountAnthropic(completionText);
const promptTokens = await getTokenCountAnthropic(
JSON.parse(requestBody ?? "{}")?.messages?.map((m: any) => m.content).join("") ?? ""
);

usage = {
totalTokens: completionTokens + promptTokens,
promptTokens: promptTokens,
completionTokens: completionTokens,
heliconeCalculated: true,
};
}

return ok({
processedBody: processedBody,
usage: usage,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { consolidateTextFields } from "../../../utils/streamParser";
import { getTokenCountGPT3 } from "../../tokens/tokenCounter";
import { PromiseGenericResult, err, ok } from "../../../packages/common/result";
import { IBodyProcessor, ParseInput, ParseOutput } from "./IBodyProcessor";
import { isParseInputJson } from "./helpers";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { PromiseGenericResult, ok } from "../../../packages/common/result";
import { IBodyProcessor, ParseInput, ParseOutput } from "./IBodyProcessor";
import { getTokenCountGPT3 } from "../../tokens/tokenCounter";
import { calculateModel } from "../../../utils/modelMapper";

export class VercelStreamProcessor implements IBodyProcessor {
Expand Down Expand Up @@ -105,66 +104,6 @@ export class VercelStreamProcessor implements IBodyProcessor {
requestModel ||
"unknown";

// If usage is all zeros or undefined, calculate tokens as fallback
if (
!usage ||
usage.totalTokens === 0 ||
(usage.promptTokens === 0 && usage.completionTokens === 0)
) {
try {
// Calculate completion tokens
const completionTokens = completionText
? await getTokenCountGPT3(completionText, model)
: 0;
let promptTokens = 0;

// Try to parse the request body to get prompt tokens
if (requestBody) {
try {
const parsedRequest = JSON.parse(requestBody);
// Vercel uses 'messages'
if (
parsedRequest.messages &&
Array.isArray(parsedRequest.messages)
) {
const promptText = parsedRequest.messages
.map((msg: any) => {
if (msg.content) {
// Handle string content
if (typeof msg.content === "string") {
return msg.content;
}
// Handle content array (structured content)
if (Array.isArray(msg.content)) {
return msg.content
.filter((c: any) => c.type === "text")
.map((c: any) => c.text || "")
.join("");
}
}
return "";
})
.join(" ");
promptTokens = promptText
? await getTokenCountGPT3(promptText, model)
: 0;
}
} catch (e) {
console.error("Error parsing request for token calculation", e);
}
}

usage = {
promptTokens,
completionTokens,
totalTokens: promptTokens + completionTokens,
heliconeCalculated: true,
};
} catch (e) {
console.error("Error calculating tokens for Vercel", e);
}
}

try {
// Create OpenAI-compatible response format
const processedBody: any = {
Expand Down
4 changes: 0 additions & 4 deletions valhalla/jawn/src/lib/tokens/gptWorker.js

This file was deleted.

12 changes: 0 additions & 12 deletions valhalla/jawn/src/lib/tokens/gptWorker.ts

This file was deleted.

Loading