langsmith 0.3.66 → 0.3.68
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/README.md +1 -0
- package/dist/client.cjs +7 -4
- package/dist/client.d.ts +2 -1
- package/dist/client.js +7 -4
- package/dist/experimental/vercel/index.cjs +15 -3
- package/dist/experimental/vercel/index.js +15 -3
- package/dist/experimental/vercel/middleware.cjs +38 -11
- package/dist/experimental/vercel/middleware.js +38 -11
- package/dist/experimental/vercel/utils.cjs +21 -3
- package/dist/experimental/vercel/utils.js +21 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run_trees.d.ts +1 -1
- package/dist/schemas.d.ts +2 -2
- package/dist/utils/error.cjs +20 -6
- package/dist/utils/error.js +20 -6
- package/dist/utils/vercel.cjs +54 -17
- package/dist/utils/vercel.d.ts +3 -2
- package/dist/utils/vercel.js +54 -17
- package/dist/vercel.cjs +1 -0
- package/dist/vercel.d.ts +3 -0
- package/dist/vercel.js +1 -0
- package/dist/wrappers/openai.cjs +19 -2
- package/dist/wrappers/openai.js +19 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ process.env.LANGSMITH_ENDPOINT = "https://api.smith.langchain.com";
|
|
|
55
55
|
// process.env.LANGSMITH_ENDPOINT = "https://eu.api.smith.langchain.com"; // If signed up in the EU region
|
|
56
56
|
process.env.LANGSMITH_API_KEY = "<YOUR-LANGSMITH-API-KEY>";
|
|
57
57
|
// process.env.LANGSMITH_PROJECT = "My Project Name"; // Optional: "default" is used if not set
|
|
58
|
+
// process.env.LANGSMITH_WORKSPACE_ID = "<YOUR-WORKSPACE-ID>"; // Required for org-scoped API keys
|
|
58
59
|
```
|
|
59
60
|
|
|
60
61
|
> **Tip:** Projects are groups of traces. All runs are logged to a project. If not specified, the project is set to `default`.
|
package/dist/client.cjs
CHANGED
|
@@ -533,7 +533,7 @@ class Client {
|
|
|
533
533
|
signal: AbortSignal.timeout(this.timeout_ms),
|
|
534
534
|
...this.fetchOptions,
|
|
535
535
|
});
|
|
536
|
-
await (0, error_js_1.raiseForStatus)(res, `
|
|
536
|
+
await (0, error_js_1.raiseForStatus)(res, `fetch ${path}`);
|
|
537
537
|
return res;
|
|
538
538
|
});
|
|
539
539
|
return response;
|
|
@@ -556,7 +556,7 @@ class Client {
|
|
|
556
556
|
signal: AbortSignal.timeout(this.timeout_ms),
|
|
557
557
|
...this.fetchOptions,
|
|
558
558
|
});
|
|
559
|
-
await (0, error_js_1.raiseForStatus)(res, `
|
|
559
|
+
await (0, error_js_1.raiseForStatus)(res, `fetch ${path}`);
|
|
560
560
|
return res;
|
|
561
561
|
});
|
|
562
562
|
const items = transform
|
|
@@ -584,7 +584,7 @@ class Client {
|
|
|
584
584
|
...this.fetchOptions,
|
|
585
585
|
body,
|
|
586
586
|
});
|
|
587
|
-
await (0, error_js_1.raiseForStatus)(res, `
|
|
587
|
+
await (0, error_js_1.raiseForStatus)(res, `fetch ${path}`);
|
|
588
588
|
return res;
|
|
589
589
|
});
|
|
590
590
|
const responseBody = await response.json();
|
|
@@ -1987,7 +1987,7 @@ class Client {
|
|
|
1987
1987
|
}
|
|
1988
1988
|
throw new Error("No projects found to resolve tenant.");
|
|
1989
1989
|
}
|
|
1990
|
-
async *listProjects({ projectIds, name, nameContains, referenceDatasetId, referenceDatasetName, datasetVersion, referenceFree, metadata, } = {}) {
|
|
1990
|
+
async *listProjects({ projectIds, name, nameContains, referenceDatasetId, referenceDatasetName, includeStats, datasetVersion, referenceFree, metadata, } = {}) {
|
|
1991
1991
|
const params = new URLSearchParams();
|
|
1992
1992
|
if (projectIds !== undefined) {
|
|
1993
1993
|
for (const projectId of projectIds) {
|
|
@@ -2009,6 +2009,9 @@ class Client {
|
|
|
2009
2009
|
});
|
|
2010
2010
|
params.append("reference_dataset", dataset.id);
|
|
2011
2011
|
}
|
|
2012
|
+
if (includeStats !== undefined) {
|
|
2013
|
+
params.append("include_stats", includeStats.toString());
|
|
2014
|
+
}
|
|
2012
2015
|
if (datasetVersion !== undefined) {
|
|
2013
2016
|
params.append("dataset_version", datasetVersion);
|
|
2014
2017
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -556,12 +556,13 @@ export declare class Client implements LangSmithTracingClientInterface {
|
|
|
556
556
|
datasetName?: string;
|
|
557
557
|
}): Promise<string>;
|
|
558
558
|
private _getTenantId;
|
|
559
|
-
listProjects({ projectIds, name, nameContains, referenceDatasetId, referenceDatasetName, datasetVersion, referenceFree, metadata, }?: {
|
|
559
|
+
listProjects({ projectIds, name, nameContains, referenceDatasetId, referenceDatasetName, includeStats, datasetVersion, referenceFree, metadata, }?: {
|
|
560
560
|
projectIds?: string[];
|
|
561
561
|
name?: string;
|
|
562
562
|
nameContains?: string;
|
|
563
563
|
referenceDatasetId?: string;
|
|
564
564
|
referenceDatasetName?: string;
|
|
565
|
+
includeStats?: boolean;
|
|
565
566
|
datasetVersion?: string;
|
|
566
567
|
referenceFree?: boolean;
|
|
567
568
|
metadata?: RecordStringAny;
|
package/dist/client.js
CHANGED
|
@@ -495,7 +495,7 @@ export class Client {
|
|
|
495
495
|
signal: AbortSignal.timeout(this.timeout_ms),
|
|
496
496
|
...this.fetchOptions,
|
|
497
497
|
});
|
|
498
|
-
await raiseForStatus(res, `
|
|
498
|
+
await raiseForStatus(res, `fetch ${path}`);
|
|
499
499
|
return res;
|
|
500
500
|
});
|
|
501
501
|
return response;
|
|
@@ -518,7 +518,7 @@ export class Client {
|
|
|
518
518
|
signal: AbortSignal.timeout(this.timeout_ms),
|
|
519
519
|
...this.fetchOptions,
|
|
520
520
|
});
|
|
521
|
-
await raiseForStatus(res, `
|
|
521
|
+
await raiseForStatus(res, `fetch ${path}`);
|
|
522
522
|
return res;
|
|
523
523
|
});
|
|
524
524
|
const items = transform
|
|
@@ -546,7 +546,7 @@ export class Client {
|
|
|
546
546
|
...this.fetchOptions,
|
|
547
547
|
body,
|
|
548
548
|
});
|
|
549
|
-
await raiseForStatus(res, `
|
|
549
|
+
await raiseForStatus(res, `fetch ${path}`);
|
|
550
550
|
return res;
|
|
551
551
|
});
|
|
552
552
|
const responseBody = await response.json();
|
|
@@ -1949,7 +1949,7 @@ export class Client {
|
|
|
1949
1949
|
}
|
|
1950
1950
|
throw new Error("No projects found to resolve tenant.");
|
|
1951
1951
|
}
|
|
1952
|
-
async *listProjects({ projectIds, name, nameContains, referenceDatasetId, referenceDatasetName, datasetVersion, referenceFree, metadata, } = {}) {
|
|
1952
|
+
async *listProjects({ projectIds, name, nameContains, referenceDatasetId, referenceDatasetName, includeStats, datasetVersion, referenceFree, metadata, } = {}) {
|
|
1953
1953
|
const params = new URLSearchParams();
|
|
1954
1954
|
if (projectIds !== undefined) {
|
|
1955
1955
|
for (const projectId of projectIds) {
|
|
@@ -1971,6 +1971,9 @@ export class Client {
|
|
|
1971
1971
|
});
|
|
1972
1972
|
params.append("reference_dataset", dataset.id);
|
|
1973
1973
|
}
|
|
1974
|
+
if (includeStats !== undefined) {
|
|
1975
|
+
params.append("include_stats", includeStats.toString());
|
|
1976
|
+
}
|
|
1974
1977
|
if (datasetVersion !== undefined) {
|
|
1975
1978
|
params.append("dataset_version", datasetVersion);
|
|
1976
1979
|
}
|
|
@@ -203,7 +203,7 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
|
|
|
203
203
|
}
|
|
204
204
|
const { content } = lastStep;
|
|
205
205
|
return (0, utils_js_1.convertMessageToTracedFormat)({
|
|
206
|
-
content,
|
|
206
|
+
content: content ?? outputs.outputs.text,
|
|
207
207
|
role: "assistant",
|
|
208
208
|
});
|
|
209
209
|
}
|
|
@@ -331,8 +331,20 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
|
|
|
331
331
|
if (outputs.outputs == null || typeof outputs.outputs !== "object") {
|
|
332
332
|
return outputs;
|
|
333
333
|
}
|
|
334
|
-
|
|
335
|
-
if (content
|
|
334
|
+
let content;
|
|
335
|
+
if ("content" in outputs.outputs && outputs.outputs.content != null) {
|
|
336
|
+
content = await outputs.outputs.content;
|
|
337
|
+
}
|
|
338
|
+
else if ("text" in outputs.outputs &&
|
|
339
|
+
outputs.outputs.text != null) {
|
|
340
|
+
// AI SDK 4 shim
|
|
341
|
+
content = await outputs.outputs.text;
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
return outputs;
|
|
345
|
+
}
|
|
346
|
+
if (content == null ||
|
|
347
|
+
!["object", "string"].includes(typeof content)) {
|
|
336
348
|
return outputs;
|
|
337
349
|
}
|
|
338
350
|
return (0, utils_js_1.convertMessageToTracedFormat)({
|
|
@@ -199,7 +199,7 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
|
|
|
199
199
|
}
|
|
200
200
|
const { content } = lastStep;
|
|
201
201
|
return convertMessageToTracedFormat({
|
|
202
|
-
content,
|
|
202
|
+
content: content ?? outputs.outputs.text,
|
|
203
203
|
role: "assistant",
|
|
204
204
|
});
|
|
205
205
|
}
|
|
@@ -327,8 +327,20 @@ const wrapAISDK = ({ wrapLanguageModel, generateText, streamText, streamObject,
|
|
|
327
327
|
if (outputs.outputs == null || typeof outputs.outputs !== "object") {
|
|
328
328
|
return outputs;
|
|
329
329
|
}
|
|
330
|
-
|
|
331
|
-
if (content
|
|
330
|
+
let content;
|
|
331
|
+
if ("content" in outputs.outputs && outputs.outputs.content != null) {
|
|
332
|
+
content = await outputs.outputs.content;
|
|
333
|
+
}
|
|
334
|
+
else if ("text" in outputs.outputs &&
|
|
335
|
+
outputs.outputs.text != null) {
|
|
336
|
+
// AI SDK 4 shim
|
|
337
|
+
content = await outputs.outputs.text;
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
return outputs;
|
|
341
|
+
}
|
|
342
|
+
if (content == null ||
|
|
343
|
+
!["object", "string"].includes(typeof content)) {
|
|
332
344
|
return outputs;
|
|
333
345
|
}
|
|
334
346
|
return convertMessageToTracedFormat({
|
|
@@ -26,13 +26,24 @@ const setUsageMetadataOnRunTree = (result, runTree) => {
|
|
|
26
26
|
if (result.usage == null || typeof result.usage !== "object") {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
+
// Shim for AI SDK 4
|
|
30
|
+
const inputTokens = result.usage?.inputTokens ??
|
|
31
|
+
result.usage?.promptTokens;
|
|
32
|
+
const outputTokens = result.usage?.outputTokens ??
|
|
33
|
+
result.usage?.completionTokens;
|
|
34
|
+
let totalTokens = result.usage?.totalTokens;
|
|
35
|
+
if (typeof totalTokens !== "number" &&
|
|
36
|
+
typeof inputTokens === "number" &&
|
|
37
|
+
typeof outputTokens === "number") {
|
|
38
|
+
totalTokens = inputTokens + outputTokens;
|
|
39
|
+
}
|
|
29
40
|
const langsmithUsage = {
|
|
30
|
-
input_tokens:
|
|
31
|
-
output_tokens:
|
|
32
|
-
total_tokens:
|
|
41
|
+
input_tokens: inputTokens,
|
|
42
|
+
output_tokens: outputTokens,
|
|
43
|
+
total_tokens: totalTokens,
|
|
33
44
|
};
|
|
34
|
-
const inputTokenDetails = (0, vercel_js_1.extractInputTokenDetails)(result.
|
|
35
|
-
const outputTokenDetails = (0, vercel_js_1.extractOutputTokenDetails)(result.usage
|
|
45
|
+
const inputTokenDetails = (0, vercel_js_1.extractInputTokenDetails)(result.usage, result.providerMetadata);
|
|
46
|
+
const outputTokenDetails = (0, vercel_js_1.extractOutputTokenDetails)(result.usage, result.providerMetadata);
|
|
36
47
|
runTree.extra = {
|
|
37
48
|
...runTree.extra,
|
|
38
49
|
metadata: {
|
|
@@ -130,19 +141,35 @@ function LangSmithMiddleware(config) {
|
|
|
130
141
|
try {
|
|
131
142
|
const output = chunks.reduce((aggregated, chunk) => {
|
|
132
143
|
if (chunk.type === "text-delta") {
|
|
133
|
-
if (chunk.delta
|
|
144
|
+
if (chunk.delta != null) {
|
|
145
|
+
return {
|
|
146
|
+
...aggregated,
|
|
147
|
+
content: aggregated.content + chunk.delta,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
else if ("textDelta" in chunk &&
|
|
151
|
+
chunk.textDelta != null) {
|
|
152
|
+
// AI SDK 4 shim
|
|
153
|
+
return {
|
|
154
|
+
...aggregated,
|
|
155
|
+
content: aggregated.content + chunk.textDelta,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
134
159
|
return aggregated;
|
|
135
160
|
}
|
|
136
|
-
return {
|
|
137
|
-
...aggregated,
|
|
138
|
-
content: aggregated.content + chunk.delta,
|
|
139
|
-
};
|
|
140
161
|
}
|
|
141
162
|
else if (chunk.type === "tool-call") {
|
|
142
163
|
const matchingToolCall = aggregated.tool_calls.find((call) => call.id === chunk.toolCallId);
|
|
143
164
|
if (matchingToolCall != null) {
|
|
144
165
|
return aggregated;
|
|
145
166
|
}
|
|
167
|
+
let chunkArgs = chunk.input;
|
|
168
|
+
if (chunkArgs == null &&
|
|
169
|
+
"args" in chunk &&
|
|
170
|
+
typeof chunk.args === "string") {
|
|
171
|
+
chunkArgs = chunk.args;
|
|
172
|
+
}
|
|
146
173
|
return {
|
|
147
174
|
...aggregated,
|
|
148
175
|
tool_calls: [
|
|
@@ -152,7 +179,7 @@ function LangSmithMiddleware(config) {
|
|
|
152
179
|
type: "function",
|
|
153
180
|
function: {
|
|
154
181
|
name: chunk.toolName,
|
|
155
|
-
arguments:
|
|
182
|
+
arguments: chunkArgs,
|
|
156
183
|
},
|
|
157
184
|
},
|
|
158
185
|
],
|
|
@@ -23,13 +23,24 @@ const setUsageMetadataOnRunTree = (result, runTree) => {
|
|
|
23
23
|
if (result.usage == null || typeof result.usage !== "object") {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
+
// Shim for AI SDK 4
|
|
27
|
+
const inputTokens = result.usage?.inputTokens ??
|
|
28
|
+
result.usage?.promptTokens;
|
|
29
|
+
const outputTokens = result.usage?.outputTokens ??
|
|
30
|
+
result.usage?.completionTokens;
|
|
31
|
+
let totalTokens = result.usage?.totalTokens;
|
|
32
|
+
if (typeof totalTokens !== "number" &&
|
|
33
|
+
typeof inputTokens === "number" &&
|
|
34
|
+
typeof outputTokens === "number") {
|
|
35
|
+
totalTokens = inputTokens + outputTokens;
|
|
36
|
+
}
|
|
26
37
|
const langsmithUsage = {
|
|
27
|
-
input_tokens:
|
|
28
|
-
output_tokens:
|
|
29
|
-
total_tokens:
|
|
38
|
+
input_tokens: inputTokens,
|
|
39
|
+
output_tokens: outputTokens,
|
|
40
|
+
total_tokens: totalTokens,
|
|
30
41
|
};
|
|
31
|
-
const inputTokenDetails = extractInputTokenDetails(result.
|
|
32
|
-
const outputTokenDetails = extractOutputTokenDetails(result.usage
|
|
42
|
+
const inputTokenDetails = extractInputTokenDetails(result.usage, result.providerMetadata);
|
|
43
|
+
const outputTokenDetails = extractOutputTokenDetails(result.usage, result.providerMetadata);
|
|
33
44
|
runTree.extra = {
|
|
34
45
|
...runTree.extra,
|
|
35
46
|
metadata: {
|
|
@@ -127,19 +138,35 @@ export function LangSmithMiddleware(config) {
|
|
|
127
138
|
try {
|
|
128
139
|
const output = chunks.reduce((aggregated, chunk) => {
|
|
129
140
|
if (chunk.type === "text-delta") {
|
|
130
|
-
if (chunk.delta
|
|
141
|
+
if (chunk.delta != null) {
|
|
142
|
+
return {
|
|
143
|
+
...aggregated,
|
|
144
|
+
content: aggregated.content + chunk.delta,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
else if ("textDelta" in chunk &&
|
|
148
|
+
chunk.textDelta != null) {
|
|
149
|
+
// AI SDK 4 shim
|
|
150
|
+
return {
|
|
151
|
+
...aggregated,
|
|
152
|
+
content: aggregated.content + chunk.textDelta,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
131
156
|
return aggregated;
|
|
132
157
|
}
|
|
133
|
-
return {
|
|
134
|
-
...aggregated,
|
|
135
|
-
content: aggregated.content + chunk.delta,
|
|
136
|
-
};
|
|
137
158
|
}
|
|
138
159
|
else if (chunk.type === "tool-call") {
|
|
139
160
|
const matchingToolCall = aggregated.tool_calls.find((call) => call.id === chunk.toolCallId);
|
|
140
161
|
if (matchingToolCall != null) {
|
|
141
162
|
return aggregated;
|
|
142
163
|
}
|
|
164
|
+
let chunkArgs = chunk.input;
|
|
165
|
+
if (chunkArgs == null &&
|
|
166
|
+
"args" in chunk &&
|
|
167
|
+
typeof chunk.args === "string") {
|
|
168
|
+
chunkArgs = chunk.args;
|
|
169
|
+
}
|
|
143
170
|
return {
|
|
144
171
|
...aggregated,
|
|
145
172
|
tool_calls: [
|
|
@@ -149,7 +176,7 @@ export function LangSmithMiddleware(config) {
|
|
|
149
176
|
type: "function",
|
|
150
177
|
function: {
|
|
151
178
|
name: chunk.toolName,
|
|
152
|
-
arguments:
|
|
179
|
+
arguments: chunkArgs,
|
|
153
180
|
},
|
|
154
181
|
},
|
|
155
182
|
],
|
|
@@ -109,14 +109,17 @@ const convertMessageToTracedFormat = (message) => {
|
|
|
109
109
|
block.type === "tool-call");
|
|
110
110
|
});
|
|
111
111
|
const toolCalls = toolCallBlocks.map((block) => {
|
|
112
|
+
// AI SDK 4 shim
|
|
113
|
+
let toolArgs = block.input ?? (("args" in block && block.args) || undefined);
|
|
114
|
+
if (typeof toolArgs !== "string") {
|
|
115
|
+
toolArgs = JSON.stringify(toolArgs);
|
|
116
|
+
}
|
|
112
117
|
return {
|
|
113
118
|
id: block.toolCallId,
|
|
114
119
|
type: "function",
|
|
115
120
|
function: {
|
|
116
121
|
name: block.toolName,
|
|
117
|
-
arguments:
|
|
118
|
-
? JSON.stringify(block.input)
|
|
119
|
-
: block.input,
|
|
122
|
+
arguments: toolArgs,
|
|
120
123
|
},
|
|
121
124
|
};
|
|
122
125
|
});
|
|
@@ -147,6 +150,21 @@ const convertMessageToTracedFormat = (message) => {
|
|
|
147
150
|
});
|
|
148
151
|
formattedMessage.content = newContent;
|
|
149
152
|
}
|
|
153
|
+
else if (message.content == null && "text" in message) {
|
|
154
|
+
// AI SDK 4 shim
|
|
155
|
+
formattedMessage.content = message.text ?? "";
|
|
156
|
+
if ("toolCalls" in message &&
|
|
157
|
+
Array.isArray(message.toolCalls) &&
|
|
158
|
+
!("tool_calls" in formattedMessage)) {
|
|
159
|
+
formattedMessage.tool_calls = message.toolCalls.map((toolCall) => {
|
|
160
|
+
return {
|
|
161
|
+
id: toolCall.toolCallId,
|
|
162
|
+
type: "function",
|
|
163
|
+
function: { name: toolCall.toolName, arguments: toolCall.args },
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
150
168
|
return formattedMessage;
|
|
151
169
|
};
|
|
152
170
|
exports.convertMessageToTracedFormat = convertMessageToTracedFormat;
|
|
@@ -105,14 +105,17 @@ export const convertMessageToTracedFormat = (message) => {
|
|
|
105
105
|
block.type === "tool-call");
|
|
106
106
|
});
|
|
107
107
|
const toolCalls = toolCallBlocks.map((block) => {
|
|
108
|
+
// AI SDK 4 shim
|
|
109
|
+
let toolArgs = block.input ?? (("args" in block && block.args) || undefined);
|
|
110
|
+
if (typeof toolArgs !== "string") {
|
|
111
|
+
toolArgs = JSON.stringify(toolArgs);
|
|
112
|
+
}
|
|
108
113
|
return {
|
|
109
114
|
id: block.toolCallId,
|
|
110
115
|
type: "function",
|
|
111
116
|
function: {
|
|
112
117
|
name: block.toolName,
|
|
113
|
-
arguments:
|
|
114
|
-
? JSON.stringify(block.input)
|
|
115
|
-
: block.input,
|
|
118
|
+
arguments: toolArgs,
|
|
116
119
|
},
|
|
117
120
|
};
|
|
118
121
|
});
|
|
@@ -143,5 +146,20 @@ export const convertMessageToTracedFormat = (message) => {
|
|
|
143
146
|
});
|
|
144
147
|
formattedMessage.content = newContent;
|
|
145
148
|
}
|
|
149
|
+
else if (message.content == null && "text" in message) {
|
|
150
|
+
// AI SDK 4 shim
|
|
151
|
+
formattedMessage.content = message.text ?? "";
|
|
152
|
+
if ("toolCalls" in message &&
|
|
153
|
+
Array.isArray(message.toolCalls) &&
|
|
154
|
+
!("tool_calls" in formattedMessage)) {
|
|
155
|
+
formattedMessage.tool_calls = message.toolCalls.map((toolCall) => {
|
|
156
|
+
return {
|
|
157
|
+
id: toolCall.toolCallId,
|
|
158
|
+
type: "function",
|
|
159
|
+
function: { name: toolCall.toolName, arguments: toolCall.args },
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
146
164
|
return formattedMessage;
|
|
147
165
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -10,4 +10,4 @@ Object.defineProperty(exports, "overrideFetchImplementation", { enumerable: true
|
|
|
10
10
|
var project_js_1 = require("./utils/project.cjs");
|
|
11
11
|
Object.defineProperty(exports, "getDefaultProjectName", { enumerable: true, get: function () { return project_js_1.getDefaultProjectName; } });
|
|
12
12
|
// Update using yarn bump-version
|
|
13
|
-
exports.__version__ = "0.3.
|
|
13
|
+
exports.__version__ = "0.3.68";
|
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export type { Dataset, Example, TracerSession, Run, Feedback, RetrieverOutput, }
|
|
|
3
3
|
export { RunTree, type RunTreeConfig } from "./run_trees.js";
|
|
4
4
|
export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
5
5
|
export { getDefaultProjectName } from "./utils/project.js";
|
|
6
|
-
export declare const __version__ = "0.3.
|
|
6
|
+
export declare const __version__ = "0.3.68";
|
package/dist/index.js
CHANGED
|
@@ -3,4 +3,4 @@ export { RunTree } from "./run_trees.js";
|
|
|
3
3
|
export { overrideFetchImplementation } from "./singletons/fetch.js";
|
|
4
4
|
export { getDefaultProjectName } from "./utils/project.js";
|
|
5
5
|
// Update using yarn bump-version
|
|
6
|
-
export const __version__ = "0.3.
|
|
6
|
+
export const __version__ = "0.3.68";
|
package/dist/run_trees.d.ts
CHANGED
|
@@ -121,7 +121,7 @@ export declare class RunTree implements BaseRun {
|
|
|
121
121
|
addEvent(event: RunEvent | string): void;
|
|
122
122
|
static fromRunnableConfig(parentConfig: RunnableConfigLike, props: RunTreeConfig): RunTree;
|
|
123
123
|
static fromDottedOrder(dottedOrder: string): RunTree | undefined;
|
|
124
|
-
static fromHeaders(headers: Record<string, string | string[]> | HeadersLike, inheritArgs?: RunTreeConfig): RunTree | undefined;
|
|
124
|
+
static fromHeaders(headers: Record<string, string | string[]> | HeadersLike, inheritArgs?: Partial<RunTreeConfig>): RunTree | undefined;
|
|
125
125
|
toHeaders(headers?: HeadersLike): {
|
|
126
126
|
"langsmith-trace": string;
|
|
127
127
|
baggage: string;
|
package/dist/schemas.d.ts
CHANGED
|
@@ -485,7 +485,7 @@ export type InputTokenDetails = {
|
|
|
485
485
|
* Since there was a cache miss, the cache was created from these tokens.
|
|
486
486
|
*/
|
|
487
487
|
cache_creation?: number;
|
|
488
|
-
}
|
|
488
|
+
} & Record<string, number>;
|
|
489
489
|
/**
|
|
490
490
|
* Breakdown of output token counts.
|
|
491
491
|
*
|
|
@@ -503,7 +503,7 @@ export type OutputTokenDetails = {
|
|
|
503
503
|
* OpenAI's o1 models) that are not returned as part of model output.
|
|
504
504
|
*/
|
|
505
505
|
reasoning?: number;
|
|
506
|
-
}
|
|
506
|
+
} & Record<string, number>;
|
|
507
507
|
/**
|
|
508
508
|
* Usage metadata for a message, such as token counts.
|
|
509
509
|
*/
|
package/dist/utils/error.cjs
CHANGED
|
@@ -93,21 +93,35 @@ async function raiseForStatus(response, context, consumeOnSuccess) {
|
|
|
93
93
|
const errorData = await response.json();
|
|
94
94
|
const errorCode = errorData?.error;
|
|
95
95
|
if (errorCode === "org_scoped_key_requires_workspace") {
|
|
96
|
-
|
|
97
|
-
"
|
|
98
|
-
|
|
96
|
+
errorBody =
|
|
97
|
+
"This API key is org-scoped and requires workspace specification. " +
|
|
98
|
+
"Please provide 'workspaceId' parameter, " +
|
|
99
|
+
"or set LANGSMITH_WORKSPACE_ID environment variable.";
|
|
99
100
|
}
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
102
|
}
|
|
101
103
|
catch (e) {
|
|
102
|
-
|
|
104
|
+
const errorWithStatus = new Error(`${response.status} ${response.statusText}`);
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
errorWithStatus.status = response?.status;
|
|
107
|
+
throw errorWithStatus;
|
|
103
108
|
}
|
|
104
109
|
}
|
|
105
|
-
errorBody
|
|
106
|
-
|
|
110
|
+
if (errorBody === undefined) {
|
|
111
|
+
try {
|
|
112
|
+
errorBody = await response.text();
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
errorBody = "";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const fullMessage = `Failed to ${context}. Received status [${response.status}]: ${response.statusText}. Message: ${errorBody}`;
|
|
107
120
|
if (response.status === 409) {
|
|
108
121
|
throw new LangSmithConflictError(fullMessage);
|
|
109
122
|
}
|
|
110
123
|
const err = new Error(fullMessage);
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
125
|
err.status = response.status;
|
|
112
126
|
throw err;
|
|
113
127
|
}
|
package/dist/utils/error.js
CHANGED
|
@@ -86,21 +86,35 @@ export async function raiseForStatus(response, context, consumeOnSuccess) {
|
|
|
86
86
|
const errorData = await response.json();
|
|
87
87
|
const errorCode = errorData?.error;
|
|
88
88
|
if (errorCode === "org_scoped_key_requires_workspace") {
|
|
89
|
-
|
|
90
|
-
"
|
|
91
|
-
|
|
89
|
+
errorBody =
|
|
90
|
+
"This API key is org-scoped and requires workspace specification. " +
|
|
91
|
+
"Please provide 'workspaceId' parameter, " +
|
|
92
|
+
"or set LANGSMITH_WORKSPACE_ID environment variable.";
|
|
92
93
|
}
|
|
94
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
93
95
|
}
|
|
94
96
|
catch (e) {
|
|
95
|
-
|
|
97
|
+
const errorWithStatus = new Error(`${response.status} ${response.statusText}`);
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
errorWithStatus.status = response?.status;
|
|
100
|
+
throw errorWithStatus;
|
|
96
101
|
}
|
|
97
102
|
}
|
|
98
|
-
errorBody
|
|
99
|
-
|
|
103
|
+
if (errorBody === undefined) {
|
|
104
|
+
try {
|
|
105
|
+
errorBody = await response.text();
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
errorBody = "";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const fullMessage = `Failed to ${context}. Received status [${response.status}]: ${response.statusText}. Message: ${errorBody}`;
|
|
100
113
|
if (response.status === 409) {
|
|
101
114
|
throw new LangSmithConflictError(fullMessage);
|
|
102
115
|
}
|
|
103
116
|
const err = new Error(fullMessage);
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
118
|
err.status = response.status;
|
|
105
119
|
throw err;
|
|
106
120
|
}
|
package/dist/utils/vercel.cjs
CHANGED
|
@@ -3,17 +3,41 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.extractOutputTokenDetails = extractOutputTokenDetails;
|
|
4
4
|
exports.extractInputTokenDetails = extractInputTokenDetails;
|
|
5
5
|
exports.extractUsageMetadata = extractUsageMetadata;
|
|
6
|
-
function
|
|
6
|
+
function extractTraceableServiceTier(providerMetadata) {
|
|
7
|
+
if (providerMetadata?.openai != null &&
|
|
8
|
+
typeof providerMetadata.openai === "object") {
|
|
9
|
+
const openai = providerMetadata.openai;
|
|
10
|
+
if (openai.serviceTier != null &&
|
|
11
|
+
typeof openai.serviceTier === "string" &&
|
|
12
|
+
["priority", "flex"].includes(openai.serviceTier)) {
|
|
13
|
+
return openai.serviceTier;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
function extractOutputTokenDetails(usage, providerMetadata) {
|
|
19
|
+
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
20
|
+
const outputTokenDetailsKeyPrefix = openAIServiceTier
|
|
21
|
+
? `${openAIServiceTier}_`
|
|
22
|
+
: "";
|
|
7
23
|
const outputTokenDetails = {};
|
|
8
|
-
if (typeof reasoningTokens === "number") {
|
|
9
|
-
outputTokenDetails
|
|
24
|
+
if (typeof usage?.reasoningTokens === "number") {
|
|
25
|
+
outputTokenDetails[`${outputTokenDetailsKeyPrefix}reasoning`] =
|
|
26
|
+
usage.reasoningTokens;
|
|
27
|
+
}
|
|
28
|
+
if (openAIServiceTier && typeof usage?.outputTokens === "number") {
|
|
29
|
+
// Avoid counting reasoning tokens towards the output token count
|
|
30
|
+
// since service tier tokens are already priced differently
|
|
31
|
+
outputTokenDetails[openAIServiceTier] =
|
|
32
|
+
usage.outputTokens -
|
|
33
|
+
(outputTokenDetails[`${outputTokenDetailsKeyPrefix}reasoning`] ?? 0);
|
|
10
34
|
}
|
|
11
35
|
return outputTokenDetails;
|
|
12
36
|
}
|
|
13
|
-
function extractInputTokenDetails(
|
|
37
|
+
function extractInputTokenDetails(usage, providerMetadata) {
|
|
14
38
|
const inputTokenDetails = {};
|
|
15
|
-
if (providerMetadata
|
|
16
|
-
typeof providerMetadata
|
|
39
|
+
if (providerMetadata?.anthropic != null &&
|
|
40
|
+
typeof providerMetadata?.anthropic === "object") {
|
|
17
41
|
const anthropic = providerMetadata.anthropic;
|
|
18
42
|
if (anthropic.usage != null && typeof anthropic.usage === "object") {
|
|
19
43
|
// Raw usage from Anthropic returned in AI SDK 5
|
|
@@ -54,15 +78,28 @@ function extractInputTokenDetails(providerMetadata, cachedTokenUsage) {
|
|
|
54
78
|
}
|
|
55
79
|
return inputTokenDetails;
|
|
56
80
|
}
|
|
57
|
-
else if (providerMetadata
|
|
58
|
-
typeof providerMetadata
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
else if (providerMetadata?.openai != null &&
|
|
82
|
+
typeof providerMetadata?.openai === "object") {
|
|
83
|
+
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
84
|
+
const outputTokenDetailsKeyPrefix = openAIServiceTier
|
|
85
|
+
? `${openAIServiceTier}_`
|
|
86
|
+
: "";
|
|
87
|
+
if (typeof usage?.cachedInputTokens === "number") {
|
|
88
|
+
inputTokenDetails[`${outputTokenDetailsKeyPrefix}cache_read`] =
|
|
89
|
+
usage.cachedInputTokens;
|
|
90
|
+
}
|
|
91
|
+
else if ("cachedPromptTokens" in providerMetadata.openai &&
|
|
92
|
+
providerMetadata.openai.cachedPromptTokens != null &&
|
|
93
|
+
typeof providerMetadata.openai.cachedPromptTokens === "number") {
|
|
94
|
+
inputTokenDetails[`${outputTokenDetailsKeyPrefix}cache_read`] =
|
|
95
|
+
providerMetadata.openai.cachedPromptTokens;
|
|
63
96
|
}
|
|
64
|
-
|
|
65
|
-
|
|
97
|
+
if (openAIServiceTier && typeof usage?.inputTokens === "number") {
|
|
98
|
+
// Avoid counting cached input tokens towards the input token count
|
|
99
|
+
// since service tier tokens are already priced differently
|
|
100
|
+
inputTokenDetails[openAIServiceTier] =
|
|
101
|
+
usage.inputTokens -
|
|
102
|
+
(inputTokenDetails[`${outputTokenDetailsKeyPrefix}cache_read`] ?? 0);
|
|
66
103
|
}
|
|
67
104
|
}
|
|
68
105
|
return inputTokenDetails;
|
|
@@ -96,9 +133,9 @@ function extractUsageMetadata(span) {
|
|
|
96
133
|
if (typeof span.attributes["ai.response.providerMetadata"] === "string") {
|
|
97
134
|
try {
|
|
98
135
|
const providerMetadata = JSON.parse(span.attributes["ai.response.providerMetadata"]);
|
|
99
|
-
usageMetadata.input_token_details = extractInputTokenDetails(
|
|
100
|
-
? span.attributes["ai.usage.cachedInputTokens"]
|
|
101
|
-
: undefined);
|
|
136
|
+
usageMetadata.input_token_details = extractInputTokenDetails(typeof span.attributes["ai.usage.cachedInputTokens"] === "number"
|
|
137
|
+
? { cachedInputTokens: span.attributes["ai.usage.cachedInputTokens"] }
|
|
138
|
+
: undefined, providerMetadata);
|
|
102
139
|
if (providerMetadata.anthropic != null &&
|
|
103
140
|
typeof providerMetadata.anthropic === "object") {
|
|
104
141
|
// AI SDK does not include Anthropic cache tokens in their stated input token
|
package/dist/utils/vercel.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { LanguageModelV2Usage } from "@ai-sdk/provider";
|
|
1
2
|
import { KVMap } from "../schemas.js";
|
|
2
|
-
export declare function extractOutputTokenDetails(
|
|
3
|
-
export declare function extractInputTokenDetails(providerMetadata
|
|
3
|
+
export declare function extractOutputTokenDetails(usage?: Partial<LanguageModelV2Usage>, providerMetadata?: Record<string, unknown>): Record<string, number>;
|
|
4
|
+
export declare function extractInputTokenDetails(usage?: Partial<LanguageModelV2Usage>, providerMetadata?: Record<string, unknown>): Record<string, number>;
|
|
4
5
|
export declare function extractUsageMetadata(span?: {
|
|
5
6
|
status?: {
|
|
6
7
|
code: number;
|
package/dist/utils/vercel.js
CHANGED
|
@@ -1,14 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
function extractTraceableServiceTier(providerMetadata) {
|
|
2
|
+
if (providerMetadata?.openai != null &&
|
|
3
|
+
typeof providerMetadata.openai === "object") {
|
|
4
|
+
const openai = providerMetadata.openai;
|
|
5
|
+
if (openai.serviceTier != null &&
|
|
6
|
+
typeof openai.serviceTier === "string" &&
|
|
7
|
+
["priority", "flex"].includes(openai.serviceTier)) {
|
|
8
|
+
return openai.serviceTier;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
export function extractOutputTokenDetails(usage, providerMetadata) {
|
|
14
|
+
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
15
|
+
const outputTokenDetailsKeyPrefix = openAIServiceTier
|
|
16
|
+
? `${openAIServiceTier}_`
|
|
17
|
+
: "";
|
|
2
18
|
const outputTokenDetails = {};
|
|
3
|
-
if (typeof reasoningTokens === "number") {
|
|
4
|
-
outputTokenDetails
|
|
19
|
+
if (typeof usage?.reasoningTokens === "number") {
|
|
20
|
+
outputTokenDetails[`${outputTokenDetailsKeyPrefix}reasoning`] =
|
|
21
|
+
usage.reasoningTokens;
|
|
22
|
+
}
|
|
23
|
+
if (openAIServiceTier && typeof usage?.outputTokens === "number") {
|
|
24
|
+
// Avoid counting reasoning tokens towards the output token count
|
|
25
|
+
// since service tier tokens are already priced differently
|
|
26
|
+
outputTokenDetails[openAIServiceTier] =
|
|
27
|
+
usage.outputTokens -
|
|
28
|
+
(outputTokenDetails[`${outputTokenDetailsKeyPrefix}reasoning`] ?? 0);
|
|
5
29
|
}
|
|
6
30
|
return outputTokenDetails;
|
|
7
31
|
}
|
|
8
|
-
export function extractInputTokenDetails(
|
|
32
|
+
export function extractInputTokenDetails(usage, providerMetadata) {
|
|
9
33
|
const inputTokenDetails = {};
|
|
10
|
-
if (providerMetadata
|
|
11
|
-
typeof providerMetadata
|
|
34
|
+
if (providerMetadata?.anthropic != null &&
|
|
35
|
+
typeof providerMetadata?.anthropic === "object") {
|
|
12
36
|
const anthropic = providerMetadata.anthropic;
|
|
13
37
|
if (anthropic.usage != null && typeof anthropic.usage === "object") {
|
|
14
38
|
// Raw usage from Anthropic returned in AI SDK 5
|
|
@@ -49,15 +73,28 @@ export function extractInputTokenDetails(providerMetadata, cachedTokenUsage) {
|
|
|
49
73
|
}
|
|
50
74
|
return inputTokenDetails;
|
|
51
75
|
}
|
|
52
|
-
else if (providerMetadata
|
|
53
|
-
typeof providerMetadata
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
else if (providerMetadata?.openai != null &&
|
|
77
|
+
typeof providerMetadata?.openai === "object") {
|
|
78
|
+
const openAIServiceTier = extractTraceableServiceTier(providerMetadata ?? {});
|
|
79
|
+
const outputTokenDetailsKeyPrefix = openAIServiceTier
|
|
80
|
+
? `${openAIServiceTier}_`
|
|
81
|
+
: "";
|
|
82
|
+
if (typeof usage?.cachedInputTokens === "number") {
|
|
83
|
+
inputTokenDetails[`${outputTokenDetailsKeyPrefix}cache_read`] =
|
|
84
|
+
usage.cachedInputTokens;
|
|
85
|
+
}
|
|
86
|
+
else if ("cachedPromptTokens" in providerMetadata.openai &&
|
|
87
|
+
providerMetadata.openai.cachedPromptTokens != null &&
|
|
88
|
+
typeof providerMetadata.openai.cachedPromptTokens === "number") {
|
|
89
|
+
inputTokenDetails[`${outputTokenDetailsKeyPrefix}cache_read`] =
|
|
90
|
+
providerMetadata.openai.cachedPromptTokens;
|
|
58
91
|
}
|
|
59
|
-
|
|
60
|
-
|
|
92
|
+
if (openAIServiceTier && typeof usage?.inputTokens === "number") {
|
|
93
|
+
// Avoid counting cached input tokens towards the input token count
|
|
94
|
+
// since service tier tokens are already priced differently
|
|
95
|
+
inputTokenDetails[openAIServiceTier] =
|
|
96
|
+
usage.inputTokens -
|
|
97
|
+
(inputTokenDetails[`${outputTokenDetailsKeyPrefix}cache_read`] ?? 0);
|
|
61
98
|
}
|
|
62
99
|
}
|
|
63
100
|
return inputTokenDetails;
|
|
@@ -91,9 +128,9 @@ export function extractUsageMetadata(span) {
|
|
|
91
128
|
if (typeof span.attributes["ai.response.providerMetadata"] === "string") {
|
|
92
129
|
try {
|
|
93
130
|
const providerMetadata = JSON.parse(span.attributes["ai.response.providerMetadata"]);
|
|
94
|
-
usageMetadata.input_token_details = extractInputTokenDetails(
|
|
95
|
-
? span.attributes["ai.usage.cachedInputTokens"]
|
|
96
|
-
: undefined);
|
|
131
|
+
usageMetadata.input_token_details = extractInputTokenDetails(typeof span.attributes["ai.usage.cachedInputTokens"] === "number"
|
|
132
|
+
? { cachedInputTokens: span.attributes["ai.usage.cachedInputTokens"] }
|
|
133
|
+
: undefined, providerMetadata);
|
|
97
134
|
if (providerMetadata.anthropic != null &&
|
|
98
135
|
typeof providerMetadata.anthropic === "object") {
|
|
99
136
|
// AI SDK does not include Anthropic cache tokens in their stated input token
|
package/dist/vercel.cjs
CHANGED
|
@@ -265,6 +265,7 @@ function getParentSpanId(span) {
|
|
|
265
265
|
return (span.parentSpanId ?? span.parentSpanContext?.spanId ?? undefined);
|
|
266
266
|
}
|
|
267
267
|
/**
|
|
268
|
+
* @deprecated Use `wrapAISDK` from `langsmith/experimental/vercel` instead.
|
|
268
269
|
* OpenTelemetry trace exporter for Vercel AI SDK.
|
|
269
270
|
*
|
|
270
271
|
* @example
|
package/dist/vercel.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { generateText } from "ai";
|
|
2
2
|
import { Client } from "./index.js";
|
|
3
|
+
/** @deprecated Use `wrapAISDK` from `langsmith/experimental/vercel` instead. */
|
|
3
4
|
export type AITelemetrySettings = Exclude<Parameters<typeof generateText>[0]["experimental_telemetry"], undefined>;
|
|
5
|
+
/** @deprecated Use `wrapAISDK` from `langsmith/experimental/vercel` instead. */
|
|
4
6
|
export interface TelemetrySettings extends AITelemetrySettings {
|
|
5
7
|
/** ID of the run sent to LangSmith */
|
|
6
8
|
runId?: string;
|
|
@@ -9,6 +11,7 @@ export interface TelemetrySettings extends AITelemetrySettings {
|
|
|
9
11
|
}
|
|
10
12
|
export declare const parseStrippedIsoTime: (stripped: string) => string;
|
|
11
13
|
/**
|
|
14
|
+
* @deprecated Use `wrapAISDK` from `langsmith/experimental/vercel` instead.
|
|
12
15
|
* OpenTelemetry trace exporter for Vercel AI SDK.
|
|
13
16
|
*
|
|
14
17
|
* @example
|
package/dist/vercel.js
CHANGED
|
@@ -261,6 +261,7 @@ function getParentSpanId(span) {
|
|
|
261
261
|
return (span.parentSpanId ?? span.parentSpanContext?.spanId ?? undefined);
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
264
|
+
* @deprecated Use `wrapAISDK` from `langsmith/experimental/vercel` instead.
|
|
264
265
|
* OpenTelemetry trace exporter for Vercel AI SDK.
|
|
265
266
|
*
|
|
266
267
|
* @example
|
package/dist/wrappers/openai.cjs
CHANGED
|
@@ -129,6 +129,12 @@ const textAggregator = (allChunks
|
|
|
129
129
|
};
|
|
130
130
|
function processChatCompletion(outputs) {
|
|
131
131
|
const chatCompletion = outputs;
|
|
132
|
+
const recognizedServiceTier = ["priority", "flex"].includes(chatCompletion.service_tier ?? "")
|
|
133
|
+
? chatCompletion.service_tier
|
|
134
|
+
: undefined;
|
|
135
|
+
const serviceTierPrefix = recognizedServiceTier
|
|
136
|
+
? `${recognizedServiceTier}_`
|
|
137
|
+
: "";
|
|
132
138
|
// copy the original object, minus usage
|
|
133
139
|
const result = { ...chatCompletion };
|
|
134
140
|
const usage = chatCompletion.usage;
|
|
@@ -138,7 +144,7 @@ function processChatCompletion(outputs) {
|
|
|
138
144
|
audio: usage.prompt_tokens_details?.audio_tokens,
|
|
139
145
|
}),
|
|
140
146
|
...(usage.prompt_tokens_details?.cached_tokens !== null && {
|
|
141
|
-
cache_read: usage.prompt_tokens_details?.cached_tokens,
|
|
147
|
+
[`${serviceTierPrefix}cache_read`]: usage.prompt_tokens_details?.cached_tokens,
|
|
142
148
|
}),
|
|
143
149
|
};
|
|
144
150
|
const outputTokenDetails = {
|
|
@@ -146,9 +152,20 @@ function processChatCompletion(outputs) {
|
|
|
146
152
|
audio: usage.completion_tokens_details?.audio_tokens,
|
|
147
153
|
}),
|
|
148
154
|
...(usage.completion_tokens_details?.reasoning_tokens !== null && {
|
|
149
|
-
reasoning: usage.completion_tokens_details?.reasoning_tokens,
|
|
155
|
+
[`${serviceTierPrefix}reasoning`]: usage.completion_tokens_details?.reasoning_tokens,
|
|
150
156
|
}),
|
|
151
157
|
};
|
|
158
|
+
if (recognizedServiceTier) {
|
|
159
|
+
// Avoid counting cache read and reasoning tokens towards the
|
|
160
|
+
// service tier token count since service tier tokens are already
|
|
161
|
+
// priced differently
|
|
162
|
+
inputTokenDetails[recognizedServiceTier] =
|
|
163
|
+
usage.prompt_tokens -
|
|
164
|
+
(inputTokenDetails[`${serviceTierPrefix}cache_read`] ?? 0);
|
|
165
|
+
outputTokenDetails[recognizedServiceTier] =
|
|
166
|
+
usage.completion_tokens -
|
|
167
|
+
(outputTokenDetails[`${serviceTierPrefix}reasoning`] ?? 0);
|
|
168
|
+
}
|
|
152
169
|
result.usage_metadata = {
|
|
153
170
|
input_tokens: usage.prompt_tokens ?? 0,
|
|
154
171
|
output_tokens: usage.completion_tokens ?? 0,
|
package/dist/wrappers/openai.js
CHANGED
|
@@ -126,6 +126,12 @@ const textAggregator = (allChunks
|
|
|
126
126
|
};
|
|
127
127
|
function processChatCompletion(outputs) {
|
|
128
128
|
const chatCompletion = outputs;
|
|
129
|
+
const recognizedServiceTier = ["priority", "flex"].includes(chatCompletion.service_tier ?? "")
|
|
130
|
+
? chatCompletion.service_tier
|
|
131
|
+
: undefined;
|
|
132
|
+
const serviceTierPrefix = recognizedServiceTier
|
|
133
|
+
? `${recognizedServiceTier}_`
|
|
134
|
+
: "";
|
|
129
135
|
// copy the original object, minus usage
|
|
130
136
|
const result = { ...chatCompletion };
|
|
131
137
|
const usage = chatCompletion.usage;
|
|
@@ -135,7 +141,7 @@ function processChatCompletion(outputs) {
|
|
|
135
141
|
audio: usage.prompt_tokens_details?.audio_tokens,
|
|
136
142
|
}),
|
|
137
143
|
...(usage.prompt_tokens_details?.cached_tokens !== null && {
|
|
138
|
-
cache_read: usage.prompt_tokens_details?.cached_tokens,
|
|
144
|
+
[`${serviceTierPrefix}cache_read`]: usage.prompt_tokens_details?.cached_tokens,
|
|
139
145
|
}),
|
|
140
146
|
};
|
|
141
147
|
const outputTokenDetails = {
|
|
@@ -143,9 +149,20 @@ function processChatCompletion(outputs) {
|
|
|
143
149
|
audio: usage.completion_tokens_details?.audio_tokens,
|
|
144
150
|
}),
|
|
145
151
|
...(usage.completion_tokens_details?.reasoning_tokens !== null && {
|
|
146
|
-
reasoning: usage.completion_tokens_details?.reasoning_tokens,
|
|
152
|
+
[`${serviceTierPrefix}reasoning`]: usage.completion_tokens_details?.reasoning_tokens,
|
|
147
153
|
}),
|
|
148
154
|
};
|
|
155
|
+
if (recognizedServiceTier) {
|
|
156
|
+
// Avoid counting cache read and reasoning tokens towards the
|
|
157
|
+
// service tier token count since service tier tokens are already
|
|
158
|
+
// priced differently
|
|
159
|
+
inputTokenDetails[recognizedServiceTier] =
|
|
160
|
+
usage.prompt_tokens -
|
|
161
|
+
(inputTokenDetails[`${serviceTierPrefix}cache_read`] ?? 0);
|
|
162
|
+
outputTokenDetails[recognizedServiceTier] =
|
|
163
|
+
usage.completion_tokens -
|
|
164
|
+
(outputTokenDetails[`${serviceTierPrefix}reasoning`] ?? 0);
|
|
165
|
+
}
|
|
149
166
|
result.usage_metadata = {
|
|
150
167
|
input_tokens: usage.prompt_tokens ?? 0,
|
|
151
168
|
output_tokens: usage.completion_tokens ?? 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.68",
|
|
4
4
|
"description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.",
|
|
5
5
|
"packageManager": "yarn@1.22.19",
|
|
6
6
|
"files": [
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
},
|
|
150
150
|
"devDependencies": {
|
|
151
151
|
"@ai-sdk/anthropic": "^2.0.1",
|
|
152
|
-
"@ai-sdk/openai": "^2.0.
|
|
152
|
+
"@ai-sdk/openai": "^2.0.23",
|
|
153
153
|
"@babel/preset-env": "^7.22.4",
|
|
154
154
|
"@faker-js/faker": "^8.4.1",
|
|
155
155
|
"@jest/globals": "^29.5.0",
|