Skip to content

Commit

Permalink
Remove unused docker files and add version (#327)
Browse files Browse the repository at this point in the history
This pr does a few things:

1. Removes unneeded docker files since we don't have hub in beta anymore
2. Adds version
3. Cleans up ngrok
4. Few fixes for api path etc now that we do everything through port 80.
  • Loading branch information
langchain-infra authored Dec 14, 2023
2 parents c4b250e + 6f29c22 commit 41d83c0
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 450 deletions.
2 changes: 1 addition & 1 deletion js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "langsmith",
"version": "0.0.49",
"version": "0.0.50",
"description": "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform.",
"files": [
"dist/",
Expand Down
19 changes: 0 additions & 19 deletions js/src/cli/docker-compose.beta.yaml

This file was deleted.

19 changes: 0 additions & 19 deletions js/src/cli/docker-compose.dev.yaml

This file was deleted.

17 changes: 0 additions & 17 deletions js/src/cli/docker-compose.ngrok.yaml

This file was deleted.

10 changes: 5 additions & 5 deletions js/src/cli/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
version: "3"
services:
langchain-playground:
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-playground:latest
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-playground:${_LANGSMITH_IMAGE_VERSION-:latest}
ports:
- 3001:3001
langchain-frontend:
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-frontend-dynamic:latest
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-frontend-dynamic:${_LANGSMITH_IMAGE_VERSION-:latest}
ports:
- 80:80
volumes:
Expand All @@ -15,7 +15,7 @@ services:
- langchain-playground
- langchain-hub
langchain-backend:
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:latest
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:${_LANGSMITH_IMAGE_VERSION-:latest}
environment:
- PORT=1984
- LANGCHAIN_ENV=local_docker
Expand All @@ -28,14 +28,14 @@ services:
- langchain-db
- langchain-redis
langchain-queue:
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:latest
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainplus-backend:${_LANGSMITH_IMAGE_VERSION-:latest}
environment:
- LANGCHAIN_ENV=local_docker
- LOG_LEVEL=warning
- LANGSMITH_LICENSE_KEY=${LANGSMITH_LICENSE_KEY}
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"
langchain-hub:
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainhub-backend:latest
image: langchain/${_LANGSMITH_IMAGE_PREFIX-}langchainhub-backend:${_LANGSMITH_IMAGE_VERSION-:latest}
environment:
- PORT=1985
- LANGCHAIN_ENV=local_docker
Expand Down
162 changes: 22 additions & 140 deletions js/src/cli/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as child_process from "child_process";
import * as fs from "fs";
import * as path from "path";
import * as util from "util";

Expand All @@ -13,8 +12,6 @@ import { Command } from "commander";
import { spawn } from "child_process";

const currentFileName = __filename;
const currentDirName = __dirname;

const program = new Command();

async function getDockerComposeCommand(): Promise<string[]> {
Expand Down Expand Up @@ -69,90 +66,25 @@ async function pprintServices(servicesStatus: any[]) {
serviceMessage.push(serviceStr + stateStr + portsStr);
}

let langchainEndpoint = "http://localhost:1984";
const usedNgrok = services.some((service) =>
service["Service"].includes("ngrok")
);
if (usedNgrok) {
langchainEndpoint = await getNgrokUrl();
}

serviceMessage.push(
"\nTo connect, set the following environment variables" +
" in your LangChain application:" +
"\nLANGCHAIN_TRACING_V2=true" +
`\nLANGCHAIN_ENDPOINT=${langchainEndpoint}`
`\nLANGCHAIN_ENDPOINT=http://localhost:80/api`
);
console.info(serviceMessage.join("\n"));
}

async function getNgrokUrl(): Promise<string> {
const ngrokUrl = "http://localhost:4040/api/tunnels";
try {
// const response = await axios.get(ngrokUrl);
const response = await fetch(ngrokUrl);
if (response.status !== 200) {
throw new Error(
`Could not connect to ngrok console. ${response.status}, ${response.statusText}`
);
}
const result = await response.json();
const exposedUrl = result["tunnels"][0]["public_url"];
return exposedUrl;
} catch (error) {
throw new Error(`Could not connect to ngrok console. ${error}`);
}
}

async function createNgrokConfig(authToken: string | null): Promise<string> {
const configPath = path.join(currentDirName, "ngrok_config.yaml");
// Check if is a directory
if (fs.existsSync(configPath) && fs.lstatSync(configPath).isDirectory()) {
fs.rmdirSync(configPath, { recursive: true });
} else if (fs.existsSync(configPath)) {
fs.unlinkSync(configPath);
}
let ngrokConfig = `
region: us
tunnels:
langchain:
addr: langchain-backend:1984
proto: http
version: '2'
`;

if (authToken !== null) {
ngrokConfig += `authtoken: ${authToken}`;
}
fs.writeFileSync(configPath, ngrokConfig);
return configPath;
}

class SmithCommand {
dockerComposeCommand: string[] = [];
dockerComposeFile = "";
dockerComposeDevFile = "";
dockerComposeBetaFile = "";
ngrokPath = "";

constructor({ dockerComposeCommand }: { dockerComposeCommand: string[] }) {
this.dockerComposeCommand = dockerComposeCommand;
this.dockerComposeFile = path.join(
path.dirname(currentFileName),
"docker-compose.yaml"
);
this.dockerComposeDevFile = path.join(
path.dirname(currentFileName),
"docker-compose.dev.yaml"
);
this.dockerComposeBetaFile = path.join(
path.dirname(currentFileName),
"docker-compose.beta.yaml"
);
this.ngrokPath = path.join(
path.dirname(currentFileName),
"docker-compose.ngrok.yaml"
);
}

async executeCommand(command: string[]) {
Expand Down Expand Up @@ -183,12 +115,13 @@ class SmithCommand {
return new SmithCommand({ dockerComposeCommand });
}

async pull({ stage = "prod" }) {
async pull({ stage = "prod", version = "latest" }) {
if (stage === "dev") {
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "dev-");
} else if (stage === "beta") {
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
}
setEnvironmentVariable("_LANGSMITH_IMAGE_VERSION", version);

const command = [
...this.dockerComposeCommand,
Expand All @@ -199,19 +132,13 @@ class SmithCommand {
await this.executeCommand(command);
}

async startLocal(stage = "prod") {
async startLocal() {
const command = [
...this.dockerComposeCommand,
"-f",
this.dockerComposeFile,
];

if (stage === "dev") {
command.push("-f", this.dockerComposeDevFile);
} else if (stage === "beta") {
command.push("-f", this.dockerComposeBetaFile);
}

command.push("up", "--quiet-pull", "--wait");
await this.executeCommand(command);

Expand All @@ -224,51 +151,14 @@ class SmithCommand {
);

console.info("\tLANGCHAIN_TRACING_V2=true");
}

async startAndExpose(ngrokAuthToken: string | null, stage = "prod") {
const configPath = await createNgrokConfig(ngrokAuthToken);
const command = [
...this.dockerComposeCommand,
"-f",
this.dockerComposeFile,
"-f",
this.ngrokPath,
];

if (stage === "dev") {
command.push("-f", this.dockerComposeDevFile);
} else if (stage === "beta") {
command.push("-f", this.dockerComposeBetaFile);
}

command.push("up", "--quiet-pull", "--wait");
await this.executeCommand(command);

console.info(
"ngrok is running. You can view the dashboard at http://0.0.0.0:4040"
);
const ngrokUrl = await getNgrokUrl();
console.info(
"LangSmith server is running at http://localhost:1984." +
"To view the app, navigate your browser to http://localhost:80" +
"\n\nTo connect your LangChain application to the server" +
" remotely, set the following environment variable" +
" when running your LangChain application."
);
console.info("\tLANGCHAIN_TRACING_V2=true");
console.info(`\tLANGCHAIN_ENDPOINT=${ngrokUrl}`);

fs.unlinkSync(configPath);
console.info("\tLANGCHAIN_ENDPOINT=http://localhost:80/api");
}

async stop() {
const command = [
...this.dockerComposeCommand,
"-f",
this.dockerComposeFile,
"-f",
this.ngrokPath,
"down",
];
await this.executeCommand(command);
Expand Down Expand Up @@ -314,14 +204,6 @@ class SmithCommand {

const startCommand = new Command("start")
.description("Start the LangSmith server")
.option(
"--expose",
"Expose the server to the internet via ngrok (requires ngrok to be installed)"
)
.option(
"--ngrok-authtoken <ngrokAuthtoken>",
"Your ngrok auth token. If this is set, --expose is implied."
)
.option(
"--stage <stage>",
"Which version of LangSmith to run. Options: prod, dev, beta (default: prod)"
Expand All @@ -338,25 +220,23 @@ const startCommand = new Command("start")
" License Key will be read from the LANGSMITH_LICENSE_KEY environment variable." +
" If neither are provided, the Langsmith application will not spin up."
)
.option(
"--version <version>",
"The LangSmith version to use for LangSmith. Defaults to latest." +
" We recommend pegging this to the latest static version available at" +
" https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
" if you are using Langsmith in production."
)
.action(async (args) => {
const smith = await SmithCommand.create();
if (args.stage === "dev") {
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "dev-");
} else if (args.stage === "beta") {
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
}
if (args.openaiApiKey) {
setEnvironmentVariable("OPENAI_API_KEY", args.openaiApiKey);
}
if (args.langsmithLicenseKey) {
setEnvironmentVariable("LANGSMITH_LICENSE_KEY", args.langsmithLicenseKey);
}
await smith.pull({ stage: args.stage });
if (args.expose) {
await smith.startAndExpose(args.ngrokAuthtoken, args.stage);
} else {
await smith.startLocal(args.stage);
}
await smith.pull({ stage: args.stage, version: args.version });
await smith.startLocal();
});

const stopCommand = new Command("stop")
Expand All @@ -372,14 +252,16 @@ const pullCommand = new Command("pull")
"--stage <stage>",
"Which version of LangSmith to pull. Options: prod, dev, beta (default: prod)"
)
.option(
"--version <version>",
"The LangSmith version to use for LangSmith. Defaults to latest." +
" We recommend pegging this to the latest static version available at" +
" https://hub.docker.com/repository/docker/langchain/langchainplus-backend" +
" if you are using Langsmith in production."
)
.action(async (args) => {
const smith = await SmithCommand.create();
if (args.stage === "dev") {
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "dev-");
} else if (args.stage === "beta") {
setEnvironmentVariable("_LANGSMITH_IMAGE_PREFIX", "rc-");
}
await smith.pull({ stage: args.stage });
await smith.pull({ stage: args.stage, version: args.version });
});

const statusCommand = new Command("status")
Expand Down
19 changes: 0 additions & 19 deletions python/langsmith/cli/docker-compose.beta.yaml

This file was deleted.

Loading

0 comments on commit 41d83c0

Please sign in to comment.