langsmith 0.7.4 → 0.7.6

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.
Files changed (38) hide show
  1. package/README.md +41 -0
  2. package/dist/client.cjs +42 -8
  3. package/dist/client.d.ts +11 -3
  4. package/dist/client.js +42 -8
  5. package/dist/evaluation/_runner.cjs +77 -0
  6. package/dist/evaluation/_runner.d.ts +4 -0
  7. package/dist/evaluation/_runner.js +77 -0
  8. package/dist/evaluation/evaluate_comparative.cjs +1 -1
  9. package/dist/evaluation/evaluate_comparative.d.ts +7 -1
  10. package/dist/evaluation/evaluate_comparative.js +1 -1
  11. package/dist/index.cjs +4 -2
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.js +3 -1
  14. package/dist/sandbox/index.cjs +5 -1
  15. package/dist/sandbox/index.d.ts +2 -1
  16. package/dist/sandbox/index.js +1 -0
  17. package/dist/sandbox/proxy_config.cjs +47 -0
  18. package/dist/sandbox/proxy_config.d.ts +12 -0
  19. package/dist/sandbox/proxy_config.js +42 -0
  20. package/dist/sandbox/types.d.ts +23 -1
  21. package/dist/utils/fs.browser.cjs +11 -0
  22. package/dist/utils/fs.browser.d.ts +3 -0
  23. package/dist/utils/fs.browser.js +8 -0
  24. package/dist/utils/fs.cjs +22 -0
  25. package/dist/utils/fs.d.ts +3 -0
  26. package/dist/utils/fs.js +19 -0
  27. package/dist/utils/profile-lock.cjs +140 -0
  28. package/dist/utils/profile-lock.d.ts +20 -0
  29. package/dist/utils/profile-lock.js +103 -0
  30. package/dist/utils/profiles.cjs +28 -2
  31. package/dist/utils/profiles.d.ts +1 -0
  32. package/dist/utils/profiles.js +28 -2
  33. package/dist/wrappers/gemini.cjs +3 -40
  34. package/dist/wrappers/gemini.js +3 -40
  35. package/dist/wrappers/gemini.utils.cjs +41 -0
  36. package/dist/wrappers/gemini.utils.d.ts +3 -0
  37. package/dist/wrappers/gemini.utils.js +37 -0
  38. package/package.json +2 -2
package/README.md CHANGED
@@ -25,6 +25,47 @@ A typical workflow looks like:
25
25
 
26
26
  We'll walk through these steps in more detail below.
27
27
 
28
+ ## Sandbox AWS auth proxy
29
+
30
+ When you create a LangSmith sandbox that needs to call AWS services, use the
31
+ sandbox AWS auth proxy helpers. The proxy keeps the real AWS credentials outside
32
+ the sandbox and signs supported AWS HTTPS requests with SigV4, so code in the
33
+ sandbox can use AWS SDKs normally without storing long-lived AWS keys in files,
34
+ environment variables, shell history, or logs.
35
+
36
+ First, store `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` as LangSmith
37
+ workspace secrets. Then create the sandbox with an AWS auth proxy config:
38
+
39
+ ```ts
40
+ import {
41
+ SandboxClient,
42
+ awsAuthProxyConfig,
43
+ workspaceSecret,
44
+ } from "langsmith/sandbox";
45
+
46
+ const client = new SandboxClient();
47
+
48
+ const sandbox = await client.createSandbox({
49
+ name: "aws-sandbox",
50
+ proxyConfig: awsAuthProxyConfig({
51
+ accessKeyId: workspaceSecret("AWS_ACCESS_KEY_ID"),
52
+ secretAccessKey: workspaceSecret("AWS_SECRET_ACCESS_KEY"),
53
+ }),
54
+ });
55
+
56
+ try {
57
+ // Your sandbox code can use the AWS SDK, the AWS CLI, or other AWS tooling normally.
58
+ const result = await sandbox.run("node your-aws-script.js");
59
+ console.log(result.stdout);
60
+ } finally {
61
+ await sandbox.delete();
62
+ }
63
+ ```
64
+
65
+ Use `opaqueSecret("...")` instead of `workspaceSecret(...)` when your application
66
+ needs to pass short-lived write-only AWS credentials at sandbox creation time.
67
+ Plaintext AWS credential values are not supported.
68
+
28
69
  ## 1. Connect to LangSmith
29
70
 
30
71
  Sign up for [LangSmith](https://smith.langchain.com/) using your GitHub, Discord accounts, or an email address and password. If you sign up with an email, make sure to verify your email address before logging in.
package/dist/client.cjs CHANGED
@@ -2557,7 +2557,7 @@ class Client {
2557
2557
  _hostUrl: this.getHostUrl(),
2558
2558
  }));
