diff --git a/docs/modules/agents/tools/examples/awslambda.ipynb b/docs/modules/agents/tools/examples/awslambda.ipynb new file mode 100644 index 00000000..038fb976 --- /dev/null +++ b/docs/modules/agents/tools/examples/awslambda.ipynb @@ -0,0 +1,119 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## AWS Lambda API" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook goes over how to use the AWS Lambda Tool component.\n", + "\n", + "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.\n", + "\n", + "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.\n", + "\n", + "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.\n", + "\n", + "First, you need to install `boto3` python package." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "!pip install boto3 > /dev/null" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order for an agent to use the tool, you must provide it with the name and description that match the functionality of you lambda function's logic. \n", + "\n", + "You must also provide the name of your function. " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that because this tool is effectively just a wrapper around the boto3 library, you will need to run `aws configure` in order to make use of the tool. For more detail, see [here](https://docs.aws.amazon.com/cli/index.html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [ + "from langchain import OpenAI\n", + "from langchain.agents import load_tools, AgentType\n", + "\n", + "llm = OpenAI(temperature=0)\n", + "\n", + "tools = load_tools(\n", + " [\"awslambda\"],\n", + " awslambda_tool_name=\"email-sender\",\n", + " awslambda_tool_description=\"sends an email with the specified content to test@testing123.com\",\n", + " function_name=\"testFunction1\"\n", + ")\n", + "\n", + "agent = initialize_agent(tools, llm, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)\n", + "\n", + "agent.run(\"Send an email to test@testing123.com saying hello world.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "vscode": { + "languageId": "shellscript" + } + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.2" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/langchain/agents/load_tools.py b/langchain/agents/load_tools.py index e11440e8..d5255de7 100644 --- a/langchain/agents/load_tools.py +++ b/langchain/agents/load_tools.py @@ -37,6 +37,7 @@ from langchain.utilities.bing_search import BingSearchAPIWrapper from langchain.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper from langchain.utilities.google_search import GoogleSearchAPIWrapper from langchain.utilities.google_serper import GoogleSerperAPIWrapper +from langchain.utilities.awslambda import LambdaWrapper from langchain.utilities.searx_search import SearxSearchWrapper from langchain.utilities.serpapi import SerpAPIWrapper from langchain.utilities.wikipedia import WikipediaAPIWrapper @@ -165,6 +166,14 @@ def _get_podcast_api(llm: BaseLLM, **kwargs: Any) -> BaseTool: ) +def _get_lambda_api(**kwargs: Any) -> BaseTool: + return Tool( + name=kwargs["awslambda_tool_name"], + description=kwargs["awslambda_tool_description"], + func=LambdaWrapper(**kwargs).run, + ) + + def _get_wolfram_alpha(**kwargs: Any) -> BaseTool: return WolframAlphaQueryRun(api_wrapper=WolframAlphaAPIWrapper(**kwargs)) @@ -249,6 +258,10 @@ _EXTRA_OPTIONAL_TOOLS: Dict[str, Tuple[Callable[[KwArg(Any)], BaseTool], List[st "searx-search": (_get_searx_search, ["searx_host", "engines", "aiosession"]), "wikipedia": (_get_wikipedia, ["top_k_results", "lang"]), "human": (_get_human_tool, ["prompt_func", "input_func"]), + "awslambda": ( + _get_lambda_api, + ["awslambda_tool_name", "awslambda_tool_description", "function_name"], + ), } diff --git a/langchain/utilities/__init__.py b/langchain/utilities/__init__.py index 02477629..7269444d 100644 --- a/langchain/utilities/__init__.py +++ b/langchain/utilities/__init__.py @@ -2,6 +2,7 @@ from langchain.requests import TextRequestsWrapper from langchain.utilities.apify import ApifyWrapper from langchain.utilities.arxiv import ArxivAPIWrapper +from langchain.utilities.awslambda import LambdaWrapper from langchain.utilities.bash import BashProcess from langchain.utilities.bing_search import BingSearchAPIWrapper from langchain.utilities.google_places_api import GooglePlacesAPIWrapper @@ -30,5 +31,6 @@ __all__ = [ "WikipediaAPIWrapper", "OpenWeatherMapAPIWrapper", "PythonREPL", + "LambdaWrapper", "PowerBIDataset", ] diff --git a/langchain/utilities/awslambda.py b/langchain/utilities/awslambda.py new file mode 100644 index 00000000..9a1beebf --- /dev/null +++ b/langchain/utilities/awslambda.py @@ -0,0 +1,66 @@ +"""Util that calls Lambda.""" +import json +from typing import Any, Dict, Optional + +from pydantic import BaseModel, Extra, root_validator + + +class LambdaWrapper(BaseModel): + """Wrapper for AWS Lambda SDK. + + Docs for using: + + 1. pip install boto3 + 2. Create a lambda function using the AWS Console or CLI + 3. Run `aws configure` and enter your AWS credentials + + """ + + lambda_client: Any #: :meta private: + function_name: Optional[str] = None + awslambda_tool_name: Optional[str] = None + awslambda_tool_description: Optional[str] = None + + class Config: + """Configuration for this pydantic object.""" + + extra = Extra.forbid + + @root_validator() + def validate_environment(cls, values: Dict) -> Dict: + """Validate that python package exists in environment.""" + + try: + import boto3 + + except ImportError: + raise ImportError( + "boto3 is not installed." "Please install it with `pip install boto3`" + ) + + values["lambda_client"] = boto3.client("lambda") + values["function_name"] = values["function_name"] + + return values + + def run(self, query: str) -> str: + """Invoke Lambda function and parse result.""" + res = self.lambda_client.invoke( + FunctionName=self.function_name, + InvocationType="RequestResponse", + Payload=json.dumps({"body": query}), + ) + + try: + payload_stream = res["Payload"] + payload_string = payload_stream.read().decode("utf-8") + answer = json.loads(payload_string)["body"] + + except StopIteration: + return "Failed to parse response from Lambda" + + if answer is None or answer == "": + # We don't want to return the assumption alone if answer is empty + return "Request failed." + else: + return f"Result: {answer}"