langsmith 0.1.42 → 0.1.44

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 CHANGED
@@ -32,6 +32,7 @@ const index_js_1 = require("./index.cjs");
32
32
  const _uuid_js_1 = require("./utils/_uuid.cjs");
33
33
  const warn_js_1 = require("./utils/warn.cjs");
34
34
  const prompts_js_1 = require("./utils/prompts.cjs");
35
+ const error_js_1 = require("./utils/error.cjs");
35
36
  async function mergeRuntimeEnvIntoRunCreates(runs) {
36
37
  const runtimeEnv = await (0, env_js_1.getRuntimeEnvironment)();
37
38
  const envVars = (0, env_js_1.getLangChainEnvVarsMetadata)();
@@ -72,14 +73,6 @@ const isLocalhost = (url) => {
72
73
  const hostname = strippedUrl.split("/")[0].split(":")[0];
73
74
  return (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1");
74
75
  };
75
- const raiseForStatus = async (response, operation) => {
76
- // consume the response body to release the connection
77
- // https://undici.nodejs.org/#/?id=garbage-collection
78
- const body = await response.text();
79
- if (!response.ok) {
80
- throw new Error(`Failed to ${operation}: ${response.status} ${response.statusText} ${body}`);
81
- }
82
- };
83
76
  async function toArray(iterable) {
84
77
  const result = [];
85
78
  for await (const item of iterable) {
@@ -387,9 +380,7 @@ class Client {
387
380
  signal: AbortSignal.timeout(this.timeout_ms),
388
381
  ...this.fetchOptions,
389
382
  });
390
- if (!response.ok) {
391
- throw new Error(`Failed to fetch ${path}: ${response.status} ${response.statusText}`);
392
- }
383
+ await (0, error_js_1.raiseForStatus)(response, `Failed to fetch ${path}`);
393
384
  return response;
394
385
  }
395
386
  async _get(path, queryParams) {
@@ -409,9 +400,7 @@ class Client {
409
400
  signal: AbortSignal.timeout(this.timeout_ms),
410
401
  ...this.fetchOptions,
411
402
  });
412
- if (!response.ok) {
413
- throw new Error(`Failed to fetch ${path}: ${response.status} ${response.statusText}`);
414
- }
403
+ await (0, error_js_1.raiseForStatus)(response, `Failed to fetch ${path}`);
415
404
  const items = transform
416
405
  ? transform(await response.json())
417
406
  : await response.json();
@@ -528,12 +517,7 @@ class Client {
528
517
  signal: AbortSignal.timeout(this.timeout_ms),
529
518
  ...this.fetchOptions,
530
519
  });
531
- if (!response.ok) {
532
- // consume the response body to release the connection
533
- // https://undici.nodejs.org/#/?id=garbage-collection
534
- await response.text();
535
- throw new Error("Failed to retrieve server info.");
536
- }
520
+ await (0, error_js_1.raiseForStatus)(response, "get server info");
537
521
  return response.json();
538
522
  }
539
523
  async batchEndpointIsSupported() {
@@ -582,7 +566,7 @@ class Client {
582
566
  signal: AbortSignal.timeout(this.timeout_ms),
583
567
  ...this.fetchOptions,
584
568
  });
585
- await raiseForStatus(response, "create run");
569
+ await (0, error_js_1.raiseForStatus)(response, "create run", true);
586
570
  }
