Skip to content

Commit

Permalink
azure-dynamic-sessions[major]: Add new package (#5788)
Browse files Browse the repository at this point in the history
* Add Azure Container Apps sessions REPL

* Rename package

* Update to API version 2024-02-02-preview

* Update to JSON output

* Add user agent

* Bump version to 0.1.0

* Update (#1)

* refactor: use azure identity refresh token

* chore: formatting

* refactor: lint issues

* refactor: uniformize user agent prefix

* feat: add default fallback to env variable

* fix: incorrect template string

* chore: add lc serialization

* fix: token scope

* docs: add .env.example

* test: fix unit tests

* test: update integration tests

* refactor: rename integration tests

* docs: add azure dynamic sessions documentation

* Fix build and make it CJS compatible

* Update error message

* Add sessions to platform docs

* Formatting

* Add env var

* Add package to examples

* Fix agent example

* Add readme

* Fix bad merge

* Add missing package

* Fix formatting

* Fix langchain/core dependency

* Regenerate lockfile

* Format, update example

* refactor: fix comments

* Remove unneeded import

---------

Co-authored-by: Yohan Lasorsa <noda@free.fr>
Co-authored-by: jacoblee93 <jacoblee93@gmail.com>
  • Loading branch information
3 people committed Jun 21, 2024
1 parent 4c93201 commit f7bb6d3
Show file tree
Hide file tree
Showing 26 changed files with 942 additions and 1 deletion.
18 changes: 18 additions & 0 deletions docs/core_docs/docs/integrations/platforms/microsoft.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,21 @@ See a [usage example for the Azure Files](/docs/integrations/document_loaders/we
```typescript
import { AzureBlobStorageFileLoader } from "@langchain/community/document_loaders/web/azure_blob_storage_file";
```

## Tools

### Azure Container Apps Dynamic Sessions

> [Azure Container Apps dynamic sessions](https://learn.microsoft.com/azure/container-apps/sessions) provide fast access to secure sandboxed environments that are ideal for running code or applications that require strong isolation from other workloads.
<IntegrationInstallTooltip></IntegrationInstallTooltip>

```bash npm2yarn
npm install @langchain/azure-dynamic-sessions
```

See a [usage example](/docs/integrations/tools/azure_dynamic_sessions).

```typescript
import { SessionsPythonREPLTool } from "@langchain/azure-dynamic-sessions";
```
42 changes: 42 additions & 0 deletions docs/core_docs/docs/integrations/tools/azure_dynamic_sessions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Azure Container Apps Dynamic Sessions

> [Azure Container Apps dynamic sessions](https://learn.microsoft.com/azure/container-apps/sessions) provide fast access to secure sandboxed environments that are ideal for running code or applications that require strong isolation from other workloads.
You can learn more about Azure Container Apps dynamic sessions and its code interpretation capabilities on [this page](https://learn.microsoft.com/azure/container-apps/sessions). If you don't have an Azure account, you can [create a free account](https://azure.microsoft.com/free/) to get started.

## Setup

You'll first need to install the [`@langchain/azure-dynamic-sessions`](https://www.npmjs.com/package/@langchain/azure-dynamic-sessions) package:

import IntegrationInstallTooltip from "@mdx_components/integration_install_tooltip.mdx";

<IntegrationInstallTooltip></IntegrationInstallTooltip>

```bash npm2yarn
npm install @langchain/azure-dynamic-sessions
```

You'll also need to have a code interpreter session pool instance running. You can deploy a version using [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) following [this guide](https://learn.microsoft.com/azure/container-apps/sessions-code-interpreter).

Once you have your instance running, you need to make sure you have properly set up the Azure Entra authentication for it. You can find the instructions on how to do that [here](https://learn.microsoft.com/azure/container-apps/sessions?tabs=azure-cli#authentication).

After you've added the role for your identity, you need to retrieve the **session pool management endpoint**. You can find it in the Azure Portal, under the "Overview" section of your instance. Then you need to set the following environment variable:

import CodeBlock from "@theme/CodeBlock";
import EnvVars from "@examples/tools/azure_dynamic_sessions/.env.example";

<CodeBlock language="text">{EnvVars}</CodeBlock>

## Usage example

Below is a simple example that creates a new Python code interpreter session, invoke the tool and prints the result.

import Example from "@examples/tools/azure_dynamic_sessions/azure_dynamic_sessions.ts";

<CodeBlock language="typescript">{Example}</CodeBlock>

Here is a complete example where we use an Azure OpenAI chat model to call the Python code interpreter session tool to execute the code and get the result:

import AgentExample from "@examples/tools/azure_dynamic_sessions/azure_dynamic_sessions-agent.ts";

<CodeBlock language="typescript">{AgentExample}</CodeBlock>
2 changes: 2 additions & 0 deletions examples/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME=ADD_YOURS_HERE # Azure Portal -> Co
AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME=ADD_YOURS_HERE # Azure Portal -> Cognitive Services -> OpenAI -> Choose your instance -> Go to Azure OpenAI Studio -> Deployments
AZURE_OPENAI_API_VERSION=ADD_YOURS_HERE # Azure Portal -> Cognitive Services -> OpenAI -> Choose your instance -> Go to Azure OpenAI Studio -> Completions/Chat -> Choose Deployment -> View Code
AZURE_OPENAI_BASE_PATH=ADD_YOURS_HERE # Azure Portal -> Cognitive Services -> OpenAI -> Choose your instance -> Endpoint (optional)
AZURE_OPENAI_BASE_PATH=ADD_YOURS_HERE # Azure Portal -> Cognitive Services -> OpenAI -> Choose your instance -> Endpoint (optional)
AZURE_CONTAINER_APP_SESSION_POOL_MANAGEMENT_ENDPOINT=ADD_YOURS_HERE # Azure Portal -> Container App Session Pools -> Choose your app -> Pool management endpoint -> Copy the URL
CONNERY_RUNNER_URL=ADD_YOURS_HERE
CONNERY_RUNNER_API_KEY=ADD_YOURS_HERE
ELASTIC_URL=ADD_YOURS_HERE # http://127.0.0.1:9200
Expand Down
1 change: 1 addition & 0 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@gomomento/sdk": "^1.51.1",
"@google/generative-ai": "^0.7.0",
"@langchain/anthropic": "workspace:*",
"@langchain/azure-dynamic-sessions": "workspace:^",
"@langchain/azure-openai": "workspace:*",
"@langchain/cloudflare": "workspace:*",
"@langchain/cohere": "workspace:*",
Expand Down
1 change: 1 addition & 0 deletions examples/src/tools/azure_dynamic_sessions/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
AZURE_CONTAINER_APP_SESSION_POOL_MANAGEMENT_ENDPOINT=<your_endpoint>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { ChatPromptTemplate } from "@langchain/core/prompts";
import { pull } from "langchain/hub";
import { AgentExecutor, createToolCallingAgent } from "langchain/agents";
import { SessionsPythonREPLTool } from "@langchain/azure-dynamic-sessions";
import { AzureChatOpenAI } from "@langchain/openai";

const tools = [
new SessionsPythonREPLTool({
poolManagementEndpoint:
process.env.AZURE_CONTAINER_APP_SESSION_POOL_MANAGEMENT_ENDPOINT || "",
}),
];

// Note: you need a model deployment that supports function calling,
// like `gpt-35-turbo` version `1106`.
const llm = new AzureChatOpenAI({
temperature: 0,
});

// Get the prompt to use - you can modify this!
// If you want to see the prompt in full, you can at:
// https://smith.langchain.com/hub/jacob/tool-calling-agent
const prompt = await pull<ChatPromptTemplate>("jacob/tool-calling-agent");

const agent = await createToolCallingAgent({
llm,
tools,
prompt,
});

const agentExecutor = new AgentExecutor({
agent,
tools,
});

const result = await agentExecutor.invoke({
input:
"Create a Python program that prints the Python version and return the result.",
});

console.log(result);
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { SessionsPythonREPLTool } from "@langchain/azure-dynamic-sessions";

const tool = new SessionsPythonREPLTool({
poolManagementEndpoint:
process.env.AZURE_CONTAINER_APP_SESSION_POOL_MANAGEMENT_ENDPOINT || "",
});

const result = await tool.invoke("print('Hello, World!')\n1+2");

console.log(result);

// {
// stdout: "Hello, World!\n",
// stderr: "",
// result: 3,
// }
2 changes: 2 additions & 0 deletions libs/langchain-azure-dynamic-sessions/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Azure Container App Session Pool Management Endpoint
AZURE_CONTAINER_APP_SESSION_POOL_MANAGEMENT_ENDPOINT=<your-endpoint>
66 changes: 66 additions & 0 deletions libs/langchain-azure-dynamic-sessions/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
module.exports = {
extends: [
"airbnb-base",
"eslint:recommended",
"prettier",
"plugin:@typescript-eslint/recommended",
],
parserOptions: {
ecmaVersion: 12,
parser: "@typescript-eslint/parser",
project: "./tsconfig.json",
sourceType: "module",
},
plugins: ["@typescript-eslint", "no-instanceof"],
ignorePatterns: [
".eslintrc.cjs",
"scripts",
"node_modules",
"dist",
"dist-cjs",
"*.js",
"*.cjs",
"*.d.ts",
],
rules: {
"no-process-env": 2,
"no-instanceof/no-instanceof": 2,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-shadow": 0,
"@typescript-eslint/no-empty-interface": 0,
"@typescript-eslint/no-use-before-define": ["error", "nofunc"],
"@typescript-eslint/no-unused-vars": ["warn", { args: "none" }],
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error",
camelcase: 0,
"class-methods-use-this": 0,
"import/extensions": [2, "ignorePackages"],
"import/no-extraneous-dependencies": [
"error",
{ devDependencies: ["**/*.test.ts"] },
],
"import/no-unresolved": 0,
"import/prefer-default-export": 0,
"keyword-spacing": "error",
"max-classes-per-file": 0,
"max-len": 0,
"no-await-in-loop": 0,
"no-bitwise": 0,
"no-console": 0,
"no-restricted-syntax": 0,
"no-shadow": 0,
"no-continue": 0,
"no-void": 0,
"no-underscore-dangle": 0,
"no-use-before-define": 0,
"no-useless-constructor": 0,
"no-return-await": 0,
"consistent-return": 0,
"no-else-return": 0,
"func-names": 0,
"no-lonely-if": 0,
"prefer-rest-params": 0,
"new-cap": ["error", { properties: false, capIsNew: false }],
},
};
7 changes: 7 additions & 0 deletions libs/langchain-azure-dynamic-sessions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
index.cjs
index.js
index.d.ts
index.d.cts
node_modules
dist
.yarn
19 changes: 19 additions & 0 deletions libs/langchain-azure-dynamic-sessions/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"quoteProps": "as-needed",
"jsxSingleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "always",
"requirePragma": false,
"insertPragma": false,
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "css",
"vueIndentScriptAndStyle": false,
"endOfLine": "lf"
}
10 changes: 10 additions & 0 deletions libs/langchain-azure-dynamic-sessions/.release-it.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"github": {
"release": true,
"autoGenerate": true,
"tokenRef": "GITHUB_TOKEN_RELEASE"
},
"npm": {
"versionArgs": ["--workspaces-update=false"]
}
}
21 changes: 21 additions & 0 deletions libs/langchain-azure-dynamic-sessions/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License

Copyright (c) 2023 LangChain

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
60 changes: 60 additions & 0 deletions libs/langchain-azure-dynamic-sessions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# @langchain/azure-dynamic-sessions

This package contains the [Azure Container Apps dynamic sessions](https://learn.microsoft.com/azure/container-apps/sessions) tool integration.

Learn more about how to use this tool in the [LangChain documentation](https://js.langchain.com/docs/integrations/tools/azure_dynamic_sessions).

## Installation

```bash npm2yarn
npm install @langchain/azure-dynamic-sessions
```

This package, along with the main LangChain package, depends on [`@langchain/core`](https://npmjs.com/package/@langchain/core/).
If you are using this package with other LangChain packages, you should make sure that all of the packages depend on the same instance of @langchain/core.
You can do so by adding appropriate fields to your project's `package.json` like this:

```json
{
"name": "your-project",
"version": "0.0.0",
"dependencies": {
"@langchain/azure-openai": "^0.0.4",
"langchain": "0.0.207"
},
"resolutions": {
"@langchain/core": "0.1.5"
},
"overrides": {
"@langchain/core": "0.1.5"
},
"pnpm": {
"overrides": {
"@langchain/core": "0.1.5"
}
}
}
```

The field you need depends on the package manager you're using, but we recommend adding a field for the common `yarn`, `npm`, and `pnpm` to maximize compatibility.

## Tool usage

```typescript
import { SessionsPythonREPLTool } from "@langchain/azure-dynamic-sessions";

const tool = new SessionsPythonREPLTool({
poolManagementEndpoint:
process.env.AZURE_CONTAINER_APP_SESSION_POOL_MANAGEMENT_ENDPOINT || "",
});

const result = await tool.invoke("print('Hello, World!')\n1+2");

console.log(result);

// {
// stdout: "Hello, World!\n",
// stderr: "",
// result: 3,
// }
```
21 changes: 21 additions & 0 deletions libs/langchain-azure-dynamic-sessions/jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: "ts-jest/presets/default-esm",
testEnvironment: "./jest.env.cjs",
modulePathIgnorePatterns: ["dist/", "docs/"],
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
transform: {
"^.+\\.tsx?$": ["@swc/jest"],
},
transformIgnorePatterns: [
"/node_modules/",
"\\.pnp\\.[^\\/]+$",
"./scripts/jest-setup-after-env.js",
],
setupFiles: ["dotenv/config"],
testTimeout: 20_000,
passWithNoTests: true,
collectCoverageFrom: ["src/**/*.ts"],
};
12 changes: 12 additions & 0 deletions libs/langchain-azure-dynamic-sessions/jest.env.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { TestEnvironment } = require("jest-environment-node");

class AdjustedTestEnvironmentToSupportFloat32Array extends TestEnvironment {
constructor(config, context) {
// Make `instanceof Float32Array` return true in tests
// to avoid https://github.com/xenova/transformers.js/issues/57 and https://github.com/jestjs/jest/issues/2549
super(config, context);
this.global.Float32Array = Float32Array;
}
}

module.exports = AdjustedTestEnvironmentToSupportFloat32Array;
22 changes: 22 additions & 0 deletions libs/langchain-azure-dynamic-sessions/langchain.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";

/**
* @param {string} relativePath
* @returns {string}
*/
function abs(relativePath) {
return resolve(dirname(fileURLToPath(import.meta.url)), relativePath);
}

export const config = {
internals: [/node\:/, /@langchain\/core\//],
entrypoints: {
index: "index",
},
requiresOptionalDependency: [],
tsConfigPath: resolve("./tsconfig.json"),
cjsSource: "./dist-cjs",
cjsDestination: "./dist",
abs,
};
Loading

0 comments on commit f7bb6d3

Please sign in to comment.