-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add AWSLambda tool * Update yarn.lock * Update yarn.lock * updated package.json * Remove from index, add entrypoint, subclass dynamictool * Update lambda_agent.md --------- Co-authored-by: Nuno Campos <nuno@boringbits.io>
- Loading branch information
1 parent
f913496
commit 91d90ad
Showing
10 changed files
with
241 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
--- | ||
sidebar_label: Agent with AWS Lambda | ||
hide_table_of_contents: true | ||
--- | ||
|
||
# Agent with AWS Lambda Integration | ||
|
||
Full docs here: https://docs.aws.amazon.com/lambda/index.html | ||
|
||
**AWS Lambda** is a serverless computing service provided by Amazon Web Services (AWS), designed to allow developers to build and run applications and services without the need for provisioning or managing servers. This serverless architecture enables you to focus on writing and deploying code, while AWS automatically takes care of scaling, patching, and managing the infrastructure required to run your applications. | ||
|
||
By including a AWSLambda in the list of tools provided to an Agent, you can grant your Agent the ability to invoke code running in your AWS Cloud for whatever purposes you need. | ||
|
||
When an Agent uses the AWSLambda tool, it will provide an argument of type `string` which will in turn be passed into the Lambda function via the `event` parameter. | ||
|
||
This quick start will demonstrate how an Agent could use a Lambda function to send an email via [Amazon Simple Email Service](https://aws.amazon.com/ses/). The lambda code which sends the email is not provided, but if you'd like to learn how this could be done, see [here](https://repost.aws/knowledge-center/lambda-send-email-ses). Keep in mind this is an intentionally simple example; Lambda can used to execute code for a near infinite number of other purposes (including executing more Langchains)! | ||
|
||
```typescript | ||
import { OpenAI } from "langchain"; | ||
import { SerpAPI, AWSLambda } from "langchain/tools"; | ||
import { initializeAgentExecutor } from "langchain/agents"; | ||
const model = new OpenAI({ temperature: 0 }); | ||
const emailSenderTool = new AWSLambda( | ||
"email-sender", // name: tell the Agent what this tool is called | ||
"Sends an email with the specified content to testing123@gmail.com", // description: tell the Agent precisely what the tool does | ||
{ | ||
region: "us-east-1", // the region in which the function is deployed in the AWS cloud | ||
accessKeyId: "abc123", // the access key for a user which has the IAM permissions necessary to invoke the function | ||
secretAccessKey: "xyz456", // the secret access key for a user which has the IAM permissions necessary to invoke the function | ||
functionName: "SendEmailViaSES", // the function name as seen in the AWS Lambda console | ||
} | ||
); | ||
const tools = [emailSenderTool, new SerpAPI("api_key_goes_here")]; | ||
const executor = await initializeAgentExecutor( | ||
tools, | ||
model, | ||
"zero-shot-react-description" | ||
); | ||
const input = `Find out the capital of Croatia. Once you have it, email the answer to testing123@gmail.com.`; | ||
const result = await executor.call({ input }); | ||
console.log(result); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { test, jest, expect } from "@jest/globals"; | ||
import LambdaClient from "@aws-sdk/client-lambda"; | ||
|
||
import { AWSLambda } from "../../tools/aws_lambda.js"; | ||
|
||
// eslint-disable-next-line tree-shaking/no-side-effects-in-initialization | ||
jest.mock("@aws-sdk/client-lambda", () => ({ | ||
LambdaClient: jest.fn().mockImplementation(() => ({ | ||
send: jest.fn().mockImplementation(() => | ||
Promise.resolve({ | ||
Payload: new TextEncoder().encode( | ||
JSON.stringify({ body: "email sent." }) | ||
), | ||
}) | ||
), | ||
})), | ||
InvokeCommand: jest.fn().mockImplementation(() => ({})), | ||
})); | ||
|
||
test("AWSLambda invokes the correct lambda function and returns the response.body contents", async () => { | ||
if (!LambdaClient) { | ||
// this is to avoid a linting error. S3Client is mocked above. | ||
} | ||
|
||
const lambda = new AWSLambda({ | ||
name: "email-sender", | ||
description: | ||
"Sends an email with the specified content to holtkam2@gmail.com", | ||
region: "us-east-1", | ||
accessKeyId: "abc123", | ||
secretAccessKey: "xyz456/1T+PzUZ2fd", | ||
functionName: "testFunction1", | ||
}); | ||
|
||
const result = await lambda.call("Hello world! This is an email."); | ||
|
||
expect(result).toBe("email sent."); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { DynamicTool, DynamicToolParams } from "./dynamic.js"; | ||
|
||
interface LambdaConfig { | ||
region: string; | ||
accessKeyId: string; | ||
secretAccessKey: string; | ||
functionName: string; | ||
} | ||
|
||
class AWSLambda extends DynamicTool { | ||
private lambdaConfig: LambdaConfig; | ||
|
||
constructor({ | ||
name, | ||
description, | ||
...rest | ||
}: LambdaConfig & Omit<DynamicToolParams, "func">) { | ||
super({ | ||
name, | ||
description, | ||
func: async (input: string) => this._func(input), | ||
}); | ||
|
||
this.lambdaConfig = rest; | ||
} | ||
|
||
async _func(input: string): Promise<string> { | ||
const { Client, Invoker } = await LambdaImports(); | ||
|
||
const lambdaClient = new Client({ | ||
region: this.lambdaConfig.region, | ||
credentials: { | ||
accessKeyId: this.lambdaConfig.accessKeyId, | ||
secretAccessKey: this.lambdaConfig.secretAccessKey, | ||
}, | ||
}); | ||
|
||
return new Promise((resolve) => { | ||
const payloadUint8Array = new TextEncoder().encode(JSON.stringify(input)); | ||
|
||
const command = new Invoker({ | ||
FunctionName: this.lambdaConfig.functionName, | ||
InvocationType: "RequestResponse", | ||
Payload: payloadUint8Array, | ||
}); | ||
|
||
lambdaClient | ||
.send(command) | ||
.then((response) => { | ||
const responseData = JSON.parse( | ||
new TextDecoder().decode(response.Payload) | ||
); | ||
|
||
resolve(responseData.body ? responseData.body : "request completed."); | ||
}) | ||
.catch((error: Error) => { | ||
console.error("Error invoking Lambda function:", error); | ||
resolve("failed to complete request"); | ||
}); | ||
}); | ||
} | ||
} | ||
|
||
async function LambdaImports() { | ||
try { | ||
const { LambdaClient, InvokeCommand } = await import( | ||
"@aws-sdk/client-lambda" | ||
); | ||
|
||
return { | ||
Client: LambdaClient as typeof LambdaClient, | ||
Invoker: InvokeCommand as typeof InvokeCommand, | ||
}; | ||
} catch (e) { | ||
console.error(e); | ||
throw new Error( | ||
"Failed to load @aws-sdk/client-lambda'. Please install it eg. `yarn add @aws-sdk/client-lambda`." | ||
); | ||
} | ||
} | ||
|
||
export { AWSLambda }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91d90ad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
langchainjs-docs – ./
langchainjs-docs-ruddy.vercel.app
langchainjs-docs-git-main-langchain.vercel.app
langchainjs-docs-langchain.vercel.app
js.langchain.com