langsmith 0.1.40-rc.0 → 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/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/traceable.cjs +58 -1
- package/dist/traceable.d.ts +1 -0
- package/dist/traceable.js +58 -1
- 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 -45
- package/dist/wrappers/openai.d.ts +0 -18
- package/dist/wrappers/openai.js +0 -43
- 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 +19 -3
- 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
package/dist/index.cjs
CHANGED
|
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "Client", { enumerable: true, get: function () {
|
|
|
6
6
|
var run_trees_js_1 = require("./run_trees.cjs");
|
|
7
7
|
Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () { return run_trees_js_1.RunTree; } });
|
|
8
8
|
// Update using yarn bump-version
|
|
9
|
-
exports.__version__ = "0.1.
|
|
9
|
+
exports.__version__ = "0.1.40";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { Client } from "./client.js";
|
|
2
2
|
export type { Dataset, Example, TracerSession, Run, Feedback, RetrieverOutput, } from "./schemas.js";
|
|
3
3
|
export { RunTree, type RunTreeConfig } from "./run_trees.js";
|
|
4
|
-
export declare const __version__ = "0.1.
|
|
4
|
+
export declare const __version__ = "0.1.40";
|
package/dist/index.js
CHANGED
package/dist/traceable.cjs
CHANGED
|
@@ -192,7 +192,7 @@ const convertSerializableArg = (arg) => {
|
|
|
192
192
|
*/
|
|
193
193
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
194
194
|
function traceable(wrappedFunc, config) {
|
|
195
|
-
const { aggregator, argsConfigPath, ...runTreeConfig } = config ?? {};
|
|
195
|
+
const { aggregator, argsConfigPath, __finalTracedIteratorKey, ...runTreeConfig } = config ?? {};
|
|
196
196
|
const traceableFunc = (...args) => {
|
|
197
197
|
let ensuredConfig;
|
|
198
198
|
try {
|
|
@@ -294,6 +294,38 @@ function traceable(wrappedFunc, config) {
|
|
|
294
294
|
}
|
|
295
295
|
return chunks;
|
|
296
296
|
}
|
|
297
|
+
function tapReadableStreamForTracing(stream, snapshot) {
|
|
298
|
+
const reader = stream.getReader();
|
|
299
|
+
let finished = false;
|
|
300
|
+
const chunks = [];
|
|
301
|
+
const tappedStream = new ReadableStream({
|
|
302
|
+
async start(controller) {
|
|
303
|
+
// eslint-disable-next-line no-constant-condition
|
|
304
|
+
while (true) {
|
|
305
|
+
const result = await (snapshot
|
|
306
|
+
? snapshot(() => reader.read())
|
|
307
|
+
: reader.read());
|
|
308
|
+
if (result.done) {
|
|
309
|
+
finished = true;
|
|
310
|
+
await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks)));
|
|
311
|
+
await handleEnd();
|
|
312
|
+
controller.close();
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
chunks.push(result.value);
|
|
316
|
+
controller.enqueue(result.value);
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
async cancel(reason) {
|
|
320
|
+
if (!finished)
|
|
321
|
+
await currentRunTree?.end(undefined, "Cancelled");
|
|
322
|
+
await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks)));
|
|
323
|
+
await handleEnd();
|
|
324
|
+
return reader.cancel(reason);
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
return tappedStream;
|
|
328
|
+
}
|
|
297
329
|
async function* wrapAsyncIteratorForTracing(iterator, snapshot) {
|
|
298
330
|
let finished = false;
|
|
299
331
|
const chunks = [];
|
|
@@ -322,6 +354,9 @@ function traceable(wrappedFunc, config) {
|
|
|
322
354
|
}
|
|
323
355
|
}
|
|
324
356
|
function wrapAsyncGeneratorForTracing(iterable, snapshot) {
|
|
357
|
+
if ((0, asserts_js_1.isReadableStream)(iterable)) {
|
|
358
|
+
return tapReadableStreamForTracing(iterable, snapshot);
|
|
359
|
+
}
|
|
325
360
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
326
361
|
const wrappedIterator = wrapAsyncIteratorForTracing(iterator, snapshot);
|
|
327
362
|
iterable[Symbol.asyncIterator] = () => wrappedIterator;
|
|
@@ -362,6 +397,17 @@ function traceable(wrappedFunc, config) {
|
|
|
362
397
|
const snapshot = node_async_hooks_1.AsyncLocalStorage.snapshot();
|
|
363
398
|
return wrapAsyncGeneratorForTracing(returnValue, snapshot);
|
|
364
399
|
}
|
|
400
|
+
if (!Array.isArray(returnValue) &&
|
|
401
|
+
typeof returnValue === "object" &&
|
|
402
|
+
returnValue != null &&
|
|
403
|
+
__finalTracedIteratorKey !== undefined &&
|
|
404
|
+
(0, asserts_js_1.isAsyncIterable)(returnValue[__finalTracedIteratorKey])) {
|
|
405
|
+
const snapshot = node_async_hooks_1.AsyncLocalStorage.snapshot();
|
|
406
|
+
return {
|
|
407
|
+
...returnValue,
|
|
408
|
+
[__finalTracedIteratorKey]: wrapAsyncGeneratorForTracing(returnValue[__finalTracedIteratorKey], snapshot),
|
|
409
|
+
};
|
|
410
|
+
}
|
|
365
411
|
const tracedPromise = new Promise((resolve, reject) => {
|
|
366
412
|
Promise.resolve(returnValue)
|
|
367
413
|
.then(async (rawOutput) => {
|
|
@@ -369,6 +415,17 @@ function traceable(wrappedFunc, config) {
|
|
|
369
415
|
const snapshot = node_async_hooks_1.AsyncLocalStorage.snapshot();
|
|
370
416
|
return resolve(wrapAsyncGeneratorForTracing(rawOutput, snapshot));
|
|
371
417
|
}
|
|
418
|
+
if (!Array.isArray(rawOutput) &&
|
|
419
|
+
typeof rawOutput === "object" &&
|
|
420
|
+
rawOutput != null &&
|
|
421
|
+
__finalTracedIteratorKey !== undefined &&
|
|
422
|
+
(0, asserts_js_1.isAsyncIterable)(rawOutput[__finalTracedIteratorKey])) {
|
|
423
|
+
const snapshot = node_async_hooks_1.AsyncLocalStorage.snapshot();
|
|
424
|
+
return {
|
|
425
|
+
...rawOutput,
|
|
426
|
+
[__finalTracedIteratorKey]: wrapAsyncGeneratorForTracing(rawOutput[__finalTracedIteratorKey], snapshot),
|
|
427
|
+
};
|
|
428
|
+
}
|
|
372
429
|
if ((0, asserts_js_1.isGenerator)(wrappedFunc) && (0, asserts_js_1.isIteratorLike)(rawOutput)) {
|
|
373
430
|
const chunks = gatherAll(rawOutput);
|
|
374
431
|
await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks.reduce((memo, { value, done }) => {
|
package/dist/traceable.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { TraceableFunction } from "./singletons/types.js";
|
|
|
18
18
|
export declare function traceable<Func extends (...args: any[]) => any>(wrappedFunc: Func, config?: Partial<RunTreeConfig> & {
|
|
19
19
|
aggregator?: (args: any[]) => any;
|
|
20
20
|
argsConfigPath?: [number] | [number, string];
|
|
21
|
+
__finalTracedIteratorKey?: string;
|
|
21
22
|
/**
|
|
22
23
|
* Extract invocation parameters from the arguments of the traced function.
|
|
23
24
|
* This is useful for LangSmith to properly track common metadata like
|
package/dist/traceable.js
CHANGED
|
@@ -189,7 +189,7 @@ const convertSerializableArg = (arg) => {
|
|
|
189
189
|
*/
|
|
190
190
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
191
191
|
export function traceable(wrappedFunc, config) {
|
|
192
|
-
const { aggregator, argsConfigPath, ...runTreeConfig } = config ?? {};
|
|
192
|
+
const { aggregator, argsConfigPath, __finalTracedIteratorKey, ...runTreeConfig } = config ?? {};
|
|
193
193
|
const traceableFunc = (...args) => {
|
|
194
194
|
let ensuredConfig;
|
|
195
195
|
try {
|
|
@@ -291,6 +291,38 @@ export function traceable(wrappedFunc, config) {
|
|
|
291
291
|
}
|
|
292
292
|
return chunks;
|
|
293
293
|
}
|
|
294
|
+
function tapReadableStreamForTracing(stream, snapshot) {
|
|
295
|
+
const reader = stream.getReader();
|
|
296
|
+
let finished = false;
|
|
297
|
+
const chunks = [];
|
|
298
|
+
const tappedStream = new ReadableStream({
|
|
299
|
+
async start(controller) {
|
|
300
|
+
// eslint-disable-next-line no-constant-condition
|
|
301
|
+
while (true) {
|
|
302
|
+
const result = await (snapshot
|
|
303
|
+
? snapshot(() => reader.read())
|
|
304
|
+
: reader.read());
|
|
305
|
+
if (result.done) {
|
|
306
|
+
finished = true;
|
|
307
|
+
await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks)));
|
|
308
|
+
await handleEnd();
|
|
309
|
+
controller.close();
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
chunks.push(result.value);
|
|
313
|
+
controller.enqueue(result.value);
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
async cancel(reason) {
|
|
317
|
+
if (!finished)
|
|
318
|
+
await currentRunTree?.end(undefined, "Cancelled");
|
|
319
|
+
await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks)));
|
|
320
|
+
await handleEnd();
|
|
321
|
+
return reader.cancel(reason);
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
return tappedStream;
|
|
325
|
+
}
|
|
294
326
|
async function* wrapAsyncIteratorForTracing(iterator, snapshot) {
|
|
295
327
|
let finished = false;
|
|
296
328
|
const chunks = [];
|
|
@@ -319,6 +351,9 @@ export function traceable(wrappedFunc, config) {
|
|
|
319
351
|
}
|
|
320
352
|
}
|
|
321
353
|
function wrapAsyncGeneratorForTracing(iterable, snapshot) {
|
|
354
|
+
if (isReadableStream(iterable)) {
|
|
355
|
+
return tapReadableStreamForTracing(iterable, snapshot);
|
|
356
|
+
}
|
|
322
357
|
const iterator = iterable[Symbol.asyncIterator]();
|
|
323
358
|
const wrappedIterator = wrapAsyncIteratorForTracing(iterator, snapshot);
|
|
324
359
|
iterable[Symbol.asyncIterator] = () => wrappedIterator;
|
|
@@ -359,6 +394,17 @@ export function traceable(wrappedFunc, config) {
|
|
|
359
394
|
const snapshot = AsyncLocalStorage.snapshot();
|
|
360
395
|
return wrapAsyncGeneratorForTracing(returnValue, snapshot);
|
|
361
396
|
}
|
|
397
|
+
if (!Array.isArray(returnValue) &&
|
|
398
|
+
typeof returnValue === "object" &&
|
|
399
|
+
returnValue != null &&
|
|
400
|
+
__finalTracedIteratorKey !== undefined &&
|
|
401
|
+
isAsyncIterable(returnValue[__finalTracedIteratorKey])) {
|
|
402
|
+
const snapshot = AsyncLocalStorage.snapshot();
|
|
403
|
+
return {
|
|
404
|
+
...returnValue,
|
|
405
|
+
[__finalTracedIteratorKey]: wrapAsyncGeneratorForTracing(returnValue[__finalTracedIteratorKey], snapshot),
|
|
406
|
+
};
|
|
407
|
+
}
|
|
362
408
|
const tracedPromise = new Promise((resolve, reject) => {
|
|
363
409
|
Promise.resolve(returnValue)
|
|
364
410
|
.then(async (rawOutput) => {
|
|
@@ -366,6 +412,17 @@ export function traceable(wrappedFunc, config) {
|
|
|
366
412
|
const snapshot = AsyncLocalStorage.snapshot();
|
|
367
413
|
return resolve(wrapAsyncGeneratorForTracing(rawOutput, snapshot));
|
|
368
414
|
}
|
|
415
|
+
if (!Array.isArray(rawOutput) &&
|
|
416
|
+
typeof rawOutput === "object" &&
|
|
417
|
+
rawOutput != null &&
|
|
418
|
+
__finalTracedIteratorKey !== undefined &&
|
|
419
|
+
isAsyncIterable(rawOutput[__finalTracedIteratorKey])) {
|
|
420
|
+
const snapshot = AsyncLocalStorage.snapshot();
|
|
421
|
+
return {
|
|
422
|
+
...rawOutput,
|
|
423
|
+
[__finalTracedIteratorKey]: wrapAsyncGeneratorForTracing(rawOutput[__finalTracedIteratorKey], snapshot),
|
|
424
|
+
};
|
|
425
|
+
}
|
|
369
426
|
if (isGenerator(wrappedFunc) && isIteratorLike(rawOutput)) {
|
|
370
427
|
const chunks = gatherAll(rawOutput);
|
|
371
428
|
await currentRunTree?.end(handleRunOutputs(await handleChunks(chunks.reduce((memo, { value, done }) => {
|
|
@@ -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,47 +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), {
|
|
200
|
-
run_type: "llm",
|
|
201
|
-
...options,
|
|
202
|
-
name: [runName, propKey.toString()].join("."),
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
else if (originalValue != null &&
|
|
206
|
-
!Array.isArray(originalValue) &&
|
|
207
|
-
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
208
|
-
!(originalValue instanceof Date) &&
|
|
209
|
-
typeof originalValue === "object") {
|
|
210
|
-
return _wrapClient(originalValue, [runName, propKey.toString()].join("."), options);
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
return Reflect.get(target, propKey, receiver);
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
});
|
|
217
|
-
};
|
|
218
|
-
/**
|
|
219
|
-
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
220
|
-
* Method signatures are unchanged.
|
|
221
|
-
*
|
|
222
|
-
* Note that this will wrap and trace ALL SDK methods, not just
|
|
223
|
-
* LLM completion methods. If the passed SDK contains other methods,
|
|
224
|
-
* we recommend using the wrapped instance for LLM calls only.
|
|
225
|
-
* @param sdk An arbitrary SDK instance.
|
|
226
|
-
* @param options LangSmith options.
|
|
227
|
-
* @returns
|
|
228
|
-
*/
|
|
229
|
-
const wrapSDK = (sdk, options) => {
|
|
230
|
-
const traceableOptions = options ? { ...options } : undefined;
|
|
231
|
-
if (traceableOptions != null) {
|
|
232
|
-
delete traceableOptions.runName;
|
|
233
|
-
delete traceableOptions.name;
|
|
234
|
-
}
|
|
235
|
-
return _wrapClient(sdk, options?.name ?? options?.runName ?? sdk.constructor?.name, traceableOptions);
|
|
236
|
-
};
|
|
237
|
-
exports.wrapSDK = wrapSDK;
|
|
@@ -63,22 +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
|
-
type WrapSDKOptions = Partial<RunTreeConfig & {
|
|
67
|
-
/**
|
|
68
|
-
* @deprecated Use `name` instead.
|
|
69
|
-
*/
|
|
70
|
-
runName: string;
|
|
71
|
-
}>;
|
|
72
|
-
/**
|
|
73
|
-
* Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
|
|
74
|
-
* Method signatures are unchanged.
|
|
75
|
-
*
|
|
76
|
-
* Note that this will wrap and trace ALL SDK methods, not just
|
|
77
|
-
* LLM completion methods. If the passed SDK contains other methods,
|
|
78
|
-
* we recommend using the wrapped instance for LLM calls only.
|
|
79
|
-
* @param sdk An arbitrary SDK instance.
|
|
80
|
-
* @param options LangSmith options.
|
|
81
|
-
* @returns
|
|
82
|
-
*/
|
|
83
|
-
export declare const wrapSDK: <T extends object>(sdk: T, options?: WrapSDKOptions) => T;
|
|
84
66
|
export {};
|
package/dist/wrappers/openai.js
CHANGED
|
@@ -187,46 +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), {
|
|
196
|
-
run_type: "llm",
|
|
197
|
-
...options,
|
|
198
|
-
name: [runName, propKey.toString()].join("."),
|
|
199
|
-
});
|
|
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
|
-
export const wrapSDK = (sdk, options) => {
|
|
226
|
-
const traceableOptions = options ? { ...options } : undefined;
|
|
227
|
-
if (traceableOptions != null) {
|
|
228
|
-
delete traceableOptions.runName;
|
|
229
|
-
delete traceableOptions.name;
|
|
230
|
-
}
|
|
231
|
-
return _wrapClient(sdk, options?.name ?? options?.runName ?? sdk.constructor?.name, traceableOptions);
|
|
232
|
-
};
|
|
@@ -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.40
|
|
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",
|
|
@@ -101,10 +105,10 @@
|
|
|
101
105
|
"uuid": "^9.0.0"
|
|
102
106
|
},
|
|
103
107
|
"devDependencies": {
|
|
108
|
+
"@ai-sdk/openai": "^0.0.40",
|
|
104
109
|
"@babel/preset-env": "^7.22.4",
|
|
105
110
|
"@faker-js/faker": "^8.4.1",
|
|
106
111
|
"@jest/globals": "^29.5.0",
|
|
107
|
-
"langchain": "^0.2.10",
|
|
108
112
|
"@langchain/core": "^0.2.17",
|
|
109
113
|
"@langchain/langgraph": "^0.0.29",
|
|
110
114
|
"@langchain/openai": "^0.2.5",
|
|
@@ -112,6 +116,7 @@
|
|
|
112
116
|
"@types/jest": "^29.5.1",
|
|
113
117
|
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
|
114
118
|
"@typescript-eslint/parser": "^5.59.8",
|
|
119
|
+
"ai": "^3.2.37",
|
|
115
120
|
"babel-jest": "^29.5.0",
|
|
116
121
|
"cross-env": "^7.0.3",
|
|
117
122
|
"dotenv": "^16.1.3",
|
|
@@ -121,11 +126,13 @@
|
|
|
121
126
|
"eslint-plugin-no-instanceof": "^1.0.1",
|
|
122
127
|
"eslint-plugin-prettier": "^4.2.1",
|
|
123
128
|
"jest": "^29.5.0",
|
|
129
|
+
"langchain": "^0.2.10",
|
|
124
130
|
"openai": "^4.38.5",
|
|
125
131
|
"prettier": "^2.8.8",
|
|
126
132
|
"ts-jest": "^29.1.0",
|
|
127
133
|
"ts-node": "^10.9.1",
|
|
128
|
-
"typescript": "^5.4.5"
|
|
134
|
+
"typescript": "^5.4.5",
|
|
135
|
+
"zod": "^3.23.8"
|
|
129
136
|
},
|
|
130
137
|
"peerDependencies": {
|
|
131
138
|
"@langchain/core": "*",
|
|
@@ -249,6 +256,15 @@
|
|
|
249
256
|
"import": "./wrappers/openai.js",
|
|
250
257
|
"require": "./wrappers/openai.cjs"
|
|
251
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
|
+
},
|
|
252
268
|
"./singletons/traceable": {
|
|
253
269
|
"types": {
|
|
254
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'
|