langsmith 0.1.39 → 0.1.40
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/client.cjs +319 -2
- package/dist/client.d.ts +57 -1
- package/dist/client.js +319 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/schemas.d.ts +49 -0
- package/dist/traceable.cjs +58 -1
- package/dist/traceable.d.ts +1 -0
- package/dist/traceable.js +58 -1
- package/dist/utils/prompts.cjs +38 -0
- package/dist/utils/prompts.d.ts +2 -0
- package/dist/utils/prompts.js +33 -0
- package/dist/wrappers/generic.cjs +49 -0
- package/dist/wrappers/generic.d.ts +21 -0
- package/dist/wrappers/generic.js +44 -0
- package/dist/wrappers/index.cjs +3 -0
- package/dist/wrappers/index.d.ts +1 -0
- package/dist/wrappers/index.js +1 -0
- package/dist/wrappers/openai.cjs +1 -38
- package/dist/wrappers/openai.d.ts +1 -16
- package/dist/wrappers/openai.js +0 -36
- package/dist/wrappers/vercel.cjs +100 -0
- package/dist/wrappers/vercel.d.ts +30 -0
- package/dist/wrappers/vercel.js +96 -0
- package/package.json +25 -10
- package/wrappers/vercel.cjs +1 -0
- package/wrappers/vercel.d.cts +1 -0
- package/wrappers/vercel.d.ts +1 -0
- package/wrappers/vercel.js +1 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { parse as parseVersion } from "semver";
|
|
2
|
+
export function isVersionGreaterOrEqual(current_version, target_version) {
|
|
3
|
+
const current = parseVersion(current_version);
|
|
4
|
+
const target = parseVersion(target_version);
|
|
5
|
+
if (!current || !target) {
|
|
6
|
+
throw new Error("Invalid version format.");
|
|
7
|
+
}
|
|
8
|
+
return current.compare(target) >= 0;
|
|
9
|
+
}
|
|
10
|
+
export function parsePromptIdentifier(identifier) {
|
|
11
|
+
if (!identifier ||
|
|
12
|
+
identifier.split("/").length > 2 ||
|
|
13
|
+
identifier.startsWith("/") ||
|
|
14
|
+
identifier.endsWith("/") ||
|
|
15
|
+
identifier.split(":").length > 2) {
|
|
16
|
+
throw new Error(`Invalid identifier format: ${identifier}`);
|
|
17
|
+
}
|
|
18
|
+
const [ownerNamePart, commitPart] = identifier.split(":");
|
|
19
|
+
const commit = commitPart || "latest";
|
|
20
|
+
if (ownerNamePart.includes("/")) {
|
|
21
|
+
const [owner, name] = ownerNamePart.split("/", 2);
|
|
22
|
+
if (!owner || !name) {
|
|
23
|
+
throw new Error(`Invalid identifier format: ${identifier}`);
|
|
24
|
+
}
|
|
25
|
+
return [owner, name, commit];
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
if (!ownerNamePart) {
|
|
29
|
+
throw new Error(`Invalid identifier format: ${identifier}`);
|
|
30
|
+
}
|
|
31
|
+
return ["-", ownerNamePart, commit];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.wrapSDK = exports._wrapClient = void 0;
|
|
4
|
+
const traceable_js_1 = require("../traceable.cjs");
|
|
5
|
+
const _wrapClient = (sdk, runName, options) => {
|
|
6
|
+
return new Proxy(sdk, {
|
|
7
|
+
get(target, propKey, receiver) {
|
|
8
|
+
const originalValue = target[propKey];
|
|
9
|
+
if (typeof originalValue === "function") {
|
|
10
|
+
return (0, traceable_js_1.traceable)(originalValue.bind(target), {
|
|
11
|
+
run_type: "llm",
|
|
12
|
+
...options,
|
|
13
|
+
name: [runName, propKey.toString()].join("."),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
else if (originalValue != null &&
|
|
17
|
+
!Array.isArray(originalValue) &&
|
|
18
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
19
|
+
!(originalValue instanceof Date) &&
|
|
20
|
+
typeof originalValue === "object") {
|
|
21
|
+
return (0, exports._wrapClient)(originalValue, [runName, propKey.toString()].join("."), options);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return Reflect.get(target, propKey, receiver);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
exports._wrapClient = _wrapClient;
|
|
30
|
+
/**
|
|
31
|
+
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
32
|
+
* Method signatures are unchanged.
|
|
33
|
+
*
|
|
34
|
+
* Note that this will wrap and trace ALL SDK methods, not just
|
|
35
|
+
* LLM completion methods. If the passed SDK contains other methods,
|
|
36
|
+
* we recommend using the wrapped instance for LLM calls only.
|
|
37
|
+
* @param sdk An arbitrary SDK instance.
|
|
38
|
+
* @param options LangSmith options.
|
|
39
|
+
* @returns
|
|
40
|
+
*/
|
|
41
|
+
const wrapSDK = (sdk, options) => {
|
|
42
|
+
const traceableOptions = options ? { ...options } : undefined;
|
|
43
|
+
if (traceableOptions != null) {
|
|
44
|
+
delete traceableOptions.runName;
|
|
45
|
+
delete traceableOptions.name;
|
|
46
|
+
}
|
|
47
|
+
return (0, exports._wrapClient)(sdk, options?.name ?? options?.runName ?? sdk.constructor?.name, traceableOptions);
|
|
48
|
+
};
|
|
49
|
+
exports.wrapSDK = wrapSDK;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RunTreeConfig } from "../index.js";
|
|
2
|
+
export declare const _wrapClient: <T extends object>(sdk: T, runName: string, options?: Omit<RunTreeConfig, "name">) => T;
|
|
3
|
+
type WrapSDKOptions = Partial<RunTreeConfig & {
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated Use `name` instead.
|
|
6
|
+
*/
|
|
7
|
+
runName: string;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
11
|
+
* Method signatures are unchanged.
|
|
12
|
+
*
|
|
13
|
+
* Note that this will wrap and trace ALL SDK methods, not just
|
|
14
|
+
* LLM completion methods. If the passed SDK contains other methods,
|
|
15
|
+
* we recommend using the wrapped instance for LLM calls only.
|
|
16
|
+
* @param sdk An arbitrary SDK instance.
|
|
17
|
+
* @param options LangSmith options.
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
export declare const wrapSDK: <T extends object>(sdk: T, options?: WrapSDKOptions) => T;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { traceable } from "../traceable.js";
|
|
2
|
+
export const _wrapClient = (sdk, runName, options) => {
|
|
3
|
+
return new Proxy(sdk, {
|
|
4
|
+
get(target, propKey, receiver) {
|
|
5
|
+
const originalValue = target[propKey];
|
|
6
|
+
if (typeof originalValue === "function") {
|
|
7
|
+
return traceable(originalValue.bind(target), {
|
|
8
|
+
run_type: "llm",
|
|
9
|
+
...options,
|
|
10
|
+
name: [runName, propKey.toString()].join("."),
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
else if (originalValue != null &&
|
|
14
|
+
!Array.isArray(originalValue) &&
|
|
15
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
16
|
+
!(originalValue instanceof Date) &&
|
|
17
|
+
typeof originalValue === "object") {
|
|
18
|
+
return _wrapClient(originalValue, [runName, propKey.toString()].join("."), options);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
return Reflect.get(target, propKey, receiver);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
28
|
+
* Method signatures are unchanged.
|
|
29
|
+
*
|
|
30
|
+
* Note that this will wrap and trace ALL SDK methods, not just
|
|
31
|
+
* LLM completion methods. If the passed SDK contains other methods,
|
|
32
|
+
* we recommend using the wrapped instance for LLM calls only.
|
|
33
|
+
* @param sdk An arbitrary SDK instance.
|
|
34
|
+
* @param options LangSmith options.
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
export const wrapSDK = (sdk, options) => {
|
|
38
|
+
const traceableOptions = options ? { ...options } : undefined;
|
|
39
|
+
if (traceableOptions != null) {
|
|
40
|
+
delete traceableOptions.runName;
|
|
41
|
+
delete traceableOptions.name;
|
|
42
|
+
}
|
|
43
|
+
return _wrapClient(sdk, options?.name ?? options?.runName ?? sdk.constructor?.name, traceableOptions);
|
|
44
|
+
};
|
package/dist/wrappers/index.cjs
CHANGED
|
@@ -14,4 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.wrapSDK = void 0;
|
|
17
18
|
__exportStar(require("./openai.cjs"), exports);
|
|
19
|
+
var generic_js_1 = require("./generic.cjs");
|
|
20
|
+
Object.defineProperty(exports, "wrapSDK", { enumerable: true, get: function () { return generic_js_1.wrapSDK; } });
|
package/dist/wrappers/index.d.ts
CHANGED
package/dist/wrappers/index.js
CHANGED
package/dist/wrappers/openai.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.wrapOpenAI = void 0;
|
|
4
4
|
const traceable_js_1 = require("../traceable.cjs");
|
|
5
5
|
function _combineChatCompletionChoices(choices
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -191,40 +191,3 @@ const wrapOpenAI = (openai, options) => {
|
|
|
191
191
|
return openai;
|
|
192
192
|
};
|
|
193
193
|
exports.wrapOpenAI = wrapOpenAI;
|
|
194
|
-
const _wrapClient = (sdk, runName, options) => {
|
|
195
|
-
return new Proxy(sdk, {
|
|
196
|
-
get(target, propKey, receiver) {
|
|
197
|
-
const originalValue = target[propKey];
|
|
198
|
-
if (typeof originalValue === "function") {
|
|
199
|
-
return (0, traceable_js_1.traceable)(originalValue.bind(target), Object.assign({ name: [runName, propKey.toString()].join("."), run_type: "llm" }, options));
|
|
200
|
-
}
|
|
201
|
-
else if (originalValue != null &&
|
|
202
|
-
!Array.isArray(originalValue) &&
|
|
203
|
-
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
204
|
-
!(originalValue instanceof Date) &&
|
|
205
|
-
typeof originalValue === "object") {
|
|
206
|
-
return _wrapClient(originalValue, [runName, propKey.toString()].join("."), options);
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
return Reflect.get(target, propKey, receiver);
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
});
|
|
213
|
-
};
|
|
214
|
-
/**
|
|
215
|
-
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
216
|
-
* Method signatures are unchanged.
|
|
217
|
-
*
|
|
218
|
-
* Note that this will wrap and trace ALL SDK methods, not just
|
|
219
|
-
* LLM completion methods. If the passed SDK contains other methods,
|
|
220
|
-
* we recommend using the wrapped instance for LLM calls only.
|
|
221
|
-
* @param sdk An arbitrary SDK instance.
|
|
222
|
-
* @param options LangSmith options.
|
|
223
|
-
* @returns
|
|
224
|
-
*/
|
|
225
|
-
const wrapSDK = (sdk, options) => {
|
|
226
|
-
return _wrapClient(sdk, options?.runName ?? sdk.constructor?.name, {
|
|
227
|
-
client: options?.client,
|
|
228
|
-
});
|
|
229
|
-
};
|
|
230
|
-
exports.wrapSDK = wrapSDK;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OpenAI } from "openai";
|
|
2
2
|
import type { APIPromise } from "openai/core";
|
|
3
|
-
import type {
|
|
3
|
+
import type { RunTreeConfig } from "../index.js";
|
|
4
4
|
type OpenAIType = {
|
|
5
5
|
chat: {
|
|
6
6
|
completions: {
|
|
@@ -63,19 +63,4 @@ type PatchedOpenAIClient<T extends OpenAIType> = T & {
|
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
65
|
export declare const wrapOpenAI: <T extends OpenAIType>(openai: T, options?: Partial<RunTreeConfig>) => PatchedOpenAIClient<T>;
|
|
66
|
-
/**
|
|
67
|
-
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
68
|
-
* Method signatures are unchanged.
|
|
69
|
-
*
|
|
70
|
-
* Note that this will wrap and trace ALL SDK methods, not just
|
|
71
|
-
* LLM completion methods. If the passed SDK contains other methods,
|
|
72
|
-
* we recommend using the wrapped instance for LLM calls only.
|
|
73
|
-
* @param sdk An arbitrary SDK instance.
|
|
74
|
-
* @param options LangSmith options.
|
|
75
|
-
* @returns
|
|
76
|
-
*/
|
|
77
|
-
export declare const wrapSDK: <T extends object>(sdk: T, options?: {
|
|
78
|
-
client?: Client;
|
|
79
|
-
runName?: string;
|
|
80
|
-
}) => T;
|
|
81
66
|
export {};
|
package/dist/wrappers/openai.js
CHANGED
|
@@ -187,39 +187,3 @@ export const wrapOpenAI = (openai, options) => {
|
|
|
187
187
|
});
|
|
188
188
|
return openai;
|
|
189
189
|
};
|
|
190
|
-
const _wrapClient = (sdk, runName, options) => {
|
|
191
|
-
return new Proxy(sdk, {
|
|
192
|
-
get(target, propKey, receiver) {
|
|
193
|
-
const originalValue = target[propKey];
|
|
194
|
-
if (typeof originalValue === "function") {
|
|
195
|
-
return traceable(originalValue.bind(target), Object.assign({ name: [runName, propKey.toString()].join("."), run_type: "llm" }, options));
|
|
196
|
-
}
|
|
197
|
-
else if (originalValue != null &&
|
|
198
|
-
!Array.isArray(originalValue) &&
|
|
199
|
-
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
200
|
-
!(originalValue instanceof Date) &&
|
|
201
|
-
typeof originalValue === "object") {
|
|
202
|
-
return _wrapClient(originalValue, [runName, propKey.toString()].join("."), options);
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
return Reflect.get(target, propKey, receiver);
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
});
|
|
209
|
-
};
|
|
210
|
-
/**
|
|
211
|
-
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
212
|
-
* Method signatures are unchanged.
|
|
213
|
-
*
|
|
214
|
-
* Note that this will wrap and trace ALL SDK methods, not just
|
|
215
|
-
* LLM completion methods. If the passed SDK contains other methods,
|
|
216
|
-
* we recommend using the wrapped instance for LLM calls only.
|
|
217
|
-
* @param sdk An arbitrary SDK instance.
|
|
218
|
-
* @param options LangSmith options.
|
|
219
|
-
* @returns
|
|
220
|
-
*/
|
|
221
|
-
export const wrapSDK = (sdk, options) => {
|
|
222
|
-
return _wrapClient(sdk, options?.runName ?? sdk.constructor?.name, {
|
|
223
|
-
client: options?.client,
|
|
224
|
-
});
|
|
225
|
-
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.wrapAISDKModel = void 0;
|
|
4
|
+
const traceable_js_1 = require("../traceable.cjs");
|
|
5
|
+
const generic_js_1 = require("./generic.cjs");
|
|
6
|
+
/**
|
|
7
|
+
* Wrap a Vercel AI SDK model, enabling automatic LangSmith tracing.
|
|
8
|
+
* After wrapping a model, you can use it with the Vercel AI SDK Core
|
|
9
|
+
* methods as normal.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { anthropic } from "@ai-sdk/anthropic";
|
|
14
|
+
* import { streamText } from "ai";
|
|
15
|
+
* import { wrapAISDKModel } from "langsmith/wrappers/vercel";
|
|
16
|
+
*
|
|
17
|
+
* const anthropicModel = anthropic("claude-3-haiku-20240307");
|
|
18
|
+
*
|
|
19
|
+
* const modelWithTracing = wrapAISDKModel(anthropicModel);
|
|
20
|
+
*
|
|
21
|
+
* const { textStream } = await streamText({
|
|
22
|
+
* model: modelWithTracing,
|
|
23
|
+
* prompt: "Write a vegetarian lasagna recipe for 4 people.",
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* for await (const chunk of textStream) {
|
|
27
|
+
* console.log(chunk);
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
* @param model An AI SDK model instance.
|
|
31
|
+
* @param options LangSmith options.
|
|
32
|
+
* @returns
|
|
33
|
+
*/
|
|
34
|
+
const wrapAISDKModel = (model, options) => {
|
|
35
|
+
if (!("doStream" in model) ||
|
|
36
|
+
typeof model.doStream !== "function" ||
|
|
37
|
+
!("doGenerate" in model) ||
|
|
38
|
+
typeof model.doGenerate !== "function") {
|
|
39
|
+
throw new Error(`Received invalid input. This version of wrapAISDKModel only supports Vercel LanguageModelV1 instances.`);
|
|
40
|
+
}
|
|
41
|
+
const runName = options?.name ?? model.constructor?.name;
|
|
42
|
+
return new Proxy(model, {
|
|
43
|
+
get(target, propKey, receiver) {
|
|
44
|
+
const originalValue = target[propKey];
|
|
45
|
+
if (typeof originalValue === "function") {
|
|
46
|
+
let __finalTracedIteratorKey;
|
|
47
|
+
let aggregator;
|
|
48
|
+
if (propKey === "doStream") {
|
|
49
|
+
__finalTracedIteratorKey = "stream";
|
|
50
|
+
aggregator = (chunks) => {
|
|
51
|
+
return chunks.reduce((aggregated, chunk) => {
|
|
52
|
+
if (chunk.type === "text-delta") {
|
|
53
|
+
return {
|
|
54
|
+
...aggregated,
|
|
55
|
+
text: aggregated.text + chunk.textDelta,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
else if (chunk.type === "tool-call") {
|
|
59
|
+
return {
|
|
60
|
+
...aggregated,
|
|
61
|
+
...chunk,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
else if (chunk.type === "finish") {
|
|
65
|
+
return {
|
|
66
|
+
...aggregated,
|
|
67
|
+
usage: chunk.usage,
|
|
68
|
+
finishReason: chunk.finishReason,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
return aggregated;
|
|
73
|
+
}
|
|
74
|
+
}, {
|
|
75
|
+
text: "",
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return (0, traceable_js_1.traceable)(originalValue.bind(target), {
|
|
80
|
+
run_type: "llm",
|
|
81
|
+
name: runName,
|
|
82
|
+
...options,
|
|
83
|
+
__finalTracedIteratorKey,
|
|
84
|
+
aggregator,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else if (originalValue != null &&
|
|
88
|
+
!Array.isArray(originalValue) &&
|
|
89
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
90
|
+
!(originalValue instanceof Date) &&
|
|
91
|
+
typeof originalValue === "object") {
|
|
92
|
+
return (0, generic_js_1._wrapClient)(originalValue, [runName, propKey.toString()].join("."), options);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return Reflect.get(target, propKey, receiver);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
exports.wrapAISDKModel = wrapAISDKModel;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RunTreeConfig } from "../index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Wrap a Vercel AI SDK model, enabling automatic LangSmith tracing.
|
|
4
|
+
* After wrapping a model, you can use it with the Vercel AI SDK Core
|
|
5
|
+
* methods as normal.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { anthropic } from "@ai-sdk/anthropic";
|
|
10
|
+
* import { streamText } from "ai";
|
|
11
|
+
* import { wrapAISDKModel } from "langsmith/wrappers/vercel";
|
|
12
|
+
*
|
|
13
|
+
* const anthropicModel = anthropic("claude-3-haiku-20240307");
|
|
14
|
+
*
|
|
15
|
+
* const modelWithTracing = wrapAISDKModel(anthropicModel);
|
|
16
|
+
*
|
|
17
|
+
* const { textStream } = await streamText({
|
|
18
|
+
* model: modelWithTracing,
|
|
19
|
+
* prompt: "Write a vegetarian lasagna recipe for 4 people.",
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* for await (const chunk of textStream) {
|
|
23
|
+
* console.log(chunk);
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
* @param model An AI SDK model instance.
|
|
27
|
+
* @param options LangSmith options.
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
export declare const wrapAISDKModel: <T extends object>(model: T, options?: Partial<RunTreeConfig>) => T;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { traceable } from "../traceable.js";
|
|
2
|
+
import { _wrapClient } from "./generic.js";
|
|
3
|
+
/**
|
|
4
|
+
* Wrap a Vercel AI SDK model, enabling automatic LangSmith tracing.
|
|
5
|
+
* After wrapping a model, you can use it with the Vercel AI SDK Core
|
|
6
|
+
* methods as normal.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { anthropic } from "@ai-sdk/anthropic";
|
|
11
|
+
* import { streamText } from "ai";
|
|
12
|
+
* import { wrapAISDKModel } from "langsmith/wrappers/vercel";
|
|
13
|
+
*
|
|
14
|
+
* const anthropicModel = anthropic("claude-3-haiku-20240307");
|
|
15
|
+
*
|
|
16
|
+
* const modelWithTracing = wrapAISDKModel(anthropicModel);
|
|
17
|
+
*
|
|
18
|
+
* const { textStream } = await streamText({
|
|
19
|
+
* model: modelWithTracing,
|
|
20
|
+
* prompt: "Write a vegetarian lasagna recipe for 4 people.",
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* for await (const chunk of textStream) {
|
|
24
|
+
* console.log(chunk);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
* @param model An AI SDK model instance.
|
|
28
|
+
* @param options LangSmith options.
|
|
29
|
+
* @returns
|
|
30
|
+
*/
|
|
31
|
+
export const wrapAISDKModel = (model, options) => {
|
|
32
|
+
if (!("doStream" in model) ||
|
|
33
|
+
typeof model.doStream !== "function" ||
|
|
34
|
+
!("doGenerate" in model) ||
|
|
35
|
+
typeof model.doGenerate !== "function") {
|
|
36
|
+
throw new Error(`Received invalid input. This version of wrapAISDKModel only supports Vercel LanguageModelV1 instances.`);
|
|
37
|
+
}
|
|
38
|
+
const runName = options?.name ?? model.constructor?.name;
|
|
39
|
+
return new Proxy(model, {
|
|
40
|
+
get(target, propKey, receiver) {
|
|
41
|
+
const originalValue = target[propKey];
|
|
42
|
+
if (typeof originalValue === "function") {
|
|
43
|
+
let __finalTracedIteratorKey;
|
|
44
|
+
let aggregator;
|
|
45
|
+
if (propKey === "doStream") {
|
|
46
|
+
__finalTracedIteratorKey = "stream";
|
|
47
|
+
aggregator = (chunks) => {
|
|
48
|
+
return chunks.reduce((aggregated, chunk) => {
|
|
49
|
+
if (chunk.type === "text-delta") {
|
|
50
|
+
return {
|
|
51
|
+
...aggregated,
|
|
52
|
+
text: aggregated.text + chunk.textDelta,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
else if (chunk.type === "tool-call") {
|
|
56
|
+
return {
|
|
57
|
+
...aggregated,
|
|
58
|
+
...chunk,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
else if (chunk.type === "finish") {
|
|
62
|
+
return {
|
|
63
|
+
...aggregated,
|
|
64
|
+
usage: chunk.usage,
|
|
65
|
+
finishReason: chunk.finishReason,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return aggregated;
|
|
70
|
+
}
|
|
71
|
+
}, {
|
|
72
|
+
text: "",
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return traceable(originalValue.bind(target), {
|
|
77
|
+
run_type: "llm",
|
|
78
|
+
name: runName,
|
|
79
|
+
...options,
|
|
80
|
+
__finalTracedIteratorKey,
|
|
81
|
+
aggregator,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
else if (originalValue != null &&
|
|
85
|
+
!Array.isArray(originalValue) &&
|
|
86
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
87
|
+
!(originalValue instanceof Date) &&
|
|
88
|
+
typeof originalValue === "object") {
|
|
89
|
+
return _wrapClient(originalValue, [runName, propKey.toString()].join("."), options);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return Reflect.get(target, propKey, receiver);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.40",
|
|
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": [
|
|
@@ -45,6 +45,10 @@
|
|
|
45
45
|
"wrappers/openai.js",
|
|
46
46
|
"wrappers/openai.d.ts",
|
|
47
47
|
"wrappers/openai.d.cts",
|
|
48
|
+
"wrappers/vercel.cjs",
|
|
49
|
+
"wrappers/vercel.js",
|
|
50
|
+
"wrappers/vercel.d.ts",
|
|
51
|
+
"wrappers/vercel.d.cts",
|
|
48
52
|
"singletons/traceable.cjs",
|
|
49
53
|
"singletons/traceable.js",
|
|
50
54
|
"singletons/traceable.d.ts",
|
|
@@ -97,19 +101,22 @@
|
|
|
97
101
|
"commander": "^10.0.1",
|
|
98
102
|
"p-queue": "^6.6.2",
|
|
99
103
|
"p-retry": "4",
|
|
104
|
+
"semver": "^7.6.3",
|
|
100
105
|
"uuid": "^9.0.0"
|
|
101
106
|
},
|
|
102
107
|
"devDependencies": {
|
|
108
|
+
"@ai-sdk/openai": "^0.0.40",
|
|
103
109
|
"@babel/preset-env": "^7.22.4",
|
|
104
110
|
"@faker-js/faker": "^8.4.1",
|
|
105
111
|
"@jest/globals": "^29.5.0",
|
|
106
|
-
"langchain": "^0.2.
|
|
107
|
-
"@langchain/
|
|
108
|
-
"@langchain/
|
|
112
|
+
"@langchain/core": "^0.2.17",
|
|
113
|
+
"@langchain/langgraph": "^0.0.29",
|
|
114
|
+
"@langchain/openai": "^0.2.5",
|
|
109
115
|
"@tsconfig/recommended": "^1.0.2",
|
|
110
116
|
"@types/jest": "^29.5.1",
|
|
111
117
|
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
|
112
118
|
"@typescript-eslint/parser": "^5.59.8",
|
|
119
|
+
"ai": "^3.2.37",
|
|
113
120
|
"babel-jest": "^29.5.0",
|
|
114
121
|
"cross-env": "^7.0.3",
|
|
115
122
|
"dotenv": "^16.1.3",
|
|
@@ -119,16 +126,18 @@
|
|
|
119
126
|
"eslint-plugin-no-instanceof": "^1.0.1",
|
|
120
127
|
"eslint-plugin-prettier": "^4.2.1",
|
|
121
128
|
"jest": "^29.5.0",
|
|
129
|
+
"langchain": "^0.2.10",
|
|
122
130
|
"openai": "^4.38.5",
|
|
123
131
|
"prettier": "^2.8.8",
|
|
124
132
|
"ts-jest": "^29.1.0",
|
|
125
133
|
"ts-node": "^10.9.1",
|
|
126
|
-
"typescript": "^5.4.5"
|
|
134
|
+
"typescript": "^5.4.5",
|
|
135
|
+
"zod": "^3.23.8"
|
|
127
136
|
},
|
|
128
137
|
"peerDependencies": {
|
|
129
|
-
"
|
|
138
|
+
"@langchain/core": "*",
|
|
130
139
|
"langchain": "*",
|
|
131
|
-
"
|
|
140
|
+
"openai": "*"
|
|
132
141
|
},
|
|
133
142
|
"peerDependenciesMeta": {
|
|
134
143
|
"openai": {
|
|
@@ -141,9 +150,6 @@
|
|
|
141
150
|
"optional": true
|
|
142
151
|
}
|
|
143
152
|
},
|
|
144
|
-
"resolutions": {
|
|
145
|
-
"@langchain/core": "0.2.0"
|
|
146
|
-
},
|
|
147
153
|
"lint-staged": {
|
|
148
154
|
"**/*.{ts,tsx}": [
|
|
149
155
|
"prettier --write --ignore-unknown",
|
|
@@ -250,6 +256,15 @@
|
|
|
250
256
|
"import": "./wrappers/openai.js",
|
|
251
257
|
"require": "./wrappers/openai.cjs"
|
|
252
258
|
},
|
|
259
|
+
"./wrappers/vercel": {
|
|
260
|
+
"types": {
|
|
261
|
+
"import": "./wrappers/vercel.d.ts",
|
|
262
|
+
"require": "./wrappers/vercel.d.cts",
|
|
263
|
+
"default": "./wrappers/vercel.d.ts"
|
|
264
|
+
},
|
|
265
|
+
"import": "./wrappers/vercel.js",
|
|
266
|
+
"require": "./wrappers/vercel.cjs"
|
|
267
|
+
},
|
|
253
268
|
"./singletons/traceable": {
|
|
254
269
|
"types": {
|
|
255
270
|
"import": "./singletons/traceable.d.ts",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('../dist/wrappers/vercel.cjs');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/wrappers/vercel.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/wrappers/vercel.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../dist/wrappers/vercel.js'
|