langsmith 0.1.11 → 0.1.13

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/README.md CHANGED
@@ -292,6 +292,38 @@ export async function POST(req: Request) {
292
292
 
293
293
  See the [AI SDK docs](https://sdk.vercel.ai/docs) for more examples.
294
294
 
295
+ ## Arbitrary SDKs
296
+
297
+ You can use the generic `wrapSDK` method to add tracing for arbitrary SDKs.
298
+
299
+ Do note that this will trace ALL methods in the SDK, not just chat completion endpoints.
300
+ If the SDK you are wrapping has other methods, we recommend using it for only LLM calls.
301
+
302
+ Here's an example using the Anthropic SDK:
303
+
304
+ ```ts
305
+ import { wrapSDK } from "langsmith/wrappers";
306
+ import { Anthropic } from "@anthropic-ai/sdk";
307
+
308
+ const originalSDK = new Anthropic();
309
+ const sdkWithTracing = wrapSDK(originalSDK);
310
+
311
+ const response = await sdkWithTracing.messages.create({
312
+ messages: [
313
+ {
314
+ role: "user",
315
+ content: `What is 1 + 1? Respond only with "2" and nothing else.`,
316
+ },
317
+ ],
318
+ model: "claude-3-sonnet-20240229",
319
+ max_tokens: 1024,
320
+ });
321
+ ```
322
+
323
+ :::tip
324
+ [Click here](https://smith.langchain.com/public/0e7248af-bbed-47cf-be9f-5967fea1dec1/r) to see an example LangSmith trace of the above.
325
+ :::
326
+
295
327
  #### Alternatives: **Log traces using a RunTree.**
296
328
 
297
329
  A RunTree tracks your application. Each RunTree object is required to have a name and run_type. These and other important attributes are as follows:
package/dist/client.cjs CHANGED
@@ -1260,6 +1260,27 @@ class Client {
1260
1260
  }
1261
1261
  return result;
1262
1262
  }
1263
+ async diffDatasetVersions({ datasetId, datasetName, fromVersion, toVersion, }) {
1264
+ let datasetId_ = datasetId;
1265
+ if (datasetId_ === undefined && datasetName === undefined) {
1266
+ throw new Error("Must provide either datasetName or datasetId");
1267
+ }
1268
+ else if (datasetId_ !== undefined && datasetName !== undefined) {
1269
+ throw new Error("Must provide either datasetName or datasetId, not both");
1270
+ }
1271
+ else if (datasetId_ === undefined) {
1272
+ const dataset = await this.readDataset({ datasetName });
1273
+ datasetId_ = dataset.id;
1274
+ }
1275
+ const urlParams = new URLSearchParams({
1276
+ from_version: typeof fromVersion === "string"
1277
+ ? fromVersion
1278
+ : fromVersion.toISOString(),
1279
+ to_version: typeof toVersion === "string" ? toVersion : toVersion.toISOString(),
1280
+ });
1281
+ const response = await this._get(`/datasets/${datasetId_}/versions/diff`, urlParams);
1282
+ return response;
1283
+ }
1263
1284
  async readDatasetOpenaiFinetuning({ datasetId, datasetName, }) {
1264
1285
  const path = "/datasets";
1265
1286
  if (datasetId !== undefined) {
@@ -1413,7 +1434,7 @@ class Client {
1413
1434
  const path = `/examples/${exampleId}`;
1414
1435
  return await this._get(path);
1415
1436
  }
1416
- async *listExamples({ datasetId, datasetName, exampleIds, } = {}) {
1437
+ async *listExamples({ datasetId, datasetName, exampleIds, asOf, inlineS3Urls, } = {}) {
1417
1438
  let datasetId_;
1418
1439
  if (datasetId !== undefined && datasetName !== undefined) {
1419
1440
  throw new Error("Must provide either datasetName or datasetId, not both");
@@ -1429,6 +1450,16 @@ class Client {
1429
1450
  throw new Error("Must provide a datasetName or datasetId");
1430
1451
  }
1431
1452
  const params = new URLSearchParams({ dataset: datasetId_ });
1453
+ const dataset_version = asOf
1454
+ ? typeof asOf === "string"
1455
+ ? asOf
1456
+ : asOf?.toISOString()
1457
+ : undefined;
1458
+ if (dataset_version) {
1459
+ params.append("as_of", dataset_version);
1460
+ }
1461
+ const inlineS3Urls_ = inlineS3Urls ?? true;
1462
+ params.append("inline_s3_urls", inlineS3Urls_.toString());
1432
1463
  if (exampleIds !== undefined) {
1433
1464
  for (const id_ of exampleIds) {
1434
1465
  params.append("id", id_);
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AsyncCallerParams } from "./utils/async_caller.js";
2
- import { DataType, Dataset, DatasetShareSchema, Example, ExampleUpdate, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, Run, RunCreate, RunUpdate, ScoreType, TimeDelta, TracerSession, TracerSessionResult, ValueType } from "./schemas.js";
2
+ import { DataType, Dataset, DatasetDiffInfo, DatasetShareSchema, Example, ExampleUpdate, Feedback, FeedbackConfig, FeedbackIngestToken, KVMap, LangChainBaseMessage, Run, RunCreate, RunUpdate, ScoreType, TimeDelta, TracerSession, TracerSessionResult, ValueType } from "./schemas.js";
3
3
  import { RunEvaluator } from "./evaluation/evaluator.js";
4
4
  interface ClientConfig {
5
5
  apiUrl?: string;
@@ -344,6 +344,12 @@ export declare class Client {
344
344
  datasetId?: string;
345
345
  datasetName?: string;
346
346
  }): Promise<Dataset>;
347
+ diffDatasetVersions({ datasetId, datasetName, fromVersion, toVersion, }: {
348
+ datasetId?: string;
349
+ datasetName?: string;
350
+ fromVersion: string | Date;
351
+ toVersion: string | Date;
352
+ }): Promise<DatasetDiffInfo>;
347
353
  readDatasetOpenaiFinetuning({ datasetId, datasetName, }: {
348
354
  datasetId?: string;
349
355
  datasetName?: string;
@@ -371,10 +377,12 @@ export declare class Client {
371
377
  createLLMExample(input: string, generation: string | undefined, options: CreateExampleOptions): Promise<Example>;
372
378
  createChatExample(input: KVMap[] | LangChainBaseMessage[], generations: KVMap | LangChainBaseMessage | undefined, options: CreateExampleOptions): Promise<Example>;
373
379
  readExample(exampleId: string): Promise<Example>;
374
- listExamples({ datasetId, datasetName, exampleIds, }?: {
380
+ listExamples({ datasetId, datasetName, exampleIds, asOf, inlineS3Urls, }?: {
375
381
  datasetId?: string;
376
382
  datasetName?: string;
377
383
  exampleIds?: string[];
384
+ asOf?: string | Date;
385
+ inlineS3Urls?: boolean;
378
386
  }): AsyncIterable<Example>;
379
387
  deleteExample(exampleId: string): Promise<void>;
380
388
  updateExample(exampleId: string, update: ExampleUpdate): Promise<object>;
package/dist/client.js CHANGED
@@ -1233,6 +1233,27 @@ export class Client {
1233
1233
  }
1234
1234
  return result;
1235
1235
  }
1236
+ async diffDatasetVersions({ datasetId, datasetName, fromVersion, toVersion, }) {
1237
+ let datasetId_ = datasetId;
1238
+ if (datasetId_ === undefined && datasetName === undefined) {
1239
+ throw new Error("Must provide either datasetName or datasetId");
1240
+ }
1241
+ else if (datasetId_ !== undefined && datasetName !== undefined) {
1242
+ throw new Error("Must provide either datasetName or datasetId, not both");
1243
+ }
1244
+ else if (datasetId_ === undefined) {
1245
+ const dataset = await this.readDataset({ datasetName });
1246
+ datasetId_ = dataset.id;
1247
+ }
1248
+ const urlParams = new URLSearchParams({
1249
+ from_version: typeof fromVersion === "string"
1250
+ ? fromVersion
1251
+ : fromVersion.toISOString(),
1252
+ to_version: typeof toVersion === "string" ? toVersion : toVersion.toISOString(),
1253
+ });
1254
+ const response = await this._get(`/datasets/${datasetId_}/versions/diff`, urlParams);
1255
+ return response;
1256
+ }
1236
1257
  async readDatasetOpenaiFinetuning({ datasetId, datasetName, }) {
1237
1258
  const path = "/datasets";
1238
1259
  if (datasetId !== undefined) {
@@ -1386,7 +1407,7 @@ export class Client {
1386
1407
  const path = `/examples/${exampleId}`;
1387
1408
  return await this._get(path);
1388
1409
  }
1389
- async *listExamples({ datasetId, datasetName, exampleIds, } = {}) {
1410
+ async *listExamples({ datasetId, datasetName, exampleIds, asOf, inlineS3Urls, } = {}) {
1390
1411
  let datasetId_;
1391
1412
  if (datasetId !== undefined && datasetName !== undefined) {
1392
1413
  throw new Error("Must provide either datasetName or datasetId, not both");
@@ -1402,6 +1423,16 @@ export class Client {
1402
1423
  throw new Error("Must provide a datasetName or datasetId");
1403
1424
  }
1404
1425
  const params = new URLSearchParams({ dataset: datasetId_ });
1426
+ const dataset_version = asOf
1427
+ ? typeof asOf === "string"
1428
+ ? asOf
1429
+ : asOf?.toISOString()
1430
+ : undefined;
1431
+ if (dataset_version) {
1432
+ params.append("as_of", dataset_version);
1433
+ }
1434
+ const inlineS3Urls_ = inlineS3Urls ?? true;
1435
+ params.append("inline_s3_urls", inlineS3Urls_.toString());
1405
1436
  if (exampleIds !== undefined) {
1406
1437
  for (const id_ of exampleIds) {
1407
1438
  params.append("id", id_);
package/dist/index.cjs CHANGED
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "Client", { enumerable: true, get: function () {
6
6
  var run_trees_js_1 = require("./run_trees.cjs");
7
7
  Object.defineProperty(exports, "RunTree", { enumerable: true, get: function () { return run_trees_js_1.RunTree; } });
8
8
  // Update using yarn bump-version
9
- exports.__version__ = "0.1.11";
9
+ exports.__version__ = "0.1.13";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Client } from "./client.js";
2
2
  export type { Dataset, Example, TracerSession, Run, Feedback, } from "./schemas.js";
3
3
  export { RunTree, type RunTreeConfig } from "./run_trees.js";
4
- export declare const __version__ = "0.1.11";
4
+ export declare const __version__ = "0.1.13";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { Client } from "./client.js";
2
2
  export { RunTree } from "./run_trees.js";
3
3
  // Update using yarn bump-version
4
- export const __version__ = "0.1.11";
4
+ export const __version__ = "0.1.13";
package/dist/schemas.d.ts CHANGED
@@ -247,3 +247,8 @@ export interface FeedbackConfig {
247
247
  */
248
248
  categories?: FeedbackCategory[] | null;
249
249
  }
250
+ export interface DatasetDiffInfo {
251
+ examples_modified: string[];
252
+ examples_added: string[];
253
+ examples_removed: string[];
254
+ }
package/dist/wrappers.cjs CHANGED
@@ -1,12 +1,54 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.wrapOpenAI = void 0;
3
+ exports.wrapSDK = exports.wrapOpenAI = void 0;
4
4
  const traceable_js_1 = require("./traceable.cjs");
5
+ /**
6
+ * Wraps an OpenAI client's completion methods, enabling automatic LangSmith
7
+ * tracing. Method signatures are unchanged.
8
+ * @param openai An OpenAI client instance.
9
+ * @param options LangSmith options.
10
+ * @returns
11
+ */
5
12
  const wrapOpenAI = (openai, options) => {
6
- // @ts-expect-error Promise<APIPromise<...>> != APIPromise<...>
7
13
  openai.chat.completions.create = (0, traceable_js_1.traceable)(openai.chat.completions.create.bind(openai.chat.completions), Object.assign({ name: "ChatOpenAI", run_type: "llm" }, options?.client));
8
- // @ts-expect-error Promise<APIPromise<...>> != APIPromise<...>
9
14
  openai.completions.create = (0, traceable_js_1.traceable)(openai.completions.create.bind(openai.completions), Object.assign({ name: "OpenAI", run_type: "llm" }, options?.client));
10
15
  return openai;
11
16
  };
12
17
  exports.wrapOpenAI = wrapOpenAI;
18
+ const _wrapClient = (sdk, runName, options) => {
19
+ return new Proxy(sdk, {
20
+ get(target, propKey, receiver) {
21
+ const originalValue = target[propKey];
22
+ if (typeof originalValue === "function") {
23
+ return (0, traceable_js_1.traceable)(originalValue.bind(target), Object.assign({ name: [runName, propKey.toString()].join("."), run_type: "llm" }, options?.client));
24
+ }
25
+ else if (originalValue != null &&
26
+ !Array.isArray(originalValue) &&
27
+ // eslint-disable-next-line no-instanceof/no-instanceof
28
+ !(originalValue instanceof Date) &&
29
+ typeof originalValue === "object") {
30
+ return _wrapClient(originalValue, [runName, propKey.toString()].join("."), options);
31
+ }
32
+ else {
33
+ return Reflect.get(target, propKey, receiver);
34
+ }
35
+ },
36
+ });
37
+ };
38
+ /**
39
+ * Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
40
+ * Method signatures are unchanged.
41
+ *
42
+ * Note that this will wrap and trace ALL SDK methods, not just
43
+ * LLM completion methods. If the passed SDK contains other methods,
44
+ * we recommend using the wrapped instance for LLM calls only.
45
+ * @param sdk An arbitrary SDK instance.
46
+ * @param options LangSmith options.
47
+ * @returns
48
+ */
49
+ const wrapSDK = (sdk, options) => {
50
+ return _wrapClient(sdk, options?.runName ?? sdk.constructor?.name, {
51
+ client: options?.client,
52
+ });
53
+ };
54
+ exports.wrapSDK = wrapSDK;
@@ -1,5 +1,37 @@
1
- import type { OpenAI } from "openai";
2
1
  import type { Client } from "./index.js";
3
- export declare const wrapOpenAI: (openai: OpenAI, options?: {
2
+ type OpenAIType = {
3
+ chat: {
4
+ completions: {
5
+ create: (...args: any[]) => any;
6
+ };
7
+ };
8
+ completions: {
9
+ create: (...args: any[]) => any;
10
+ };
11
+ };
12
+ /**
13
+ * Wraps an OpenAI client's completion methods, enabling automatic LangSmith
14
+ * tracing. Method signatures are unchanged.
15
+ * @param openai An OpenAI client instance.
16
+ * @param options LangSmith options.
17
+ * @returns
18
+ */
19
+ export declare const wrapOpenAI: <T extends OpenAIType>(openai: T, options?: {
4
20
  client?: Client;
5
- }) => OpenAI;
21
+ }) => T;
22
+ /**
23
+ * Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
24
+ * Method signatures are unchanged.
25
+ *
26
+ * Note that this will wrap and trace ALL SDK methods, not just
27
+ * LLM completion methods. If the passed SDK contains other methods,
28
+ * we recommend using the wrapped instance for LLM calls only.
29
+ * @param sdk An arbitrary SDK instance.
30
+ * @param options LangSmith options.
31
+ * @returns
32
+ */
33
+ export declare const wrapSDK: <T extends object>(sdk: T, options?: {
34
+ client?: Client;
35
+ runName?: string;
36
+ }) => T;
37
+ export {};
package/dist/wrappers.js CHANGED
@@ -1,8 +1,49 @@
1
1
  import { traceable } from "./traceable.js";
2
+ /**
3
+ * Wraps an OpenAI client's completion methods, enabling automatic LangSmith
4
+ * tracing. Method signatures are unchanged.
5
+ * @param openai An OpenAI client instance.
6
+ * @param options LangSmith options.
7
+ * @returns
8
+ */
2
9
  export const wrapOpenAI = (openai, options) => {
3
- // @ts-expect-error Promise<APIPromise<...>> != APIPromise<...>
4
10
  openai.chat.completions.create = traceable(openai.chat.completions.create.bind(openai.chat.completions), Object.assign({ name: "ChatOpenAI", run_type: "llm" }, options?.client));
5
- // @ts-expect-error Promise<APIPromise<...>> != APIPromise<...>
6
11
  openai.completions.create = traceable(openai.completions.create.bind(openai.completions), Object.assign({ name: "OpenAI", run_type: "llm" }, options?.client));
7
12
  return openai;
8
13
  };
14
+ const _wrapClient = (sdk, runName, options) => {
15
+ return new Proxy(sdk, {
16
+ get(target, propKey, receiver) {
17
+ const originalValue = target[propKey];
18
+ if (typeof originalValue === "function") {
19
+ return traceable(originalValue.bind(target), Object.assign({ name: [runName, propKey.toString()].join("."), run_type: "llm" }, options?.client));
20
+ }
21
+ else if (originalValue != null &&
22
+ !Array.isArray(originalValue) &&
23
+ // eslint-disable-next-line no-instanceof/no-instanceof
24
+ !(originalValue instanceof Date) &&
25
+ typeof originalValue === "object") {
26
+ return _wrapClient(originalValue, [runName, propKey.toString()].join("."), options);
27
+ }
28
+ else {
29
+ return Reflect.get(target, propKey, receiver);
30
+ }
31
+ },
32
+ });
33
+ };
34
+ /**
35
+ * Wrap an arbitrary SDK, enabling automatic LangSmith tracing.
36
+ * Method signatures are unchanged.
37
+ *
38
+ * Note that this will wrap and trace ALL SDK methods, not just
39
+ * LLM completion methods. If the passed SDK contains other methods,
40
+ * we recommend using the wrapped instance for LLM calls only.
41
+ * @param sdk An arbitrary SDK instance.
42
+ * @param options LangSmith options.
43
+ * @returns
44
+ */
45
+ export const wrapSDK = (sdk, options) => {
46
+ return _wrapClient(sdk, options?.runName ?? sdk.constructor?.name, {
47
+ client: options?.client,
48
+ });
49
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langsmith",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.",
5
5
  "packageManager": "yarn@1.22.19",
6
6
  "files": [
@@ -29,12 +29,9 @@
29
29
  ],
30
30
  "type": "module",
31
31
  "main": "./dist/index.js",
32
- "bin": {
33
- "langsmith": "./dist/cli/main.cjs"
34
- },
35
32
  "types": "./dist/index.d.ts",
36
33
  "scripts": {
37
- "build": "yarn clean && yarn build:esm && yarn build:cjs && node scripts/create-entrypoints.js && node scripts/create-cli.js",
34
+ "build": "yarn clean && yarn build:esm && yarn build:cjs && node scripts/create-entrypoints.js",
38
35
  "bump-version": "node scripts/bump-version.js",
39
36
  "check-version": "node scripts/check-version.js",
40
37
  "check-npm-version": "node scripts/check-npm-version.js",
@@ -1,155 +0,0 @@
1
- version: "4"
2
- services:
3
- langchain-playground:
4
- image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-playground:${_LANGSMITH_IMAGE_VERSION:-latest}
5
- ports:
6
- - 3001:3001
7
- langchain-frontend:
8
- image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-frontend-dynamic:${_LANGSMITH_IMAGE_VERSION:-latest}
9
- ports:
10
- - 80:80
11
- depends_on:
12
- - langchain-backend
13
- - langchain-playground
14
- - langchain-hub
15
- langchain-backend:
16
- image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:${_LANGSMITH_IMAGE_VERSION:-latest}
17
- environment:
18
- - PORT=1984
19
- - LANGCHAIN_ENV=local_docker
20
- - LOG_LEVEL=warning
21
- - OPENAI_API_KEY=${OPENAI_API_KEY}
22
- - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY}
23
- ports:
24
- - 1984:1984
25
- depends_on:
26
- langchain-db:
27
- condition: service_healthy
28
- langchain-redis:
29
- condition: service_healthy
30
- clickhouse-setup:
31
- condition: service_completed_successfully
32
- postgres-setup:
33
- condition: service_completed_successfully
34
- restart: always
35
- langchain-queue:
36
- image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:${_LANGSMITH_IMAGE_VERSION:-latest}
37
- environment:
38
- - LANGCHAIN_ENV=local_docker
39
- - LOG_LEVEL=warning
40
- - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY}
41
- entrypoint: "rq worker --with-scheduler -u redis://langchain-redis:6379 --serializer lc_database.queue.serializer.ORJSONSerializer --worker-class lc_database.queue.worker.Worker --connection-class lc_database.queue.connection.RedisRetry --job-class lc_database.queue.job.AsyncJob"
42
- depends_on:
43
- langchain-db:
44
- condition: service_healthy
45
- langchain-redis:
46
- condition: service_healthy
47
- clickhouse-setup:
48
- condition: service_completed_successfully
49
- postgres-setup:
50
- condition: service_completed_successfully
51
- restart: always
52
- langchain-hub:
53
- image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainhub-backend:${_LANGSMITH_IMAGE_VERSION:-latest}
54
- environment:
55
- - PORT=1985
56
- - LANGCHAIN_ENV=local_docker
57
- - LOG_LEVEL=warning
58
- - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY}
59
- ports:
60
- - 1985:1985
61
- depends_on:
62
- langchain-db:
63
- condition: service_healthy
64
- langchain-redis:
65
- condition: service_healthy
66
- clickhouse-setup:
67
- condition: service_completed_successfully
68
- postgres-setup:
69
- condition: service_completed_successfully
70
- restart: always
71
- langchain-db:
72
- image: postgres:14.7
73
- command:
74
- [
75
- "postgres",
76
- "-c",
77
- "log_min_messages=WARNING",
78
- "-c",
79
- "client_min_messages=WARNING",
80
- ]
81
- environment:
82
- - POSTGRES_PASSWORD=postgres
83
- - POSTGRES_USER=postgres
84
- - POSTGRES_DB=postgres
85
- volumes:
86
- - langchain-db-data:/var/lib/postgresql/data
87
- ports:
88
- - 5433:5432
89
- healthcheck:
90
- test: ["CMD", "pg_isready", "-U", "postgres"]
91
- interval: 2s
92
- timeout: 2s
93
- retries: 30
94
- langchain-redis:
95
- image: redis:7
96
- ports:
97
- - 63791:6379
98
- volumes:
99
- - langchain-redis-data:/data
100
- healthcheck:
101
- test: ["CMD", "redis-cli", "ping"]
102
- interval: 2s
103
- timeout: 2s
104
- retries: 30
105
- langchain-clickhouse:
106
- image: clickhouse/clickhouse-server:23.9
107
- user: "101:101"
108
- restart: always
109
- environment:
110
- - CLICKHOUSE_DB=default
111
- - CLICKHOUSE_USER=default
112
- - CLICKHOUSE_PASSWORD=password
113
- volumes:
114
- - langchain-clickhouse-data:/var/lib/clickhouse
115
- - ./users.xml:/etc/clickhouse-server/users.d/users.xml
116
- ports:
117
- - 8124:8123
118
- - 9001:9000
119
- healthcheck:
120
- test: ["CMD", "clickhouse-client", "--query", "SELECT 1"]
121
- interval: 2s
122
- timeout: 2s
123
- retries: 30
124
- clickhouse-setup:
125
- image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:${_LANGSMITH_IMAGE_VERSION:-latest}
126
- depends_on:
127
- langchain-clickhouse:
128
- condition: service_healthy
129
- restart: "on-failure:10"
130
- entrypoint:
131
- [
132
- "bash",
133
- "-c",
134
- "migrate -source file://clickhouse/migrations -database 'clickhouse://langchain-clickhouse:9000?username=default&password=password&database=default&x-multi-statement=true&x-migrations-table-engine=MergeTree' up",
135
- ]
136
- postgres-setup:
137
- image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:${_LANGSMITH_IMAGE_VERSION:-latest}
138
- depends_on:
139
- langchain-db:
140
- condition: service_healthy
141
- environment:
142
- - LANGCHAIN_ENV=local_docker
143
- - LOG_LEVEL=warning
144
- - LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY}
145
- restart: "on-failure:10"
146
- entrypoint:
147
- [
148
- "bash",
149
- "-c",
150
- "alembic upgrade head",
151
- ]
152
- volumes:
153
- langchain-db-data:
154
- langchain-redis-data:
155
- langchain-clickhouse-data:
package/dist/cli/main.cjs DELETED
@@ -1,262 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
26
- Object.defineProperty(exports, "__esModule", { value: true });
27
- const child_process = __importStar(require("child_process"));
28
- const path = __importStar(require("path"));
29
- const util = __importStar(require("util"));
30
- const env_js_1 = require("../utils/env.cjs");
31
- const commander_1 = require("commander");
32
- const child_process_1 = require("child_process");
33
- const currentFileName = __filename;
34
- const program = new commander_1.Command();
35
- async function getDockerComposeCommand() {
36
- const exec = util.promisify(child_process.exec);
37
- try {
38
- await exec("docker compose --version");
39
- return ["docker", "compose"];
40
- }
41
- catch {
42
- try {
43
- await exec("docker-compose --version");
44
- return ["docker-compose"];
45
- }
46
- catch {
47
- throw new Error("Neither 'docker compose' nor 'docker-compose' commands are available. Please install the Docker server following the instructions for your operating system at https://docs.docker.com/engine/install/");
48
- }
49
- }
50
- }
51
- async function pprintServices(servicesStatus) {
52
- const services = [];
53
- for (const service of servicesStatus) {
54
- const serviceStatus = {
55
- Service: String(service["Service"]),
56
- Status: String(service["Status"]),
57
- };
58
- const publishers = service["Publishers"] || [];
59
- if (publishers) {
60
- serviceStatus["PublishedPorts"] = publishers
61
- .map((publisher) => String(publisher["PublishedPort"]))
62
- .join(", ");
63
- }
64
- services.push(serviceStatus);
65
- }
66
- const maxServiceLen = Math.max(...services.map((service) => service["Service"].length));
67
- const maxStateLen = Math.max(...services.map((service) => service["Status"].length));
68
- const serviceMessage = [
69
- "\n" +
70
- "Service".padEnd(maxServiceLen + 2) +
71
- "Status".padEnd(maxStateLen + 2) +
72
- "Published Ports",
73
- ];
74
- for (const service of services) {
75
- const serviceStr = service["Service"].padEnd(maxServiceLen + 2);
76
- const stateStr = service["Status"].padEnd(maxStateLen + 2);
77
- const portsStr = service["PublishedPorts"] || "";
78
- serviceMessage.push(serviceStr + stateStr + portsStr);
79
- }
80
- serviceMessage.push("\nTo connect, set the following environment variables" +
81
- " in your LangChain application:" +
82
- "\nLANGCHAIN_TRACING_V2=true" +
83
- `\nLANGCHAIN_ENDPOINT=http://localhost:80/api`);
84
- console.info(serviceMessage.join("\n"));
85
- }
86
- class SmithCommand {
87
- constructor({ dockerComposeCommand }) {
88
- Object.defineProperty(this, "dockerComposeCommand", {
89
- enumerable: true,
90
- configurable: true,
91
- writable: true,
92
- value: []
93
- });
94
- Object.defineProperty(this, "dockerComposeFile", {
95
- enumerable: true,
96
- configurable: true,
97
- writable: true,
98
- value: ""
99
- });
100
- this.dockerComposeCommand = dockerComposeCommand;
101
- this.dockerComposeFile = path.join(path.dirname(currentFileName), "docker-compose.yaml");
102
- }
103
- async executeCommand(command) {
104
- return new Promise((resolve, reject) => {
105
- const child = (0, child_process_1.spawn)(command[0], command.slice(1), { stdio: "inherit" });
106
- child.on("error", (error) => {
107
- console.error(`error: ${error.message}`);
108
- reject(error);
109
- });
110
- child.on("close", (code) => {
111
- if (code !== 0) {
112
- reject(new Error(`Process exited with code ${code}`));
113
- }
114
- else {
115
- resolve();
116
- }
117
- });
118
- });
119
- }
120
- static async create() {
121
- console.info("BY USING THIS SOFTWARE YOU AGREE TO THE TERMS OF SERVICE AT:");
122
- console.info("https://smith.langchain.com/terms-of-service.pdf");
123
- const dockerComposeCommand = await getDockerComposeCommand();
124
- return new SmithCommand({ dockerComposeCommand });
125
- }
126
- async pull({ stage = "prod", version = "latest" }) {
127
- if (stage === "dev") {
128
- (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "dev-");
129
- }
130
- else if (stage === "beta") {
131
- (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "rc-");
132
- }
133
- (0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_VERSION", version);
134
- const command = [
135
- ...this.dockerComposeCommand,
136
- "-f",
137
- this.dockerComposeFile,
138
- "pull",
139
- ];
140
- await this.executeCommand(command);
141
- }
142
- async startLocal() {
143
- const command = [
144
- ...this.dockerComposeCommand,
145
- "-f",
146
- this.dockerComposeFile,
147
- ];
148
- command.push("up", "--quiet-pull", "--wait");
149
- await this.executeCommand(command);
150
- console.info("LangSmith server is running at http://localhost:1984.\n" +
151
- "To view the app, navigate your browser to http://localhost:80" +
152
- "\n\nTo connect your LangChain application to the server" +
153
- " locally, set the following environment variable" +
154
- " when running your LangChain application.");
155
- console.info("\tLANGCHAIN_TRACING_V2=true");
156
- console.info("\tLANGCHAIN_ENDPOINT=http://localhost:80/api");
157
- }
158
- async stop() {
159
- const command = [
160
- ...this.dockerComposeCommand,
161
- "-f",
162
- this.dockerComposeFile,
163
- "down",
164
- ];
165
- await this.executeCommand(command);
166
- }
167
- async status() {
168
- const command = [
169
- ...this.dockerComposeCommand,
170
- "-f",
171
- this.dockerComposeFile,
172
- "ps",
173
- "--format",
174
- "json",
175
- ];
176
- const exec = util.promisify(child_process.exec);
177
- const result = await exec(command.join(" "));
178
- const servicesStatus = JSON.parse(result.stdout);
179
- if (servicesStatus) {
180
- console.info("The LangSmith server is currently running.");
181
- await pprintServices(servicesStatus);
182
- }
183
- else {
184
- console.info("The LangSmith server is not running.");
185
- }
186
- }
187
- async env() {
188
- const env = await (0, env_js_1.getRuntimeEnvironment)();
189
- const envVars = await (0, env_js_1.getLangChainEnvVars)();
190
- const envDict = {
191
- ...env,
192
- ...envVars,
193
- };
194
- // Pretty print
195
- const maxKeyLength = Math.max(...Object.keys(envDict).map((key) => key.length));
196
- console.info("LangChain Environment:");
197
- for (const [key, value] of Object.entries(envDict)) {
198
- console.info(`${key.padEnd(maxKeyLength)}: ${value}`);
199
- }
200
- }
201
- }
202
- const startCommand = new commander_1.Command("start")
203
- .description("Start the LangSmith server")
204
- .option("--stage <stage>", "Which version of LangSmith to run. Options: prod, dev, beta (default: prod)")
205
- .option("--openai-api-key <openaiApiKey>", "Your OpenAI API key. If not provided, the OpenAI API Key will be read" +
206
- " from the OPENAI_API_KEY environment variable. If neither are provided," +
207
- " some features of LangSmith will not be available.")
208
- .option("--langsmith-license-key <langsmithLicenseKey>", "The LangSmith license key to use for LangSmith. If not provided, the LangSmith" +
209
- " License Key will be read from the LANGSMITH_LICENSE_KEY environment variable." +
210
- " If neither are provided, the Langsmith application will not spin up.")
211
- .option("--version <version>", "The LangSmith version to use for LangSmith. Defaults to latest." +
212
- " We recommend pegging this to the latest static version available at" +
213
- " https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
214
- " if you are using Langsmith in production.")
215
- .action(async (args) => {
216
- const smith = await SmithCommand.create();
217
- if (args.openaiApiKey) {
218
- (0, env_js_1.setEnvironmentVariable)("OPENAI_API_KEY", args.openaiApiKey);
219
- }
220
- if (args.langsmithLicenseKey) {
221
- (0, env_js_1.setEnvironmentVariable)("LANGSMITH_LICENSE_KEY", args.langsmithLicenseKey);
222
- }
223
- await smith.pull({ stage: args.stage, version: args.version });
224
- await smith.startLocal();
225
- });
226
- const stopCommand = new commander_1.Command("stop")
227
- .description("Stop the LangSmith server")
228
- .action(async () => {
229
- const smith = await SmithCommand.create();
230
- await smith.stop();
231
- });
232
- const pullCommand = new commander_1.Command("pull")
233
- .description("Pull the latest version of the LangSmith server")
234
- .option("--stage <stage>", "Which version of LangSmith to pull. Options: prod, dev, beta (default: prod)")
235
- .option("--version <version>", "The LangSmith version to use for LangSmith. Defaults to latest." +
236
- " We recommend pegging this to the latest static version available at" +
237
- " https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
238
- " if you are using Langsmith in production.")
239
- .action(async (args) => {
240
- const smith = await SmithCommand.create();
241
- await smith.pull({ stage: args.stage, version: args.version });
242
- });
243
- const statusCommand = new commander_1.Command("status")
244
- .description("Get the status of the LangSmith server")
245
- .action(async () => {
246
- const smith = await SmithCommand.create();
247
- await smith.status();
248
- });
249
- const envCommand = new commander_1.Command("env")
250
- .description("Get relevant environment information for the LangSmith server")
251
- .action(async () => {
252
- const smith = await SmithCommand.create();
253
- await smith.env();
254
- });
255
- program
256
- .description("Manage the LangSmith server")
257
- .addCommand(startCommand)
258
- .addCommand(stopCommand)
259
- .addCommand(pullCommand)
260
- .addCommand(statusCommand)
261
- .addCommand(envCommand);
262
- program.parse(process.argv);
@@ -1 +0,0 @@
1
- export {};
package/dist/cli/main.js DELETED
@@ -1,236 +0,0 @@
1
- import * as child_process from "child_process";
2
- import * as path from "path";
3
- import * as util from "util";
4
- import { getLangChainEnvVars, getRuntimeEnvironment, setEnvironmentVariable, } from "../utils/env.js";
5
- import { Command } from "commander";
6
- import { spawn } from "child_process";
7
- const currentFileName = __filename;
8
- const program = new Command();
9
- async function getDockerComposeCommand() {
10
- const exec = util.promisify(child_process.exec);
11
- try {
12
- await exec("docker compose --version");
13
- return ["docker", "compose"];
14
- }
15
- catch {
16
- try {
17
- await exec("docker-compose --version");
18
- return ["docker-compose"];
19
- }
20
- catch {
21
- throw new Error("Neither 'docker compose' nor 'docker-compose' commands are available. Please install the Docker server following the instructions for your operating system at https://docs.docker.com/engine/install/");
22
- }
23
- }
24
- }
25
- async function pprintServices(servicesStatus) {
26
- const services = [];
27
- for (const service of servicesStatus) {
28
- const serviceStatus = {
29
- Service: String(service["Service"]),
30
- Status: String(service["Status"]),
31
- };
32
- const publishers = service["Publishers"] || [];
33
- if (publishers) {
34
- serviceStatus["PublishedPorts"] = publishers
35
- .map((publisher) => String(publisher["PublishedPort"]))
36
- .join(", ");
37
- }
38
- services.push(serviceStatus);
39
- }
40
- const maxServiceLen = Math.max(...services.map((service) => service["Service"].length));
41
- const maxStateLen = Math.max(...services.map((service) => service["Status"].length));
42
- const serviceMessage = [
43
- "\n" +
44
- "Service".padEnd(maxServiceLen + 2) +
45
- "Status".padEnd(maxStateLen + 2) +
46
- "Published Ports",
47
- ];
48
- for (const service of services) {
49
- const serviceStr = service["Service"].padEnd(maxServiceLen + 2);
50
- const stateStr = service["Status"].padEnd(maxStateLen + 2);
51
- const portsStr = service["PublishedPorts"] || "";
52
- serviceMessage.push(serviceStr + stateStr + portsStr);
53
- }
54
- serviceMessage.push("\nTo connect, set the following environment variables" +
55
- " in your LangChain application:" +
56
- "\nLANGCHAIN_TRACING_V2=true" +
57
- `\nLANGCHAIN_ENDPOINT=http://localhost:80/api`);
58
- console.info(serviceMessage.join("\n"));
59
- }
60
- class SmithCommand {
61
- constructor({ dockerComposeCommand }) {
62
- Object.defineProperty(this, "dockerComposeCommand", {
63
- enumerable: true,
64
- configurable: true,
65
- writable: true,
66
- value: []
67
- });
68
- Object.defineProperty(this, "dockerComposeFile", {
69
- enumerable: true,
70
- configurable: true,
71
- writable: true,
72
- value: ""
73
- });
74
- this.dockerComposeCommand = dockerComposeCommand;
75
- this.dockerComposeFile = path.join(path.dirname(currentFileName), "docker-compose.yaml");
76
- }
77
- async executeCommand(command) {
78
- return new Promise((resolve, reject) => {
79
- const child = spawn(command[0], command.slice(1), { stdio: "inherit" });
80
- child.on("error", (error) => {
81
- console.error(`error: ${error.message}`);
82
- reject(error);
83
- });
84
- child.on("close", (code) => {
85
- if (code !== 0) {
86
- reject(new Error(`Process exited with code ${code}`));
87
- }
88
- else {
89
- resolve();
90
- }
91
- });
92
- });
93
- }
94
- static async create() {
95
- console.info("BY USING THIS SOFTWARE YOU AGREE TO THE TERMS OF SERVICE AT:");
96
- console.info("https://smith.langchain.com/terms-of-service.pdf");
97
- const dockerComposeCommand = await getDockerComposeCommand();
98
- return new SmithCommand({ dockerComposeCommand });
99
- }
100
- async pull({ stage = "prod", version = "latest" }) {
101
- if (stage === "dev") {
102
- setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "dev-");
103
- }
104
- else if (stage === "beta") {
105
- setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
106
- }
107
- setEnvironmentVariable("_LANGSMITH_IMAGE_VERSION", version);
108
- const command = [
109
- ...this.dockerComposeCommand,
110
- "-f",
111
- this.dockerComposeFile,
112
- "pull",
113
- ];
114
- await this.executeCommand(command);
115
- }
116
- async startLocal() {
117
- const command = [
118
- ...this.dockerComposeCommand,
119
- "-f",
120
- this.dockerComposeFile,
121
- ];
122
- command.push("up", "--quiet-pull", "--wait");
123
- await this.executeCommand(command);
124
- console.info("LangSmith server is running at http://localhost:1984.\n" +
125
- "To view the app, navigate your browser to http://localhost:80" +
126
- "\n\nTo connect your LangChain application to the server" +
127
- " locally, set the following environment variable" +
128
- " when running your LangChain application.");
129
- console.info("\tLANGCHAIN_TRACING_V2=true");
130
- console.info("\tLANGCHAIN_ENDPOINT=http://localhost:80/api");
131
- }
132
- async stop() {
133
- const command = [
134
- ...this.dockerComposeCommand,
135
- "-f",
136
- this.dockerComposeFile,
137
- "down",
138
- ];
139
- await this.executeCommand(command);
140
- }
141
- async status() {
142
- const command = [
143
- ...this.dockerComposeCommand,
144
- "-f",
145
- this.dockerComposeFile,
146
- "ps",
147
- "--format",
148
- "json",
149
- ];
150
- const exec = util.promisify(child_process.exec);
151
- const result = await exec(command.join(" "));
152
- const servicesStatus = JSON.parse(result.stdout);
153
- if (servicesStatus) {
154
- console.info("The LangSmith server is currently running.");
155
- await pprintServices(servicesStatus);
156
- }
157
- else {
158
- console.info("The LangSmith server is not running.");
159
- }
160
- }
161
- async env() {
162
- const env = await getRuntimeEnvironment();
163
- const envVars = await getLangChainEnvVars();
164
- const envDict = {
165
- ...env,
166
- ...envVars,
167
- };
168
- // Pretty print
169
- const maxKeyLength = Math.max(...Object.keys(envDict).map((key) => key.length));
170
- console.info("LangChain Environment:");
171
- for (const [key, value] of Object.entries(envDict)) {
172
- console.info(`${key.padEnd(maxKeyLength)}: ${value}`);
173
- }
174
- }
175
- }
176
- const startCommand = new Command("start")
177
- .description("Start the LangSmith server")
178
- .option("--stage <stage>", "Which version of LangSmith to run. Options: prod, dev, beta (default: prod)")
179
- .option("--openai-api-key <openaiApiKey>", "Your OpenAI API key. If not provided, the OpenAI API Key will be read" +
180
- " from the OPENAI_API_KEY environment variable. If neither are provided," +
181
- " some features of LangSmith will not be available.")
182
- .option("--langsmith-license-key <langsmithLicenseKey>", "The LangSmith license key to use for LangSmith. If not provided, the LangSmith" +
183
- " License Key will be read from the LANGSMITH_LICENSE_KEY environment variable." +
184
- " If neither are provided, the Langsmith application will not spin up.")
185
- .option("--version <version>", "The LangSmith version to use for LangSmith. Defaults to latest." +
186
- " We recommend pegging this to the latest static version available at" +
187
- " https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
188
- " if you are using Langsmith in production.")
189
- .action(async (args) => {
190
- const smith = await SmithCommand.create();
191
- if (args.openaiApiKey) {
192
- setEnvironmentVariable("OPENAI_API_KEY", args.openaiApiKey);
193
- }
194
- if (args.langsmithLicenseKey) {
195
- setEnvironmentVariable("LANGSMITH_LICENSE_KEY", args.langsmithLicenseKey);
196
- }
197
- await smith.pull({ stage: args.stage, version: args.version });
198
- await smith.startLocal();
199
- });
200
- const stopCommand = new Command("stop")
201
- .description("Stop the LangSmith server")
202
- .action(async () => {
203
- const smith = await SmithCommand.create();
204
- await smith.stop();
205
- });
206
- const pullCommand = new Command("pull")
207
- .description("Pull the latest version of the LangSmith server")
208
- .option("--stage <stage>", "Which version of LangSmith to pull. Options: prod, dev, beta (default: prod)")
209
- .option("--version <version>", "The LangSmith version to use for LangSmith. Defaults to latest." +
210
- " We recommend pegging this to the latest static version available at" +
211
- " https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
212
- " if you are using Langsmith in production.")
213
- .action(async (args) => {
214
- const smith = await SmithCommand.create();
215
- await smith.pull({ stage: args.stage, version: args.version });
216
- });
217
- const statusCommand = new Command("status")
218
- .description("Get the status of the LangSmith server")
219
- .action(async () => {
220
- const smith = await SmithCommand.create();
221
- await smith.status();
222
- });
223
- const envCommand = new Command("env")
224
- .description("Get relevant environment information for the LangSmith server")
225
- .action(async () => {
226
- const smith = await SmithCommand.create();
227
- await smith.env();
228
- });
229
- program
230
- .description("Manage the LangSmith server")
231
- .addCommand(startCommand)
232
- .addCommand(stopCommand)
233
- .addCommand(pullCommand)
234
- .addCommand(statusCommand)
235
- .addCommand(envCommand);
236
- program.parse(process.argv);
package/dist/cli/main.ts DELETED
@@ -1,289 +0,0 @@
1
- import * as child_process from "child_process";
2
- import * as path from "path";
3
- import * as util from "util";
4
-
5
- import {
6
- getLangChainEnvVars,
7
- getRuntimeEnvironment,
8
- setEnvironmentVariable,
9
- } from "../utils/env.js";
10
-
11
- import { Command } from "commander";
12
- import { spawn } from "child_process";
13
-
14
- const currentFileName = __filename;
15
- const program = new Command();
16
-
17
- async function getDockerComposeCommand(): Promise<string[]> {
18
- const exec = util.promisify(child_process.exec);
19
- try {
20
- await exec("docker compose --version");
21
- return ["docker", "compose"];
22
- } catch {
23
- try {
24
- await exec("docker-compose --version");
25
- return ["docker-compose"];
26
- } catch {
27
- throw new Error(
28
- "Neither 'docker compose' nor 'docker-compose' commands are available. Please install the Docker server following the instructions for your operating system at https://docs.docker.com/engine/install/"
29
- );
30
- }
31
- }
32
- }
33
-
34
- async function pprintServices(servicesStatus: any[]) {
35
- const services = [];
36
- for (const service of servicesStatus) {
37
- const serviceStatus: Record<string, string> = {
38
- Service: String(service["Service"]),
39
- Status: String(service["Status"]),
40
- };
41
- const publishers = service["Publishers"] || [];
42
- if (publishers) {
43
- serviceStatus["PublishedPorts"] = publishers
44
- .map((publisher: any) => String(publisher["PublishedPort"]))
45
- .join(", ");
46
- }
47
- services.push(serviceStatus);
48
- }
49
-
50
- const maxServiceLen = Math.max(
51
- ...services.map((service) => service["Service"].length)
52
- );
53
- const maxStateLen = Math.max(
54
- ...services.map((service) => service["Status"].length)
55
- );
56
- const serviceMessage = [
57
- "\n" +
58
- "Service".padEnd(maxServiceLen + 2) +
59
- "Status".padEnd(maxStateLen + 2) +
60
- "Published Ports",
61
- ];
62
- for (const service of services) {
63
- const serviceStr = service["Service"].padEnd(maxServiceLen + 2);
64
- const stateStr = service["Status"].padEnd(maxStateLen + 2);
65
- const portsStr = service["PublishedPorts"] || "";
66
- serviceMessage.push(serviceStr + stateStr + portsStr);
67
- }
68
-
69
- serviceMessage.push(
70
- "\nTo connect, set the following environment variables" +
71
- " in your LangChain application:" +
72
- "\nLANGCHAIN_TRACING_V2=true" +
73
- `\nLANGCHAIN_ENDPOINT=http://localhost:80/api`
74
- );
75
- console.info(serviceMessage.join("\n"));
76
- }
77
-
78
- class SmithCommand {
79
- dockerComposeCommand: string[] = [];
80
- dockerComposeFile = "";
81
-
82
- constructor({ dockerComposeCommand }: { dockerComposeCommand: string[] }) {
83
- this.dockerComposeCommand = dockerComposeCommand;
84
- this.dockerComposeFile = path.join(
85
- path.dirname(currentFileName),
86
- "docker-compose.yaml"
87
- );
88
- }
89
-
90
- async executeCommand(command: string[]) {
91
- return new Promise<void>((resolve, reject) => {
92
- const child = spawn(command[0], command.slice(1), { stdio: "inherit" });
93
-
94
- child.on("error", (error) => {
95
- console.error(`error: ${error.message}`);
96
- reject(error);
97
- });
98
-
99
- child.on("close", (code) => {
100
- if (code !== 0) {
101
- reject(new Error(`Process exited with code ${code}`));
102
- } else {
103
- resolve();
104
- }
105
- });
106
- });
107
- }
108
-
109
- public static async create() {
110
- console.info(
111
- "BY USING THIS SOFTWARE YOU AGREE TO THE TERMS OF SERVICE AT:"
112
- );
113
- console.info("https://smith.langchain.com/terms-of-service.pdf");
114
- const dockerComposeCommand = await getDockerComposeCommand();
115
- return new SmithCommand({ dockerComposeCommand });
116
- }
117
-
118
- async pull({ stage = "prod", version = "latest" }) {
119
- if (stage === "dev") {
120
- setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "dev-");
121
- } else if (stage === "beta") {
122
- setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
123
- }
124
- setEnvironmentVariable("_LANGSMITH_IMAGE_VERSION", version);
125
-
126
- const command = [
127
- ...this.dockerComposeCommand,
128
- "-f",
129
- this.dockerComposeFile,
130
- "pull",
131
- ];
132
- await this.executeCommand(command);
133
- }
134
-
135
- async startLocal() {
136
- const command = [
137
- ...this.dockerComposeCommand,
138
- "-f",
139
- this.dockerComposeFile,
140
- ];
141
-
142
- command.push("up", "--quiet-pull", "--wait");
143
- await this.executeCommand(command);
144
-
145
- console.info(
146
- "LangSmith server is running at http://localhost:1984.\n" +
147
- "To view the app, navigate your browser to http://localhost:80" +
148
- "\n\nTo connect your LangChain application to the server" +
149
- " locally, set the following environment variable" +
150
- " when running your LangChain application."
151
- );
152
-
153
- console.info("\tLANGCHAIN_TRACING_V2=true");
154
- console.info("\tLANGCHAIN_ENDPOINT=http://localhost:80/api");
155
- }
156
-
157
- async stop() {
158
- const command = [
159
- ...this.dockerComposeCommand,
160
- "-f",
161
- this.dockerComposeFile,
162
- "down",
163
- ];
164
- await this.executeCommand(command);
165
- }
166
-
167
- async status() {
168
- const command = [
169
- ...this.dockerComposeCommand,
170
- "-f",
171
- this.dockerComposeFile,
172
- "ps",
173
- "--format",
174
- "json",
175
- ];
176
- const exec = util.promisify(child_process.exec);
177
- const result = await exec(command.join(" "));
178
- const servicesStatus = JSON.parse(result.stdout);
179
- if (servicesStatus) {
180
- console.info("The LangSmith server is currently running.");
181
- await pprintServices(servicesStatus);
182
- } else {
183
- console.info("The LangSmith server is not running.");
184
- }
185
- }
186
-
187
- async env() {
188
- const env = await getRuntimeEnvironment();
189
- const envVars = await getLangChainEnvVars();
190
- const envDict = {
191
- ...env,
192
- ...envVars,
193
- };
194
- // Pretty print
195
- const maxKeyLength = Math.max(
196
- ...Object.keys(envDict).map((key) => key.length)
197
- );
198
- console.info("LangChain Environment:");
199
- for (const [key, value] of Object.entries(envDict)) {
200
- console.info(`${key.padEnd(maxKeyLength)}: ${value}`);
201
- }
202
- }
203
- }
204
-
205
- const startCommand = new Command("start")
206
- .description("Start the LangSmith server")
207
- .option(
208
- "--stage <stage>",
209
- "Which version of LangSmith to run. Options: prod, dev, beta (default: prod)"
210
- )
211
- .option(
212
- "--openai-api-key <openaiApiKey>",
213
- "Your OpenAI API key. If not provided, the OpenAI API Key will be read" +
214
- " from the OPENAI_API_KEY environment variable. If neither are provided," +
215
- " some features of LangSmith will not be available."
216
- )
217
- .option(
218
- "--langsmith-license-key <langsmithLicenseKey>",
219
- "The LangSmith license key to use for LangSmith. If not provided, the LangSmith" +
220
- " License Key will be read from the LANGSMITH_LICENSE_KEY environment variable." +
221
- " If neither are provided, the Langsmith application will not spin up."
222
- )
223
- .option(
224
- "--version <version>",
225
- "The LangSmith version to use for LangSmith. Defaults to latest." +
226
- " We recommend pegging this to the latest static version available at" +
227
- " https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
228
- " if you are using Langsmith in production."
229
- )
230
- .action(async (args) => {
231
- const smith = await SmithCommand.create();
232
- if (args.openaiApiKey) {
233
- setEnvironmentVariable("OPENAI_API_KEY", args.openaiApiKey);
234
- }
235
- if (args.langsmithLicenseKey) {
236
- setEnvironmentVariable("LANGSMITH_LICENSE_KEY", args.langsmithLicenseKey);
237
- }
238
- await smith.pull({ stage: args.stage, version: args.version });
239
- await smith.startLocal();
240
- });
241
-
242
- const stopCommand = new Command("stop")
243
- .description("Stop the LangSmith server")
244
- .action(async () => {
245
- const smith = await SmithCommand.create();
246
- await smith.stop();
247
- });
248
-
249
- const pullCommand = new Command("pull")
250
- .description("Pull the latest version of the LangSmith server")
251
- .option(
252
- "--stage <stage>",
253
- "Which version of LangSmith to pull. Options: prod, dev, beta (default: prod)"
254
- )
255
- .option(
256
- "--version <version>",
257
- "The LangSmith version to use for LangSmith. Defaults to latest." +
258
- " We recommend pegging this to the latest static version available at" +
259
- " https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
260
- " if you are using Langsmith in production."
261
- )
262
- .action(async (args) => {
263
- const smith = await SmithCommand.create();
264
- await smith.pull({ stage: args.stage, version: args.version });
265
- });
266
-
267
- const statusCommand = new Command("status")
268
- .description("Get the status of the LangSmith server")
269
- .action(async () => {
270
- const smith = await SmithCommand.create();
271
- await smith.status();
272
- });
273
-
274
- const envCommand = new Command("env")
275
- .description("Get relevant environment information for the LangSmith server")
276
- .action(async () => {
277
- const smith = await SmithCommand.create();
278
- await smith.env();
279
- });
280
-
281
- program
282
- .description("Manage the LangSmith server")
283
- .addCommand(startCommand)
284
- .addCommand(stopCommand)
285
- .addCommand(pullCommand)
286
- .addCommand(statusCommand)
287
- .addCommand(envCommand);
288
-
289
- program.parse(process.argv);
@@ -1,10 +0,0 @@
1
- <clickhouse>
2
- <users>
3
- <default>
4
- <access_management>1</access_management>
5
- <named_collection_control>1</named_collection_control>
6
- <show_named_collections>1</show_named_collections>
7
- <show_named_collections_secrets>1</show_named_collections_secrets>
8
- </default>
9
- </users>
10
- </clickhouse>