codekingpro/portable-devtools
114k
1"""[DEPRECATED]2 3## Zapier Natural Language Actions API4\5Full docs here: https://nla.zapier.com/start/6 7**Zapier Natural Language Actions** gives you access to the 5k+ apps, 20k+ actions8on Zapier's platform through a natural language API interface.9 10NLA supports apps like Gmail, Salesforce, Trello, Slack, Asana, HubSpot, Google Sheets,11Microsoft Teams, and thousands more apps: https://zapier.com/apps12 13Zapier NLA handles ALL the underlying API auth and translation from14natural language --> underlying API call --> return simplified output for LLMs15The key idea is you, or your users, expose a set of actions via an oauth-like setup16window, which you can then query and execute via a REST API.17 18NLA offers both API Key and OAuth for signing NLA API requests.19 201. Server-side (API Key): for quickly getting started, testing, and production scenarios21 where LangChain will only use actions exposed in the developer's Zapier account22 (and will use the developer's connected accounts on Zapier.com)23 242. User-facing (Oauth): for production scenarios where you are deploying an end-user25 facing application and LangChain needs access to end-user's exposed actions and26 connected accounts on Zapier.com27 28This quick start will focus on the server-side use case for brevity.29Review [full docs](https://nla.zapier.com/start/) for user-facing oauth developer30support.31 32Typically, you'd use SequentialChain, here's a basic example:33 34 1. Use NLA to find an email in Gmail35 2. Use LLMChain to generate a draft reply to (1)36 3. Use NLA to send the draft reply (2) to someone in Slack via direct message37 38In code, below:39 40```python41 42import os43 44# get from https://platform.openai.com/45os.environ["OPENAI_API_KEY"] = os.environ.get("OPENAI_API_KEY", "")46 47# get from https://nla.zapier.com/docs/authentication/48os.environ["ZAPIER_NLA_API_KEY"] = os.environ.get("ZAPIER_NLA_API_KEY", "")49 50from langchain_community.agent_toolkits import ZapierToolkit51from langchain_community.utilities.zapier import ZapierNLAWrapper52 53## step 0. expose gmail 'find email' and slack 'send channel message' actions54 55# first go here, log in, expose (enable) the two actions:56# https://nla.zapier.com/demo/start57# -- for this example, can leave all fields "Have AI guess"58# in an oauth scenario, you'd get your own <provider> id (instead of 'demo')59# which you route your users through first60 61zapier = ZapierNLAWrapper()62## To leverage OAuth you may pass the value `nla_oauth_access_token` to63## the ZapierNLAWrapper. If you do this there is no need to initialize64## the ZAPIER_NLA_API_KEY env variable65# zapier = ZapierNLAWrapper(zapier_nla_oauth_access_token="TOKEN_HERE")66toolkit = ZapierToolkit.from_zapier_nla_wrapper(zapier)67```68 69"""70 71from typing import Any, Dict, Optional72 73from langchain_core._api import warn_deprecated74from langchain_core.callbacks import (75 AsyncCallbackManagerForToolRun,76 CallbackManagerForToolRun,77)78from langchain_core.tools import BaseTool79from langchain_core.utils import pre_init80from pydantic import Field81 82from langchain_community.tools.zapier.prompt import BASE_ZAPIER_TOOL_PROMPT83from langchain_community.utilities.zapier import ZapierNLAWrapper84 85 86class ZapierNLARunAction(BaseTool):87 """Tool to run a specific action from the user's exposed actions.88 89 Params:90 action_id: a specific action ID (from list actions) of the action to execute91 (the set api_key must be associated with the action owner)92 instructions: a natural language instruction string for using the action93 (eg. "get the latest email from Mike Knoop" for "Gmail: find email" action)94 params: a dict, optional. Any params provided will *override* AI guesses95 from `instructions` (see "understanding the AI guessing flow" here:96 https://nla.zapier.com/docs/using-the-api#ai-guessing)97 98 """99 100 api_wrapper: ZapierNLAWrapper = Field(default_factory=ZapierNLAWrapper) # type: ignore[arg-type]101 action_id: str102 params: Optional[dict] = None103 base_prompt: str = BASE_ZAPIER_TOOL_PROMPT104 zapier_description: str105 params_schema: Dict[str, str] = Field(default_factory=dict)106 name: str = ""107 description: str = ""108 109 @pre_init110 def set_name_description(cls, values: Dict[str, Any]) -> Dict[str, Any]:111 zapier_description = values["zapier_description"]112 params_schema = values["params_schema"]113 if "instructions" in params_schema:114 del params_schema["instructions"]115 116 # Ensure base prompt (if overridden) contains necessary input fields117 necessary_fields = {"{zapier_description}", "{params}"}118 if not all(field in values["base_prompt"] for field in necessary_fields):119 raise ValueError(120 "Your custom base Zapier prompt must contain input fields for "121 "{zapier_description} and {params}."122 )123 124 values["name"] = zapier_description125 values["description"] = values["base_prompt"].format(126 zapier_description=zapier_description,127 params=str(list(params_schema.keys())),128 )129 return values130 131 def _run(132 self, instructions: str, run_manager: Optional[CallbackManagerForToolRun] = None133 ) -> str:134 """Use the Zapier NLA tool to return a list of all exposed user actions."""135 warn_deprecated(136 since="0.0.319",137 message=(138 "This tool will be deprecated on 2023-11-17. See "139 "<https://nla.zapier.com/sunset/> for details"140 ),141 )142 return self.api_wrapper.run_as_str(self.action_id, instructions, self.params)143 144 async def _arun(145 self,146 instructions: str,147 run_manager: Optional[AsyncCallbackManagerForToolRun] = None,148 ) -> str:149 """Use the Zapier NLA tool to return a list of all exposed user actions."""150 warn_deprecated(151 since="0.0.319",152 message=(153 "This tool will be deprecated on 2023-11-17. See "154 "<https://nla.zapier.com/sunset/> for details"155 ),156 )157 return await self.api_wrapper.arun_as_str(158 self.action_id,159 instructions,160 self.params,161 )162 163 164ZapierNLARunAction.__doc__ = ZapierNLAWrapper.run.__doc__ + ZapierNLARunAction.__doc__ # type: ignore[operator]165 166 167# other useful actions168 169 170class ZapierNLAListActions(BaseTool):171 """Tool to list all exposed actions for the user."""172 173 name: str = "ZapierNLA_list_actions"174 description: str = BASE_ZAPIER_TOOL_PROMPT + (175 "This tool returns a list of the user's exposed actions."176 )177 api_wrapper: ZapierNLAWrapper = Field(default_factory=ZapierNLAWrapper) # type: ignore[arg-type]178 179 def _run(180 self,181 _: str = "",182 run_manager: Optional[CallbackManagerForToolRun] = None,183 ) -> str:184 """Use the Zapier NLA tool to return a list of all exposed user actions."""185 warn_deprecated(186 since="0.0.319",187 message=(188 "This tool will be deprecated on 2023-11-17. See "189 "<https://nla.zapier.com/sunset/> for details"190 ),191 )192 return self.api_wrapper.list_as_str()193 194 async def _arun(195 self,196 _: str = "",197 run_manager: Optional[AsyncCallbackManagerForToolRun] = None,198 ) -> str:199 """Use the Zapier NLA tool to return a list of all exposed user actions."""200 warn_deprecated(201 since="0.0.319",202 message=(203 "This tool will be deprecated on 2023-11-17. See "204 "<https://nla.zapier.com/sunset/> for details"205 ),206 )207 return await self.api_wrapper.alist_as_str()208 209 210ZapierNLAListActions.__doc__ = (211 ZapierNLAWrapper.list.__doc__ + ZapierNLAListActions.__doc__ # type: ignore[operator]212)213 