587
571
  /**
588
572
  * Batch ingest/upsert multiple runs in the Langsmith system.
@@ -682,7 +666,7 @@ class Client {
682
666
  signal: AbortSignal.timeout(this.timeout_ms),
683
667
  ...this.fetchOptions,
684
668
  });
685
- await raiseForStatus(response, "batch create run");
669
+ await (0, error_js_1.raiseForStatus)(response, "batch create run", true);
686
670
  }
687
671
  async updateRun(runId, run) {
688
672
  (0, _uuid_js_1.assertUuid)(runId);
@@ -719,7 +703,7 @@ class Client {
719
703
  signal: AbortSignal.timeout(this.timeout_ms),
720
704
  ...this.fetchOptions,
721
705
  });
722
- await raiseForStatus(response, "update run");
706
+ await (0, error_js_1.raiseForStatus)(response, "update run", true);
723
707
  }
724
708
  async readRun(runId, { loadChildRuns } = { loadChildRuns: false }) {
725
709
  (0, _uuid_js_1.assertUuid)(runId);
@@ -1012,7 +996,7 @@ class Client {
1012
996
  signal: AbortSignal.timeout(this.timeout_ms),
1013
997
  ...this.fetchOptions,
1014
998
  });
1015
- await raiseForStatus(response, "unshare run");
999
+ await (0, error_js_1.raiseForStatus)(response, "unshare run", true);
1016
1000
  }
1017
1001
  async readRunSharedLink(runId) {
1018
1002
  (0, _uuid_js_1.assertUuid)(runId);
@@ -1097,7 +1081,7 @@ class Client {
1097
1081
  signal: AbortSignal.timeout(this.timeout_ms),
1098
1082
  ...this.fetchOptions,
1099
1083
  });
1100
- await raiseForStatus(response, "unshare dataset");
1084
+ await (0, error_js_1.raiseForStatus)(response, "unshare dataset", true);
1101
1085
  }
1102
1086
  async readSharedDataset(shareToken) {
1103
1087
  (0, _uuid_js_1.assertUuid)(shareToken);
@@ -1110,6 +1094,46 @@ class Client {
1110
1094
  const dataset = await response.json();
1111
1095
  return dataset;
1112
1096
  }
1097
+ /**
1098
+ * Get shared examples.
1099
+ *
1100
+ * @param {string} shareToken The share token to get examples for. A share token is the UUID (or LangSmith URL, including UUID) generated when explicitly marking an example as public.
1101
+ * @param {Object} [options] Additional options for listing the examples.
1102
+ * @param {string[] | undefined} [options.exampleIds] A list of example IDs to filter by.
1103
+ * @returns {Promise<Example[]>} The shared examples.
1104
+ */
1105
+ async listSharedExamples(shareToken, options) {
1106
+ const params = {};
1107
+ if (options?.exampleIds) {
1108
+ params.id = options.exampleIds;
1109
+ }
1110
+ const urlParams = new URLSearchParams();
1111
+ Object.entries(params).forEach(([key, value]) => {
1112
+ if (Array.isArray(value)) {
1113
+ value.forEach((v) => urlParams.append(key, v));
1114
+ }
1115
+ else {
1116
+ urlParams.append(key, value);
1117
+ }
1118
+ });
1119
+ const response = await this.caller.call(fetch, `${this.apiUrl}/public/${shareToken}/examples?${urlParams.toString()}`, {
1120
+ method: "GET",
1121
+ headers: this.headers,
1122
+ signal: AbortSignal.timeout(this.timeout_ms),
1123
+ ...this.fetchOptions,
1124
+ });
1125
+ const result = await response.json();
1126
+ if (!response.ok) {
1127
+ if ("detail" in result) {
1128
+ throw new Error(`Failed to list shared examples.\nStatus: ${response.status}\nMessage: ${result.detail.join("\n")}`);
1129
+ }
1130
+ throw new Error(`Failed to list shared examples: ${response.status} ${response.statusText}`);
1131
+ }
1132
+ return result.map((example) => ({
1133
+ ...example,
1134
+ _hostUrl: this.getHostUrl(),
1135
+ }));
1136
+ }
1113
1137
  async createProject({ projectName, description = null, metadata = null, upsert = false, projectExtra = null, referenceDatasetId = null, }) {
1114
1138
  const upsert_ = upsert ? `?upsert=true` : "";
1115
1139
  const endpoint = `${this.apiUrl}/sessions${upsert_}`;
@@ -1132,10 +1156,8 @@ class Client {
1132
1156
  signal: AbortSignal.timeout(this.timeout_ms),
1133
1157
  ...this.fetchOptions,
1134
1158
  });
1159
+ await (0, error_js_1.raiseForStatus)(response, "create project");
1135
1160
  const result = await response.json();
1136
- if (!response.ok) {
1137
- throw new Error(`Failed to create session ${projectName}: ${response.status} ${response.statusText}`);
1138
- }
1139
1161
  return result;
1140
1162
  }
1141
1163
  async updateProject(projectId, { name = null, description = null, metadata = null, projectExtra = null, endTime = null, }) {
@@ -1157,10 +1179,8 @@ class Client {
1157
1179
  signal: AbortSignal.timeout(this.timeout_ms),
1158
1180
  ...this.fetchOptions,
1159
1181
  });
