langsmith 0.1.31 → 0.1.33
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/anonymizer.cjs +1 -0
- package/anonymizer.d.cts +1 -0
- package/anonymizer.d.ts +1 -0
- package/anonymizer.js +1 -0
- package/dist/anonymizer/index.cjs +107 -0
- package/dist/anonymizer/index.d.ts +17 -0
- package/dist/anonymizer/index.js +100 -0
- package/dist/client.cjs +45 -21
- package/dist/client.d.ts +20 -2
- package/dist/client.js +45 -21
- package/dist/evaluation/_runner.d.ts +1 -1
- package/dist/evaluation/evaluator.cjs +11 -2
- package/dist/evaluation/evaluator.d.ts +3 -2
- package/dist/evaluation/evaluator.js +11 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +16 -1
package/anonymizer.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./dist/anonymizer/index.cjs');
|
package/anonymizer.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/anonymizer/index.js'
|
package/anonymizer.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/anonymizer/index.js'
|
package/anonymizer.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist/anonymizer/index.js'
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createAnonymizer = void 0;
|
|
7
|
+
const lodash_set_1 = __importDefault(require("lodash.set"));
|
|
8
|
+
function extractStringNodes(data, options) {
|
|
9
|
+
const parsedOptions = { ...options, maxDepth: options.maxDepth ?? 10 };
|
|
10
|
+
const queue = [
|
|
11
|
+
[data, 0, ""],
|
|
12
|
+
];
|
|
13
|
+
const result = [];
|
|
14
|
+
while (queue.length > 0) {
|
|
15
|
+
const task = queue.shift();
|
|
16
|
+
if (task == null)
|
|
17
|
+
continue;
|
|
18
|
+
const [value, depth, path] = task;
|
|
19
|
+
if (typeof value === "object" && value != null) {
|
|
20
|
+
if (depth >= parsedOptions.maxDepth)
|
|
21
|
+
continue;
|
|
22
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
23
|
+
queue.push([nestedValue, depth + 1, path ? `${path}.${key}` : key]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else if (Array.isArray(value)) {
|
|
27
|
+
if (depth >= parsedOptions.maxDepth)
|
|
28
|
+
continue;
|
|
29
|
+
for (let i = 0; i < value.length; i++) {
|
|
30
|
+
queue.push([value[i], depth + 1, `${path}[${i}]`]);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (typeof value === "string") {
|
|
34
|
+
result.push({ value, path });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
function deepClone(data) {
|
|
40
|
+
if ("structuredClone" in globalThis) {
|
|
41
|
+
return globalThis.structuredClone(data);
|
|
42
|
+
}
|
|
43
|
+
return JSON.parse(JSON.stringify(data));
|
|
44
|
+
}
|
|
45
|
+
function createAnonymizer(replacer, options) {
|
|
46
|
+
return (data) => {
|
|
47
|
+
const nodes = extractStringNodes(data, {
|
|
48
|
+
maxDepth: options?.maxDepth,
|
|
49
|
+
});
|
|
50
|
+
// by default we opt-in to mutate the value directly
|
|
51
|
+
// to improve performance
|
|
52
|
+
let mutateValue = options?.deepClone ? deepClone(data) : data;
|
|
53
|
+
const processor = Array.isArray(replacer)
|
|
54
|
+
? (() => {
|
|
55
|
+
const replacers = replacer.map(({ pattern, type, replace }) => {
|
|
56
|
+
if (type != null && type !== "pattern")
|
|
57
|
+
throw new Error("Invalid anonymizer type");
|
|
58
|
+
return [
|
|
59
|
+
typeof pattern === "string"
|
|
60
|
+
? new RegExp(pattern, "g")
|
|
61
|
+
: pattern,
|
|
62
|
+
replace ?? "[redacted]",
|
|
63
|
+
];
|
|
64
|
+
});
|
|
65
|
+
if (replacers.length === 0)
|
|
66
|
+
throw new Error("No replacers provided");
|
|
67
|
+
return {
|
|
68
|
+
maskNodes: (nodes) => {
|
|
69
|
+
return nodes.reduce((memo, item) => {
|
|
70
|
+
const newValue = replacers.reduce((value, [regex, replace]) => {
|
|
71
|
+
const result = value.replace(regex, replace);
|
|
72
|
+
// make sure we reset the state of regex
|
|
73
|
+
regex.lastIndex = 0;
|
|
74
|
+
return result;
|
|
75
|
+
}, item.value);
|
|
76
|
+
if (newValue !== item.value) {
|
|
77
|
+
memo.push({ value: newValue, path: item.path });
|
|
78
|
+
}
|
|
79
|
+
return memo;
|
|
80
|
+
}, []);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
})()
|
|
84
|
+
: typeof replacer === "function"
|
|
85
|
+
? {
|
|
86
|
+
maskNodes: (nodes) => nodes.reduce((memo, item) => {
|
|
87
|
+
const newValue = replacer(item.value, item.path);
|
|
88
|
+
if (newValue !== item.value) {
|
|
89
|
+
memo.push({ value: newValue, path: item.path });
|
|
90
|
+
}
|
|
91
|
+
return memo;
|
|
92
|
+
}, []),
|
|
93
|
+
}
|
|
94
|
+
: replacer;
|
|
95
|
+
const toUpdate = processor.maskNodes(nodes);
|
|
96
|
+
for (const node of toUpdate) {
|
|
97
|
+
if (node.path === "") {
|
|
98
|
+
mutateValue = node.value;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
(0, lodash_set_1.default)(mutateValue, node.path, node.value);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return mutateValue;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
exports.createAnonymizer = createAnonymizer;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface StringNode {
|
|
2
|
+
value: string;
|
|
3
|
+
path: string;
|
|
4
|
+
}
|
|
5
|
+
export interface StringNodeProcessor {
|
|
6
|
+
maskNodes: (nodes: StringNode[]) => StringNode[];
|
|
7
|
+
}
|
|
8
|
+
export interface StringNodeRule {
|
|
9
|
+
type?: "pattern";
|
|
10
|
+
pattern: RegExp | string;
|
|
11
|
+
replace?: string;
|
|
12
|
+
}
|
|
13
|
+
export type ReplacerType = ((value: string, path?: string) => string) | StringNodeRule[] | StringNodeProcessor;
|
|
14
|
+
export declare function createAnonymizer(replacer: ReplacerType, options?: {
|
|
15
|
+
maxDepth?: number;
|
|
16
|
+
deepClone?: boolean;
|
|
17
|
+
}): <T>(data: T) => T;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import set from "lodash.set";
|
|
2
|
+
function extractStringNodes(data, options) {
|
|
3
|
+
const parsedOptions = { ...options, maxDepth: options.maxDepth ?? 10 };
|
|
4
|
+
const queue = [
|
|
5
|
+
[data, 0, ""],
|
|
6
|
+
];
|
|
7
|
+
const result = [];
|
|
8
|
+
while (queue.length > 0) {
|
|
9
|
+
const task = queue.shift();
|
|
10
|
+
if (task == null)
|
|
11
|
+
continue;
|
|
12
|
+
const [value, depth, path] = task;
|
|
13
|
+
if (typeof value === "object" && value != null) {
|
|
14
|
+
if (depth >= parsedOptions.maxDepth)
|
|
15
|
+
continue;
|
|
16
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
17
|
+
queue.push([nestedValue, depth + 1, path ? `${path}.${key}` : key]);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else if (Array.isArray(value)) {
|
|
21
|
+
if (depth >= parsedOptions.maxDepth)
|
|
22
|
+
continue;
|
|
23
|
+
for (let i = 0; i < value.length; i++) {
|
|
24
|
+
queue.push([value[i], depth + 1, `${path}[${i}]`]);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (typeof value === "string") {
|
|
28
|
+
result.push({ value, path });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function deepClone(data) {
|
|
34
|
+
if ("structuredClone" in globalThis) {
|
|
35
|
+
return globalThis.structuredClone(data);
|
|
36
|
+
}
|
|
37
|
+
return JSON.parse(JSON.stringify(data));
|
|
38
|
+
}
|
|
39
|
+
export function createAnonymizer(replacer, options) {
|
|
40
|
+
return (data) => {
|
|
41
|
+
const nodes = extractStringNodes(data, {
|
|
42
|
+
maxDepth: options?.maxDepth,
|
|
43
|
+
});
|
|
44
|
+
// by default we opt-in to mutate the value directly
|
|
45
|
+
// to improve performance
|
|
46
|
+
let mutateValue = options?.deepClone ? deepClone(data) : data;
|
|
47
|
+
const processor = Array.isArray(replacer)
|
|
48
|
+
? (() => {
|
|
49
|
+
const replacers = replacer.map(({ pattern, type, replace }) => {
|
|
50
|
+
if (type != null && type !== "pattern")
|
|
51
|
+
throw new Error("Invalid anonymizer type");
|
|
52
|
+
return [
|
|
53
|
+
typeof pattern === "string"
|
|
54
|
+
? new RegExp(pattern, "g")
|
|
55
|
+
: pattern,
|
|
56
|
+
replace ?? "[redacted]",
|
|
57
|
+
];
|
|
58
|
+
});
|
|
59
|
+
if (replacers.length === 0)
|
|
60
|
+
throw new Error("No replacers provided");
|
|
61
|
+
return {
|
|
62
|
+
maskNodes: (nodes) => {
|
|
63
|
+
return nodes.reduce((memo, item) => {
|
|
64
|
+
const newValue = replacers.reduce((value, [regex, replace]) => {
|
|
65
|
+
const result = value.replace(regex, replace);
|
|
66
|
+
// make sure we reset the state of regex
|
|
67
|
+
regex.lastIndex = 0;
|
|
68
|
+
return result;
|
|
69
|
+
}, item.value);
|
|
70
|
+
if (newValue !== item.value) {
|
|
71
|
+
memo.push({ value: newValue, path: item.path });
|
|
72
|
+
}
|
|
73
|
+
return memo;
|
|
74
|
+
}, []);
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
})()
|
|
78
|
+
: typeof replacer === "function"
|
|
79
|
+
? {
|
|
80
|
+
maskNodes: (nodes) => nodes.reduce((memo, item) => {
|
|
81
|
+
const newValue = replacer(item.value, item.path);
|
|
82
|
+
if (newValue !== item.value) {
|
|
83
|
+
memo.push({ value: newValue, path: item.path });
|
|
84
|
+
}
|
|
85
|
+
return memo;
|
|
86
|
+
}, []),
|
|
87
|
+
}
|
|
88
|
+
: replacer;
|
|
89
|
+
const toUpdate = processor.maskNodes(nodes);
|
|
90
|
+
for (const node of toUpdate) {
|
|
91
|
+
if (node.path === "") {
|
|
92
|
+
mutateValue = node.value;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
set(mutateValue, node.path, node.value);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return mutateValue;
|
|
99
|
+
};
|
|
100
|
+
}
|
package/dist/client.cjs
CHANGED
|
@@ -30,6 +30,7 @@ const messages_js_1 = require("./utils/messages.cjs");
|
|
|
30
30
|
const env_js_1 = require("./utils/env.cjs");
|
|
31
31
|
const index_js_1 = require("./index.cjs");
|
|
32
32
|
const _uuid_js_1 = require("./utils/_uuid.cjs");
|
|
33
|
+
const warn_js_1 = require("./utils/warn.cjs");
|
|
33
34
|
async function mergeRuntimeEnvIntoRunCreates(runs) {
|
|
34
35
|
const runtimeEnv = await (0, env_js_1.getRuntimeEnvironment)();
|
|
35
36
|
const envVars = (0, env_js_1.getLangChainEnvVarsMetadata)();
|
|
@@ -278,8 +279,10 @@ class Client {
|
|
|
278
279
|
...(config.callerOptions ?? {}),
|
|
279
280
|
onFailedResponseHook: handle429,
|
|
280
281
|
});
|
|
281
|
-
this.hideInputs =
|
|
282
|
-
|
|
282
|
+
this.hideInputs =
|
|
283
|
+
config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs;
|
|
284
|
+
this.hideOutputs =
|
|
285
|
+
config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs;
|
|
283
286
|
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
284
287
|
this.pendingAutoBatchedRunLimit =
|
|
285
288
|
config.pendingAutoBatchedRunLimit ?? this.pendingAutoBatchedRunLimit;
|
|
@@ -1423,6 +1426,30 @@ class Client {
|
|
|
1423
1426
|
yield* datasets;
|
|
1424
1427
|
}
|
|
1425
1428
|
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Update a dataset
|
|
1431
|
+
* @param props The dataset details to update
|
|
1432
|
+
* @returns The updated dataset
|
|
1433
|
+
*/
|
|
1434
|
+
async updateDataset(props) {
|
|
1435
|
+
const { datasetId, datasetName, ...update } = props;
|
|
1436
|
+
if (!datasetId && !datasetName) {
|
|
1437
|
+
throw new Error("Must provide either datasetName or datasetId");
|
|
1438
|
+
}
|
|
1439
|
+
const _datasetId = datasetId ?? (await this.readDataset({ datasetName })).id;
|
|
1440
|
+
(0, _uuid_js_1.assertUuid)(_datasetId);
|
|
1441
|
+
const response = await this.caller.call(fetch, `${this.apiUrl}/datasets/${_datasetId}`, {
|
|
1442
|
+
method: "PATCH",
|
|
1443
|
+
headers: { ...this.headers, "Content-Type": "application/json" },
|
|
1444
|
+
body: JSON.stringify(update),
|
|
1445
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
1446
|
+
...this.fetchOptions,
|
|
1447
|
+
});
|
|
1448
|
+
if (!response.ok) {
|
|
1449
|
+
throw new Error(`Failed to update dataset ${_datasetId}: ${response.status} ${response.statusText}`);
|
|
1450
|
+
}
|
|
1451
|
+
return (await response.json());
|
|
1452
|
+
}
|
|
1426
1453
|
async deleteDataset({ datasetId, datasetName, }) {
|
|
1427
1454
|
let path = "/datasets";
|
|
1428
1455
|
let datasetId_ = datasetId;
|
|
@@ -1616,7 +1643,11 @@ class Client {
|
|
|
1616
1643
|
const result = await response.json();
|
|
1617
1644
|
return result;
|
|
1618
1645
|
}
|
|
1646
|
+
/**
|
|
1647
|
+
* @deprecated This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead.
|
|
1648
|
+
*/
|
|
1619
1649
|
async evaluateRun(run, evaluator, { sourceInfo, loadChildRuns, referenceExample, } = { loadChildRuns: false }) {
|
|
1650
|
+
(0, warn_js_1.warnOnce)("This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead.");
|
|
1620
1651
|
let run_;
|
|
1621
1652
|
if (typeof run === "string") {
|
|
1622
1653
|
run_ = await this.readRun(run, { loadChildRuns });
|
|
@@ -1632,20 +1663,8 @@ class Client {
|
|
|
1632
1663
|
referenceExample = await this.readExample(run_.reference_example_id);
|
|
1633
1664
|
}
|
|
1634
1665
|
const feedbackResult = await evaluator.evaluateRun(run_, referenceExample);
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
sourceInfo_ = { ...sourceInfo_, ...feedbackResult.evaluatorInfo };
|
|
1638
|
-
}
|
|
1639
|
-
const runId = feedbackResult.targetRunId ?? run_.id;
|
|
1640
|
-
return await this.createFeedback(runId, feedbackResult.key, {
|
|
1641
|
-
score: feedbackResult?.score,
|
|
1642
|
-
value: feedbackResult?.value,
|
|
1643
|
-
comment: feedbackResult?.comment,
|
|
1644
|
-
correction: feedbackResult?.correction,
|
|
1645
|
-
sourceInfo: sourceInfo_,
|
|
1646
|
-
feedbackSourceType: "model",
|
|
1647
|
-
sourceRunId: feedbackResult?.sourceRunId,
|
|
1648
|
-
});
|
|
1666
|
+
const [_, feedbacks] = await this._logEvaluationFeedback(feedbackResult, run_, sourceInfo);
|
|
1667
|
+
return feedbacks[0];
|
|
1649
1668
|
}
|
|
1650
1669
|
async createFeedback(runId, key, { score, value, correction, comment, sourceInfo, feedbackSourceType = "api", sourceRunId, feedbackId, feedbackConfig, projectId, comparativeExperimentId, }) {
|
|
1651
1670
|
if (!runId && !projectId) {
|
|
@@ -1852,9 +1871,10 @@ class Client {
|
|
|
1852
1871
|
}
|
|
1853
1872
|
return results_;
|
|
1854
1873
|
}
|
|
1855
|
-
async
|
|
1856
|
-
const
|
|
1857
|
-
|
|
1874
|
+
async _logEvaluationFeedback(evaluatorResponse, run, sourceInfo) {
|
|
1875
|
+
const evalResults = this._selectEvalResults(evaluatorResponse);
|
|
1876
|
+
const feedbacks = [];
|
|
1877
|
+
for (const res of evalResults) {
|
|
1858
1878
|
let sourceInfo_ = sourceInfo || {};
|
|
1859
1879
|
if (res.evaluatorInfo) {
|
|
1860
1880
|
sourceInfo_ = { ...res.evaluatorInfo, ...sourceInfo_ };
|
|
@@ -1866,7 +1886,7 @@ class Client {
|
|
|
1866
1886
|
else if (run) {
|
|
1867
1887
|
runId_ = run.id;
|
|
1868
1888
|
}
|
|
1869
|
-
await this.createFeedback(runId_, res.key, {
|
|
1889
|
+
feedbacks.push(await this.createFeedback(runId_, res.key, {
|
|
1870
1890
|
score: res.score,
|
|
1871
1891
|
value: res.value,
|
|
1872
1892
|
comment: res.comment,
|
|
@@ -1875,8 +1895,12 @@ class Client {
|
|
|
1875
1895
|
sourceRunId: res.sourceRunId,
|
|
1876
1896
|
feedbackConfig: res.feedbackConfig,
|
|
1877
1897
|
feedbackSourceType: "model",
|
|
1878
|
-
});
|
|
1898
|
+
}));
|
|
1879
1899
|
}
|
|
1900
|
+
return [evalResults, feedbacks];
|
|
1901
|
+
}
|
|
1902
|
+
async logEvaluationFeedback(evaluatorResponse, run, sourceInfo) {
|
|
1903
|
+
const [results] = await this._logEvaluationFeedback(evaluatorResponse, run, sourceInfo);
|
|
1880
1904
|
return results;
|
|
1881
1905
|
}
|
|
1882
1906
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -7,8 +7,9 @@ interface ClientConfig {
|
|
|
7
7
|
callerOptions?: AsyncCallerParams;
|
|
8
8
|
timeout_ms?: number;
|
|
9
9
|
webUrl?: string;
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
anonymizer?: (values: KVMap) => KVMap;
|
|
11
|
+
hideInputs?: boolean | ((inputs: KVMap) => KVMap);
|
|
12
|
+
hideOutputs?: boolean | ((outputs: KVMap) => KVMap);
|
|
12
13
|
autoBatchTracing?: boolean;
|
|
13
14
|
pendingAutoBatchedRunLimit?: number;
|
|
14
15
|
fetchOptions?: RequestInit;
|
|
@@ -386,6 +387,17 @@ export declare class Client {
|
|
|
386
387
|
datasetName?: string;
|
|
387
388
|
datasetNameContains?: string;
|
|
388
389
|
}): AsyncIterable<Dataset>;
|
|
390
|
+
/**
|
|
391
|
+
* Update a dataset
|
|
392
|
+
* @param props The dataset details to update
|
|
393
|
+
* @returns The updated dataset
|
|
394
|
+
*/
|
|
395
|
+
updateDataset(props: {
|
|
396
|
+
datasetId?: string;
|
|
397
|
+
datasetName?: string;
|
|
398
|
+
name?: string;
|
|
399
|
+
description?: string;
|
|
400
|
+
}): Promise<Dataset>;
|
|
389
401
|
deleteDataset({ datasetId, datasetName, }: {
|
|
390
402
|
datasetId?: string;
|
|
391
403
|
datasetName?: string;
|
|
@@ -415,6 +427,9 @@ export declare class Client {
|
|
|
415
427
|
}): AsyncIterable<Example>;
|
|
416
428
|
deleteExample(exampleId: string): Promise<void>;
|
|
417
429
|
updateExample(exampleId: string, update: ExampleUpdate): Promise<object>;
|
|
430
|
+
/**
|
|
431
|
+
* @deprecated This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead.
|
|
432
|
+
*/
|
|
418
433
|
evaluateRun(run: Run | string, evaluator: RunEvaluator, { sourceInfo, loadChildRuns, referenceExample, }?: {
|
|
419
434
|
sourceInfo?: KVMap;
|
|
420
435
|
loadChildRuns: boolean;
|
|
@@ -482,6 +497,9 @@ export declare class Client {
|
|
|
482
497
|
*/
|
|
483
498
|
listPresignedFeedbackTokens(runId: string): AsyncIterable<FeedbackIngestToken>;
|
|
484
499
|
_selectEvalResults(results: EvaluationResult | EvaluationResults): Array<EvaluationResult>;
|
|
500
|
+
_logEvaluationFeedback(evaluatorResponse: EvaluationResult | EvaluationResults, run?: Run, sourceInfo?: {
|
|
501
|
+
[key: string]: any;
|
|
502
|
+
}): Promise<[results: EvaluationResult[], feedbacks: Feedback[]]>;
|
|
485
503
|
logEvaluationFeedback(evaluatorResponse: EvaluationResult | EvaluationResults, run?: Run, sourceInfo?: {
|
|
486
504
|
[key: string]: any;
|
|
487
505
|
}): Promise<EvaluationResult[]>;
|
package/dist/client.js
CHANGED
|
@@ -4,6 +4,7 @@ import { convertLangChainMessageToExample, isLangChainMessage, } from "./utils/m
|
|
|
4
4
|
import { getEnvironmentVariable, getLangChainEnvVarsMetadata, getRuntimeEnvironment, } from "./utils/env.js";
|
|
5
5
|
import { __version__ } from "./index.js";
|
|
6
6
|
import { assertUuid } from "./utils/_uuid.js";
|
|
7
|
+
import { warnOnce } from "./utils/warn.js";
|
|
7
8
|
async function mergeRuntimeEnvIntoRunCreates(runs) {
|
|
8
9
|
const runtimeEnv = await getRuntimeEnvironment();
|
|
9
10
|
const envVars = getLangChainEnvVarsMetadata();
|
|
@@ -251,8 +252,10 @@ export class Client {
|
|
|
251
252
|
...(config.callerOptions ?? {}),
|
|
252
253
|
onFailedResponseHook: handle429,
|
|
253
254
|
});
|
|
254
|
-
this.hideInputs =
|
|
255
|
-
|
|
255
|
+
this.hideInputs =
|
|
256
|
+
config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs;
|
|
257
|
+
this.hideOutputs =
|
|
258
|
+
config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs;
|
|
256
259
|
this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing;
|
|
257
260
|
this.pendingAutoBatchedRunLimit =
|
|
258
261
|
config.pendingAutoBatchedRunLimit ?? this.pendingAutoBatchedRunLimit;
|
|
@@ -1396,6 +1399,30 @@ export class Client {
|
|
|
1396
1399
|
yield* datasets;
|
|
1397
1400
|
}
|
|
1398
1401
|
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Update a dataset
|
|
1404
|
+
* @param props The dataset details to update
|
|
1405
|
+
* @returns The updated dataset
|
|
1406
|
+
*/
|
|
1407
|
+
async updateDataset(props) {
|
|
1408
|
+
const { datasetId, datasetName, ...update } = props;
|
|
1409
|
+
if (!datasetId && !datasetName) {
|
|
1410
|
+
throw new Error("Must provide either datasetName or datasetId");
|
|
1411
|
+
}
|
|
1412
|
+
const _datasetId = datasetId ?? (await this.readDataset({ datasetName })).id;
|
|
1413
|
+
assertUuid(_datasetId);
|
|
1414
|
+
const response = await this.caller.call(fetch, `${this.apiUrl}/datasets/${_datasetId}`, {
|
|
1415
|
+
method: "PATCH",
|
|
1416
|
+
headers: { ...this.headers, "Content-Type": "application/json" },
|
|
1417
|
+
body: JSON.stringify(update),
|
|
1418
|
+
signal: AbortSignal.timeout(this.timeout_ms),
|
|
1419
|
+
...this.fetchOptions,
|
|
1420
|
+
});
|
|
1421
|
+
if (!response.ok) {
|
|
1422
|
+
throw new Error(`Failed to update dataset ${_datasetId}: ${response.status} ${response.statusText}`);
|
|
1423
|
+
}
|
|
1424
|
+
return (await response.json());
|
|
1425
|
+
}
|
|
1399
1426
|
async deleteDataset({ datasetId, datasetName, }) {
|
|
1400
1427
|
let path = "/datasets";
|
|
1401
1428
|
let datasetId_ = datasetId;
|
|
@@ -1589,7 +1616,11 @@ export class Client {
|
|
|
1589
1616
|
const result = await response.json();
|
|
1590
1617
|
return result;
|
|
1591
1618
|
}
|
|
1619
|
+
/**
|
|
1620
|
+
* @deprecated This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead.
|
|
1621
|
+
*/
|
|
1592
1622
|
async evaluateRun(run, evaluator, { sourceInfo, loadChildRuns, referenceExample, } = { loadChildRuns: false }) {
|
|
1623
|
+
warnOnce("This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead.");
|
|
1593
1624
|
let run_;
|
|
1594
1625
|
if (typeof run === "string") {
|
|
1595
1626
|
run_ = await this.readRun(run, { loadChildRuns });
|
|
@@ -1605,20 +1636,8 @@ export class Client {
|
|
|
1605
1636
|
referenceExample = await this.readExample(run_.reference_example_id);
|
|
1606
1637
|
}
|
|
1607
1638
|
const feedbackResult = await evaluator.evaluateRun(run_, referenceExample);
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
sourceInfo_ = { ...sourceInfo_, ...feedbackResult.evaluatorInfo };
|
|
1611
|
-
}
|
|
1612
|
-
const runId = feedbackResult.targetRunId ?? run_.id;
|
|
1613
|
-
return await this.createFeedback(runId, feedbackResult.key, {
|
|
1614
|
-
score: feedbackResult?.score,
|
|
1615
|
-
value: feedbackResult?.value,
|
|
1616
|
-
comment: feedbackResult?.comment,
|
|
1617
|
-
correction: feedbackResult?.correction,
|
|
1618
|
-
sourceInfo: sourceInfo_,
|
|
1619
|
-
feedbackSourceType: "model",
|
|
1620
|
-
sourceRunId: feedbackResult?.sourceRunId,
|
|
1621
|
-
});
|
|
1639
|
+
const [_, feedbacks] = await this._logEvaluationFeedback(feedbackResult, run_, sourceInfo);
|
|
1640
|
+
return feedbacks[0];
|
|
1622
1641
|
}
|
|
1623
1642
|
async createFeedback(runId, key, { score, value, correction, comment, sourceInfo, feedbackSourceType = "api", sourceRunId, feedbackId, feedbackConfig, projectId, comparativeExperimentId, }) {
|
|
1624
1643
|
if (!runId && !projectId) {
|
|
@@ -1825,9 +1844,10 @@ export class Client {
|
|
|
1825
1844
|
}
|
|
1826
1845
|
return results_;
|
|
1827
1846
|
}
|
|
1828
|
-
async
|
|
1829
|
-
const
|
|
1830
|
-
|
|
1847
|
+
async _logEvaluationFeedback(evaluatorResponse, run, sourceInfo) {
|
|
1848
|
+
const evalResults = this._selectEvalResults(evaluatorResponse);
|
|
1849
|
+
const feedbacks = [];
|
|
1850
|
+
for (const res of evalResults) {
|
|
1831
1851
|
let sourceInfo_ = sourceInfo || {};
|
|
1832
1852
|
if (res.evaluatorInfo) {
|
|
1833
1853
|
sourceInfo_ = { ...res.evaluatorInfo, ...sourceInfo_ };
|
|
@@ -1839,7 +1859,7 @@ export class Client {
|
|
|
1839
1859
|
else if (run) {
|
|
1840
1860
|
runId_ = run.id;
|
|
1841
1861
|
}
|
|
1842
|
-
await this.createFeedback(runId_, res.key, {
|
|
1862
|
+
feedbacks.push(await this.createFeedback(runId_, res.key, {
|
|
1843
1863
|
score: res.score,
|
|
1844
1864
|
value: res.value,
|
|
1845
1865
|
comment: res.comment,
|
|
@@ -1848,8 +1868,12 @@ export class Client {
|
|
|
1848
1868
|
sourceRunId: res.sourceRunId,
|
|
1849
1869
|
feedbackConfig: res.feedbackConfig,
|
|
1850
1870
|
feedbackSourceType: "model",
|
|
1851
|
-
});
|
|
1871
|
+
}));
|
|
1852
1872
|
}
|
|
1873
|
+
return [evalResults, feedbacks];
|
|
1874
|
+
}
|
|
1875
|
+
async logEvaluationFeedback(evaluatorResponse, run, sourceInfo) {
|
|
1876
|
+
const [results] = await this._logEvaluationFeedback(evaluatorResponse, run, sourceInfo);
|
|
1853
1877
|
return results;
|
|
1854
1878
|
}
|
|
1855
1879
|
}
|
|
@@ -8,7 +8,7 @@ type TargetT<TInput = any, TOutput = KVMap> = ((input: TInput, config?: KVMap) =
|
|
|
8
8
|
};
|
|
9
9
|
type DataT = string | AsyncIterable<Example> | Example[];
|
|
10
10
|
type SummaryEvaluatorT = ((runs: Array<Run>, examples: Array<Example>) => Promise<EvaluationResult | EvaluationResults>) | ((runs: Array<Run>, examples: Array<Example>) => EvaluationResult | EvaluationResults);
|
|
11
|
-
type EvaluatorT = RunEvaluator | ((run: Run, example?: Example) => EvaluationResult) | ((run: Run, example?: Example) => Promise<EvaluationResult>);
|
|
11
|
+
type EvaluatorT = RunEvaluator | ((run: Run, example?: Example) => EvaluationResult | EvaluationResults) | ((run: Run, example?: Example) => Promise<EvaluationResult | EvaluationResults>);
|
|
12
12
|
interface _ForwardResults {
|
|
13
13
|
run: Run;
|
|
14
14
|
example: Example;
|
|
@@ -19,9 +19,18 @@ class DynamicRunEvaluator {
|
|
|
19
19
|
return evaluator(run, example);
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
+
isEvaluationResults(x) {
|
|
23
|
+
return (typeof x === "object" &&
|
|
24
|
+
x != null &&
|
|
25
|
+
"results" in x &&
|
|
26
|
+
Array.isArray(x.results) &&
|
|
27
|
+
x.results.length > 0);
|
|
28
|
+
}
|
|
22
29
|
coerceEvaluationResults(results, sourceRunId) {
|
|
23
|
-
if (
|
|
24
|
-
|
|
30
|
+
if (this.isEvaluationResults(results)) {
|
|
31
|
+
return {
|
|
32
|
+
results: results.results.map((r) => this.coerceEvaluationResult(r, sourceRunId, false)),
|
|
33
|
+
};
|
|
25
34
|
}
|
|
26
35
|
return this.coerceEvaluationResult(results, sourceRunId, true);
|
|
27
36
|
}
|
|
@@ -70,7 +70,7 @@ export type EvaluationResults = {
|
|
|
70
70
|
results: Array<EvaluationResult>;
|
|
71
71
|
};
|
|
72
72
|
export interface RunEvaluator {
|
|
73
|
-
evaluateRun(run: Run, example?: Example, options?: Partial<RunTreeConfig>): Promise<EvaluationResult>;
|
|
73
|
+
evaluateRun(run: Run, example?: Example, options?: Partial<RunTreeConfig>): Promise<EvaluationResult | EvaluationResults>;
|
|
74
74
|
}
|
|
75
75
|
export type RunEvaluatorLike = ((run: Run, example?: Example) => Promise<EvaluationResult | EvaluationResults>) | ((run: Run, example?: Example) => EvaluationResult | EvaluationResults);
|
|
76
76
|
/**
|
|
@@ -79,6 +79,7 @@ export type RunEvaluatorLike = ((run: Run, example?: Example) => Promise<Evaluat
|
|
|
79
79
|
export declare class DynamicRunEvaluator<Func extends (...args: any[]) => any> implements RunEvaluator {
|
|
80
80
|
func: Func;
|
|
81
81
|
constructor(evaluator: Func);
|
|
82
|
+
private isEvaluationResults;
|
|
82
83
|
private coerceEvaluationResults;
|
|
83
84
|
private coerceEvaluationResult;
|
|
84
85
|
/**
|
|
@@ -87,6 +88,6 @@ export declare class DynamicRunEvaluator<Func extends (...args: any[]) => any> i
|
|
|
87
88
|
* @param example The optional example to use for evaluation.
|
|
88
89
|
* @returns A promise that extracts to the evaluation result.
|
|
89
90
|
*/
|
|
90
|
-
evaluateRun(run: Run, example?: Example, options?: Partial<RunTreeConfig>): Promise<EvaluationResult>;
|
|
91
|
+
evaluateRun(run: Run, example?: Example, options?: Partial<RunTreeConfig>): Promise<EvaluationResult | EvaluationResults>;
|
|
91
92
|
}
|
|
92
93
|
export declare function runEvaluator(func: RunEvaluatorLike): RunEvaluator;
|
|
@@ -16,9 +16,18 @@ export class DynamicRunEvaluator {
|
|
|
16
16
|
return evaluator(run, example);
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
+
isEvaluationResults(x) {
|
|
20
|
+
return (typeof x === "object" &&
|
|
21
|
+
x != null &&
|
|
22
|
+
"results" in x &&
|
|
23
|
+
Array.isArray(x.results) &&
|
|
24
|
+
x.results.length > 0);
|
|
25
|
+
}
|
|
19
26
|
coerceEvaluationResults(results, sourceRunId) {
|
|
20
|
-
if (
|
|
21
|
-
|
|
27
|
+
if (this.isEvaluationResults(results)) {
|
|
28
|
+
return {
|
|
29
|
+
results: results.results.map((r) => this.coerceEvaluationResult(r, sourceRunId, false)),
|
|
30
|
+
};
|
|
22
31
|
}
|
|
23
32
|
return this.coerceEvaluationResult(results, sourceRunId, true);
|
|
24
33
|
}
|
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.33";
|
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.33";
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "langsmith",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.33",
|
|
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": [
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
"wrappers.js",
|
|
38
38
|
"wrappers.d.ts",
|
|
39
39
|
"wrappers.d.cts",
|
|
40
|
+
"anonymizer.cjs",
|
|
41
|
+
"anonymizer.js",
|
|
42
|
+
"anonymizer.d.ts",
|
|
43
|
+
"anonymizer.d.cts",
|
|
40
44
|
"wrappers/openai.cjs",
|
|
41
45
|
"wrappers/openai.js",
|
|
42
46
|
"wrappers/openai.d.ts",
|
|
@@ -91,6 +95,7 @@
|
|
|
91
95
|
"dependencies": {
|
|
92
96
|
"@types/uuid": "^9.0.1",
|
|
93
97
|
"commander": "^10.0.1",
|
|
98
|
+
"lodash.set": "^4.3.2",
|
|
94
99
|
"p-queue": "^6.6.2",
|
|
95
100
|
"p-retry": "4",
|
|
96
101
|
"uuid": "^9.0.0"
|
|
@@ -104,6 +109,7 @@
|
|
|
104
109
|
"@langchain/langgraph": "^0.0.19",
|
|
105
110
|
"@tsconfig/recommended": "^1.0.2",
|
|
106
111
|
"@types/jest": "^29.5.1",
|
|
112
|
+
"@types/lodash.set": "^4.3.9",
|
|
107
113
|
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
|
108
114
|
"@typescript-eslint/parser": "^5.59.8",
|
|
109
115
|
"babel-jest": "^29.5.0",
|
|
@@ -228,6 +234,15 @@
|
|
|
228
234
|
"import": "./wrappers.js",
|
|
229
235
|
"require": "./wrappers.cjs"
|
|
230
236
|
},
|
|
237
|
+
"./anonymizer": {
|
|
238
|
+
"types": {
|
|
239
|
+
"import": "./anonymizer.d.ts",
|
|
240
|
+
"require": "./anonymizer.d.cts",
|
|
241
|
+
"default": "./anonymizer.d.ts"
|
|
242
|
+
},
|
|
243
|
+
"import": "./anonymizer.js",
|
|
244
|
+
"require": "./anonymizer.cjs"
|
|
245
|
+
},
|
|
231
246
|
"./wrappers/openai": {
|
|
232
247
|
"types": {
|
|
233
248
|
"import": "./wrappers/openai.d.ts",
|