@gammatech/aijsx 0.15.3-dev.2024-10-21 → 0.16.0-dev.2024-10-28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +20 -15
- package/dist/index.d.ts +20 -15
- package/dist/index.js +268 -154
- package/dist/index.mjs +264 -148
- package/dist/{jsx-dev-runtime-lYsmphqH.d.mts → jsx-dev-runtime-yLtSq2UV.d.mts} +13 -6
- package/dist/{jsx-dev-runtime-lYsmphqH.d.ts → jsx-dev-runtime-yLtSq2UV.d.ts} +13 -6
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-dev-runtime.d.ts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/package.json +4 -6
package/dist/index.js
CHANGED
|
@@ -61,16 +61,14 @@ __export(src_exports, {
|
|
|
61
61
|
Trace: () => Trace,
|
|
62
62
|
UserMessage: () => UserMessage,
|
|
63
63
|
VertexAI: () => import_vertexai2.VertexAI,
|
|
64
|
-
anthropicTokenizer: () => anthropicTokenizer,
|
|
65
64
|
attachedContextSymbol: () => attachedContextSymbol,
|
|
66
|
-
computeUsage: () => computeUsage,
|
|
67
65
|
createAIElement: () => createAIElement,
|
|
68
66
|
createContext: () => createContext,
|
|
69
67
|
createPrompt: () => createPrompt,
|
|
70
68
|
createRenderContext: () => createRenderContext,
|
|
71
69
|
evaluatePrompt: () => evaluatePrompt,
|
|
70
|
+
experimental__AnthropicPromptCacheDebugger: () => AnthropicPromptCacheDebugger,
|
|
72
71
|
isPromptParsed: () => isPromptParsed2,
|
|
73
|
-
openaiTokenizer: () => openaiTokenizer,
|
|
74
72
|
toDebugMessage: () => toDebugMessage,
|
|
75
73
|
tracing: () => tracing
|
|
76
74
|
});
|
|
@@ -245,7 +243,7 @@ var UserChatMessageBuilder = class {
|
|
|
245
243
|
this.content.push(props);
|
|
246
244
|
return this;
|
|
247
245
|
}
|
|
248
|
-
async build() {
|
|
246
|
+
async build(opts) {
|
|
249
247
|
const promises = this.content.map(
|
|
250
248
|
async (part) => {
|
|
251
249
|
if (typeof part === "string") {
|
|
@@ -266,7 +264,8 @@ var UserChatMessageBuilder = class {
|
|
|
266
264
|
);
|
|
267
265
|
return {
|
|
268
266
|
role: "user",
|
|
269
|
-
content: await Promise.all(promises)
|
|
267
|
+
content: await Promise.all(promises),
|
|
268
|
+
cachePrompt: opts.cachePrompt
|
|
270
269
|
};
|
|
271
270
|
}
|
|
272
271
|
};
|
|
@@ -284,34 +283,29 @@ var UserMessage = (props) => {
|
|
|
284
283
|
var AssistantMessage = (props) => {
|
|
285
284
|
return props.children;
|
|
286
285
|
};
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
return {
|
|
298
|
-
prompt,
|
|
299
|
-
completion,
|
|
300
|
-
total: prompt + completion
|
|
301
|
-
};
|
|
286
|
+
var ChatMessageXmlAttributes = {
|
|
287
|
+
AssistantMessage: {
|
|
288
|
+
cachePrompt: true
|
|
289
|
+
},
|
|
290
|
+
UserMessage: {
|
|
291
|
+
cachePrompt: true
|
|
292
|
+
},
|
|
293
|
+
SystemMessage: {
|
|
294
|
+
cachePrompt: true
|
|
295
|
+
}
|
|
302
296
|
};
|
|
303
297
|
|
|
304
298
|
// src/createElement.ts
|
|
305
|
-
function createAIElement(
|
|
299
|
+
function createAIElement(tag2, props, ...children) {
|
|
306
300
|
const propsToPass = {
|
|
307
301
|
...props ?? {},
|
|
308
302
|
...children.length === 0 ? {} : { children: children.length === 1 ? children[0] : children }
|
|
309
303
|
};
|
|
310
304
|
const result = {
|
|
311
|
-
tag,
|
|
305
|
+
tag: tag2,
|
|
312
306
|
props: propsToPass,
|
|
313
307
|
render: (ctx) => {
|
|
314
|
-
return
|
|
308
|
+
return tag2(propsToPass, ctx);
|
|
315
309
|
}
|
|
316
310
|
};
|
|
317
311
|
return result;
|
|
@@ -2044,56 +2038,14 @@ var errorToChatCompletionError = (error, requestData) => {
|
|
|
2044
2038
|
);
|
|
2045
2039
|
};
|
|
2046
2040
|
|
|
2047
|
-
// src/lib/openai/tokenizer.ts
|
|
2048
|
-
var import_js_tiktoken = require("js-tiktoken");
|
|
2049
|
-
var cl100kTokenizer = (0, import_js_tiktoken.getEncoding)("cl100k_base");
|
|
2050
|
-
var tokenizer = {
|
|
2051
|
-
encode: (text) => cl100kTokenizer.encode(text),
|
|
2052
|
-
decode: (tokens) => cl100kTokenizer.decode(tokens)
|
|
2053
|
-
};
|
|
2054
|
-
var TOKENS_PER_MESSAGE = 3;
|
|
2055
|
-
var textCost = (content) => {
|
|
2056
|
-
return TOKENS_PER_MESSAGE + tokenizer.encode(content).length;
|
|
2057
|
-
};
|
|
2058
|
-
var COST_PER_LOW = 85;
|
|
2059
|
-
var COST_PER_512x512 = 170;
|
|
2060
|
-
var imageCost = (w, h) => {
|
|
2061
|
-
const area = w * h;
|
|
2062
|
-
return Math.ceil(area / (512 * 512)) * COST_PER_512x512 + COST_PER_LOW;
|
|
2063
|
-
};
|
|
2064
|
-
var openaiTokenizer = (message) => {
|
|
2065
|
-
switch (message.role) {
|
|
2066
|
-
case "assistant":
|
|
2067
|
-
case "system":
|
|
2068
|
-
return textCost(message.content || "");
|
|
2069
|
-
case "user":
|
|
2070
|
-
if (typeof message.content === "string") {
|
|
2071
|
-
return textCost(message.content);
|
|
2072
|
-
}
|
|
2073
|
-
return message.content.reduce((acc, part) => {
|
|
2074
|
-
if (part.type === "text") {
|
|
2075
|
-
return acc + textCost(part.text);
|
|
2076
|
-
} else {
|
|
2077
|
-
if (part.image.detail === "low") {
|
|
2078
|
-
return acc + 85;
|
|
2079
|
-
}
|
|
2080
|
-
if (part.image.dimensions) {
|
|
2081
|
-
return acc + imageCost(
|
|
2082
|
-
part.image.dimensions.width,
|
|
2083
|
-
part.image.dimensions.height
|
|
2084
|
-
);
|
|
2085
|
-
}
|
|
2086
|
-
return acc + imageCost(1024, 1024);
|
|
2087
|
-
}
|
|
2088
|
-
}, 0);
|
|
2089
|
-
}
|
|
2090
|
-
};
|
|
2091
|
-
|
|
2092
2041
|
// src/chat/buildMessages.ts
|
|
2093
2042
|
async function toXml(ctx, children) {
|
|
2094
2043
|
const childrenXml = await ctx.render(children, {
|
|
2095
2044
|
preserveTags: true,
|
|
2096
|
-
renderedProps:
|
|
2045
|
+
renderedProps: {
|
|
2046
|
+
...IMAGE_RENDERED_PROPS,
|
|
2047
|
+
...ChatMessageXmlAttributes
|
|
2048
|
+
}
|
|
2097
2049
|
});
|
|
2098
2050
|
const topLevelTags = ["UserMessage", "AssistantMessage", "SystemMessage"];
|
|
2099
2051
|
const chatMessageTags = [...topLevelTags, "ImagePart"];
|
|
@@ -2133,25 +2085,35 @@ async function buildChatMessages(ctx, children, opts) {
|
|
|
2133
2085
|
throw new Error("Invalid User ChildNode, expecting Text or ImagePart");
|
|
2134
2086
|
}
|
|
2135
2087
|
}
|
|
2136
|
-
return builder.build(
|
|
2088
|
+
return builder.build({
|
|
2089
|
+
cachePrompt: node.attributes.cachePrompt === true
|
|
2090
|
+
});
|
|
2137
2091
|
};
|
|
2138
2092
|
return iterateChatMessageXml(nodes, async (node) => {
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2093
|
+
const cachePrompt = node.attributes.cachePrompt === true;
|
|
2094
|
+
const getMessageWithoutCachePrompt = () => {
|
|
2095
|
+
switch (node.nodeName) {
|
|
2096
|
+
case "UserMessage":
|
|
2097
|
+
return handleUserMessage(node);
|
|
2098
|
+
case "SystemMessage":
|
|
2099
|
+
return {
|
|
2100
|
+
role: "system",
|
|
2101
|
+
content: node.textContent
|
|
2102
|
+
};
|
|
2103
|
+
case "AssistantMessage":
|
|
2104
|
+
return {
|
|
2105
|
+
role: "assistant",
|
|
2106
|
+
content: node.textContent
|
|
2107
|
+
};
|
|
2108
|
+
default:
|
|
2109
|
+
throw new Error("Invalid top level chat message tags");
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
2112
|
+
const message = await getMessageWithoutCachePrompt();
|
|
2113
|
+
return cachePrompt ? {
|
|
2114
|
+
...message,
|
|
2115
|
+
cachePrompt: true
|
|
2116
|
+
} : message;
|
|
2155
2117
|
});
|
|
2156
2118
|
}
|
|
2157
2119
|
|
|
@@ -2251,6 +2213,9 @@ async function* OpenAIChatCompletionInner(props, ctx) {
|
|
|
2251
2213
|
const chatCompletionRequest = {
|
|
2252
2214
|
model: props.model,
|
|
2253
2215
|
max_tokens: props.maxTokens,
|
|
2216
|
+
stream_options: {
|
|
2217
|
+
include_usage: true
|
|
2218
|
+
},
|
|
2254
2219
|
temperature: props.temperature,
|
|
2255
2220
|
stop: props.stop,
|
|
2256
2221
|
messages: openAIMessages,
|
|
@@ -2288,8 +2253,24 @@ async function* OpenAIChatCompletionInner(props, ctx) {
|
|
|
2288
2253
|
}
|
|
2289
2254
|
let finishReason = void 0;
|
|
2290
2255
|
let content = "";
|
|
2256
|
+
let tokensUsed = {
|
|
2257
|
+
prompt: 0,
|
|
2258
|
+
completion: 0,
|
|
2259
|
+
total: 0,
|
|
2260
|
+
cachedPromptTokensCreated: 0,
|
|
2261
|
+
cachedPromptTokensRead: 0
|
|
2262
|
+
};
|
|
2291
2263
|
try {
|
|
2292
2264
|
for await (const message of chatResponse) {
|
|
2265
|
+
if (message.usage) {
|
|
2266
|
+
tokensUsed = {
|
|
2267
|
+
prompt: message.usage.prompt_tokens,
|
|
2268
|
+
completion: message.usage.completion_tokens,
|
|
2269
|
+
total: message.usage.total_tokens,
|
|
2270
|
+
cachedPromptTokensCreated: 0,
|
|
2271
|
+
cachedPromptTokensRead: message.usage.prompt_tokens_details?.cached_tokens || 0
|
|
2272
|
+
};
|
|
2273
|
+
}
|
|
2293
2274
|
if (!message.choices || !message.choices[0]) {
|
|
2294
2275
|
continue;
|
|
2295
2276
|
}
|
|
@@ -2315,10 +2296,6 @@ async function* OpenAIChatCompletionInner(props, ctx) {
|
|
|
2315
2296
|
role: "assistant",
|
|
2316
2297
|
content
|
|
2317
2298
|
};
|
|
2318
|
-
const tokensUsed = computeUsage(
|
|
2319
|
-
[...chatMessages, outputMessage],
|
|
2320
|
-
openaiTokenizer
|
|
2321
|
-
);
|
|
2322
2299
|
const cost = costFn?.(props.model, tokensUsed) ?? void 0;
|
|
2323
2300
|
const responseData = {
|
|
2324
2301
|
...logRequestData,
|
|
@@ -2376,32 +2353,6 @@ var import_openai3 = require("openai");
|
|
|
2376
2353
|
|
|
2377
2354
|
// src/lib/anthropic/Anthropic.tsx
|
|
2378
2355
|
var import_sdk = __toESM(require("@anthropic-ai/sdk"));
|
|
2379
|
-
|
|
2380
|
-
// src/lib/anthropic/tokenizer.ts
|
|
2381
|
-
var import_tokenizer4 = require("@anthropic-ai/tokenizer");
|
|
2382
|
-
var DEFAULT_IMAGE_TOKEN_COST = 1334;
|
|
2383
|
-
var imageTokens = (w, h) => {
|
|
2384
|
-
return Math.ceil(w * h / 750);
|
|
2385
|
-
};
|
|
2386
|
-
var anthropicTokenizer = (message) => {
|
|
2387
|
-
if (message.role === "system") {
|
|
2388
|
-
return (0, import_tokenizer4.countTokens)(message.content);
|
|
2389
|
-
}
|
|
2390
|
-
if (message.role === "assistant") {
|
|
2391
|
-
return (0, import_tokenizer4.countTokens)(message.content);
|
|
2392
|
-
}
|
|
2393
|
-
return message.content.reduce((carry, item) => {
|
|
2394
|
-
let tokens = 0;
|
|
2395
|
-
if (item.type === "text") {
|
|
2396
|
-
tokens = (0, import_tokenizer4.countTokens)(item.text);
|
|
2397
|
-
} else {
|
|
2398
|
-
tokens = item.image.dimensions ? imageTokens(item.image.dimensions.width, item.image.dimensions.height) : DEFAULT_IMAGE_TOKEN_COST;
|
|
2399
|
-
}
|
|
2400
|
-
return carry + tokens;
|
|
2401
|
-
}, 0);
|
|
2402
|
-
};
|
|
2403
|
-
|
|
2404
|
-
// src/lib/anthropic/Anthropic.tsx
|
|
2405
2356
|
var defaultClient2 = null;
|
|
2406
2357
|
var AnthropicClientContext = createContext(async () => {
|
|
2407
2358
|
if (defaultClient2) {
|
|
@@ -2417,21 +2368,73 @@ var AnthropicClientContext = createContext(async () => {
|
|
|
2417
2368
|
return defaultClient2;
|
|
2418
2369
|
});
|
|
2419
2370
|
var defaultMaxTokens = 4096;
|
|
2371
|
+
var populateCacheControl = (message, cachePrompt) => {
|
|
2372
|
+
if (!cachePrompt) {
|
|
2373
|
+
return message;
|
|
2374
|
+
}
|
|
2375
|
+
const content = message.content;
|
|
2376
|
+
if (typeof content === "string") {
|
|
2377
|
+
return {
|
|
2378
|
+
role: message.role,
|
|
2379
|
+
content: [
|
|
2380
|
+
{
|
|
2381
|
+
type: "text",
|
|
2382
|
+
text: content,
|
|
2383
|
+
// @ts-ignore - AnthropicSDK isn't up to date with this
|
|
2384
|
+
cache_control: {
|
|
2385
|
+
type: "ephemeral"
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
]
|
|
2389
|
+
};
|
|
2390
|
+
}
|
|
2391
|
+
if (content.length === 0) {
|
|
2392
|
+
return message;
|
|
2393
|
+
}
|
|
2394
|
+
const lastcontent = {
|
|
2395
|
+
...content[content.length - 1],
|
|
2396
|
+
cache_control: {
|
|
2397
|
+
type: "ephemeral"
|
|
2398
|
+
}
|
|
2399
|
+
};
|
|
2400
|
+
return {
|
|
2401
|
+
role: message.role,
|
|
2402
|
+
content: [...content.slice(0, -1), lastcontent]
|
|
2403
|
+
};
|
|
2404
|
+
};
|
|
2420
2405
|
var buildAnthropicMessages = (chatMesssages) => {
|
|
2421
2406
|
let system = "";
|
|
2422
2407
|
const messages = [];
|
|
2423
|
-
chatMesssages.forEach(({ role, content }) => {
|
|
2408
|
+
chatMesssages.forEach(({ role, content, cachePrompt }) => {
|
|
2424
2409
|
if (role === "system") {
|
|
2425
|
-
|
|
2410
|
+
if (cachePrompt) {
|
|
2411
|
+
system = [
|
|
2412
|
+
{
|
|
2413
|
+
type: "text",
|
|
2414
|
+
text: content,
|
|
2415
|
+
// @ts-ignore - AnthropicSDK isn't up to date with this
|
|
2416
|
+
cache_control: {
|
|
2417
|
+
type: "ephemeral"
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
];
|
|
2421
|
+
} else {
|
|
2422
|
+
system = content;
|
|
2423
|
+
}
|
|
2426
2424
|
return;
|
|
2427
2425
|
}
|
|
2428
2426
|
if (role === "user") {
|
|
2429
2427
|
const userContent = content;
|
|
2430
2428
|
if (userContent.length === 1 && userContent[0].type === "text") {
|
|
2431
|
-
messages.push(
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2429
|
+
messages.push(
|
|
2430
|
+
populateCacheControl(
|
|
2431
|
+
{
|
|
2432
|
+
role,
|
|
2433
|
+
content: userContent[0].text
|
|
2434
|
+
},
|
|
2435
|
+
cachePrompt
|
|
2436
|
+
)
|
|
2437
|
+
);
|
|
2435
2438
|
return;
|
|
2436
2439
|
}
|
|
2437
2440
|
const c = userContent.map((part) => {
|
|
@@ -2456,17 +2459,27 @@ var buildAnthropicMessages = (chatMesssages) => {
|
|
|
2456
2459
|
a.type === "image" || a.type === "text" && a.text.trim().length > 0
|
|
2457
2460
|
)
|
|
2458
2461
|
);
|
|
2459
|
-
messages.push(
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2462
|
+
messages.push(
|
|
2463
|
+
populateCacheControl(
|
|
2464
|
+
{
|
|
2465
|
+
role,
|
|
2466
|
+
content: c
|
|
2467
|
+
},
|
|
2468
|
+
cachePrompt
|
|
2469
|
+
)
|
|
2470
|
+
);
|
|
2463
2471
|
return;
|
|
2464
2472
|
}
|
|
2465
2473
|
if (role === "assistant") {
|
|
2466
|
-
messages.push(
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2474
|
+
messages.push(
|
|
2475
|
+
populateCacheControl(
|
|
2476
|
+
{
|
|
2477
|
+
role,
|
|
2478
|
+
content
|
|
2479
|
+
},
|
|
2480
|
+
cachePrompt
|
|
2481
|
+
)
|
|
2482
|
+
);
|
|
2470
2483
|
return;
|
|
2471
2484
|
}
|
|
2472
2485
|
throw new Error(`Invalid role: ${role}`);
|
|
@@ -2519,6 +2532,9 @@ function AnthropicChatCompletion(props, ctx) {
|
|
|
2519
2532
|
}
|
|
2520
2533
|
);
|
|
2521
2534
|
}
|
|
2535
|
+
var ANTHROPIC_DEFAULT_HEADERS = {
|
|
2536
|
+
"anthropic-beta": "prompt-caching-2024-07-31"
|
|
2537
|
+
};
|
|
2522
2538
|
async function* AnthropicChatCompletionInner(props, ctx) {
|
|
2523
2539
|
const startTime = performance.now();
|
|
2524
2540
|
const { logger, tracer, getContext } = ctx;
|
|
@@ -2556,9 +2572,12 @@ async function* AnthropicChatCompletionInner(props, ctx) {
|
|
|
2556
2572
|
stop_sequences: stopSequences,
|
|
2557
2573
|
model: props.model
|
|
2558
2574
|
};
|
|
2559
|
-
const requestOptions =
|
|
2560
|
-
headers:
|
|
2561
|
-
|
|
2575
|
+
const requestOptions = {
|
|
2576
|
+
headers: {
|
|
2577
|
+
...ANTHROPIC_DEFAULT_HEADERS,
|
|
2578
|
+
...props.extraHeaders
|
|
2579
|
+
}
|
|
2580
|
+
};
|
|
2562
2581
|
const chatCompletionRequestToLog = cleanChatCompletionRequest2(
|
|
2563
2582
|
anthropicCompletionRequest
|
|
2564
2583
|
);
|
|
@@ -2604,13 +2623,27 @@ async function* AnthropicChatCompletionInner(props, ctx) {
|
|
|
2604
2623
|
throw err;
|
|
2605
2624
|
}
|
|
2606
2625
|
let content = "";
|
|
2607
|
-
let outputUsage;
|
|
2608
|
-
let inputUsage;
|
|
2609
2626
|
let finishReason = null;
|
|
2627
|
+
const tokensUsed = {
|
|
2628
|
+
prompt: 0,
|
|
2629
|
+
completion: 0,
|
|
2630
|
+
total: 0,
|
|
2631
|
+
cachedPromptTokensCreated: 0,
|
|
2632
|
+
cachedPromptTokensRead: 0
|
|
2633
|
+
};
|
|
2610
2634
|
try {
|
|
2611
2635
|
for await (const event of response) {
|
|
2612
2636
|
if (event.type === "message_start") {
|
|
2613
|
-
inputUsage = event.message.usage
|
|
2637
|
+
const inputUsage = event.message.usage;
|
|
2638
|
+
if (inputUsage) {
|
|
2639
|
+
const cacheCreated = inputUsage.cache_creation_input_tokens || 0;
|
|
2640
|
+
const cacheRead = inputUsage.cache_read_input_tokens || 0;
|
|
2641
|
+
const promptTokens = inputUsage.input_tokens + cacheCreated + cacheRead;
|
|
2642
|
+
logger.info(`inputUsage: ${JSON.stringify(inputUsage, null, 2)}`);
|
|
2643
|
+
tokensUsed.prompt = promptTokens;
|
|
2644
|
+
tokensUsed.cachedPromptTokensCreated = cacheCreated;
|
|
2645
|
+
tokensUsed.cachedPromptTokensRead = cacheRead;
|
|
2646
|
+
}
|
|
2614
2647
|
}
|
|
2615
2648
|
if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
|
|
2616
2649
|
const chunk = event.delta.text;
|
|
@@ -2619,7 +2652,8 @@ async function* AnthropicChatCompletionInner(props, ctx) {
|
|
|
2619
2652
|
}
|
|
2620
2653
|
if (event.type === "message_delta") {
|
|
2621
2654
|
finishReason = event.delta.stop_reason;
|
|
2622
|
-
|
|
2655
|
+
tokensUsed.completion = event.usage?.output_tokens || 0;
|
|
2656
|
+
tokensUsed.total = tokensUsed.prompt + tokensUsed.completion;
|
|
2623
2657
|
span.setAttributes({
|
|
2624
2658
|
finishReason
|
|
2625
2659
|
});
|
|
@@ -2637,11 +2671,6 @@ async function* AnthropicChatCompletionInner(props, ctx) {
|
|
|
2637
2671
|
role: "assistant",
|
|
2638
2672
|
content
|
|
2639
2673
|
};
|
|
2640
|
-
const tokensUsed = inputUsage !== void 0 && outputUsage !== void 0 ? {
|
|
2641
|
-
prompt: inputUsage,
|
|
2642
|
-
completion: outputUsage,
|
|
2643
|
-
total: inputUsage + outputUsage
|
|
2644
|
-
} : computeUsage([...chatMessages, outputMessage], anthropicTokenizer);
|
|
2645
2674
|
const cost = costFn?.(props.model, tokensUsed) ?? void 0;
|
|
2646
2675
|
const responseData = {
|
|
2647
2676
|
...logRequestData,
|
|
@@ -2699,6 +2728,92 @@ function cleanChatCompletionRequest2(chatCompletionRequest) {
|
|
|
2699
2728
|
// src/lib/anthropic/index.ts
|
|
2700
2729
|
var import_sdk2 = __toESM(require("@anthropic-ai/sdk"));
|
|
2701
2730
|
|
|
2731
|
+
// src/lib/anthropic/AnthropicPromptCacheDebugger.tsx
|
|
2732
|
+
var import_crypto = __toESM(require("crypto"));
|
|
2733
|
+
var renderAttrs = (attrs) => {
|
|
2734
|
+
if (!attrs || Object.keys(attrs).length === 0)
|
|
2735
|
+
return "";
|
|
2736
|
+
return Object.entries(attrs).map(([key, value]) => ` ${key}="${value}"`).join("");
|
|
2737
|
+
};
|
|
2738
|
+
var indentOver = (str, indent) => {
|
|
2739
|
+
const lines = str.split("\n");
|
|
2740
|
+
return lines.map((l) => " ".repeat(indent) + l).join("\n");
|
|
2741
|
+
};
|
|
2742
|
+
var renderTag = (tag2, indent, slice = null) => {
|
|
2743
|
+
if (Array.isArray(tag2)) {
|
|
2744
|
+
return tag2.map((t) => renderTag(t, indent, slice)).join("\n");
|
|
2745
|
+
}
|
|
2746
|
+
if (typeof tag2.children === "string") {
|
|
2747
|
+
const sliced = slice == null ? tag2.children : tag2.children.slice(0, slice);
|
|
2748
|
+
return indentOver(sliced, indent);
|
|
2749
|
+
}
|
|
2750
|
+
if (Array.isArray(tag2.children)) {
|
|
2751
|
+
const children = tag2.children.map((c) => {
|
|
2752
|
+
return renderTag(c, indent + 1, slice);
|
|
2753
|
+
}).join("\n");
|
|
2754
|
+
const res = `<${tag2.type}${renderAttrs(tag2.attrs)}>
|
|
2755
|
+
${children}
|
|
2756
|
+
</${tag2.type}>`;
|
|
2757
|
+
return indentOver(res, indent);
|
|
2758
|
+
}
|
|
2759
|
+
};
|
|
2760
|
+
var tag = (type, attrs, children) => {
|
|
2761
|
+
let c;
|
|
2762
|
+
if (typeof children === "string") {
|
|
2763
|
+
c = children;
|
|
2764
|
+
} else if (!Array.isArray(children)) {
|
|
2765
|
+
c = [children];
|
|
2766
|
+
} else {
|
|
2767
|
+
c = children;
|
|
2768
|
+
}
|
|
2769
|
+
return {
|
|
2770
|
+
type,
|
|
2771
|
+
attrs,
|
|
2772
|
+
children: c
|
|
2773
|
+
};
|
|
2774
|
+
};
|
|
2775
|
+
var AnthropicPromptCacheDebugger = async (props, ctx) => {
|
|
2776
|
+
const chatMessages = await buildChatMessages(ctx, props.children, {
|
|
2777
|
+
useBase64Images: true
|
|
2778
|
+
});
|
|
2779
|
+
const breakpointIndices = chatMessages.map((m, i) => {
|
|
2780
|
+
if (m.cachePrompt) {
|
|
2781
|
+
return i;
|
|
2782
|
+
}
|
|
2783
|
+
return void 0;
|
|
2784
|
+
}).filter((a) => a !== void 0);
|
|
2785
|
+
const messagesToTags = (messages) => {
|
|
2786
|
+
return messages.map((m) => {
|
|
2787
|
+
const role = m.role;
|
|
2788
|
+
const co = m.content;
|
|
2789
|
+
let inner = "";
|
|
2790
|
+
if (typeof co === "string") {
|
|
2791
|
+
inner = co;
|
|
2792
|
+
} else if (Array.isArray(co)) {
|
|
2793
|
+
inner = co.map((c) => {
|
|
2794
|
+
if (c.type === "text") {
|
|
2795
|
+
return tag(c.type, {}, c.text);
|
|
2796
|
+
} else if (c.type === "image") {
|
|
2797
|
+
return tag(c.type, {}, c.image.data?.slice(0, 22) || "image data");
|
|
2798
|
+
}
|
|
2799
|
+
throw new Error("Invalid content");
|
|
2800
|
+
});
|
|
2801
|
+
}
|
|
2802
|
+
return tag(role, {}, inner);
|
|
2803
|
+
});
|
|
2804
|
+
};
|
|
2805
|
+
const final = breakpointIndices.map((acc, i) => {
|
|
2806
|
+
const lastIndex = breakpointIndices[i - 1];
|
|
2807
|
+
const thisIndex = breakpointIndices[i];
|
|
2808
|
+
const toHash = messagesToTags(chatMessages.slice(0, thisIndex + 1));
|
|
2809
|
+
const content = chatMessages.slice(lastIndex + 1, thisIndex + 1);
|
|
2810
|
+
const hash = import_crypto.default.createHash("sha256").update(renderTag(toHash, 0)).digest("hex").slice(0, 8);
|
|
2811
|
+
return tag("breakpoint", { index: i, hash }, messagesToTags(content));
|
|
2812
|
+
});
|
|
2813
|
+
const res = final.map((t) => renderTag(t, 0)).join("\n");
|
|
2814
|
+
return res;
|
|
2815
|
+
};
|
|
2816
|
+
|
|
2702
2817
|
// src/lib/google/Google.tsx
|
|
2703
2818
|
var import_vertexai = require("@google-cloud/vertexai");
|
|
2704
2819
|
|
|
@@ -2899,8 +3014,13 @@ async function* GoogleChatCompletionInner(props, ctx) {
|
|
|
2899
3014
|
throw errorToChatCompletionError2(err, logRequestData);
|
|
2900
3015
|
}
|
|
2901
3016
|
let content = "";
|
|
2902
|
-
|
|
2903
|
-
|
|
3017
|
+
const tokensUsed = {
|
|
3018
|
+
prompt: 0,
|
|
3019
|
+
completion: 0,
|
|
3020
|
+
total: 0,
|
|
3021
|
+
cachedPromptTokensCreated: 0,
|
|
3022
|
+
cachedPromptTokensRead: 0
|
|
3023
|
+
};
|
|
2904
3024
|
let finishReason = null;
|
|
2905
3025
|
try {
|
|
2906
3026
|
for await (const event of response.stream) {
|
|
@@ -2913,10 +3033,10 @@ async function* GoogleChatCompletionInner(props, ctx) {
|
|
|
2913
3033
|
}
|
|
2914
3034
|
if (event.usageMetadata) {
|
|
2915
3035
|
if (event.usageMetadata.promptTokenCount) {
|
|
2916
|
-
|
|
3036
|
+
tokensUsed.prompt = event.usageMetadata.promptTokenCount;
|
|
2917
3037
|
}
|
|
2918
3038
|
if (event.usageMetadata.candidatesTokenCount) {
|
|
2919
|
-
|
|
3039
|
+
tokensUsed.completion = event.usageMetadata.candidatesTokenCount;
|
|
2920
3040
|
}
|
|
2921
3041
|
}
|
|
2922
3042
|
const chunk = event.candidates[0].content;
|
|
@@ -2954,11 +3074,7 @@ async function* GoogleChatCompletionInner(props, ctx) {
|
|
|
2954
3074
|
role: "assistant",
|
|
2955
3075
|
content
|
|
2956
3076
|
};
|
|
2957
|
-
|
|
2958
|
-
prompt: inputUsage,
|
|
2959
|
-
completion: outputUsage,
|
|
2960
|
-
total: inputUsage + outputUsage
|
|
2961
|
-
};
|
|
3077
|
+
tokensUsed.total = tokensUsed.prompt + tokensUsed.completion;
|
|
2962
3078
|
const cost = costFn?.(props.model, tokensUsed) ?? void 0;
|
|
2963
3079
|
const responseData = {
|
|
2964
3080
|
...logRequestData,
|
|
@@ -3040,16 +3156,14 @@ var import_vertexai2 = require("@google-cloud/vertexai");
|
|
|
3040
3156
|
Trace,
|
|
3041
3157
|
UserMessage,
|
|
3042
3158
|
VertexAI,
|
|
3043
|
-
anthropicTokenizer,
|
|
3044
3159
|
attachedContextSymbol,
|
|
3045
|
-
computeUsage,
|
|
3046
3160
|
createAIElement,
|
|
3047
3161
|
createContext,
|
|
3048
3162
|
createPrompt,
|
|
3049
3163
|
createRenderContext,
|
|
3050
3164
|
evaluatePrompt,
|
|
3165
|
+
experimental__AnthropicPromptCacheDebugger,
|
|
3051
3166
|
isPromptParsed,
|
|
3052
|
-
openaiTokenizer,
|
|
3053
3167
|
toDebugMessage,
|
|
3054
3168
|
tracing
|
|
3055
3169
|
});
|