2559
2559
  }
2560
- async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, }) {
2560
+ async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, }) {
2561
2561
  const upsert_ = upsert ? `?upsert=true` : "";
2562
2562
  const endpoint = `${this.apiUrl}/sessions${upsert_}`;
2563
2563
  const extra = projectExtra || {};
@@ -2572,6 +2572,15 @@ class Client {
2572
2572
  if (referenceDatasetId !== null) {
2573
2573
  body["reference_dataset_id"] = referenceDatasetId;
2574
2574
  }
2575
+ if (numExamples != null) {
2576
+ body["num_examples"] = numExamples;
2577
+ }
2578
+ if (numRepetitions != null) {
2579
+ body["num_repetitions"] = numRepetitions;
2580
+ }
2581
+ if (evaluatorKeys != null && evaluatorKeys.length > 0) {
2582
+ body["evaluator_keys"] = evaluatorKeys;
2583
+ }
2575
2584
  const serializedBody = JSON.stringify(body);
2576
2585
  const response = await this.caller.call(async () => {
2577
2586
  const res = await this._fetch(endpoint, {
@@ -4103,6 +4112,23 @@ class Client {
4103
4112
  }
4104
4113
  return json.commits[0].commit_hash;
4105
4114
  }
4115
+ async _createCommitTags(promptOwnerAndName, commitId, tags) {
4116
+ const tagList = typeof tags === "string" ? [tags] : tags;
4117
+ await Promise.all(tagList.map(async (tag) => this.caller.call(async () => {
4118
+ const res = await this._fetch(`${this.apiUrl}/repos/${promptOwnerAndName}/tags`, {
4119
+ method: "POST",
4120
+ headers: {
4121
+ ...this._mergedHeaders,
4122
+ "Content-Type": "application/json",
4123
+ },
4124
+ signal: AbortSignal.timeout(this.timeout_ms),
4125
+ ...this.fetchOptions,
4126
+ body: JSON.stringify({ tag_name: tag, commit_id: commitId }),
4127
+ });
4128
+ await (0, error_js_1.raiseForStatus)(res, "create commit tag");
4129
+ return res;
4130
+ })));
4131
+ }
4106
4132
  async _likeOrUnlikePrompt(promptIdentifier, like) {
4107
4133
  const [owner, promptName, _] = (0, prompts_js_1.parseHubIdentifier)(promptIdentifier);
4108
4134
  const body = JSON.stringify({ like: like });
@@ -4369,6 +4395,8 @@ class Client {
4369
4395
  * @param object - The prompt object/manifest to commit (e.g., ChatPromptTemplate, messages array, etc.)
4370
4396
  * @param options - Optional configuration for the commit
4371
4397
  * @param options.parentCommitHash - The parent commit hash. Defaults to "latest" (the most recent commit).
4398
+ * @param options.tags - A tag or list of tags to apply to the commit.
4399
+ * @param options.description - A description for the commit.
4372
4400
  * @returns A Promise that resolves to the URL of the newly created commit
4373
4401
  * @throws {Error} If the prompt does not exist
4374
4402
  * @example
@@ -4384,9 +4412,9 @@ class Client {
4384
4412
  * const commitUrl = await client.createCommit("my-prompt", template);
4385
4413
  * console.log(`Commit created: ${commitUrl}`);
4386
4414
  *
4387
- * // Create a commit based on a specific parent commit
4415
+ * // Create a commit with tags
4388
4416
  * const commitUrl2 = await client.createCommit("my-prompt", template, {
4389
- * parentCommitHash: "abc123def456"
4417
+ * tags: ["production", "v1"]
4390
4418
  * });
4391
4419
  * ```
4392
4420
  */
@@ -4421,7 +4449,11 @@ class Client {
4421
4449
  return res;
4422
4450
  });
4423
4451
  const result = await response.json();
4424
- return this._getPromptUrl(`${owner}/${promptName}${result.commit_hash ? `:${result.commit_hash}` : ""}`);
4452
+ const commit = result.commit ?? result;
4453
+ if (options?.tags) {
4454
+ await this._createCommitTags(`${owner}/${promptName}`, commit.id, options.tags);
4455
+ }
4456
+ return this._getPromptUrl(`${owner}/${promptName}${commit.commit_hash ? `:${commit.commit_hash}` : ""}`);
4425
4457
  }
4426
4458
  /**
4427
4459
  * Update examples with attachments using multipart form data.
@@ -4756,7 +4788,8 @@ class Client {
4756
4788
  async pushPrompt(promptIdentifier, options) {
4757
4789
  // Create or update prompt metadata
4758
4790
  if (await this.promptExists(promptIdentifier)) {
4759
- if (options && Object.keys(options).some((key) => key !== "object")) {
4791
+ if (options &&
4792
+ ["description", "readme", "tags", "isPublic"].some((key) => options[key] !== undefined)) {
4760
4793
  await this.updatePrompt(promptIdentifier, {
4761
4794
  description: options?.description,
4762
4795
  readme: options?.readme,
@@ -4779,6 +4812,7 @@ class Client {
4779
4812
  // Create a commit with the new manifest
4780
4813
  const url = await this.createCommit(promptIdentifier, options?.object, {
4781
4814
  parentCommitHash: options?.parentCommitHash,
4815
+ tags: options?.commitTags,
4782
4816
  description: options?.commitDescription,
4783
4817
  });
4784
4818
  return url;
@@ -4866,7 +4900,7 @@ class Client {
4866
4900
  async _pullDirectory(identifier, repoType, version) {
4867
4901
  const [owner, name, parsedVersion] = (0, prompts_js_1.parseHubIdentifier)(identifier);
4868
4902
  const resolvedVersion = version ?? (parsedVersion !== "latest" ? parsedVersion : undefined);
4869
- const url = new URL(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`);
4903
+ const url = new URL(`${this.apiUrl}${this._getPlatformEndpointPath(`hub/repos/${owner}/${name}/directories`)}`);
4870
4904
  url.searchParams.set("repo_type", repoType);
4871
4905
  if (resolvedVersion) {
4872
4906
  url.searchParams.set("commit", resolvedVersion);
@@ -4912,7 +4946,7 @@ class Client {
4912
4946
  body.parent_commit = options.parentCommit;
4913
4947
  }
4914
4948
  const response = await this.caller.call(async () => {
4915
- const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories/commits`, {
4949
+ const res = await this._fetch(`${this.apiUrl}${this._getPlatformEndpointPath(`hub/repos/${owner}/${name}/directories/commits`)}`, {
4916
4950
  method: "POST",
4917
4951
  headers: {
4918
4952
  ...this._mergedHeaders,
@@ -4937,7 +4971,7 @@ class Client {
4937
4971
  throw await this._ownerConflictError("delete", owner);
4938
4972
  }
4939
4973
  await this.caller.call(async () => {
4940
- const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`, {
4974
+ const res = await this._fetch(`${this.apiUrl}${this._getPlatformEndpointPath(`hub/repos/${owner}/${name}/directories`)}`, {
4941
4975
  method: "DELETE",
4942
4976
  headers: this._mergedHeaders,
4943
4977
  signal: AbortSignal.timeout(this.timeout_ms),
package/dist/client.d.ts CHANGED
@@ -349,6 +349,9 @@ export type CreateProjectParams = {
349
349
  upsert?: boolean;
350
350
  projectExtra?: RecordStringAny | null;
351
351
  referenceDatasetId?: string | null;
352
+ numExamples?: number | null;
353
+ numRepetitions?: number | null;
354
+ evaluatorKeys?: string[] | null;
352
355
  };
353
356
  type AutoBatchQueueItem = {
354
357
  action: "create" | "update";
@@ -714,7 +717,7 @@ export declare class Client implements LangSmithTracingClientInterface {
714
717
  listSharedExamples(shareToken: string, options?: {
715
718
  exampleIds?: string[];
716
719
  }): Promise<Example[]>;
717
- createProject({ projectName, description, metadata, upsert, projectExtra, referenceDatasetId, }: CreateProjectParams): Promise<TracerSession>;
720
+ createProject({ projectName, description, metadata, upsert, projectExtra, referenceDatasetId, numExamples, numRepetitions, evaluatorKeys, }: CreateProjectParams): Promise<TracerSession>;
718
721
  updateProject(projectId: string, { name, description, metadata, projectExtra, endTime, }: {
719
722
  name?: string | null;
720
723
  description?: string | null;
@@ -1129,6 +1132,7 @@ export declare class Client implements LangSmithTracingClientInterface {
1129
1132
  protected _currentTenantIsOwner(owner: string): Promise<boolean>;
1130
1133
  protected _ownerConflictError(action: string, owner: string): Promise<Error>;
1131
1134
  protected _getLatestCommitHash(promptOwnerAndName: string): Promise<string | undefined>;
1135
+ protected _createCommitTags(promptOwnerAndName: string, commitId: string, tags: string | string[]): Promise<void>;
1132
1136
  protected _likeOrUnlikePrompt(promptIdentifier: string, like: boolean): Promise<LikePromptResponse>;
1133
1137
  protected _getPromptUrl(promptIdentifier: string): Promise<string>;
1134
1138
  /**
@@ -1287,6 +1291,8 @@ export declare class Client implements LangSmithTracingClientInterface {
1287
1291
  * @param object - The prompt object/manifest to commit (e.g., ChatPromptTemplate, messages array, etc.)
1288
1292
  * @param options - Optional configuration for the commit
1289
1293
  * @param options.parentCommitHash - The parent commit hash. Defaults to "latest" (the most recent commit).
1294
+ * @param options.tags - A tag or list of tags to apply to the commit.
1295
+ * @param options.description - A description for the commit.
1290
1296
  * @returns A Promise that resolves to the URL of the newly created commit
1291
1297
  * @throws {Error} If the prompt does not exist
1292
1298
  * @example
@@ -1302,14 +1308,15 @@ export declare class Client implements LangSmithTracingClientInterface {
1302
1308
  * const commitUrl = await client.createCommit("my-prompt", template);
1303
1309
  * console.log(`Commit created: ${commitUrl}`);
1304
1310
  *
1305
- * // Create a commit based on a specific parent commit
1311
+ * // Create a commit with tags
1306
1312
  * const commitUrl2 = await client.createCommit("my-prompt", template, {
1307
- * parentCommitHash: "abc123def456"
1313
+ * tags: ["production", "v1"]
1308
1314
  * });
1309
1315
  * ```
1310
1316
  */
1311
1317
  createCommit(promptIdentifier: string, object: any, options?: {
1312
1318
  parentCommitHash?: string;
1319
+ tags?: string | string[];
1313
1320
  description?: string;
1314
1321
  }): Promise<string>;
1315
1322
  /**
@@ -1413,6 +1420,7 @@ export declare class Client implements LangSmithTracingClientInterface {
1413
1420
  description?: string;
1414
1421
  readme?: string;
1415
1422
  tags?: string[];
1423
+ commitTags?: string | string[];
1416
1424
  commitDescription?: string;
1417
1425
  }): Promise<string>;
1418
1426
  /**
package/dist/client.js CHANGED
@@ -2519,7 +2519,7 @@ export class Client {
2519
2519
  _hostUrl: this.getHostUrl(),
2520
2520
  }));
2521
2521
  }
2522
- async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, }) {
2522
+ async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, numExamples = null, numRepetitions = null, evaluatorKeys = null, }) {
2523
2523
  const upsert_ = upsert ? `?upsert=true` : "";
2524
2524
  const endpoint = `${this.apiUrl}/sessions${upsert_}`;
2525
2525
  const extra = projectExtra || {};
@@ -2534,6 +2534,15 @@ export class Client {
2534
2534
  if (referenceDatasetId !== null) {
2535
2535
  body["reference_dataset_id"] = referenceDatasetId;
2536
2536
  }
2537
+ if (numExamples != null) {
2538
+ body["num_examples"] = numExamples;
2539
+ }
2540
+ if (numRepetitions != null) {
2541
+ body["num_repetitions"] = numRepetitions;
2542
+ }
2543
+ if (evaluatorKeys != null && evaluatorKeys.length > 0) {
2544
+ body["evaluator_keys"] = evaluatorKeys;
2545
+ }
2537
2546
  const serializedBody = JSON.stringify(body);
2538
2547
  const response = await this.caller.call(async () => {
2539
2548
  const res = await this._fetch(endpoint, {
@@ -4065,6 +4074,23 @@ export class Client {
4065
4074
  }
4066
4075
  return json.commits[0].commit_hash;
4067
4076
  }
4077
+ async _createCommitTags(promptOwnerAndName, commitId, tags) {
4078
+ const tagList = typeof tags === "string" ? [tags] : tags;
4079
+ await Promise.all(tagList.map(async (tag) => this.caller.call(async () => {
4080
+ const res = await this._fetch(`${this.apiUrl}/repos/${promptOwnerAndName}/tags`, {
4081
+ method: "POST",
4082
+ headers: {
4083
+ ...this._mergedHeaders,
4084
+ "Content-Type": "application/json",
4085
+ },
4086
+ signal: AbortSignal.timeout(this.timeout_ms),
4087
+ ...this.fetchOptions,
4088
+ body: JSON.stringify({ tag_name: tag, commit_id: commitId }),
4089
+ });
4090
+ await raiseForStatus(res, "create commit tag");
4091
+ return res;
4092
+ })));
4093
+ }
4068
4094
  async _likeOrUnlikePrompt(promptIdentifier, like) {
4069
4095
  const [owner, promptName, _] = parseHubIdentifier(promptIdentifier);
4070
4096
  const body = JSON.stringify({ like: like });
@@ -4331,6 +4357,8 @@ export class Client {
4331
4357
  * @param object - The prompt object/manifest to commit (e.g., ChatPromptTemplate, messages array, etc.)
4332
4358
  * @param options - Optional configuration for the commit
4333
4359
  * @param options.parentCommitHash - The parent commit hash. Defaults to "latest" (the most recent commit).
4360
+ * @param options.tags - A tag or list of tags to apply to the commit.
4361
+ * @param options.description - A description for the commit.
4334
4362
  * @returns A Promise that resolves to the URL of the newly created commit
4335
4363
  * @throws {Error} If the prompt does not exist
4336
4364
  * @example
@@ -4346,9 +4374,9 @@ export class Client {
4346
4374
  * const commitUrl = await client.createCommit("my-prompt", template);
4347
4375
  * console.log(`Commit created: ${commitUrl}`);
4348
4376
  *
4349
- * // Create a commit based on a specific parent commit
4377
+ * // Create a commit with tags
4350
4378
  * const commitUrl2 = await client.createCommit("my-prompt", template, {
4351
- * parentCommitHash: "abc123def456"
4379
+ * tags: ["production", "v1"]
4352
4380
  * });
4353
4381
  * ```
4354
4382
  */
@@ -4383,7 +4411,11 @@ export class Client {
4383
4411
  return res;
4384
4412
  });
4385
4413
  const result = await response.json();
4386
- return this._getPromptUrl(`${owner}/${promptName}${result.commit_hash ? `:${result.commit_hash}` : ""}`);
4414
+ const commit = result.commit ?? result;
4415
+ if (options?.tags) {
4416
+ await this._createCommitTags(`${owner}/${promptName}`, commit.id, options.tags);
4417
+ }
4418
+ return this._getPromptUrl(`${owner}/${promptName}${commit.commit_hash ? `:${commit.commit_hash}` : ""}`);
4387
4419
  }
4388
4420
  /**
4389
4421
  * Update examples with attachments using multipart form data.
@@ -4718,7 +4750,8 @@ export class Client {
4718
4750
  async pushPrompt(promptIdentifier, options) {
4719
4751
  // Create or update prompt metadata
4720
4752
  if (await this.promptExists(promptIdentifier)) {
4721
- if (options && Object.keys(options).some((key) => key !== "object")) {
4753
+ if (options &&
4754
+ ["description", "readme", "tags", "isPublic"].some((key) => options[key] !== undefined)) {
4722
4755
  await this.updatePrompt(promptIdentifier, {
4723
4756
  description: options?.description,
4724
4757
  readme: options?.readme,
@@ -4741,6 +4774,7 @@ export class Client {
4741
4774
  // Create a commit with the new manifest
4742
4775
  const url = await this.createCommit(promptIdentifier, options?.object, {
4743
4776
  parentCommitHash: options?.parentCommitHash,
4777
+ tags: options?.commitTags,
4744
4778
  description: options?.commitDescription,
4745
4779
  });
4746
4780
  return url;
@@ -4828,7 +4862,7 @@ export class Client {
4828
4862
  async _pullDirectory(identifier, repoType, version) {
4829
4863
  const [owner, name, parsedVersion] = parseHubIdentifier(identifier);
4830
4864
  const resolvedVersion = version ?? (parsedVersion !== "latest" ? parsedVersion : undefined);
4831
- const url = new URL(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`);
4865
+ const url = new URL(`${this.apiUrl}${this._getPlatformEndpointPath(`hub/repos/${owner}/${name}/directories`)}`);
4832
4866
  url.searchParams.set("repo_type", repoType);
4833
4867
  if (resolvedVersion) {
4834
4868
  url.searchParams.set("commit", resolvedVersion);
@@ -4874,7 +4908,7 @@ export class Client {
4874
4908
  body.parent_commit = options.parentCommit;
4875
4909
  }
4876
4910
  const response = await this.caller.call(async () => {
4877
- const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories/commits`, {
4911
+ const res = await this._fetch(`${this.apiUrl}${this._getPlatformEndpointPath(`hub/repos/${owner}/${name}/directories/commits`)}`, {
4878
4912
  method: "POST",
4879
4913
  headers: {
4880
4914
  ...this._mergedHeaders,
@@ -4899,7 +4933,7 @@ export class Client {
4899
4933
  throw await this._ownerConflictError("delete", owner);
4900
4934
  }
4901
4935
  await this.caller.call(async () => {
4902
- const res = await this._fetch(`${this.apiUrl}/v1/platform/hub/repos/${owner}/${name}/directories`, {
4936
+ const res = await this._fetch(`${this.apiUrl}${this._getPlatformEndpointPath(`hub/repos/${owner}/${name}/directories`)}`, {
4903
4937
  method: "DELETE",
4904
4938
  headers: this._mergedHeaders,
4905
4939
  signal: AbortSignal.timeout(this.timeout_ms),
@@ -149,12 +149,24 @@ class _ExperimentManager {
149
149
  writable: true,
150
150
  value: void 0
151
151
  });
152
+ Object.defineProperty(this, "_numExamples", {
153
+ enumerable: true,
154
+ configurable: true,
155
+ writable: true,
156
+ value: void 0
157
+ });
152
158
  Object.defineProperty(this, "_numRepetitions", {
153
159
  enumerable: true,
154
160
  configurable: true,
155
161
  writable: true,
156
162
  value: void 0
157
163
  });
164
+ Object.defineProperty(this, "_evaluatorKeys", {
165
+ enumerable: true,
166
+ configurable: true,
167
+ writable: true,
168
+ value: void 0
169
+ });
158
170
  Object.defineProperty(this, "_runsArray", {
159
171
  enumerable: true,
160
172
  configurable: true,
@@ -231,6 +243,8 @@ class _ExperimentManager {
231
243
  this._summaryResults = args.summaryResults;
232
244
  this._resultRows = args.resultRows;
233
245
  this._numRepetitions = args.numRepetitions;
246
+ this._numExamples = args.numExamples;
247
+ this._evaluatorKeys = args.evaluatorKeys;
234
248
  this._includeAttachments = args.includeAttachments;
235
249
  }
236
250
  _getExperiment() {
@@ -263,6 +277,12 @@ class _ExperimentManager {
263
277
  // Create the project, updating the experimentName until we find a unique one.
264
278
  let project;
265
279
  const originalExperimentName = this._experimentName;
280
+ if (this._numExamples === undefined) {
281
+ this._numExamples = await _resolveNumExamples(this._data, this.client);
282
+ }
283
+ const numExamples = this._numExamples ?? null;
284
+ const numRepetitions = this._numRepetitions ?? null;
285
+ const evaluatorKeys = this._evaluatorKeys ?? null;
266
286
  for (let i = 0; i < 10; i++) {
267
287
  try {
268
288
  project = await this.client.createProject({
@@ -270,6 +290,9 @@ class _ExperimentManager {
270
290
  referenceDatasetId: firstExample.dataset_id,
271
291
  metadata: projectMetadata,
272
292
  description: this._description,
293
+ numExamples,
294
+ numRepetitions,
295
+ evaluatorKeys,
273
296
  });
274
297
  return project;
275
298
  }
@@ -319,6 +342,9 @@ class _ExperimentManager {
319
342
  client: this.client,
320
343
  evaluationResults: this._evaluationResults,
321
344
  summaryResults: this._summaryResults,
345
+ numRepetitions: this._numRepetitions,
346
+ numExamples: this._numExamples,
347
+ evaluatorKeys: this._evaluatorKeys,
322
348
  includeAttachments: this._includeAttachments,
323
349
  });
324
350
  }
@@ -345,6 +371,9 @@ class _ExperimentManager {
345
371
  yield pred.run;
346
372
  }
347
373
  })(),
374
+ numRepetitions: this._numRepetitions,
375
+ numExamples: this._numExamples,
376
+ evaluatorKeys: this._evaluatorKeys,
348
377
  includeAttachments: this._includeAttachments,
349
378
  });
350
379
  }
@@ -369,6 +398,9 @@ class _ExperimentManager {
369
398
  }
370
399
  })(),
371
400
  summaryResults: this._summaryResults,
401
+ numRepetitions: this._numRepetitions,
402
+ numExamples: this._numExamples,
403
+ evaluatorKeys: this._evaluatorKeys,
372
404
  includeAttachments: this._includeAttachments,
373
405
  });
374
406
  }
@@ -384,6 +416,9 @@ class _ExperimentManager {
384
416
  evaluationResults: this._evaluationResults,
385
417
  resultRows: this._resultRows,
386
418
  summaryResults: aggregateFeedbackGen,
419
+ numRepetitions: this._numRepetitions,
420
+ numExamples: this._numExamples,
421
+ evaluatorKeys: this._evaluatorKeys,
387
422
  includeAttachments: this._includeAttachments,
388
423
  });
389
424
  }
@@ -732,6 +767,7 @@ async function _evaluate(target, fields) {
732
767
  experiment: experiment_ ?? fields.experimentPrefix,
733
768
  runs: newRuns ?? undefined,
734
769
  numRepetitions: fields.numRepetitions ?? 1,
770
+ evaluatorKeys: _collectEvaluatorKeys(standardFields.evaluators),
735
771
  includeAttachments: standardFields.includeAttachments,
736
772
  }).start();
737
773
  const targetConcurrency = standardFields.targetConcurrency ?? standardFields.maxConcurrency ?? 0;
@@ -852,6 +888,47 @@ Try setting "LANGSMITH_TRACING=true" in your environment.`);
852
888
  example,
853
889
  };
854
890
  }
891
+ function _collectEvaluatorKeys(evaluators) {
892
+ if (!evaluators)
893
+ return [];
894
+ const keys = [];
895
+ for (const ev of evaluators) {
896
+ const name = ev.name;
897
+ if (name && name.length > 0)
898
+ keys.push(name);
899
+ }
900
+ return keys;
901
+ }
902
+ async function _resolveNumExamples(data, client) {
903
+ // Best-effort dataset size for the experiment progress hint. Returns
904
+ // undefined for lazy async iterators where size cannot be inferred without
905
+ // consuming.
906
+ if (data === undefined)
907
+ return undefined;
908
+ try {
909
+ if (Array.isArray(data)) {
910
+ return data.length;
911
+ }
912
+ if (typeof data === "string") {
913
+ let isUUID = false;
914
+ try {
915
+ (0, _uuid_js_1.assertUuid)(data);
916
+ isUUID = true;
917
+ }
918
+ catch (_) {
919
+ isUUID = false;
920
+ }
921
+ const dataset = isUUID
922
+ ? await client.readDataset({ datasetId: data })
923
+ : await client.readDataset({ datasetName: data });
924
+ return dataset.example_count ?? undefined;
925
+ }
926
+ return undefined;
927
+ }
928
+ catch (_) {
929
+ return undefined;
930
+ }
931
+ }
855
932
  function _resolveData(data, options) {
856
933
  let isUUID = false;
857
934
  try {
@@ -68,6 +68,8 @@ interface _ExperimentManagerArgs {
68
68
  summaryResults?: AsyncGenerator<(runsArray: Run[]) => AsyncGenerator<EvaluationResults, any, unknown>, any, unknown>;
69
69
  examples?: Example[];
70
70
  numRepetitions?: number;
71
+ numExamples?: number;
72
+ evaluatorKeys?: string[];
71
73
  _runsArray?: Run[];
72
74
  resultRows?: AsyncGenerator<_ExperimentResultRowWithIndex>;
73
75
  includeAttachments?: boolean;
@@ -182,7 +184,9 @@ export declare class _ExperimentManager {
182
184
  _summaryResults?: AsyncGenerator<(runsArray: Run[]) => AsyncGenerator<EvaluationResults, any, unknown>, any, unknown>;
183
185
  _resultRows?: AsyncGenerator<_ExperimentResultRowWithIndex>;
184
186
  _examples?: Example[];
187
+ _numExamples?: number;
185
188
  _numRepetitions?: number;
189
+ _evaluatorKeys?: string[];
186
190
  _runsArray?: Run[];
187
191
  client: Client;
188
192
  _experiment?: TracerSession;
@@ -143,12 +143,24 @@ export class _ExperimentManager {
143
143
  writable: true,
144
144
  value: void 0
145
145
  });
146
+ Object.defineProperty(this, "_numExamples", {
147
+ enumerable: true,
148
+ configurable: true,
149
+ writable: true,
150
+ value: void 0
151
+ });
146
152
  Object.defineProperty(this, "_numRepetitions", {
147
153
  enumerable: true,
148
154
  configurable: true,
149
155
  writable: true,
150
156
  value: void 0
151
157
  });
158
+ Object.defineProperty(this, "_evaluatorKeys", {
159
+ enumerable: true,
160
+ configurable: true,
161
+ writable: true,
162
+ value: void 0
163
+ });
152
164
  Object.defineProperty(this, "_runsArray", {
153
165
  enumerable: true,
154
166
  configurable: true,
@@ -225,6 +237,8 @@ export class _ExperimentManager {
225
237
  this._summaryResults = args.summaryResults;
226
238
  this._resultRows = args.resultRows;
227
239
  this._numRepetitions = args.numRepetitions;
240
+ this._numExamples = args.numExamples;
241
+ this._evaluatorKeys = args.evaluatorKeys;
228
242
  this._includeAttachments = args.includeAttachments;
229
243
  }
230
244
  _getExperiment() {
@@ -257,6 +271,12 @@ export class _ExperimentManager {
257
271
  // Create the project, updating the experimentName until we find a unique one.
258
272
  let project;
259
273
  const originalExperimentName = this._experimentName;
274
+ if (this._numExamples === undefined) {
275
+ this._numExamples = await _resolveNumExamples(this._data, this.client);
276
+ }
277
+ const numExamples = this._numExamples ?? null;
278
+ const numRepetitions = this._numRepetitions ?? null;
279
+ const evaluatorKeys = this._evaluatorKeys ?? null;
260
280
  for (let i = 0; i < 10; i++) {
261
281
  try {
262
282
  project = await this.client.createProject({
@@ -264,6 +284,9 @@ export class _ExperimentManager {
264
284
  referenceDatasetId: firstExample.dataset_id,
265
285
  metadata: projectMetadata,
266
286
  description: this._description,
287
+ numExamples,
288
+ numRepetitions,
289
+ evaluatorKeys,
267
290
  });
268
291
  return project;
269
292
  }
@@ -313,6 +336,9 @@ export class _ExperimentManager {
313
336
  client: this.client,
314
337
  evaluationResults: this._evaluationResults,
315
338
  summaryResults: this._summaryResults,
339
+ numRepetitions: this._numRepetitions,
340
+ numExamples: this._numExamples,
341
+ evaluatorKeys: this._evaluatorKeys,
316
342
  includeAttachments: this._includeAttachments,
317
343
  });
318
344
  }
@@ -339,6 +365,9 @@ export class _ExperimentManager {
339
365
  yield pred.run;
340
366
  }
341
367
  })(),
368
+ numRepetitions: this._numRepetitions,
369
+ numExamples: this._numExamples,
370
+ evaluatorKeys: this._evaluatorKeys,
342
371
  includeAttachments: this._includeAttachments,
343
372
  });
344
373
  }
@@ -363,6 +392,9 @@ export class _ExperimentManager {
363
392
  }
364
393
  })(),
365
394
  summaryResults: this._summaryResults,
395
+ numRepetitions: this._numRepetitions,
396
+ numExamples: this._numExamples,
397
+ evaluatorKeys: this._evaluatorKeys,
366
398
  includeAttachments: this._includeAttachments,
367
399
  });
368
400
  }
@@ -378,6 +410,9 @@ export class _ExperimentManager {
378
410
  evaluationResults: this._evaluationResults,
379
411
  resultRows: this._resultRows,
380
412
  summaryResults: aggregateFeedbackGen,
413
+ numRepetitions: this._numRepetitions,
414
+ numExamples: this._numExamples,
415
+ evaluatorKeys: this._evaluatorKeys,
381
416
  includeAttachments: this._includeAttachments,
382
417
  });
383
418
  }
@@ -725,6 +760,7 @@ async function _evaluate(target, fields) {
725
760
  experiment: experiment_ ?? fields.experimentPrefix,
726
761
  runs: newRuns ?? undefined,
727
762
  numRepetitions: fields.numRepetitions ?? 1,
763
+ evaluatorKeys: _collectEvaluatorKeys(standardFields.evaluators),
728
764
  includeAttachments: standardFields.includeAttachments,
729
765
  }).start();
730
766
  const targetConcurrency = standardFields.targetConcurrency ?? standardFields.maxConcurrency ?? 0;
@@ -845,6 +881,47 @@ Try setting "LANGSMITH_TRACING=true" in your environment.`);
845
881
  example,
846
882
  };
847
883
  }
884
+ function _collectEvaluatorKeys(evaluators) {
885
+ if (!evaluators)
886
+ return [];
887
+ const keys = [];
888
+ for (const ev of evaluators) {
889
+ const name = ev.name;
890
+ if (name && name.length > 0)
891
+ keys.push(name);
892
+ }
893
+ return keys;
894
+ }
895
+ async function _resolveNumExamples(data, client) {
896
+ // Best-effort dataset size for the experiment progress hint. Returns
897
+ // undefined for lazy async iterators where size cannot be inferred without
898
+ // consuming.
899
+ if (data === undefined)
900
+ return undefined;
901
+ try {
902
+ if (Array.isArray(data)) {
903
+ return data.length;
904
+ }
905
+ if (typeof data === "string") {
906
+ let isUUID = false;
907
+ try {
908
+ assertUuid(data);
909
+ isUUID = true;
910
+ }
911
+ catch (_) {
912
+ isUUID = false;
913
+ }
914
+ const dataset = isUUID
915
+ ? await client.readDataset({ datasetId: data })
916
+ : await client.readDataset({ datasetName: data });
917
+ return dataset.example_count ?? undefined;
918
+ }
919
+ return undefined;
920
+ }
921
+ catch (_) {
922
+ return undefined;
923
+ }
924
+ }
848
925
  function _resolveData(data, options) {
849
926
  let isUUID = false;
850
927
  try {