1182
+ await (0, error_js_1.raiseForStatus)(response, "update project");
1160
1183
  const result = await response.json();
1161
- if (!response.ok) {
1162
- throw new Error(`Failed to update project ${projectId}: ${response.status} ${response.statusText}`);
1163
- }
1164
1184
  return result;
1165
1185
  }
1166
1186
  async hasProject({ projectId, projectName, }) {
@@ -1316,7 +1336,7 @@ class Client {
1316
1336
  signal: AbortSignal.timeout(this.timeout_ms),
1317
1337
  ...this.fetchOptions,
1318
1338
  });
1319
- await raiseForStatus(response, `delete session ${projectId_} (${projectName})`);
1339
+ await (0, error_js_1.raiseForStatus)(response, `delete session ${projectId_} (${projectName})`, true);
1320
1340
  }
1321
1341
  async uploadCsv({ csvFile, fileName, inputKeys, outputKeys, description, dataType, name, }) {
1322
1342
  const url = `${this.apiUrl}/datasets/upload`;
@@ -1344,17 +1364,11 @@ class Client {
1344
1364
  signal: AbortSignal.timeout(this.timeout_ms),
1345
1365
  ...this.fetchOptions,
1346
1366
  });
1347
- if (!response.ok) {
1348
- const result = await response.json();
1349
- if (result.detail && result.detail.includes("already exists")) {
1350
- throw new Error(`Dataset ${fileName} already exists`);
1351
- }
1352
- throw new Error(`Failed to upload CSV: ${response.status} ${response.statusText}`);
1353
- }
1367
+ await (0, error_js_1.raiseForStatus)(response, "upload CSV");
1354
1368
  const result = await response.json();
1355
1369
  return result;
1356
1370
  }
