langsmith 0.0.3 → 0.0.5
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 +10 -10
- package/dist/cli/docker-compose.dev.yaml +7 -0
- package/dist/cli/docker-compose.yaml +3 -3
- package/dist/cli/main.cjs +54 -24
- package/dist/cli/main.js +54 -24
- package/dist/cli/main.ts +54 -25
- package/dist/client.cjs +1 -1
- package/dist/client.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LangSmith Client SDK
|
|
2
2
|
|
|
3
|
-
This package contains the TypeScript client for interacting with the [LangSmith platform](https://
|
|
3
|
+
This package contains the TypeScript client for interacting with the [LangSmith platform](https://smith.langchain.com/).
|
|
4
4
|
|
|
5
5
|
To install:
|
|
6
6
|
|
|
@@ -14,7 +14,7 @@ LangSmith helps you and your team develop and evaluate language models and intel
|
|
|
14
14
|
|
|
15
15
|
A typical workflow looks like:
|
|
16
16
|
|
|
17
|
-
1. Set up an account with LangSmith or host your [local server](https://docs.langchain.
|
|
17
|
+
1. Set up an account with LangSmith or host your [local server](https://docs.smith.langchain.com/docs/additional-resources/local_installation).
|
|
18
18
|
2. Log traces.
|
|
19
19
|
3. Debug, Create Datasets, and Evaluate Runs.
|
|
20
20
|
|
|
@@ -22,9 +22,9 @@ We'll walk through these steps in more detail below.
|
|
|
22
22
|
|
|
23
23
|
## 1. Connect to LangSmith
|
|
24
24
|
|
|
25
|
-
Sign up for [LangSmith](https://
|
|
25
|
+
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.
|
|
26
26
|
|
|
27
|
-
Then, create a unique API key on the [Settings Page](https://
|
|
27
|
+
Then, create a unique API key on the [Settings Page](https://smith.langchain.com/settings), which is found in the menu at the top right corner of the page.
|
|
28
28
|
|
|
29
29
|
Note: Save the API Key in a secure location. It will not be shown again.
|
|
30
30
|
|
|
@@ -46,8 +46,8 @@ Tracing can be activated by setting the following environment variables or by ma
|
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
48
|
process.env["LANGCHAIN_TRACING_V2"] = "true";
|
|
49
|
-
process.env["LANGCHAIN_ENDPOINT"] = "https://api.langchain.
|
|
50
|
-
process.env["LANGCHAIN_API_KEY"] = "<YOUR-
|
|
49
|
+
process.env["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"; // or your own server
|
|
50
|
+
process.env["LANGCHAIN_API_KEY"] = "<YOUR-LANGSMITH-API-KEY>";
|
|
51
51
|
// process.env["LANGCHAIN_PROJECT"] = "My Project Name"; // Optional: "default" is used if not set
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -78,8 +78,8 @@ or by directly specifying the connection information in the RunTree.
|
|
|
78
78
|
1. **Copy the environment variables from the Settings Page and add them to your application.**
|
|
79
79
|
|
|
80
80
|
```typescript
|
|
81
|
-
process.env["LANGCHAIN_ENDPOINT"] = "https://api.langchain.
|
|
82
|
-
process.env["LANGCHAIN_API_KEY"] = "<YOUR-
|
|
81
|
+
process.env["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"; // or your own server
|
|
82
|
+
process.env["LANGCHAIN_API_KEY"] = "<YOUR-LANGSMITH-API-KEY>";
|
|
83
83
|
// process.env["LANGCHAIN_PROJECT"] = "My Project Name"; // Optional: "default" is used if not set
|
|
84
84
|
```
|
|
85
85
|
|
|
@@ -177,7 +177,7 @@ await parentRun.postRun({
|
|
|
177
177
|
|
|
178
178
|
Once your runs are stored in LangSmith, you can convert them into a dataset.
|
|
179
179
|
For this example, we will do so using the Client, but you can also do this using
|
|
180
|
-
the web interface, as explained in the [LangSmith docs](https://docs.langchain.
|
|
180
|
+
the web interface, as explained in the [LangSmith docs](https://docs.smith.langchain.com/docs/).
|
|
181
181
|
|
|
182
182
|
```typescript
|
|
183
183
|
import { Client } from "langsmith/client";
|
|
@@ -259,4 +259,4 @@ for (const run of runs) {
|
|
|
259
259
|
|
|
260
260
|
## Additional Documentation
|
|
261
261
|
|
|
262
|
-
To learn more about the LangSmith platform, check out the [docs](https://docs.langchain.
|
|
262
|
+
To learn more about the LangSmith platform, check out the [docs](https://docs.smith.langchain.com/docs/).
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
version: "3"
|
|
2
2
|
services:
|
|
3
3
|
langchain-playground:
|
|
4
|
-
image: langchain/${
|
|
4
|
+
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-playground:latest
|
|
5
5
|
langchain-frontend:
|
|
6
|
-
image: langchain/${
|
|
6
|
+
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-frontend:latest
|
|
7
7
|
ports:
|
|
8
8
|
- 80:80
|
|
9
9
|
environment:
|
|
@@ -14,7 +14,7 @@ services:
|
|
|
14
14
|
volumes:
|
|
15
15
|
- ./conf/nginx.conf:/etc/nginx/default.conf:ro
|
|
16
16
|
langchain-backend:
|
|
17
|
-
image: langchain/${
|
|
17
|
+
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:latest
|
|
18
18
|
environment:
|
|
19
19
|
- PORT=1984
|
|
20
20
|
- LANGCHAIN_ENV=local_docker
|
package/dist/cli/main.cjs
CHANGED
|
@@ -30,11 +30,12 @@ const util = __importStar(require("util"));
|
|
|
30
30
|
const commander_1 = require("commander");
|
|
31
31
|
const child_process = __importStar(require("child_process"));
|
|
32
32
|
const env_js_1 = require("../utils/env.cjs");
|
|
33
|
+
const child_process_1 = require("child_process");
|
|
33
34
|
const currentFileName = __filename;
|
|
34
35
|
const currentDirName = __dirname;
|
|
35
|
-
const exec = util.promisify(child_process.exec);
|
|
36
36
|
const program = new commander_1.Command();
|
|
37
37
|
async function getDockerComposeCommand() {
|
|
38
|
+
const exec = util.promisify(child_process.exec);
|
|
38
39
|
try {
|
|
39
40
|
await exec("docker compose --version");
|
|
40
41
|
return ["docker", "compose"];
|
|
@@ -128,7 +129,7 @@ version: '2'
|
|
|
128
129
|
fs.writeFileSync(configPath, ngrokConfig);
|
|
129
130
|
return configPath;
|
|
130
131
|
}
|
|
131
|
-
class
|
|
132
|
+
class SmithCommand {
|
|
132
133
|
constructor({ dockerComposeCommand }) {
|
|
133
134
|
Object.defineProperty(this, "dockerComposeCommand", {
|
|
134
135
|
enumerable: true,
|
|
@@ -142,6 +143,12 @@ class PlusCommand {
|
|
|
142
143
|
writable: true,
|
|
143
144
|
value: ""
|
|
144
145
|
});
|
|
146
|
+
Object.defineProperty(this, "dockerComposeDevFile", {
|
|
147
|
+
enumerable: true,
|
|
148
|
+
configurable: true,
|
|
149
|
+
writable: true,
|
|
150
|
+
value: ""
|
|
151
|
+
});
|
|
145
152
|
Object.defineProperty(this, "ngrokPath", {
|
|
146
153
|
enumerable: true,
|
|
147
154
|
configurable: true,
|
|
@@ -150,30 +157,48 @@ class PlusCommand {
|
|
|
150
157
|
});
|
|
151
158
|
this.dockerComposeCommand = dockerComposeCommand;
|
|
152
159
|
this.dockerComposeFile = path.join(path.dirname(currentFileName), "docker-compose.yaml");
|
|
160
|
+
this.dockerComposeDevFile = path.join(path.dirname(currentFileName), "docker-compose.dev.yaml");
|
|
153
161
|
this.ngrokPath = path.join(path.dirname(currentFileName), "docker-compose.ngrok.yaml");
|
|
154
162
|
}
|
|
163
|
+
async executeCommand(command) {
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
const child = (0, child_process_1.spawn)(command[0], command.slice(1), { stdio: "inherit" });
|
|
166
|
+
child.on("error", (error) => {
|
|
167
|
+
console.error(`error: ${error.message}`);
|
|
168
|
+
reject(error);
|
|
169
|
+
});
|
|
170
|
+
child.on("close", (code) => {
|
|
171
|
+
if (code !== 0) {
|
|
172
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
resolve();
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
}
|
|
155
180
|
static async create() {
|
|
156
181
|
const dockerComposeCommand = await getDockerComposeCommand();
|
|
157
|
-
return new
|
|
182
|
+
return new SmithCommand({ dockerComposeCommand });
|
|
158
183
|
}
|
|
159
184
|
async start(args) {
|
|
160
185
|
if (args.dev) {
|
|
161
|
-
(0, env_js_1.setEnvironmentVariable)("
|
|
186
|
+
(0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "rc-");
|
|
162
187
|
}
|
|
163
188
|
if (args.openaiApiKey) {
|
|
164
189
|
(0, env_js_1.setEnvironmentVariable)("OPENAI_API_KEY", args.openaiApiKey);
|
|
165
190
|
}
|
|
166
191
|
await this.pull(args);
|
|
167
192
|
if (args.expose) {
|
|
168
|
-
await this.startAndExpose(args.ngrokAuthtoken);
|
|
193
|
+
await this.startAndExpose(args.ngrokAuthtoken, args.dev);
|
|
169
194
|
}
|
|
170
195
|
else {
|
|
171
|
-
await this.startLocal();
|
|
196
|
+
await this.startLocal(args.dev);
|
|
172
197
|
}
|
|
173
198
|
}
|
|
174
199
|
async pull(args) {
|
|
175
200
|
if (args.dev) {
|
|
176
|
-
(0, env_js_1.setEnvironmentVariable)("
|
|
201
|
+
(0, env_js_1.setEnvironmentVariable)("_LANGSMITH_IMAGE_PREFIX", "rc-");
|
|
177
202
|
}
|
|
178
203
|
const command = [
|
|
179
204
|
...this.dockerComposeCommand,
|
|
@@ -181,22 +206,23 @@ class PlusCommand {
|
|
|
181
206
|
this.dockerComposeFile,
|
|
182
207
|
"pull",
|
|
183
208
|
];
|
|
184
|
-
await
|
|
209
|
+
await this.executeCommand(command);
|
|
185
210
|
}
|
|
186
|
-
async startLocal() {
|
|
211
|
+
async startLocal(dev) {
|
|
187
212
|
const command = [
|
|
188
213
|
...this.dockerComposeCommand,
|
|
189
214
|
"-f",
|
|
190
215
|
this.dockerComposeFile,
|
|
191
|
-
"up",
|
|
192
|
-
"--quiet-pull",
|
|
193
|
-
"--wait",
|
|
194
216
|
];
|
|
195
|
-
|
|
217
|
+
if (dev) {
|
|
218
|
+
command.push("-f", this.dockerComposeDevFile);
|
|
219
|
+
}
|
|
220
|
+
command.push("up", "--quiet-pull", "--wait");
|
|
221
|
+
await this.executeCommand(command);
|
|
196
222
|
console.info("LangSmith server is running at http://localhost:1984. To connect locally, set the following environment variable when running your LangChain application.");
|
|
197
223
|
console.info("\tLANGCHAIN_TRACING_V2=true");
|
|
198
224
|
}
|
|
199
|
-
async startAndExpose(ngrokAuthToken) {
|
|
225
|
+
async startAndExpose(ngrokAuthToken, dev) {
|
|
200
226
|
const configPath = await createNgrokConfig(ngrokAuthToken);
|
|
201
227
|
const command = [
|
|
202
228
|
...this.dockerComposeCommand,
|
|
@@ -204,11 +230,12 @@ class PlusCommand {
|
|
|
204
230
|
this.dockerComposeFile,
|
|
205
231
|
"-f",
|
|
206
232
|
this.ngrokPath,
|
|
207
|
-
"up",
|
|
208
|
-
"--quiet-pull",
|
|
209
|
-
"--wait",
|
|
210
233
|
];
|
|
211
|
-
|
|
234
|
+
if (dev) {
|
|
235
|
+
command.push("-f", this.dockerComposeDevFile);
|
|
236
|
+
}
|
|
237
|
+
command.push("up", "--quiet-pull", "--wait");
|
|
238
|
+
await this.executeCommand(command);
|
|
212
239
|
console.info("ngrok is running. You can view the dashboard at http://0.0.0.0:4040");
|
|
213
240
|
const ngrokUrl = await getNgrokUrl();
|
|
214
241
|
console.info("LangSmith server is running at http://localhost:1984. To connect remotely, set the following environment variable when running your LangChain application.");
|
|
@@ -225,7 +252,7 @@ class PlusCommand {
|
|
|
225
252
|
this.ngrokPath,
|
|
226
253
|
"down",
|
|
227
254
|
];
|
|
228
|
-
await
|
|
255
|
+
await this.executeCommand(command);
|
|
229
256
|
}
|
|
230
257
|
async status() {
|
|
231
258
|
const command = [
|
|
@@ -236,6 +263,7 @@ class PlusCommand {
|
|
|
236
263
|
"--format",
|
|
237
264
|
"json",
|
|
238
265
|
];
|
|
266
|
+
const exec = util.promisify(child_process.exec);
|
|
239
267
|
const result = await exec(command.join(" "));
|
|
240
268
|
const servicesStatus = JSON.parse(result.stdout);
|
|
241
269
|
if (servicesStatus) {
|
|
@@ -252,21 +280,23 @@ const startCommand = new commander_1.Command("start")
|
|
|
252
280
|
.option("--expose", "Expose the server to the internet via ngrok (requires ngrok to be installed)")
|
|
253
281
|
.option("--ngrok-authtoken <ngrokAuthtoken>", "Your ngrok auth token. If this is set, --expose is implied.")
|
|
254
282
|
.option("--dev", "Run the development version of the LangSmith server")
|
|
255
|
-
.option("--openai-api-key <openaiApiKey>", "Your OpenAI API key. If
|
|
256
|
-
.
|
|
283
|
+
.option("--openai-api-key <openaiApiKey>", "Your OpenAI API key. If not provided, the OpenAI API Key will be read" +
|
|
284
|
+
" from the OPENAI_API_KEY environment variable. If neither are provided," +
|
|
285
|
+
" some features of LangSmith will not be available.")
|
|
286
|
+
.action(async (args) => (await SmithCommand.create()).start(args));
|
|
257
287
|
const stopCommand = new commander_1.Command("stop")
|
|
258
288
|
.command("stop")
|
|
259
289
|
.description("Stop the LangSmith server")
|
|
260
|
-
.action(async () => (await
|
|
290
|
+
.action(async () => (await SmithCommand.create()).stop());
|
|
261
291
|
const pullCommand = new commander_1.Command("pull")
|
|
262
292
|
.command("pull")
|
|
263
293
|
.description("Pull the latest version of the LangSmith server")
|
|
264
294
|
.option("--dev", "Pull the development version of the LangSmith server")
|
|
265
|
-
.action(async (args) => (await
|
|
295
|
+
.action(async (args) => (await SmithCommand.create()).pull(args));
|
|
266
296
|
const statusCommand = new commander_1.Command("status")
|
|
267
297
|
.command("status")
|
|
268
298
|
.description("Get the status of the LangSmith server")
|
|
269
|
-
.action(async () => (await
|
|
299
|
+
.action(async () => (await SmithCommand.create()).status());
|
|
270
300
|
program
|
|
271
301
|
.description("Manage the LangSmith server")
|
|
272
302
|
.addCommand(startCommand)
|
package/dist/cli/main.js
CHANGED
|
@@ -4,11 +4,12 @@ import * as util from "util";
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import * as child_process from "child_process";
|
|
6
6
|
import { setEnvironmentVariable } from "../utils/env.js";
|
|
7
|
+
import { spawn } from "child_process";
|
|
7
8
|
const currentFileName = __filename;
|
|
8
9
|
const currentDirName = __dirname;
|
|
9
|
-
const exec = util.promisify(child_process.exec);
|
|
10
10
|
const program = new Command();
|
|
11
11
|
async function getDockerComposeCommand() {
|
|
12
|
+
const exec = util.promisify(child_process.exec);
|
|
12
13
|
try {
|
|
13
14
|
await exec("docker compose --version");
|
|
14
15
|
return ["docker", "compose"];
|
|
@@ -102,7 +103,7 @@ version: '2'
|
|
|
102
103
|
fs.writeFileSync(configPath, ngrokConfig);
|
|
103
104
|
return configPath;
|
|
104
105
|
}
|
|
105
|
-
class
|
|
106
|
+
class SmithCommand {
|
|
106
107
|
constructor({ dockerComposeCommand }) {
|
|
107
108
|
Object.defineProperty(this, "dockerComposeCommand", {
|
|
108
109
|
enumerable: true,
|
|
@@ -116,6 +117,12 @@ class PlusCommand {
|
|
|
116
117
|
writable: true,
|
|
117
118
|
value: ""
|
|
118
119
|
});
|
|
120
|
+
Object.defineProperty(this, "dockerComposeDevFile", {
|
|
121
|
+
enumerable: true,
|
|
122
|
+
configurable: true,
|
|
123
|
+
writable: true,
|
|
124
|
+
value: ""
|
|
125
|
+
});
|
|
119
126
|
Object.defineProperty(this, "ngrokPath", {
|
|
120
127
|
enumerable: true,
|
|
121
128
|
configurable: true,
|
|
@@ -124,30 +131,48 @@ class PlusCommand {
|
|
|
124
131
|
});
|
|
125
132
|
this.dockerComposeCommand = dockerComposeCommand;
|
|
126
133
|
this.dockerComposeFile = path.join(path.dirname(currentFileName), "docker-compose.yaml");
|
|
134
|
+
this.dockerComposeDevFile = path.join(path.dirname(currentFileName), "docker-compose.dev.yaml");
|
|
127
135
|
this.ngrokPath = path.join(path.dirname(currentFileName), "docker-compose.ngrok.yaml");
|
|
128
136
|
}
|
|
137
|
+
async executeCommand(command) {
|
|
138
|
+
return new Promise((resolve, reject) => {
|
|
139
|
+
const child = spawn(command[0], command.slice(1), { stdio: "inherit" });
|
|
140
|
+
child.on("error", (error) => {
|
|
141
|
+
console.error(`error: ${error.message}`);
|
|
142
|
+
reject(error);
|
|
143
|
+
});
|
|
144
|
+
child.on("close", (code) => {
|
|
145
|
+
if (code !== 0) {
|
|
146
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
resolve();
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
}
|
|
129
154
|
static async create() {
|
|
130
155
|
const dockerComposeCommand = await getDockerComposeCommand();
|
|
131
|
-
return new
|
|
156
|
+
return new SmithCommand({ dockerComposeCommand });
|
|
132
157
|
}
|
|
133
158
|
async start(args) {
|
|
134
159
|
if (args.dev) {
|
|
135
|
-
setEnvironmentVariable("
|
|
160
|
+
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
|
|
136
161
|
}
|
|
137
162
|
if (args.openaiApiKey) {
|
|
138
163
|
setEnvironmentVariable("OPENAI_API_KEY", args.openaiApiKey);
|
|
139
164
|
}
|
|
140
165
|
await this.pull(args);
|
|
141
166
|
if (args.expose) {
|
|
142
|
-
await this.startAndExpose(args.ngrokAuthtoken);
|
|
167
|
+
await this.startAndExpose(args.ngrokAuthtoken, args.dev);
|
|
143
168
|
}
|
|
144
169
|
else {
|
|
145
|
-
await this.startLocal();
|
|
170
|
+
await this.startLocal(args.dev);
|
|
146
171
|
}
|
|
147
172
|
}
|
|
148
173
|
async pull(args) {
|
|
149
174
|
if (args.dev) {
|
|
150
|
-
setEnvironmentVariable("
|
|
175
|
+
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
|
|
151
176
|
}
|
|
152
177
|
const command = [
|
|
153
178
|
...this.dockerComposeCommand,
|
|
@@ -155,22 +180,23 @@ class PlusCommand {
|
|
|
155
180
|
this.dockerComposeFile,
|
|
156
181
|
"pull",
|
|
157
182
|
];
|
|
158
|
-
await
|
|
183
|
+
await this.executeCommand(command);
|
|
159
184
|
}
|
|
160
|
-
async startLocal() {
|
|
185
|
+
async startLocal(dev) {
|
|
161
186
|
const command = [
|
|
162
187
|
...this.dockerComposeCommand,
|
|
163
188
|
"-f",
|
|
164
189
|
this.dockerComposeFile,
|
|
165
|
-
"up",
|
|
166
|
-
"--quiet-pull",
|
|
167
|
-
"--wait",
|
|
168
190
|
];
|
|
169
|
-
|
|
191
|
+
if (dev) {
|
|
192
|
+
command.push("-f", this.dockerComposeDevFile);
|
|
193
|
+
}
|
|
194
|
+
command.push("up", "--quiet-pull", "--wait");
|
|
195
|
+
await this.executeCommand(command);
|
|
170
196
|
console.info("LangSmith server is running at http://localhost:1984. To connect locally, set the following environment variable when running your LangChain application.");
|
|
171
197
|
console.info("\tLANGCHAIN_TRACING_V2=true");
|
|
172
198
|
}
|
|
173
|
-
async startAndExpose(ngrokAuthToken) {
|
|
199
|
+
async startAndExpose(ngrokAuthToken, dev) {
|
|
174
200
|
const configPath = await createNgrokConfig(ngrokAuthToken);
|
|
175
201
|
const command = [
|
|
176
202
|
...this.dockerComposeCommand,
|
|
@@ -178,11 +204,12 @@ class PlusCommand {
|
|
|
178
204
|
this.dockerComposeFile,
|
|
179
205
|
"-f",
|
|
180
206
|
this.ngrokPath,
|
|
181
|
-
"up",
|
|
182
|
-
"--quiet-pull",
|
|
183
|
-
"--wait",
|
|
184
207
|
];
|
|
185
|
-
|
|
208
|
+
if (dev) {
|
|
209
|
+
command.push("-f", this.dockerComposeDevFile);
|
|
210
|
+
}
|
|
211
|
+
command.push("up", "--quiet-pull", "--wait");
|
|
212
|
+
await this.executeCommand(command);
|
|
186
213
|
console.info("ngrok is running. You can view the dashboard at http://0.0.0.0:4040");
|
|
187
214
|
const ngrokUrl = await getNgrokUrl();
|
|
188
215
|
console.info("LangSmith server is running at http://localhost:1984. To connect remotely, set the following environment variable when running your LangChain application.");
|
|
@@ -199,7 +226,7 @@ class PlusCommand {
|
|
|
199
226
|
this.ngrokPath,
|
|
200
227
|
"down",
|
|
201
228
|
];
|
|
202
|
-
await
|
|
229
|
+
await this.executeCommand(command);
|
|
203
230
|
}
|
|
204
231
|
async status() {
|
|
205
232
|
const command = [
|
|
@@ -210,6 +237,7 @@ class PlusCommand {
|
|
|
210
237
|
"--format",
|
|
211
238
|
"json",
|
|
212
239
|
];
|
|
240
|
+
const exec = util.promisify(child_process.exec);
|
|
213
241
|
const result = await exec(command.join(" "));
|
|
214
242
|
const servicesStatus = JSON.parse(result.stdout);
|
|
215
243
|
if (servicesStatus) {
|
|
@@ -226,21 +254,23 @@ const startCommand = new Command("start")
|
|
|
226
254
|
.option("--expose", "Expose the server to the internet via ngrok (requires ngrok to be installed)")
|
|
227
255
|
.option("--ngrok-authtoken <ngrokAuthtoken>", "Your ngrok auth token. If this is set, --expose is implied.")
|
|
228
256
|
.option("--dev", "Run the development version of the LangSmith server")
|
|
229
|
-
.option("--openai-api-key <openaiApiKey>", "Your OpenAI API key. If
|
|
230
|
-
.
|
|
257
|
+
.option("--openai-api-key <openaiApiKey>", "Your OpenAI API key. If not provided, the OpenAI API Key will be read" +
|
|
258
|
+
" from the OPENAI_API_KEY environment variable. If neither are provided," +
|
|
259
|
+
" some features of LangSmith will not be available.")
|
|
260
|
+
.action(async (args) => (await SmithCommand.create()).start(args));
|
|
231
261
|
const stopCommand = new Command("stop")
|
|
232
262
|
.command("stop")
|
|
233
263
|
.description("Stop the LangSmith server")
|
|
234
|
-
.action(async () => (await
|
|
264
|
+
.action(async () => (await SmithCommand.create()).stop());
|
|
235
265
|
const pullCommand = new Command("pull")
|
|
236
266
|
.command("pull")
|
|
237
267
|
.description("Pull the latest version of the LangSmith server")
|
|
238
268
|
.option("--dev", "Pull the development version of the LangSmith server")
|
|
239
|
-
.action(async (args) => (await
|
|
269
|
+
.action(async (args) => (await SmithCommand.create()).pull(args));
|
|
240
270
|
const statusCommand = new Command("status")
|
|
241
271
|
.command("status")
|
|
242
272
|
.description("Get the status of the LangSmith server")
|
|
243
|
-
.action(async () => (await
|
|
273
|
+
.action(async () => (await SmithCommand.create()).status());
|
|
244
274
|
program
|
|
245
275
|
.description("Manage the LangSmith server")
|
|
246
276
|
.addCommand(startCommand)
|
package/dist/cli/main.ts
CHANGED
|
@@ -4,15 +4,15 @@ import * as util from "util";
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import * as child_process from "child_process";
|
|
6
6
|
import { setEnvironmentVariable } from "../utils/env.js";
|
|
7
|
+
import { spawn } from "child_process";
|
|
7
8
|
|
|
8
9
|
const currentFileName = __filename;
|
|
9
10
|
const currentDirName = __dirname;
|
|
10
11
|
|
|
11
|
-
const exec = util.promisify(child_process.exec);
|
|
12
|
-
|
|
13
12
|
const program = new Command();
|
|
14
13
|
|
|
15
14
|
async function getDockerComposeCommand(): Promise<string[]> {
|
|
15
|
+
const exec = util.promisify(child_process.exec);
|
|
16
16
|
try {
|
|
17
17
|
await exec("docker compose --version");
|
|
18
18
|
return ["docker", "compose"];
|
|
@@ -122,9 +122,10 @@ version: '2'
|
|
|
122
122
|
return configPath;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
class
|
|
125
|
+
class SmithCommand {
|
|
126
126
|
dockerComposeCommand: string[] = [];
|
|
127
127
|
dockerComposeFile = "";
|
|
128
|
+
dockerComposeDevFile = "";
|
|
128
129
|
ngrokPath = "";
|
|
129
130
|
|
|
130
131
|
constructor({ dockerComposeCommand }: { dockerComposeCommand: string[] }) {
|
|
@@ -133,35 +134,58 @@ class PlusCommand {
|
|
|
133
134
|
path.dirname(currentFileName),
|
|
134
135
|
"docker-compose.yaml"
|
|
135
136
|
);
|
|
137
|
+
this.dockerComposeDevFile = path.join(
|
|
138
|
+
path.dirname(currentFileName),
|
|
139
|
+
"docker-compose.dev.yaml"
|
|
140
|
+
);
|
|
136
141
|
this.ngrokPath = path.join(
|
|
137
142
|
path.dirname(currentFileName),
|
|
138
143
|
"docker-compose.ngrok.yaml"
|
|
139
144
|
);
|
|
140
145
|
}
|
|
141
146
|
|
|
147
|
+
async executeCommand(command: string[]) {
|
|
148
|
+
return new Promise<void>((resolve, reject) => {
|
|
149
|
+
const child = spawn(command[0], command.slice(1), { stdio: "inherit" });
|
|
150
|
+
|
|
151
|
+
child.on("error", (error) => {
|
|
152
|
+
console.error(`error: ${error.message}`);
|
|
153
|
+
reject(error);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
child.on("close", (code) => {
|
|
157
|
+
if (code !== 0) {
|
|
158
|
+
reject(new Error(`Process exited with code ${code}`));
|
|
159
|
+
} else {
|
|
160
|
+
resolve();
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
142
166
|
public static async create() {
|
|
143
167
|
const dockerComposeCommand = await getDockerComposeCommand();
|
|
144
|
-
return new
|
|
168
|
+
return new SmithCommand({ dockerComposeCommand });
|
|
145
169
|
}
|
|
146
170
|
|
|
147
171
|
async start(args: any) {
|
|
148
172
|
if (args.dev) {
|
|
149
|
-
setEnvironmentVariable("
|
|
173
|
+
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
|
|
150
174
|
}
|
|
151
175
|
if (args.openaiApiKey) {
|
|
152
176
|
setEnvironmentVariable("OPENAI_API_KEY", args.openaiApiKey);
|
|
153
177
|
}
|
|
154
178
|
await this.pull(args);
|
|
155
179
|
if (args.expose) {
|
|
156
|
-
await this.startAndExpose(args.ngrokAuthtoken);
|
|
180
|
+
await this.startAndExpose(args.ngrokAuthtoken, args.dev);
|
|
157
181
|
} else {
|
|
158
|
-
await this.startLocal();
|
|
182
|
+
await this.startLocal(args.dev);
|
|
159
183
|
}
|
|
160
184
|
}
|
|
161
185
|
|
|
162
186
|
async pull(args: any) {
|
|
163
187
|
if (args.dev) {
|
|
164
|
-
setEnvironmentVariable("
|
|
188
|
+
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
|
|
165
189
|
}
|
|
166
190
|
|
|
167
191
|
const command = [
|
|
@@ -170,26 +194,27 @@ class PlusCommand {
|
|
|
170
194
|
this.dockerComposeFile,
|
|
171
195
|
"pull",
|
|
172
196
|
];
|
|
173
|
-
await
|
|
197
|
+
await this.executeCommand(command);
|
|
174
198
|
}
|
|
175
199
|
|
|
176
|
-
async startLocal() {
|
|
200
|
+
async startLocal(dev: boolean) {
|
|
177
201
|
const command = [
|
|
178
202
|
...this.dockerComposeCommand,
|
|
179
203
|
"-f",
|
|
180
204
|
this.dockerComposeFile,
|
|
181
|
-
"up",
|
|
182
|
-
"--quiet-pull",
|
|
183
|
-
"--wait",
|
|
184
205
|
];
|
|
185
|
-
|
|
206
|
+
if (dev) {
|
|
207
|
+
command.push("-f", this.dockerComposeDevFile);
|
|
208
|
+
}
|
|
209
|
+
command.push("up", "--quiet-pull", "--wait");
|
|
210
|
+
await this.executeCommand(command);
|
|
186
211
|
console.info(
|
|
187
212
|
"LangSmith server is running at http://localhost:1984. To connect locally, set the following environment variable when running your LangChain application."
|
|
188
213
|
);
|
|
189
214
|
console.info("\tLANGCHAIN_TRACING_V2=true");
|
|
190
215
|
}
|
|
191
216
|
|
|
192
|
-
async startAndExpose(ngrokAuthToken: string | null) {
|
|
217
|
+
async startAndExpose(ngrokAuthToken: string | null, dev: boolean) {
|
|
193
218
|
const configPath = await createNgrokConfig(ngrokAuthToken);
|
|
194
219
|
const command = [
|
|
195
220
|
...this.dockerComposeCommand,
|
|
@@ -197,11 +222,12 @@ class PlusCommand {
|
|
|
197
222
|
this.dockerComposeFile,
|
|
198
223
|
"-f",
|
|
199
224
|
this.ngrokPath,
|
|
200
|
-
"up",
|
|
201
|
-
"--quiet-pull",
|
|
202
|
-
"--wait",
|
|
203
225
|
];
|
|
204
|
-
|
|
226
|
+
if (dev) {
|
|
227
|
+
command.push("-f", this.dockerComposeDevFile);
|
|
228
|
+
}
|
|
229
|
+
command.push("up", "--quiet-pull", "--wait");
|
|
230
|
+
await this.executeCommand(command);
|
|
205
231
|
console.info(
|
|
206
232
|
"ngrok is running. You can view the dashboard at http://0.0.0.0:4040"
|
|
207
233
|
);
|
|
@@ -224,7 +250,7 @@ class PlusCommand {
|
|
|
224
250
|
this.ngrokPath,
|
|
225
251
|
"down",
|
|
226
252
|
];
|
|
227
|
-
await
|
|
253
|
+
await this.executeCommand(command);
|
|
228
254
|
}
|
|
229
255
|
async status() {
|
|
230
256
|
const command = [
|
|
@@ -235,6 +261,7 @@ class PlusCommand {
|
|
|
235
261
|
"--format",
|
|
236
262
|
"json",
|
|
237
263
|
];
|
|
264
|
+
const exec = util.promisify(child_process.exec);
|
|
238
265
|
const result = await exec(command.join(" "));
|
|
239
266
|
const servicesStatus = JSON.parse(result.stdout);
|
|
240
267
|
if (servicesStatus) {
|
|
@@ -259,25 +286,27 @@ const startCommand = new Command("start")
|
|
|
259
286
|
.option("--dev", "Run the development version of the LangSmith server")
|
|
260
287
|
.option(
|
|
261
288
|
"--openai-api-key <openaiApiKey>",
|
|
262
|
-
"Your OpenAI API key. If
|
|
289
|
+
"Your OpenAI API key. If not provided, the OpenAI API Key will be read" +
|
|
290
|
+
" from the OPENAI_API_KEY environment variable. If neither are provided," +
|
|
291
|
+
" some features of LangSmith will not be available."
|
|
263
292
|
)
|
|
264
|
-
.action(async (args: string[]) => (await
|
|
293
|
+
.action(async (args: string[]) => (await SmithCommand.create()).start(args));
|
|
265
294
|
|
|
266
295
|
const stopCommand = new Command("stop")
|
|
267
296
|
.command("stop")
|
|
268
297
|
.description("Stop the LangSmith server")
|
|
269
|
-
.action(async () => (await
|
|
298
|
+
.action(async () => (await SmithCommand.create()).stop());
|
|
270
299
|
|
|
271
300
|
const pullCommand = new Command("pull")
|
|
272
301
|
.command("pull")
|
|
273
302
|
.description("Pull the latest version of the LangSmith server")
|
|
274
303
|
.option("--dev", "Pull the development version of the LangSmith server")
|
|
275
|
-
.action(async (args: string[]) => (await
|
|
304
|
+
.action(async (args: string[]) => (await SmithCommand.create()).pull(args));
|
|
276
305
|
|
|
277
306
|
const statusCommand = new Command("status")
|
|
278
307
|
.command("status")
|
|
279
308
|
.description("Get the status of the LangSmith server")
|
|
280
|
-
.action(async () => (await
|
|
309
|
+
.action(async () => (await SmithCommand.create()).status());
|
|
281
310
|
|
|
282
311
|
program
|
|
283
312
|
.description("Manage the LangSmith server")
|
package/dist/client.cjs
CHANGED
|
@@ -83,7 +83,7 @@ class Client {
|
|
|
83
83
|
validateApiKeyIfHosted() {
|
|
84
84
|
const isLocal = isLocalhost(this.apiUrl);
|
|
85
85
|
if (!isLocal && !this.apiKey) {
|
|
86
|
-
throw new Error("API key must be provided when using hosted
|
|
86
|
+
throw new Error("API key must be provided when using hosted LangSmith API");
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
get headers() {
|
package/dist/client.js
CHANGED
|
@@ -57,7 +57,7 @@ export class Client {
|
|
|
57
57
|
validateApiKeyIfHosted() {
|
|
58
58
|
const isLocal = isLocalhost(this.apiUrl);
|
|
59
59
|
if (!isLocal && !this.apiKey) {
|
|
60
|
-
throw new Error("API key must be provided when using hosted
|
|
60
|
+
throw new Error("API key must be provided when using hosted LangSmith API");
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
get headers() {
|