langsmith 0.5.23 → 0.5.25
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 +102 -11
- package/dist/client.d.ts +38 -0
- package/dist/client.js +103 -12
- package/dist/evaluation/_runner.cjs +3 -3
- package/dist/evaluation/_runner.js +1 -1
- package/dist/evaluation/evaluate_comparative.cjs +10 -10
- package/dist/evaluation/evaluate_comparative.js +1 -1
- package/dist/evaluation/evaluator.cjs +2 -2
- package/dist/evaluation/evaluator.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/run_trees.cjs +8 -7
- package/dist/run_trees.d.ts +7 -0
- package/dist/run_trees.js +7 -6
- package/dist/schemas.d.ts +4 -0
- package/dist/singletons/otel.cjs +3 -2
- package/dist/singletons/otel.js +4 -3
- package/dist/traceable.cjs +1 -2
- package/dist/traceable.js +1 -2
- package/dist/utils/_uuid.cjs +2 -2
- package/dist/utils/_uuid.js +1 -1
- package/dist/utils/env.cjs +33 -0
- package/dist/utils/env.d.ts +9 -0
- package/dist/utils/env.js +32 -0
- package/dist/utils/fast-safe-stringify/index.cjs +10 -35
- package/dist/utils/fast-safe-stringify/index.d.ts +14 -1
- package/dist/utils/fast-safe-stringify/index.js +10 -35
- package/dist/utils/jestlike/index.cjs +5 -5
- package/dist/utils/jestlike/index.js +1 -1
- package/dist/utils/jestlike/vendor/evaluatedBy.cjs +3 -3
- package/dist/utils/jestlike/vendor/evaluatedBy.js +1 -1
- package/dist/utils/serialize_worker.cjs +389 -0
- package/dist/utils/serialize_worker.d.ts +67 -0
- package/dist/utils/serialize_worker.js +383 -0
- package/dist/utils/uuid/src/index.cjs +24 -0
- package/dist/utils/uuid/src/index.d.ts +10 -0
- package/dist/utils/uuid/src/index.js +9 -0
- package/dist/utils/uuid/src/max.cjs +3 -0
- package/dist/utils/uuid/src/max.d.ts +2 -0
- package/dist/utils/uuid/src/max.js +1 -0
- package/dist/utils/uuid/src/nil.cjs +3 -0
- package/dist/utils/uuid/src/nil.d.ts +2 -0
- package/dist/utils/uuid/src/nil.js +1 -0
- package/dist/utils/uuid/src/parse.cjs +23 -0
- package/dist/utils/uuid/src/parse.d.ts +3 -0
- package/dist/utils/uuid/src/parse.js +18 -0
- package/dist/utils/uuid/src/regex.cjs +3 -0
- package/dist/utils/uuid/src/regex.d.ts +2 -0
- package/dist/utils/uuid/src/regex.js +1 -0
- package/dist/utils/uuid/src/rng.cjs +10 -0
- package/dist/utils/uuid/src/rng.d.ts +1 -0
- package/dist/utils/uuid/src/rng.js +7 -0
- package/dist/utils/uuid/src/sha1.cjs +75 -0
- package/dist/utils/uuid/src/sha1.d.ts +2 -0
- package/dist/utils/uuid/src/sha1.js +73 -0
- package/dist/utils/uuid/src/stringify.cjs +55 -0
- package/dist/utils/uuid/src/stringify.d.ts +3 -0
- package/dist/utils/uuid/src/stringify.js +49 -0
- package/dist/utils/uuid/src/types.cjs +2 -0
- package/dist/utils/uuid/src/types.d.ts +22 -0
- package/dist/utils/uuid/src/types.js +1 -0
- package/dist/utils/uuid/src/v35.cjs +52 -0
- package/dist/utils/uuid/src/v35.d.ts +7 -0
- package/dist/utils/uuid/src/v35.js +44 -0
- package/dist/utils/uuid/src/v4.cjs +40 -0
- package/dist/utils/uuid/src/v4.d.ts +4 -0
- package/dist/utils/uuid/src/v4.js +35 -0
- package/dist/utils/uuid/src/v5.cjs +50 -0
- package/dist/utils/uuid/src/v5.d.ts +9 -0
- package/dist/utils/uuid/src/v5.js +9 -0
- package/dist/utils/uuid/src/v7.cjs +88 -0
- package/dist/utils/uuid/src/v7.d.ts +9 -0
- package/dist/utils/uuid/src/v7.js +82 -0
- package/dist/utils/uuid/src/validate.cjs +10 -0
- package/dist/utils/uuid/src/validate.d.ts +2 -0
- package/dist/utils/uuid/src/validate.js +5 -0
- package/dist/utils/uuid/src/version.cjs +13 -0
- package/dist/utils/uuid/src/version.d.ts +2 -0
- package/dist/utils/uuid/src/version.js +8 -0
- package/dist/utils/worker_threads.browser.cjs +16 -0
- package/dist/utils/worker_threads.browser.d.ts +14 -0
- package/dist/utils/worker_threads.browser.js +13 -0
- package/dist/utils/worker_threads.cjs +16 -0
- package/dist/utils/worker_threads.d.ts +13 -0
- package/dist/utils/worker_threads.js +13 -0
- package/dist/uuid.cjs +2 -2
- package/dist/uuid.js +1 -1
- package/package.json +4 -4
package/dist/run_trees.cjs
CHANGED
|
@@ -14,7 +14,7 @@ const project_js_1 = require("./utils/project.cjs");
|
|
|
14
14
|
const env_js_3 = require("./utils/env.cjs");
|
|
15
15
|
const warn_js_1 = require("./utils/warn.cjs");
|
|
16
16
|
const _uuid_js_1 = require("./utils/_uuid.cjs");
|
|
17
|
-
const
|
|
17
|
+
const index_js_1 = require("./utils/uuid/src/index.cjs");
|
|
18
18
|
const TIMESTAMP_LENGTH = 36;
|
|
19
19
|
// DNS namespace for UUID v5 (same as Python's uuid.NAMESPACE_DNS)
|
|
20
20
|
const UUID_NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
|
@@ -26,7 +26,7 @@ function getReplicaKey(replica) {
|
|
|
26
26
|
const keyData = sortedKeys
|
|
27
27
|
.map((key) => `${key}:${replica[key] ?? ""}`)
|
|
28
28
|
.join("|");
|
|
29
|
-
return (0,
|
|
29
|
+
return (0, index_js_1.v5)(keyData, UUID_NAMESPACE_DNS);
|
|
30
30
|
}
|
|
31
31
|
function stripNonAlphanumeric(input) {
|
|
32
32
|
return input.replace(/[-:.]/g, "");
|
|
@@ -691,8 +691,7 @@ class RunTree {
|
|
|
691
691
|
try {
|
|
692
692
|
const runtimeEnv = (0, env_js_2.getRuntimeEnvironment)();
|
|
693
693
|
if (this.replicas && this.replicas.length > 0) {
|
|
694
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, reroot } of this
|
|
695
|
-
.replicas) {
|
|
694
|
+
for (const { projectName, apiKey, apiUrl, workspaceId, reroot, client: replicaClient, } of this.replicas) {
|
|
696
695
|
const runCreate = this._remapForProject({
|
|
697
696
|
projectName: projectName ?? this.project_name,
|
|
698
697
|
runtimeEnv,
|
|
@@ -703,7 +702,8 @@ class RunTree {
|
|
|
703
702
|
apiKey,
|
|
704
703
|
workspaceId,
|
|
705
704
|
});
|
|
706
|
-
|
|
705
|
+
const targetClient = replicaClient ?? this.client;
|
|
706
|
+
await targetClient.createRun(runCreate, {
|
|
707
707
|
apiKey,
|
|
708
708
|
apiUrl,
|
|
709
709
|
workspaceId,
|
|
@@ -728,7 +728,7 @@ class RunTree {
|
|
|
728
728
|
}
|
|
729
729
|
async patchRun(options) {
|
|
730
730
|
if (this.replicas && this.replicas.length > 0) {
|
|
731
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, updates, reroot, } of this.replicas) {
|
|
731
|
+
for (const { projectName, apiKey, apiUrl, workspaceId, updates, reroot, client: replicaClient, } of this.replicas) {
|
|
732
732
|
const runData = this._remapForProject({
|
|
733
733
|
projectName: projectName ?? this.project_name,
|
|
734
734
|
runtimeEnv: undefined,
|
|
@@ -764,7 +764,8 @@ class RunTree {
|
|
|
764
764
|
if (!options?.excludeInputs) {
|
|
765
765
|
updatePayload.inputs = runData.inputs;
|
|
766
766
|
}
|
|
767
|
-
|
|
767
|
+
const targetClient = replicaClient ?? this.client;
|
|
768
|
+
await targetClient.updateRun(runData.id, updatePayload, {
|
|
768
769
|
apiKey,
|
|
769
770
|
apiUrl,
|
|
770
771
|
workspaceId,
|
package/dist/run_trees.d.ts
CHANGED
|
@@ -63,6 +63,13 @@ type WriteReplica = {
|
|
|
63
63
|
updates?: KVMap | undefined;
|
|
64
64
|
fromEnv?: boolean;
|
|
65
65
|
reroot?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Optional dedicated Client for this replica.
|
|
68
|
+
* When set, the replica's runs are dispatched through this client
|
|
69
|
+
* (and its tracing mode) instead of the RunTree's default client.
|
|
70
|
+
* Not serialized in distributed-tracing baggage headers.
|
|
71
|
+
*/
|
|
72
|
+
client?: Client;
|
|
66
73
|
};
|
|
67
74
|
type Replica = ProjectReplica | WriteReplica;
|
|
68
75
|
export declare class RunTree implements BaseRun {
|
package/dist/run_trees.js
CHANGED
|
@@ -8,7 +8,7 @@ import { getDefaultProjectName } from "./utils/project.js";
|
|
|
8
8
|
import { getLangSmithEnvironmentVariable } from "./utils/env.js";
|
|
9
9
|
import { warnOnce } from "./utils/warn.js";
|
|
10
10
|
import { uuid7FromTime, nonCryptographicUuid7Deterministic, } from "./utils/_uuid.js";
|
|
11
|
-
import { v5 as uuidv5 } from "uuid";
|
|
11
|
+
import { v5 as uuidv5 } from "./utils/uuid/src/index.js";
|
|
12
12
|
const TIMESTAMP_LENGTH = 36;
|
|
13
13
|
// DNS namespace for UUID v5 (same as Python's uuid.NAMESPACE_DNS)
|
|
14
14
|
const UUID_NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
|
@@ -685,8 +685,7 @@ export class RunTree {
|
|
|
685
685
|
try {
|
|
686
686
|
const runtimeEnv = getRuntimeEnvironment();
|
|
687
687
|
if (this.replicas && this.replicas.length > 0) {
|
|
688
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, reroot } of this
|
|
689
|
-
.replicas) {
|
|
688
|
+
for (const { projectName, apiKey, apiUrl, workspaceId, reroot, client: replicaClient, } of this.replicas) {
|
|
690
689
|
const runCreate = this._remapForProject({
|
|
691
690
|
projectName: projectName ?? this.project_name,
|
|
692
691
|
runtimeEnv,
|
|
@@ -697,7 +696,8 @@ export class RunTree {
|
|
|
697
696
|
apiKey,
|
|
698
697
|
workspaceId,
|
|
699
698
|
});
|
|
700
|
-
|
|
699
|
+
const targetClient = replicaClient ?? this.client;
|
|
700
|
+
await targetClient.createRun(runCreate, {
|
|
701
701
|
apiKey,
|
|
702
702
|
apiUrl,
|
|
703
703
|
workspaceId,
|
|
@@ -722,7 +722,7 @@ export class RunTree {
|
|
|
722
722
|
}
|
|
723
723
|
async patchRun(options) {
|
|
724
724
|
if (this.replicas && this.replicas.length > 0) {
|
|
725
|
-
for (const { projectName, apiKey, apiUrl, workspaceId, updates, reroot, } of this.replicas) {
|
|
725
|
+
for (const { projectName, apiKey, apiUrl, workspaceId, updates, reroot, client: replicaClient, } of this.replicas) {
|
|
726
726
|
const runData = this._remapForProject({
|
|
727
727
|
projectName: projectName ?? this.project_name,
|
|
728
728
|
runtimeEnv: undefined,
|
|
@@ -758,7 +758,8 @@ export class RunTree {
|
|
|
758
758
|
if (!options?.excludeInputs) {
|
|
759
759
|
updatePayload.inputs = runData.inputs;
|
|
760
760
|
}
|
|
761
|
-
|
|
761
|
+
const targetClient = replicaClient ?? this.client;
|
|
762
|
+
await targetClient.updateRun(runData.id, updatePayload, {
|
|
762
763
|
apiKey,
|
|
763
764
|
apiUrl,
|
|
764
765
|
workspaceId,
|
package/dist/schemas.d.ts
CHANGED
|
@@ -398,6 +398,10 @@ export interface PromptCommit {
|
|
|
398
398
|
manifest: Record<string, any>;
|
|
399
399
|
examples: Array<Record<any, any>>;
|
|
400
400
|
description?: string;
|
|
401
|
+
/** The model configuration for the prompt. */
|
|
402
|
+
hub_model_config?: Record<string, any>;
|
|
403
|
+
/** The model provider (e.g. ChatOpenAI) */
|
|
404
|
+
hub_model_provider?: string;
|
|
401
405
|
}
|
|
402
406
|
export interface Prompt {
|
|
403
407
|
repo_handle: string;
|
package/dist/singletons/otel.cjs
CHANGED
|
@@ -18,8 +18,9 @@ class MockTracer {
|
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
startActiveSpan(_name, ...args) {
|
|
21
|
-
if (!this.hasWarned && (0, env_js_1.
|
|
22
|
-
console.warn("
|
|
21
|
+
if (!this.hasWarned && (0, env_js_1.resolveTracingMode)() === "otel") {
|
|
22
|
+
console.warn("OTel tracing mode is active (via LANGSMITH_TRACING_MODE, OTEL_ENABLED, or " +
|
|
23
|
+
"LANGSMITH_OTEL_ENABLED), but the required OTEL instances have not been initialized. " +
|
|
23
24
|
'Please add:\n```\nimport { initializeOTEL } from "langsmith/experimental/otel/setup";\ninitializeOTEL();\n```\nat the beginning of your code.');
|
|
24
25
|
this.hasWarned = true;
|
|
25
26
|
}
|
package/dist/singletons/otel.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Should not import any OTEL packages to avoid pulling in optional deps.
|
|
2
|
-
import {
|
|
2
|
+
import { resolveTracingMode } from "../utils/env.js";
|
|
3
3
|
class MockTracer {
|
|
4
4
|
constructor() {
|
|
5
5
|
Object.defineProperty(this, "hasWarned", {
|
|
@@ -10,8 +10,9 @@ class MockTracer {
|
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
12
|
startActiveSpan(_name, ...args) {
|
|
13
|
-
if (!this.hasWarned &&
|
|
14
|
-
console.warn("
|
|
13
|
+
if (!this.hasWarned && resolveTracingMode() === "otel") {
|
|
14
|
+
console.warn("OTel tracing mode is active (via LANGSMITH_TRACING_MODE, OTEL_ENABLED, or " +
|
|
15
|
+
"LANGSMITH_OTEL_ENABLED), but the required OTEL instances have not been initialized. " +
|
|
15
16
|
'Please add:\n```\nimport { initializeOTEL } from "langsmith/experimental/otel/setup";\ninitializeOTEL();\n```\nat the beginning of your code.');
|
|
16
17
|
this.hasWarned = true;
|
|
17
18
|
}
|
package/dist/traceable.cjs
CHANGED
|
@@ -8,7 +8,6 @@ const env_js_1 = require("./env.cjs");
|
|
|
8
8
|
const traceable_js_1 = require("./singletons/traceable.cjs");
|
|
9
9
|
const constants_js_1 = require("./singletons/constants.cjs");
|
|
10
10
|
const asserts_js_1 = require("./utils/asserts.cjs");
|
|
11
|
-
const env_js_2 = require("./utils/env.cjs");
|
|
12
11
|
const index_js_1 = require("./index.cjs");
|
|
13
12
|
const otel_js_1 = require("./singletons/otel.cjs");
|
|
14
13
|
const utils_js_1 = require("./experimental/otel/utils.cjs");
|
|
@@ -20,7 +19,7 @@ traceable_js_1.AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new n
|
|
|
20
19
|
function maybeCreateOtelContext(runTree, projectName, tracer
|
|
21
20
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
21
|
) {
|
|
23
|
-
if (!runTree ||
|
|
22
|
+
if (!runTree || runTree.client.tracingMode !== "otel") {
|
|
24
23
|
return;
|
|
25
24
|
}
|
|
26
25
|
const otel_trace = (0, otel_js_1.getOTELTrace)();
|
package/dist/traceable.js
CHANGED
|
@@ -4,7 +4,6 @@ import { isTracingEnabled } from "./env.js";
|
|
|
4
4
|
import { ROOT, AsyncLocalStorageProviderSingleton, getCurrentRunTree, } from "./singletons/traceable.js";
|
|
5
5
|
import { _LC_CHILD_RUN_END_PROMISES_KEY, _LC_CONTEXT_VARIABLES_KEY, } from "./singletons/constants.js";
|
|
6
6
|
import { isKVMap, isReadableStream, isAsyncIterable, isIteratorLike, isThenable, isGenerator, isPromiseMethod, } from "./utils/asserts.js";
|
|
7
|
-
import { getOtelEnabled } from "./utils/env.js";
|
|
8
7
|
import { __version__ } from "./index.js";
|
|
9
8
|
import { getOTELTrace, getOTELContext } from "./singletons/otel.js";
|
|
10
9
|
import { getUuidFromOtelSpanId } from "./experimental/otel/utils.js";
|
|
@@ -16,7 +15,7 @@ AsyncLocalStorageProviderSingleton.initializeGlobalInstance(new AsyncLocalStorag
|
|
|
16
15
|
function maybeCreateOtelContext(runTree, projectName, tracer
|
|
17
16
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
17
|
) {
|
|
19
|
-
if (!runTree ||
|
|
18
|
+
if (!runTree || runTree.client.tracingMode !== "otel") {
|
|
20
19
|
return;
|
|
21
20
|
}
|
|
22
21
|
const otel_trace = getOTELTrace();
|
package/dist/utils/_uuid.cjs
CHANGED
|
@@ -7,7 +7,7 @@ exports.warnIfNotUuidV7 = warnIfNotUuidV7;
|
|
|
7
7
|
exports.nonCryptographicUuid7Deterministic = nonCryptographicUuid7Deterministic;
|
|
8
8
|
// Relaxed UUID validation regex (allows any valid UUID format including nil UUIDs)
|
|
9
9
|
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
10
|
-
const
|
|
10
|
+
const index_js_1 = require("./uuid/src/index.cjs");
|
|
11
11
|
const warn_js_1 = require("./warn.cjs");
|
|
12
12
|
const xxhash_js_1 = require("./xxhash/xxhash.cjs");
|
|
13
13
|
let UUID7_WARNING_EMITTED = false;
|
|
@@ -34,7 +34,7 @@ function uuid7FromTime(timestamp) {
|
|
|
34
34
|
// may not set the internal timestamp used for stringification.
|
|
35
35
|
// Providing a seq ensures the implementation updates its internal state
|
|
36
36
|
// and encodes the provided milliseconds into the UUID bytes.
|
|
37
|
-
return (0,
|
|
37
|
+
return (0, index_js_1.v7)({ msecs, seq: 0 });
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
* Get the version of a UUID string.
|
package/dist/utils/_uuid.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Relaxed UUID validation regex (allows any valid UUID format including nil UUIDs)
|
|
2
2
|
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
3
|
-
import { v7 as uuidv7 } from "uuid";
|
|
3
|
+
import { v7 as uuidv7 } from "./uuid/src/index.js";
|
|
4
4
|
import { warnOnce } from "./warn.js";
|
|
5
5
|
import { XXH3_128, xxh128ToBytes } from "./xxhash/xxhash.js";
|
|
6
6
|
let UUID7_WARNING_EMITTED = false;
|
package/dist/utils/env.cjs
CHANGED
|
@@ -9,6 +9,7 @@ exports.getLangSmithEnvironmentVariable = getLangSmithEnvironmentVariable;
|
|
|
9
9
|
exports.setEnvironmentVariable = setEnvironmentVariable;
|
|
10
10
|
exports.getShas = getShas;
|
|
11
11
|
exports.getOtelEnabled = getOtelEnabled;
|
|
12
|
+
exports.resolveTracingMode = resolveTracingMode;
|
|
12
13
|
// Inlined from https://github.com/flexdinesh/browser-or-node
|
|
13
14
|
const index_js_1 = require("../index.cjs");
|
|
14
15
|
let globalEnv;
|
|
@@ -218,3 +219,35 @@ function getOtelEnabled() {
|
|
|
218
219
|
return (getEnvironmentVariable("OTEL_ENABLED") === "true" ||
|
|
219
220
|
getLangSmithEnvironmentVariable("OTEL_ENABLED") === "true");
|
|
220
221
|
}
|
|
222
|
+
const _VALID_TRACING_MODES = new Set(["langsmith", "otel"]);
|
|
223
|
+
/**
|
|
224
|
+
* Resolve the effective tracing mode from an explicit config value and
|
|
225
|
+
* environment variables.
|
|
226
|
+
*
|
|
227
|
+
* Priority: explicit argument > `LANGSMITH_TRACING_MODE` env var >
|
|
228
|
+
* legacy `OTEL_ENABLED` / `LANGSMITH_OTEL_ENABLED` env vars > `"langsmith"`.
|
|
229
|
+
*/
|
|
230
|
+
function resolveTracingMode(configValue) {
|
|
231
|
+
if (configValue !== undefined) {
|
|
232
|
+
return configValue;
|
|
233
|
+
}
|
|
234
|
+
const envMode = getLangSmithEnvironmentVariable("TRACING_MODE");
|
|
235
|
+
if (envMode !== undefined && envMode !== "") {
|
|
236
|
+
const lower = envMode.toLowerCase();
|
|
237
|
+
if (!_VALID_TRACING_MODES.has(lower)) {
|
|
238
|
+
throw new Error(`Invalid LANGSMITH_TRACING_MODE=${JSON.stringify(envMode)}. ` +
|
|
239
|
+
`Must be one of: ${[..._VALID_TRACING_MODES].sort().join(", ")}`);
|
|
240
|
+
}
|
|
241
|
+
if (getOtelEnabled()) {
|
|
242
|
+
console.warn("Both LANGSMITH_TRACING_MODE and the legacy OTEL_ENABLED / " +
|
|
243
|
+
"LANGSMITH_OTEL_ENABLED env vars are set. " +
|
|
244
|
+
"LANGSMITH_TRACING_MODE takes precedence.");
|
|
245
|
+
}
|
|
246
|
+
return lower;
|
|
247
|
+
}
|
|
248
|
+
// Fall back to legacy env var
|
|
249
|
+
if (getOtelEnabled()) {
|
|
250
|
+
return "otel";
|
|
251
|
+
}
|
|
252
|
+
return "langsmith";
|
|
253
|
+
}
|
package/dist/utils/env.d.ts
CHANGED
|
@@ -48,4 +48,13 @@ interface ICommitSHAs {
|
|
|
48
48
|
*/
|
|
49
49
|
export declare function getShas(): ICommitSHAs;
|
|
50
50
|
export declare function getOtelEnabled(): boolean;
|
|
51
|
+
export type TracingMode = "langsmith" | "otel";
|
|
52
|
+
/**
|
|
53
|
+
* Resolve the effective tracing mode from an explicit config value and
|
|
54
|
+
* environment variables.
|
|
55
|
+
*
|
|
56
|
+
* Priority: explicit argument > `LANGSMITH_TRACING_MODE` env var >
|
|
57
|
+
* legacy `OTEL_ENABLED` / `LANGSMITH_OTEL_ENABLED` env vars > `"langsmith"`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveTracingMode(configValue?: TracingMode): TracingMode;
|
|
51
60
|
export {};
|
package/dist/utils/env.js
CHANGED
|
@@ -201,3 +201,35 @@ export function getOtelEnabled() {
|
|
|
201
201
|
return (getEnvironmentVariable("OTEL_ENABLED") === "true" ||
|
|
202
202
|
getLangSmithEnvironmentVariable("OTEL_ENABLED") === "true");
|
|
203
203
|
}
|
|
204
|
+
const _VALID_TRACING_MODES = new Set(["langsmith", "otel"]);
|
|
205
|
+
/**
|
|
206
|
+
* Resolve the effective tracing mode from an explicit config value and
|
|
207
|
+
* environment variables.
|
|
208
|
+
*
|
|
209
|
+
* Priority: explicit argument > `LANGSMITH_TRACING_MODE` env var >
|
|
210
|
+
* legacy `OTEL_ENABLED` / `LANGSMITH_OTEL_ENABLED` env vars > `"langsmith"`.
|
|
211
|
+
*/
|
|
212
|
+
export function resolveTracingMode(configValue) {
|
|
213
|
+
if (configValue !== undefined) {
|
|
214
|
+
return configValue;
|
|
215
|
+
}
|
|
216
|
+
const envMode = getLangSmithEnvironmentVariable("TRACING_MODE");
|
|
217
|
+
if (envMode !== undefined && envMode !== "") {
|
|
218
|
+
const lower = envMode.toLowerCase();
|
|
219
|
+
if (!_VALID_TRACING_MODES.has(lower)) {
|
|
220
|
+
throw new Error(`Invalid LANGSMITH_TRACING_MODE=${JSON.stringify(envMode)}. ` +
|
|
221
|
+
`Must be one of: ${[..._VALID_TRACING_MODES].sort().join(", ")}`);
|
|
222
|
+
}
|
|
223
|
+
if (getOtelEnabled()) {
|
|
224
|
+
console.warn("Both LANGSMITH_TRACING_MODE and the legacy OTEL_ENABLED / " +
|
|
225
|
+
"LANGSMITH_OTEL_ENABLED env vars are set. " +
|
|
226
|
+
"LANGSMITH_TRACING_MODE takes precedence.");
|
|
227
|
+
}
|
|
228
|
+
return lower;
|
|
229
|
+
}
|
|
230
|
+
// Fall back to legacy env var
|
|
231
|
+
if (getOtelEnabled()) {
|
|
232
|
+
return "otel";
|
|
233
|
+
}
|
|
234
|
+
return "langsmith";
|
|
235
|
+
}
|
|
@@ -61,44 +61,13 @@ function createDefaultReplacer(userReplacer) {
|
|
|
61
61
|
return serializeWellKnownTypes(val);
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Estimate the serialized JSON byte size of a value without actually
|
|
66
|
-
* serializing it. Used on hot paths (enqueuing runs for batched tracing)
|
|
67
|
-
* where the exact serialized size is not required -- only a reasonable
|
|
68
|
-
* approximation for soft memory accounting.
|
|
69
|
-
*
|
|
70
|
-
* Walks the object graph in O(n) without allocating a JSON string,
|
|
71
|
-
* avoiding the event-loop blocking that JSON.stringify causes on large
|
|
72
|
-
* payloads.
|
|
73
|
-
*
|
|
74
|
-
* Accuracy notes (all estimates are approximate, never exact):
|
|
75
|
-
* - Strings: UTF-8 byte length via Buffer.byteLength when available,
|
|
76
|
-
* falling back to code-unit length for non-Node environments. Does
|
|
77
|
-
* not account for escape expansion (\", \\, control chars, surrogate
|
|
78
|
-
* escapes) which is usually a small fraction of total size.
|
|
79
|
-
* - Binary data (Buffer / typed arrays / ArrayBuffer / DataView): sized
|
|
80
|
-
* from their JSON.stringify representations where practical
|
|
81
|
-
* ({ type: "Buffer", data: [...] } for Buffer, keyed objects for typed
|
|
82
|
-
* arrays). DataView and ArrayBuffer themselves have no enumerable own
|
|
83
|
-
* properties and serialize as "{}". Each byte contributes ~3.5
|
|
84
|
-
* characters on average in Buffer's decimal-array representation
|
|
85
|
-
* (digit(s) + comma).
|
|
86
|
-
* - Other objects with toJSON(): we invoke toJSON() once and estimate
|
|
87
|
-
* the result. This matches JSON.stringify semantics for libraries
|
|
88
|
-
* like Decimal.js, Moment, Luxon, Mongoose documents, etc.
|
|
89
|
-
* - Cycles: detected via an ancestor-path set that is pushed/popped
|
|
90
|
-
* during recursion. This matches JSON.stringify semantics --
|
|
91
|
-
* repeated references that are *not* on the current ancestor chain
|
|
92
|
-
* (shared subobjects) are counted every time they appear, because
|
|
93
|
-
* JSON.stringify will serialize them every time.
|
|
94
|
-
* - No depth limit (JSON.stringify has none either).
|
|
95
|
-
*/
|
|
96
64
|
function estimateSerializedSize(value) {
|
|
97
65
|
try {
|
|
98
66
|
// Ancestor set for cycle detection. An object is only treated as
|
|
99
67
|
// circular if it appears on the current recursion path, not merely
|
|
100
68
|
// if it has been seen before elsewhere in the graph.
|
|
101
69
|
const ancestors = new Set();
|
|
70
|
+
let maxStringLen = 0;
|
|
102
71
|
// In Node / Bun, Buffer.byteLength is a fast native way to get UTF-8
|
|
103
72
|
// byte length without allocating an encoded copy. In other runtimes
|
|
104
73
|
// we fall back to code-unit length (a small under-estimate for
|
|
@@ -108,7 +77,10 @@ function estimateSerializedSize(value) {
|
|
|
108
77
|
: (s) => s.length;
|
|
109
78
|
function estimateString(s) {
|
|
110
79
|
// +2 for the surrounding quotes. Escape expansion is not counted.
|
|
111
|
-
|
|
80
|
+
const n = byteLen(s);
|
|
81
|
+
if (n > maxStringLen)
|
|
82
|
+
maxStringLen = n;
|
|
83
|
+
return n + 2;
|
|
112
84
|
}
|
|
113
85
|
// Size of a byte sequence when rendered as a JSON array of decimal
|
|
114
86
|
// numbers: "[b0,b1,b2,...]". Each byte averages ~3.5 chars (value 0-9
|
|
@@ -279,13 +251,16 @@ function estimateSerializedSize(value) {
|
|
|
279
251
|
ancestors.delete(obj);
|
|
280
252
|
return size;
|
|
281
253
|
}
|
|
282
|
-
|
|
254
|
+
const size = estimate(value);
|
|
255
|
+
return { size, maxStringLen };
|
|
283
256
|
}
|
|
284
257
|
catch {
|
|
285
258
|
// If the estimator itself hits an unexpected edge case, fall back to the
|
|
286
259
|
// exact serialized size. This preserves correctness of queue-size
|
|
287
260
|
// accounting at the cost of a slower hot path for that one payload.
|
|
288
|
-
|
|
261
|
+
// We cannot cheaply recover maxStringLen here, so report 0: the worker
|
|
262
|
+
// gate will then fall back to sync serialization, which is safe.
|
|
263
|
+
return { size: serialize(value).length, maxStringLen: 0 };
|
|
289
264
|
}
|
|
290
265
|
}
|
|
291
266
|
// Regular stringify
|
|
@@ -30,5 +30,18 @@
|
|
|
30
30
|
* JSON.stringify will serialize them every time.
|
|
31
31
|
* - No depth limit (JSON.stringify has none either).
|
|
32
32
|
*/
|
|
33
|
-
export
|
|
33
|
+
export interface EstimatedSize {
|
|
34
|
+
/** Approximate serialized JSON byte size. */
|
|
35
|
+
size: number;
|
|
36
|
+
/**
|
|
37
|
+
* Length (in UTF-8 bytes) of the longest single string value encountered
|
|
38
|
+
* anywhere in the payload graph. Callers can use this as a shape-aware
|
|
39
|
+
* dispatch signal -- for example, to decide whether to offload serialize
|
|
40
|
+
* to a worker thread (which only pays off when a payload contains one
|
|
41
|
+
* or more large strings, since V8 shares string storage across isolates
|
|
42
|
+
* via refcount).
|
|
43
|
+
*/
|
|
44
|
+
maxStringLen: number;
|
|
45
|
+
}
|
|
46
|
+
export declare function estimateSerializedSize(value: unknown): EstimatedSize;
|
|
34
47
|
export declare function serialize(obj: any, errorContext?: any, replacer?: any, spacer?: any, options?: any): Uint8Array<ArrayBuffer>;
|
|
@@ -57,44 +57,13 @@ function createDefaultReplacer(userReplacer) {
|
|
|
57
57
|
return serializeWellKnownTypes(val);
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Estimate the serialized JSON byte size of a value without actually
|
|
62
|
-
* serializing it. Used on hot paths (enqueuing runs for batched tracing)
|
|
63
|
-
* where the exact serialized size is not required -- only a reasonable
|
|
64
|
-
* approximation for soft memory accounting.
|
|
65
|
-
*
|
|
66
|
-
* Walks the object graph in O(n) without allocating a JSON string,
|
|
67
|
-
* avoiding the event-loop blocking that JSON.stringify causes on large
|
|
68
|
-
* payloads.
|
|
69
|
-
*
|
|
70
|
-
* Accuracy notes (all estimates are approximate, never exact):
|
|
71
|
-
* - Strings: UTF-8 byte length via Buffer.byteLength when available,
|
|
72
|
-
* falling back to code-unit length for non-Node environments. Does
|
|
73
|
-
* not account for escape expansion (\", \\, control chars, surrogate
|
|
74
|
-
* escapes) which is usually a small fraction of total size.
|
|
75
|
-
* - Binary data (Buffer / typed arrays / ArrayBuffer / DataView): sized
|
|
76
|
-
* from their JSON.stringify representations where practical
|
|
77
|
-
* ({ type: "Buffer", data: [...] } for Buffer, keyed objects for typed
|
|
78
|
-
* arrays). DataView and ArrayBuffer themselves have no enumerable own
|
|
79
|
-
* properties and serialize as "{}". Each byte contributes ~3.5
|
|
80
|
-
* characters on average in Buffer's decimal-array representation
|
|
81
|
-
* (digit(s) + comma).
|
|
82
|
-
* - Other objects with toJSON(): we invoke toJSON() once and estimate
|
|
83
|
-
* the result. This matches JSON.stringify semantics for libraries
|
|
84
|
-
* like Decimal.js, Moment, Luxon, Mongoose documents, etc.
|
|
85
|
-
* - Cycles: detected via an ancestor-path set that is pushed/popped
|
|
86
|
-
* during recursion. This matches JSON.stringify semantics --
|
|
87
|
-
* repeated references that are *not* on the current ancestor chain
|
|
88
|
-
* (shared subobjects) are counted every time they appear, because
|
|
89
|
-
* JSON.stringify will serialize them every time.
|
|
90
|
-
* - No depth limit (JSON.stringify has none either).
|
|
91
|
-
*/
|
|
92
60
|
export function estimateSerializedSize(value) {
|
|
93
61
|
try {
|
|
94
62
|
// Ancestor set for cycle detection. An object is only treated as
|
|
95
63
|
// circular if it appears on the current recursion path, not merely
|
|
96
64
|
// if it has been seen before elsewhere in the graph.
|
|
97
65
|
const ancestors = new Set();
|
|
66
|
+
let maxStringLen = 0;
|
|
98
67
|
// In Node / Bun, Buffer.byteLength is a fast native way to get UTF-8
|
|
99
68
|
// byte length without allocating an encoded copy. In other runtimes
|
|
100
69
|
// we fall back to code-unit length (a small under-estimate for
|
|
@@ -104,7 +73,10 @@ export function estimateSerializedSize(value) {
|
|
|
104
73
|
: (s) => s.length;
|
|
105
74
|
function estimateString(s) {
|
|
106
75
|
// +2 for the surrounding quotes. Escape expansion is not counted.
|
|
107
|
-
|
|
76
|
+
const n = byteLen(s);
|
|
77
|
+
if (n > maxStringLen)
|
|
78
|
+
maxStringLen = n;
|
|
79
|
+
return n + 2;
|
|
108
80
|
}
|
|
109
81
|
// Size of a byte sequence when rendered as a JSON array of decimal
|
|
110
82
|
// numbers: "[b0,b1,b2,...]". Each byte averages ~3.5 chars (value 0-9
|
|
@@ -275,13 +247,16 @@ export function estimateSerializedSize(value) {
|
|
|
275
247
|
ancestors.delete(obj);
|
|
276
248
|
return size;
|
|
277
249
|
}
|
|
278
|
-
|
|
250
|
+
const size = estimate(value);
|
|
251
|
+
return { size, maxStringLen };
|
|
279
252
|
}
|
|
280
253
|
catch {
|
|
281
254
|
// If the estimator itself hits an unexpected edge case, fall back to the
|
|
282
255
|
// exact serialized size. This preserves correctness of queue-size
|
|
283
256
|
// accounting at the cost of a slower hot path for that one payload.
|
|
284
|
-
|
|
257
|
+
// We cannot cheaply recover maxStringLen here, so report 0: the worker
|
|
258
|
+
// gate will then fall back to sync serialization, which is safe.
|
|
259
|
+
return { size: serialize(value).length, maxStringLen: 0 };
|
|
285
260
|
}
|
|
286
261
|
}
|
|
287
262
|
// Regular stringify
|
|
@@ -48,7 +48,7 @@ exports._objectHash = _objectHash;
|
|
|
48
48
|
exports.generateWrapperFromJestlikeMethods = generateWrapperFromJestlikeMethods;
|
|
49
49
|
exports.isInTestContext = isInTestContext;
|
|
50
50
|
const crypto_1 = __importDefault(require("crypto"));
|
|
51
|
-
const
|
|
51
|
+
const index_js_1 = require("../uuid/src/index.cjs");
|
|
52
52
|
const os = __importStar(require("node:os"));
|
|
53
53
|
const path = __importStar(require("node:path"));
|
|
54
54
|
const fs = __importStar(require("node:fs/promises"));
|
|
@@ -137,7 +137,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
|
|
|
137
137
|
catch (e) {
|
|
138
138
|
// Naming collision
|
|
139
139
|
if (e?.name === "LangSmithConflictError") {
|
|
140
|
-
const ent = (0,
|
|
140
|
+
const ent = (0, index_js_1.v4)().slice(0, 6);
|
|
141
141
|
experimentName = `${experimentName}-${ent}`;
|
|
142
142
|
}
|
|
143
143
|
else {
|
|
@@ -158,7 +158,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
|
|
|
158
158
|
inputsHash: _objectHash(inputs),
|
|
159
159
|
outputsHash: _objectHash(outputs ?? {}),
|
|
160
160
|
});
|
|
161
|
-
return (0,
|
|
161
|
+
return (0, index_js_1.v5)(identifier, constants_js_1.UUID5_NAMESPACE);
|
|
162
162
|
}
|
|
163
163
|
async function syncExample(params) {
|
|
164
164
|
const { client, exampleId, inputs, outputs, metadata, split, createdAt, datasetId, } = params;
|
|
@@ -268,7 +268,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
|
|
|
268
268
|
});
|
|
269
269
|
return method(suiteName, () => {
|
|
270
270
|
const startTime = new Date();
|
|
271
|
-
const suiteUuid = (0,
|
|
271
|
+
const suiteUuid = (0, index_js_1.v4)();
|
|
272
272
|
const environment = experimentConfig?.metadata?.ENVIRONMENT ??
|
|
273
273
|
(0, env_js_1.getEnvironmentVariable)("ENVIRONMENT");
|
|
274
274
|
const nodeEnv = experimentConfig?.metadata?.NODE_ENV ??
|
|
@@ -418,7 +418,7 @@ function generateWrapperFromJestlikeMethods(methods, testRunnerName) {
|
|
|
418
418
|
}
|
|
419
419
|
const totalRuns = config?.repetitions ?? 1;
|
|
420
420
|
for (let i = 0; i < totalRuns; i += 1) {
|
|
421
|
-
const testUuid = (0,
|
|
421
|
+
const testUuid = (0, index_js_1.v4)().replace(/-/g, "").slice(0, 13);
|
|
422
422
|
// Jest will not group tests under the same "describe" group if you await the test and
|
|
423
423
|
// total runs is greater than 1.
|
|
424
424
|
const resultsPath = path.join(os.tmpdir(), "langsmith_test_results", `${testUuid}.json`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable import/no-extraneous-dependencies */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-namespace */
|
|
3
3
|
import crypto from "crypto";
|
|
4
|
-
import { v4, v5 } from "uuid";
|
|
4
|
+
import { v4, v5 } from "../uuid/src/index.js";
|
|
5
5
|
import * as os from "node:os";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import * as fs from "node:fs/promises";
|
|
@@ -4,7 +4,7 @@ exports.wrapEvaluator = wrapEvaluator;
|
|
|
4
4
|
exports.evaluatedBy = evaluatedBy;
|
|
5
5
|
const traceable_js_1 = require("../../../traceable.cjs");
|
|
6
6
|
const globals_js_1 = require("../globals.cjs");
|
|
7
|
-
const
|
|
7
|
+
const index_js_1 = require("../../uuid/src/index.cjs");
|
|
8
8
|
function isEvaluationResult(x) {
|
|
9
9
|
return (x != null &&
|
|
10
10
|
typeof x === "object" &&
|
|
@@ -22,7 +22,7 @@ function wrapEvaluator(evaluator) {
|
|
|
22
22
|
`See this page for more information: https://docs.smith.langchain.com/evaluation/how_to_guides/vitest_jest`,
|
|
23
23
|
].join("\n"));
|
|
24
24
|
}
|
|
25
|
-
let evalRunId = config?.runId ?? config?.id ?? (0,
|
|
25
|
+
let evalRunId = config?.runId ?? config?.id ?? (0, index_js_1.v7)();
|
|
26
26
|
let evalResult;
|
|
27
27
|
if ((0, globals_js_1.trackingEnabled)(context)) {
|
|
28
28
|
const wrappedEvaluator = (0, traceable_js_1.traceable)(async (_runTree, params) => {
|
|
@@ -83,7 +83,7 @@ async function evaluatedBy(outputs, evaluator) {
|
|
|
83
83
|
].join("\n"));
|
|
84
84
|
}
|
|
85
85
|
const wrappedEvaluator = wrapEvaluator(evaluator);
|
|
86
|
-
const evalRunId = (0,
|
|
86
|
+
const evalRunId = (0, index_js_1.v7)();
|
|
87
87
|
const evalResult = await wrappedEvaluator({
|
|
88
88
|
inputs: context.currentExample?.inputs ?? {},
|
|
89
89
|
referenceOutputs: context?.currentExample?.outputs ?? {},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ROOT, traceable } from "../../../traceable.js";
|
|
2
2
|
import { testWrapperAsyncLocalStorageInstance, _logTestFeedback, trackingEnabled, } from "../globals.js";
|
|
3
|
-
import { v7 } from "uuid";
|
|
3
|
+
import { v7 } from "../../uuid/src/index.js";
|
|
4
4
|
function isEvaluationResult(x) {
|
|
5
5
|
return (x != null &&
|
|
6
6
|
typeof x === "object" &&
|