1357
- async createDataset(name, { description, dataType, } = {}) {
1371
+ async createDataset(name, { description, dataType, inputsSchema, outputsSchema, } = {}) {
1358
1372
  const body = {
1359
1373
  name,
1360
1374
  description,
@@ -1362,6 +1376,12 @@ class Client {
1362
1376
  if (dataType) {
1363
1377
  body.data_type = dataType;
1364
1378
  }
1379
+ if (inputsSchema) {
1380
+ body.inputs_schema_definition = inputsSchema;
1381
+ }
1382
+ if (outputsSchema) {
1383
+ body.outputs_schema_definition = outputsSchema;
1384
+ }
1365
1385
  const response = await this.caller.call(fetch, `${this.apiUrl}/datasets`, {
1366
1386
  method: "POST",
1367
1387
  headers: { ...this.headers, "Content-Type": "application/json" },
@@ -1369,13 +1389,7 @@ class Client {
1369
1389
  signal: AbortSignal.timeout(this.timeout_ms),
1370
1390
  ...this.fetchOptions,
1371
1391
  });
1372
- if (!response.ok) {
1373
- const result = await response.json();
1374
- if (result.detail && result.detail.includes("already exists")) {
1375
- throw new Error(`Dataset ${name} already exists`);
1376
- }
1377
- throw new Error(`Failed to create dataset ${response.status} ${response.statusText}`);
1378
- }
1392
+ await (0, error_js_1.raiseForStatus)(response, "create dataset");
1379
1393
  const result = await response.json();
1380
1394
  return result;
1381
1395
  }
@@ -1504,9 +1518,7 @@ class Client {
1504
1518
  signal: AbortSignal.timeout(this.timeout_ms),
1505
1519
  ...this.fetchOptions,
1506
1520
  });
1507
- if (!response.ok) {
1508
- throw new Error(`Failed to update dataset ${_datasetId}: ${response.status} ${response.statusText}`);
1509
- }
1521
+ await (0, error_js_1.raiseForStatus)(response, "update dataset");
1510
1522
  return (await response.json());
1511
1523
  }
1512
1524
  async deleteDataset({ datasetId, datasetName, }) {
@@ -1532,11 +1544,75 @@ class Client {
1532
1544
  signal: AbortSignal.timeout(this.timeout_ms),
1533
1545
  ...this.fetchOptions,
1534
1546
  });
1535
- if (!response.ok) {
1536
- throw new Error(`Failed to delete ${path}: ${response.status} ${response.statusText}`);
1547
+ await (0, error_js_1.raiseForStatus)(response, `delete ${path}`);
1548
+ await response.json();
1549
+ }
1550
+ async indexDataset({ datasetId, datasetName, tag, }) {
1551
+ let datasetId_ = datasetId;
1552
+ if (!datasetId_ && !datasetName) {
1553
+ throw new Error("Must provide either datasetName or datasetId");
1554
+ }
1555
+ else if (datasetId_ && datasetName) {
1556
+ throw new Error("Must provide either datasetName or datasetId, not both");
1557
+ }
1558
+ else if (!datasetId_) {
1559
+ const dataset = await this.readDataset({ datasetName });
1560
+ datasetId_ = dataset.id;
1537
1561
  }
1562
+ (0, _uuid_js_1.assertUuid)(datasetId_);
1563
+ const data = {
1564
+ tag: tag,
1565
+ };
1566
+ const response = await this.caller.call(fetch, `${this.apiUrl}/datasets/${datasetId_}/index`, {
1567
+ method: "POST",
1568
+ headers: { ...this.headers, "Content-Type": "application/json" },
1569
+ body: JSON.stringify(data),
1570
+ signal: AbortSignal.timeout(this.timeout_ms),
1571
+ ...this.fetchOptions,
1572
+ });
1573
+ await (0, error_js_1.raiseForStatus)(response, "index dataset");
1538
1574
  await response.json();
1539
1575
  }
1576
+ /**
1577
+ * Lets you run a similarity search query on a dataset.
1578
+ *
1579
+ * Requires the dataset to be indexed. Please see the `indexDataset` method to set up indexing.
1580
+ *
1581
+ * @param inputs The input on which to run the similarity search. Must have the
1582
+ * same schema as the dataset.
1583
+ *
1584
+ * @param datasetId The dataset to search for similar examples.
1585
+ *
1586
+ * @param limit The maximum number of examples to return. Will return the top `limit` most
1587
+ * similar examples in order of most similar to least similar. If no similar
1588
+ * examples are found, random examples will be returned.
1589
+ *
1590
+ * @returns A list of similar examples.
1591
+ *
1592
+ *
1593
+ * @example
1594
+ * dataset_id = "123e4567-e89b-12d3-a456-426614174000"
1595
+ * inputs = {"text": "How many people live in Berlin?"}
1596
+ * limit = 5
1597
+ * examples = await client.similarExamples(inputs, dataset_id, limit)
1598
+ */
1599
+ async similarExamples(inputs, datasetId, limit) {
1600
+ const data = {
1601
+ limit: limit,
1602
+ inputs: inputs,
1603
+ };
1604
+ (0, _uuid_js_1.assertUuid)(datasetId);
1605
+ const response = await this.caller.call(fetch, `${this.apiUrl}/datasets/${datasetId}/search`, {
1606
+ method: "POST",
1607
+ headers: { ...this.headers, "Content-Type": "application/json" },
1608
+ body: JSON.stringify(data),
1609
+ signal: AbortSignal.timeout(this.timeout_ms),
1610
+ ...this.fetchOptions,
1611
+ });
1612
+ await (0, error_js_1.raiseForStatus)(response, "fetch similar examples");
1613
+ const result = await response.json();
1614
+ return result["examples"];
1615
+ }
1540
1616
  async createExample(inputs, outputs, { datasetId, datasetName, createdAt, exampleId, metadata, split, }) {
1541
1617
  let datasetId_ = datasetId;
1542
1618
  if (datasetId_ === undefined && datasetName === undefined) {
@@ -1566,9 +1642,7 @@ class Client {
1566
1642
  signal: AbortSignal.timeout(this.timeout_ms),
1567
1643
  ...this.fetchOptions,
1568
1644
  });
1569
- if (!response.ok) {
1570
- throw new Error(`Failed to create example: ${response.status} ${response.statusText}`);
1571
- }
1645
+ await (0, error_js_1.raiseForStatus)(response, "create example");
1572
1646
  const result = await response.json();
1573
1647
  return result;
1574
1648
  }
@@ -1603,9 +1677,7 @@ class Client {
1603
1677
  signal: AbortSignal.timeout(this.timeout_ms),
1604
1678
  ...this.fetchOptions,
1605
1679
  });
1606
- if (!response.ok) {
1607
- throw new Error(`Failed to create examples: ${response.status} ${response.statusText}`);
1608
- }
1680
+ await (0, error_js_1.raiseForStatus)(response, "create examples");
1609
1681
  const result = await response.json();
1610
1682
  return result;
1611
1683
  }
