Skip to content

Commit

Permalink
langchain-aws[major]: LangChain AWS package (#5907)
Browse files Browse the repository at this point in the history
* langchain-aws[major]: LangChain AWS package

* cr

* implemented code and tests

* refactor utils/types

* implemented streaming

* implemented bindTools

* implemented streaming tool calls

* tool_choice test

* getLsParams and standard tests

* final

* add guardrails

* docs

* chore: lint files

* cr

* export types file

* cr
  • Loading branch information
bracesproul authored Jun 28, 2024
1 parent 9110192 commit f8c69c3
Show file tree
Hide file tree
Showing 29 changed files with 3,000 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/core_docs/docs/integrations/chat/bedrock.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ sidebar_label: Bedrock
## Setup

:::tip
The [`ChatBedrockConverse` chat model is now available via `@langchain/aws`](/docs/integrations/chat/bedrock_converse). Access tool calling with more models with this package.
:::

You'll need to install the `@langchain/community` package:

import IntegrationInstallTooltip from "@mdx_components/integration_install_tooltip.mdx";
Expand Down
77 changes: 77 additions & 0 deletions docs/core_docs/docs/integrations/chat/bedrock_converse.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
sidebar_label: Bedrock Converse
---

# ChatBedrockConverse

> [Amazon Bedrock Converse](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html) is a fully managed service that makes Foundation Models (FMs)
> from leading AI startups and Amazon available via an API. You can choose from a wide range of FMs to find the model that is best suited for your use case.
## Setup

You'll need to install the `@langchain/aws` package:

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

<IntegrationInstallTooltip></IntegrationInstallTooltip>

```bash npm2yarn
npm install @langchain/aws
```

## Usage

import UnifiedModelParamsTooltip from "@mdx_components/unified_model_params_tooltip.mdx";

<UnifiedModelParamsTooltip></UnifiedModelParamsTooltip>

import CodeBlock from "@theme/CodeBlock";
import BedrockConverseExample from "@examples/models/chat/integration_bedrock_converse.ts";

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

:::tip
See the LangSmith traces for the above example [here](https://smith.langchain.com/public/7aeb0c56-9afa-441d-8659-4d52c007eae0/r), and [here for steaming](https://smith.langchain.com/public/74606291-45cd-478c-a874-568b2905427f/r).
:::

## Multimodal inputs

:::tip
Multimodal inputs are currently only supported by Anthropic Claude-3 models.
:::

Anthropic Claude-3 models hosted on Bedrock have multimodal capabilities and can reason about images. Here's an example:

import BedrockMultimodalExample from "@examples/models/chat/integration_bedrock_multimodal_converse.ts";

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

:::tip
See the LangSmith trace [here](https://smith.langchain.com/public/c40f8d09-123a-4b3b-934a-625d5ee0f57a/r).
:::

## Tool calling

The examples below demonstrate how to use tool calling, along with the `withStructuredOutput` method to easily compose structured output LLM calls.

import ToolCalling from "@examples/models/chat/integration_bedrock_tools_converse.ts";

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

Check out the output of this tool call! We can see here it's using chain-of-thought before calling the tool, where it describes what it's going to do in plain text before calling the tool: `Okay, let's get the weather for New York City.`.

:::tip
See the LangSmith trace [here](https://smith.langchain.com/public/d34e378d-5044-4b5b-9ed7-3d2486fe5d47/r)
:::

### `.withStructuredOutput({ ... })`

Using the `.withStructuredOutput` method, you can easily make the LLM return structured output, given only a Zod or JSON schema:

import WSOExample from "@examples/models/chat/integration_bedrock_wso_converse.ts";

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

:::tip
See the LangSmith trace [here](https://smith.langchain.com/public/982940c4-5f96-4168-80c9-99102c3e073a/r)
:::
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/aws": "workspace:*",
"@langchain/azure-dynamic-sessions": "workspace:^",
"@langchain/azure-openai": "workspace:*",
"@langchain/cloudflare": "workspace:*",
Expand Down
65 changes: 65 additions & 0 deletions examples/src/models/chat/integration_bedrock_converse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { ChatBedrockConverse } from "@langchain/aws";
import { HumanMessage } from "@langchain/core/messages";

const model = new ChatBedrockConverse({
model: "anthropic.claude-3-sonnet-20240229-v1:0",
region: "us-east-1",
credentials: {
accessKeyId: process.env.BEDROCK_AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.BEDROCK_AWS_SECRET_ACCESS_KEY!,
},
});

const res = await model.invoke([
new HumanMessage({ content: "Tell me a joke" }),
]);
console.log(res);

/*
AIMessage {
content: "Here's a joke for you:\n" +
'\n' +
"Why can't a bicycle stand up by itself? Because it's two-tired!",
response_metadata: { ... },
id: '08afa4fb-c212-4c1e-853a-d854972bec78',
usage_metadata: { input_tokens: 11, output_tokens: 28, total_tokens: 39 }
}
*/

const stream = await model.stream([
new HumanMessage({ content: "Tell me a joke" }),
]);

for await (const chunk of stream) {
console.log(chunk.content);
}

/*
Here
's
a
silly
joke
for
you
:
Why
di
d the
tom
ato
turn
re
d?
Because
it
saw
the
sal
a
d
dressing
!
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as fs from "node:fs/promises";

import { ChatBedrockConverse } from "@langchain/aws";
import { HumanMessage } from "@langchain/core/messages";

const model = new ChatBedrockConverse({
model: "anthropic.claude-3-sonnet-20240229-v1:0",
region: "us-east-1",
credentials: {
accessKeyId: process.env.BEDROCK_AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.BEDROCK_AWS_SECRET_ACCESS_KEY!,
},
});

const imageData = await fs.readFile("./hotdog.jpg");

const res = await model.invoke([
new HumanMessage({
content: [
{
type: "text",
text: "What's in this image?",
},
{
type: "image_url",
image_url: {
url: `data:image/jpeg;base64,${imageData.toString("base64")}`,
},
},
],
}),
]);
console.log(res);

/*
AIMessage {
content: 'The image shows a hot dog or frankfurter. It has a reddish-pink sausage inside a light tan-colored bread bun. The hot dog bun is split open, allowing the sausage filling to be visible. The image appears to be focused solely on depicting this classic American fast food item against a plain white background.',
response_metadata: { ... },
id: '1608d043-575a-450e-8eac-2fef6297cfe2',
usage_metadata: { input_tokens: 276, output_tokens: 75, total_tokens: 351 }
}
*/
55 changes: 55 additions & 0 deletions examples/src/models/chat/integration_bedrock_tools_converse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ChatBedrockConverse } from "@langchain/aws";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const model = new ChatBedrockConverse({
model: "anthropic.claude-3-sonnet-20240229-v1:0",
region: "us-east-1",
credentials: {
accessKeyId: process.env.BEDROCK_AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.BEDROCK_AWS_SECRET_ACCESS_KEY!,
},
});

const weatherTool = tool(
({ city, state }) => `The weather in ${city}, ${state} is 72°F and sunny`,
{
name: "weather_tool",
description: "Get the weather for a city",
schema: z.object({
city: z.string().describe("The city to get the weather for"),
state: z.string().describe("The state to get the weather for").optional(),
}),
}
);

const modelWithTools = model.bindTools([weatherTool]);
// Optionally, you can bind tools via the `.bind` method:
// const modelWithTools = model.bind({
// tools: [weatherTool]
// });

const res = await modelWithTools.invoke("What's the weather in New York?");
console.log(res);

/*
AIMessage {
content: [
{
type: 'text',
text: "Okay, let's get the weather for New York City."
}
],
response_metadata: { ... },
id: '49a97da0-e971-4d7f-9f04-2495e068c15e',
tool_calls: [
{
id: 'tooluse_O6Q1Ghm7SmKA9mn2ZKmBzg',
name: 'weather_tool',
args: {
'city': 'New York',
},
],
usage_metadata: { input_tokens: 289, output_tokens: 68, total_tokens: 357 }
}
*/
31 changes: 31 additions & 0 deletions examples/src/models/chat/integration_bedrock_wso_converse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ChatBedrockConverse } from "@langchain/aws";
import { z } from "zod";

const model = new ChatBedrockConverse({
model: "anthropic.claude-3-sonnet-20240229-v1:0",
region: "us-east-1",
credentials: {
accessKeyId: process.env.BEDROCK_AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.BEDROCK_AWS_SECRET_ACCESS_KEY!,
},
});

const weatherSchema = z
.object({
city: z.string().describe("The city to get the weather for"),
state: z.string().describe("The state to get the weather for").optional(),
})
.describe("Get the weather for a city");

const modelWithStructuredOutput = model.withStructuredOutput(weatherSchema, {
name: "weather_tool", // Optional, defaults to 'extract'
});

const res = await modelWithStructuredOutput.invoke(
"What's the weather in New York?"
);
console.log(res);

/*
{ city: 'New York', state: 'NY' }
*/
74 changes: 74 additions & 0 deletions libs/langchain-aws/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
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 }],
},
overrides: [
{
files: ["**/*.test.ts"],
rules: {
"@typescript-eslint/no-unused-vars": "off",
},
},
],
};
7 changes: 7 additions & 0 deletions libs/langchain-aws/.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-aws/.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"
}
Loading

0 comments on commit f8c69c3

Please sign in to comment.