@@ -1698,9 +1770,7 @@ class Client {
1698
1770
  signal: AbortSignal.timeout(this.timeout_ms),
1699
1771
  ...this.fetchOptions,
1700
1772
  });
1701
- if (!response.ok) {
1702
- throw new Error(`Failed to delete ${path}: ${response.status} ${response.statusText}`);
1703
- }
1773
+ await (0, error_js_1.raiseForStatus)(response, `delete ${path}`);
1704
1774
  await response.json();
1705
1775
  }
1706
1776
  async updateExample(exampleId, update) {
@@ -1712,9 +1782,7 @@ class Client {
1712
1782
  signal: AbortSignal.timeout(this.timeout_ms),
1713
1783
  ...this.fetchOptions,
1714
1784
  });
1715
- if (!response.ok) {
1716
- throw new Error(`Failed to update example ${exampleId}: ${response.status} ${response.statusText}`);
1717
- }
1785
+ await (0, error_js_1.raiseForStatus)(response, "update example");
1718
1786
  const result = await response.json();
1719
1787
  return result;
1720
1788
  }
@@ -1726,9 +1794,7 @@ class Client {
1726
1794
  signal: AbortSignal.timeout(this.timeout_ms),
1727
1795
  ...this.fetchOptions,
1728
1796
  });
1729
- if (!response.ok) {
1730
- throw new Error(`Failed to update examples: ${response.status} ${response.statusText}`);
1731
- }
1797
+ await (0, error_js_1.raiseForStatus)(response, "update examples");
1732
1798
  const result = await response.json();
1733
1799
  return result;
1734
1800
  }
@@ -1791,7 +1857,7 @@ class Client {
1791
1857
  signal: AbortSignal.timeout(this.timeout_ms),
1792
1858
  ...this.fetchOptions,
1793
1859
  });
1794
- await raiseForStatus(response, "update dataset splits");
1860
+ await (0, error_js_1.raiseForStatus)(response, "update dataset splits", true);
1795
1861
  }
1796
1862
  /**
1797
1863
  * @deprecated This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead.
@@ -1857,7 +1923,7 @@ class Client {
1857
1923
  signal: AbortSignal.timeout(this.timeout_ms),
1858
1924
  ...this.fetchOptions,
1859
1925
  });
1860
- await raiseForStatus(response, "create feedback");
1926
+ await (0, error_js_1.raiseForStatus)(response, "create feedback", true);
1861
1927
  return feedback;
1862
1928
  }
1863
1929
  async updateFeedback(feedbackId, { score, value, correction, comment, }) {
@@ -1882,7 +1948,7 @@ class Client {
1882
1948
  signal: AbortSignal.timeout(this.timeout_ms),
1883
1949
  ...this.fetchOptions,
1884
1950
  });
1885
- await raiseForStatus(response, "update feedback");
1951
+ await (0, error_js_1.raiseForStatus)(response, "update feedback", true);
1886
1952
  }
1887
1953
  async readFeedback(feedbackId) {
1888
1954
  (0, _uuid_js_1.assertUuid)(feedbackId);
@@ -1899,9 +1965,7 @@ class Client {
1899
1965
  signal: AbortSignal.timeout(this.timeout_ms),
1900
1966
  ...this.fetchOptions,
1901
1967
  });
1902
- if (!response.ok) {
1903
- throw new Error(`Failed to delete ${path}: ${response.status} ${response.statusText}`);
1904
- }
1968
+ await (0, error_js_1.raiseForStatus)(response, `delete ${path}`);
1905
1969
  await response.json();
1906
1970
  }
1907
1971
  async *listFeedback({ runIds, feedbackKeys, feedbackSourceTypes, } = {}) {
@@ -2094,9 +2158,7 @@ class Client {
2094
2158
  signal: AbortSignal.timeout(this.timeout_ms),
2095
2159
  ...this.fetchOptions,
2096
2160
  });
2097
- if (!response.ok) {
2098
- throw new Error(`Failed to ${like ? "like" : "unlike"} prompt: ${response.status} ${await response.text()}`);
2099
- }
2161
+ await (0, error_js_1.raiseForStatus)(response, `${like ? "like" : "unlike"} prompt`);
2100
2162
  return await response.json();
2101
2163
  }
2102
2164
  async _getPromptUrl(promptIdentifier) {
@@ -2160,9 +2222,7 @@ class Client {
2160
2222
  if (response.status === 404) {
2161
2223
  return null;
2162
2224
  }
2163
- if (!response.ok) {
2164
- throw new Error(`Failed to get prompt: ${response.status} ${await response.text()}`);
2165
- }
2225
+ await (0, error_js_1.raiseForStatus)(response, "get prompt");
2166
2226
  const result = await response.json();
2167
2227
  if (result.repo) {
2168
2228
  return result.repo;
@@ -2197,9 +2257,7 @@ class Client {
2197
2257
  signal: AbortSignal.timeout(this.timeout_ms),
2198
2258
  ...this.fetchOptions,
2199
2259
  });
2200
- if (!response.ok) {
2201
- throw new Error(`Failed to create prompt: ${response.status} ${await response.text()}`);
2202
- }
2260
+ await (0, error_js_1.raiseForStatus)(response, "create prompt");
2203
2261
  const { repo } = await response.json();
2204
2262
  return repo;
2205
2263
  }
@@ -2222,9 +2280,7 @@ class Client {
2222
2280
  signal: AbortSignal.timeout(this.timeout_ms),
2223
2281
  ...this.fetchOptions,
2224
2282
  });
2225
- if (!response.ok) {
2226
- throw new Error(`Failed to create commit: ${response.status} ${await response.text()}`);
2227
- }
2283
+ await (0, error_js_1.raiseForStatus)(response, "create commit");
2228
2284
  const result = await response.json();
2229
2285
  return this._getPromptUrl(`${owner}/${promptName}${result.commit_hash ? `:${result.commit_hash}` : ""}`);
2230
2286
  }
@@ -2261,9 +2317,7 @@ class Client {
2261
2317
  signal: AbortSignal.timeout(this.timeout_ms),
2262
2318
  ...this.fetchOptions,
2263
2319
  });
2264
- if (!response.ok) {
2265
- throw new Error(`HTTP Error: ${response.status} - ${await response.text()}`);
2266
- }
2320
+ await (0, error_js_1.raiseForStatus)(response, "update prompt");
2267
2321
  return response.json();
2268
2322
  }
2269
2323
  async deletePrompt(promptIdentifier) {
@@ -2302,9 +2356,7 @@ class Client {
2302
2356
  signal: AbortSignal.timeout(this.timeout_ms),
2303
2357
  ...this.fetchOptions,
2304
2358
  });
2305
- if (!response.ok) {
2306
- throw new Error(`Failed to pull prompt commit: ${response.status} ${response.statusText}`);
2307
- }
2359
+ await (0, error_js_1.raiseForStatus)(response, "pull prompt commit");
2308
2360
  const result = await response.json();
2309
2361
  return {
2310
2362
  owner,
@@ -2357,5 +2409,86 @@ class Client {
2357
2409
  });
2358
2410
  return url;
2359
2411
  }
2412
+ /**
2413
+ * Clone a public dataset to your own langsmith tenant.
2414
+ * This operation is idempotent. If you already have a dataset with the given name,
2415
+ * this function will do nothing.
2416
+
2417
+ * @param {string} tokenOrUrl The token of the public dataset to clone.
2418
+ * @param {Object} [options] Additional options for cloning the dataset.
2419
+ * @param {string} [options.sourceApiUrl] The URL of the langsmith server where the data is hosted. Defaults to the API URL of your current client.
2420
+ * @param {string} [options.datasetName] The name of the dataset to create in your tenant. Defaults to the name of the public dataset.
2421
+ * @returns {Promise<void>}
2422
+ */
2423
+ async clonePublicDataset(tokenOrUrl, options = {}) {
2424
+ const { sourceApiUrl = this.apiUrl, datasetName } = options;
2425
+ const [parsedApiUrl, tokenUuid] = this.parseTokenOrUrl(tokenOrUrl, sourceApiUrl);
2426
+ const sourceClient = new Client({
2427
+ apiUrl: parsedApiUrl,
2428
+ // Placeholder API key not needed anymore in most cases, but
2429
+ // some private deployments may have API key-based rate limiting
2430
+ // that would cause this to fail if we provide no value.
2431
+ apiKey: "placeholder",
2432
+ });
2433
+ const ds = await sourceClient.readSharedDataset(tokenUuid);
2434
+ const finalDatasetName = datasetName || ds.name;
2435
+ try {
2436
+ if (await this.hasDataset({ datasetId: finalDatasetName })) {
2437
+ console.log(`Dataset ${finalDatasetName} already exists in your tenant. Skipping.`);
2438
+ return;
2439
+ }
2440
+ }
2441
+ catch (_) {
2442
+ // `.hasDataset` will throw an error if the dataset does not exist.
2443
+ // no-op in that case
2444
+ }
2445
+ // Fetch examples first, then create the dataset
2446
+ const examples = await sourceClient.listSharedExamples(tokenUuid);
2447
+ const dataset = await this.createDataset(finalDatasetName, {
2448
+ description: ds.description,
2449
+ dataType: ds.data_type || "kv",
2450
+ inputsSchema: ds.inputs_schema_definition ?? undefined,
2451
+ outputsSchema: ds.outputs_schema_definition ?? undefined,
2452
+ });
2453
+ try {
2454
+ await this.createExamples({
2455
+ inputs: examples.map((e) => e.inputs),
2456
+ outputs: examples.flatMap((e) => (e.outputs ? [e.outputs] : [])),
2457
+ datasetId: dataset.id,
2458
+ });
2459
+ }
2460
+ catch (e) {
2461
+ console.error(`An error occurred while creating dataset ${finalDatasetName}. ` +
2462
+ "You should delete it manually.");
2463
+ throw e;
2464
+ }
2465
+ }
2466
+ parseTokenOrUrl(urlOrToken, apiUrl, numParts = 2, kind = "dataset") {
2467
+ // Try parsing as UUID
2468
+ try {
2469
+ (0, _uuid_js_1.assertUuid)(urlOrToken); // Will throw if it's not a UUID.
2470
+ return [apiUrl, urlOrToken];
2471
+ }
2472
+ catch (_) {
2473
+ // no-op if it's not a uuid
2474
+ }
2475
+ // Parse as URL
2476
+ try {
2477
+ const parsedUrl = new URL(urlOrToken);
2478
+ const pathParts = parsedUrl.pathname
2479
+ .split("/")
2480
+ .filter((part) => part !== "");
2481
+ if (pathParts.length >= numParts) {
2482
+ const tokenUuid = pathParts[pathParts.length - numParts];
2483
+ return [apiUrl, tokenUuid];
2484
+ }
2485
+ else {
2486
+ throw new Error(`Invalid public ${kind} URL: ${urlOrToken}`);
2487
+ }
2488
+ }
2489
+ catch (error) {
2490
+ throw new Error(`Invalid public ${kind} URL or token: ${urlOrToken}`);
2491
+ }
2492
+ }
2360
2493
  }
2361
2494
  exports.Client = Client;
package/dist/client.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AsyncCallerParams } from "./utils/async_caller.js";
2
- import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, TimeDelta, TracerSession, TracerSessionResult, ValueType } from "./schemas.js";
2
+ import { ComparativeExperiment, DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, ExampleUpdateWithId, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, LangSmithSettings, LikePromptResponse, Prompt, PromptCommit, PromptSortField, Run, RunCreate, RunUpdate, ScoreType, ExampleSearch, TimeDelta, TracerSession, TracerSessionResult, ValueType } from "./schemas.js";
3
3
  import { EvaluationResult, EvaluationResults, RunEvaluator } from "./evaluation/evaluator.js";
4
- interface ClientConfig {
4
+ export interface ClientConfig {
5
5
  apiUrl?: string;
6
6
  apiKey?: string;
7
7
  callerOptions?: AsyncCallerParams;
@@ -332,6 +332,17 @@ export declare class Client {
332
332
  shareDataset(datasetId?: string, datasetName?: string): Promise<DatasetShareSchema>;
333
333
  unshareDataset(datasetId: string): Promise<void>;
334
334
  readSharedDataset(shareToken: string): Promise<Dataset>;
335
+ /**
336
+ * Get shared examples.
337
+ *
338
+ * @param {string} shareToken The share token to get examples for. A share token is the UUID (or LangSmith URL, including UUID) generated when explicitly marking an example as public.
339
+ * @param {Object} [options] Additional options for listing the examples.
340
+ * @param {string[] | undefined} [options.exampleIds] A list of example IDs to filter by.
341
+ * @returns {Promise<Example[]>} The shared examples.
342
+ */
343
+ listSharedExamples(shareToken: string, options?: {
344
+ exampleIds?: string[];
345
+ }): Promise<Example[]>;
335
346
  createProject({ projectName, description, metadata, upsert, projectExtra, referenceDatasetId, }: {
336
347
  projectName: string;
337
348
  description?: string | null;
@@ -379,9 +390,11 @@ export declare class Client {
379
390
  projectName?: string;
380
391
  }): Promise<void>;
381
392
  uploadCsv({ csvFile, fileName, inputKeys, outputKeys, description, dataType, name, }: UploadCSVParams): Promise<Dataset>;
382
- createDataset(name: string, { description, dataType, }?: {
393
+ createDataset(name: string, { description, dataType, inputsSchema, outputsSchema, }?: {
383
394
  description?: string;
384
395
  dataType?: DataType;
396
+ inputsSchema?: KVMap;
397
+ outputsSchema?: KVMap;
385
398
  }): Promise<Dataset>;
386
399
  readDataset({ datasetId, datasetName, }: {
387
400
  datasetId?: string;
@@ -423,6 +436,35 @@ export declare class Client {
423
436
  datasetId?: string;
424
437
  datasetName?: string;
425
438
  }): Promise<void>;
439
+ indexDataset({ datasetId, datasetName, tag, }: {
440
+ datasetId?: string;
441
+ datasetName?: string;
442
+ tag?: string;
443
+ }): Promise<void>;
444
+ /**
445
+ * Lets you run a similarity search query on a dataset.
446
+ *
447
+ * Requires the dataset to be indexed. Please see the `indexDataset` method to set up indexing.
448
+ *
449
+ * @param inputs The input on which to run the similarity search. Must have the
450
+ * same schema as the dataset.
451
+ *
452
+ * @param datasetId The dataset to search for similar examples.
453
+ *
454
+ * @param limit The maximum number of examples to return. Will return the top `limit` most
455
+ * similar examples in order of most similar to least similar. If no similar
456
+ * examples are found, random examples will be returned.
457
+ *
458
+ * @returns A list of similar examples.
459
+ *
460
+ *
461
+ * @example
462
+ * dataset_id = "123e4567-e89b-12d3-a456-426614174000"
463
+ * inputs = {"text": "How many people live in Berlin?"}
464
+ * limit = 5
465
+ * examples = await client.similarExamples(inputs, dataset_id, limit)
466
+ */
467
+ similarExamples(inputs: KVMap, datasetId: string, limit: number): Promise<ExampleSearch[]>;
426
468
  createExample(inputs: KVMap, outputs: KVMap, { datasetId, datasetName, createdAt, exampleId, metadata, split, }: CreateExampleOptions): Promise<Example>;
427
469
  createExamples(props: {
428
470
  inputs: Array<KVMap>;
@@ -594,5 +636,21 @@ export declare class Client {
594
636
  readme?: string;
595
637
  tags?: string[];
596
638
  }): Promise<string>;
639
+ /**
640
+ * Clone a public dataset to your own langsmith tenant.
641
+ * This operation is idempotent. If you already have a dataset with the given name,
642
+ * this function will do nothing.
643
+
644
+ * @param {string} tokenOrUrl The token of the public dataset to clone.
645
+ * @param {Object} [options] Additional options for cloning the dataset.
646
+ * @param {string} [options.sourceApiUrl] The URL of the langsmith server where the data is hosted. Defaults to the API URL of your current client.
647
+ * @param {string} [options.datasetName] The name of the dataset to create in your tenant. Defaults to the name of the public dataset.
648
+ * @returns {Promise<void>}
649
+ */
650
+ clonePublicDataset(tokenOrUrl: string, options?: {
651
+ sourceApiUrl?: string;
652
+ datasetName?: string;
653
+ }): Promise<void>;
654
+ private parseTokenOrUrl;
597
655
  }
598
656
  export {};