initial commit

This commit is contained in:
2026-05-11 12:36:20 +05:30
commit 384cbe8019
15377 changed files with 2360544 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
"""Main entrypoint into package."""
from importlib import metadata
try:
__version__ = metadata.version(__package__)
except metadata.PackageNotFoundError:
# Case where package metadata is not available.
__version__ = ""
del metadata # optional, avoids polluting the results of dir(__package__)

View File

@@ -0,0 +1,8 @@
"""**Adapters** are used to adapt LangChain models to other APIs.
LangChain integrates with many model providers.
While LangChain has its own message and model APIs,
LangChain has also made it as easy as
possible to explore other models by exposing an **adapter** to adapt LangChain
models to the other APIs, as to the OpenAI API.
"""

View File

@@ -0,0 +1,421 @@
from __future__ import annotations
import importlib
from typing import (
Any,
AsyncIterator,
Dict,
Iterable,
List,
Mapping,
Sequence,
Union,
overload,
)
from langchain_core.chat_sessions import ChatSession
from langchain_core.messages import (
AIMessage,
AIMessageChunk,
BaseMessage,
BaseMessageChunk,
ChatMessage,
FunctionMessage,
HumanMessage,
SystemMessage,
ToolMessage,
)
from pydantic import BaseModel
from typing_extensions import Literal
async def aenumerate(
iterable: AsyncIterator[Any], start: int = 0
) -> AsyncIterator[tuple[int, Any]]:
"""Async version of enumerate function."""
i = start
async for x in iterable:
yield i, x
i += 1
class IndexableBaseModel(BaseModel):
"""Allows a BaseModel to return its fields by string variable indexing."""
def __getitem__(self, item: str) -> Any:
return getattr(self, item)
class Choice(IndexableBaseModel):
"""Choice."""
message: dict
class ChatCompletions(IndexableBaseModel):
"""Chat completions."""
choices: List[Choice]
class ChoiceChunk(IndexableBaseModel):
"""Choice chunk."""
delta: dict
class ChatCompletionChunk(IndexableBaseModel):
"""Chat completion chunk."""
choices: List[ChoiceChunk]
def convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage:
"""Convert a dictionary to a LangChain message.
Args:
_dict: The dictionary.
Returns:
The LangChain message.
"""
role = _dict.get("role")
if role == "user":
return HumanMessage(content=_dict.get("content", ""))
elif role == "assistant":
# Fix for azure
# Also OpenAI returns None for tool invocations
content = _dict.get("content", "") or ""
additional_kwargs: Dict = {}
if function_call := _dict.get("function_call"):
additional_kwargs["function_call"] = dict(function_call)
if tool_calls := _dict.get("tool_calls"):
additional_kwargs["tool_calls"] = tool_calls
if context := _dict.get("context"):
additional_kwargs["context"] = context
return AIMessage(content=content, additional_kwargs=additional_kwargs)
elif role == "system":
return SystemMessage(content=_dict.get("content", ""))
elif role == "function":
return FunctionMessage(content=_dict.get("content", ""), name=_dict.get("name")) # type: ignore[arg-type]
elif role == "tool":
additional_kwargs = {}
if "name" in _dict:
additional_kwargs["name"] = _dict["name"]
return ToolMessage(
content=_dict.get("content", ""),
tool_call_id=_dict.get("tool_call_id"),
additional_kwargs=additional_kwargs,
)
else:
return ChatMessage(content=_dict.get("content", ""), role=role) # type: ignore[arg-type]
def convert_message_to_dict(message: BaseMessage) -> dict:
"""Convert a LangChain message to a dictionary.
Args:
message: The LangChain message.
Returns:
The dictionary.
"""
message_dict: Dict[str, Any]
if isinstance(message, ChatMessage):
message_dict = {"role": message.role, "content": message.content}
elif isinstance(message, HumanMessage):
message_dict = {"role": "user", "content": message.content}
elif isinstance(message, AIMessage):
message_dict = {"role": "assistant", "content": message.content}
if "function_call" in message.additional_kwargs:
message_dict["function_call"] = message.additional_kwargs["function_call"]
# If function call only, content is None not empty string
if message_dict["content"] == "":
message_dict["content"] = None
if "tool_calls" in message.additional_kwargs:
message_dict["tool_calls"] = message.additional_kwargs["tool_calls"]
# If tool calls only, content is None not empty string
if message_dict["content"] == "":
message_dict["content"] = None
if "context" in message.additional_kwargs:
message_dict["context"] = message.additional_kwargs["context"]
# If context only, content is None not empty string
if message_dict["content"] == "":
message_dict["content"] = None
elif isinstance(message, SystemMessage):
message_dict = {"role": "system", "content": message.content}
elif isinstance(message, FunctionMessage):
message_dict = {
"role": "function",
"content": message.content,
"name": message.name,
}
elif isinstance(message, ToolMessage):
message_dict = {
"role": "tool",
"content": message.content,
"tool_call_id": message.tool_call_id,
}
else:
raise TypeError(f"Got unknown type {message}")
if "name" in message.additional_kwargs:
message_dict["name"] = message.additional_kwargs["name"]
return message_dict
def convert_openai_messages(messages: Sequence[Dict[str, Any]]) -> List[BaseMessage]:
"""Convert dictionaries representing OpenAI messages to LangChain format.
Args:
messages: List of dictionaries representing OpenAI messages
Returns:
List of LangChain BaseMessage objects.
"""
return [convert_dict_to_message(m) for m in messages]
def _convert_message_chunk(chunk: BaseMessageChunk, i: int) -> dict:
_dict: Dict[str, Any] = {}
if isinstance(chunk, AIMessageChunk):
if i == 0:
# Only shows up in the first chunk
_dict["role"] = "assistant"
if "function_call" in chunk.additional_kwargs:
_dict["function_call"] = chunk.additional_kwargs["function_call"]
# If the first chunk is a function call, the content is not empty string,
# not missing, but None.
if i == 0:
_dict["content"] = None
if "tool_calls" in chunk.additional_kwargs:
_dict["tool_calls"] = chunk.additional_kwargs["tool_calls"]
# If the first chunk is tool calls, the content is not empty string,
# not missing, but None.
if i == 0:
_dict["content"] = None
else:
_dict["content"] = chunk.content
else:
raise ValueError(f"Got unexpected streaming chunk type: {type(chunk)}")
# This only happens at the end of streams, and OpenAI returns as empty dict
if _dict == {"content": ""}:
_dict = {}
return _dict
def _convert_message_chunk_to_delta(chunk: BaseMessageChunk, i: int) -> Dict[str, Any]:
_dict = _convert_message_chunk(chunk, i)
return {"choices": [{"delta": _dict}]}
class ChatCompletion:
"""Chat completion."""
@overload
@staticmethod
def create(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[False] = False,
**kwargs: Any,
) -> dict: ...
@overload
@staticmethod
def create(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[True],
**kwargs: Any,
) -> Iterable: ...
@staticmethod
def create(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: bool = False,
**kwargs: Any,
) -> Union[dict, Iterable]:
models = importlib.import_module("langchain.chat_models")
model_cls = getattr(models, provider)
model_config = model_cls(**kwargs)
converted_messages = convert_openai_messages(messages)
if not stream:
result = model_config.invoke(converted_messages)
return {"choices": [{"message": convert_message_to_dict(result)}]}
else:
return (
_convert_message_chunk_to_delta(c, i)
for i, c in enumerate(model_config.stream(converted_messages))
)
@overload
@staticmethod
async def acreate(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[False] = False,
**kwargs: Any,
) -> dict: ...
@overload
@staticmethod
async def acreate(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[True],
**kwargs: Any,
) -> AsyncIterator: ...
@staticmethod
async def acreate(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: bool = False,
**kwargs: Any,
) -> Union[dict, AsyncIterator]:
models = importlib.import_module("langchain.chat_models")
model_cls = getattr(models, provider)
model_config = model_cls(**kwargs)
converted_messages = convert_openai_messages(messages)
if not stream:
result = await model_config.ainvoke(converted_messages)
return {"choices": [{"message": convert_message_to_dict(result)}]}
else:
return (
_convert_message_chunk_to_delta(c, i)
async for i, c in aenumerate(model_config.astream(converted_messages))
)
def _has_assistant_message(session: ChatSession) -> bool:
"""Check if chat session has an assistant message."""
return any([isinstance(m, AIMessage) for m in session["messages"]])
def convert_messages_for_finetuning(
sessions: Iterable[ChatSession],
) -> List[List[dict]]:
"""Convert messages to a list of lists of dictionaries for fine-tuning.
Args:
sessions: The chat sessions.
Returns:
The list of lists of dictionaries.
"""
return [
[convert_message_to_dict(s) for s in session["messages"]]
for session in sessions
if _has_assistant_message(session)
]
class Completions:
"""Completions."""
@overload
@staticmethod
def create(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[False] = False,
**kwargs: Any,
) -> ChatCompletions: ...
@overload
@staticmethod
def create(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[True],
**kwargs: Any,
) -> Iterable: ...
@staticmethod
def create(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: bool = False,
**kwargs: Any,
) -> Union[ChatCompletions, Iterable]:
models = importlib.import_module("langchain.chat_models")
model_cls = getattr(models, provider)
model_config = model_cls(**kwargs)
converted_messages = convert_openai_messages(messages)
if not stream:
result = model_config.invoke(converted_messages)
return ChatCompletions(
choices=[Choice(message=convert_message_to_dict(result))]
)
else:
return (
ChatCompletionChunk(
choices=[ChoiceChunk(delta=_convert_message_chunk(c, i))]
)
for i, c in enumerate(model_config.stream(converted_messages))
)
@overload
@staticmethod
async def acreate(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[False] = False,
**kwargs: Any,
) -> ChatCompletions: ...
@overload
@staticmethod
async def acreate(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: Literal[True],
**kwargs: Any,
) -> AsyncIterator: ...
@staticmethod
async def acreate(
messages: Sequence[Dict[str, Any]],
*,
provider: str = "ChatOpenAI",
stream: bool = False,
**kwargs: Any,
) -> Union[ChatCompletions, AsyncIterator]:
models = importlib.import_module("langchain.chat_models")
model_cls = getattr(models, provider)
model_config = model_cls(**kwargs)
converted_messages = convert_openai_messages(messages)
if not stream:
result = await model_config.ainvoke(converted_messages)
return ChatCompletions(
choices=[Choice(message=convert_message_to_dict(result))]
)
else:
return (
ChatCompletionChunk(
choices=[ChoiceChunk(delta=_convert_message_chunk(c, i))]
)
async for i, c in aenumerate(model_config.astream(converted_messages))
)
class Chat:
"""Chat."""
def __init__(self) -> None:
self.completions = Completions()
chat = Chat()

View File

@@ -0,0 +1,170 @@
"""**Toolkits** are sets of tools that can be used to interact with
various services and APIs.
"""
import importlib
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from langchain_community.agent_toolkits.ainetwork.toolkit import (
AINetworkToolkit,
)
from langchain_community.agent_toolkits.amadeus.toolkit import (
AmadeusToolkit,
)
from langchain_community.agent_toolkits.azure_ai_services import (
AzureAiServicesToolkit,
)
from langchain_community.agent_toolkits.azure_cognitive_services import (
AzureCognitiveServicesToolkit,
)
from langchain_community.agent_toolkits.cassandra_database.toolkit import (
CassandraDatabaseToolkit, # noqa: F401
)
from langchain_community.agent_toolkits.cogniswitch.toolkit import (
CogniswitchToolkit,
)
from langchain_community.agent_toolkits.connery import (
ConneryToolkit,
)
from langchain_community.agent_toolkits.file_management.toolkit import (
FileManagementToolkit,
)
from langchain_community.agent_toolkits.gmail.toolkit import (
GmailToolkit,
)
from langchain_community.agent_toolkits.jira.toolkit import (
JiraToolkit,
)
from langchain_community.agent_toolkits.json.base import (
create_json_agent,
)
from langchain_community.agent_toolkits.json.toolkit import (
JsonToolkit,
)
from langchain_community.agent_toolkits.multion.toolkit import (
MultionToolkit,
)
from langchain_community.agent_toolkits.nasa.toolkit import (
NasaToolkit,
)
from langchain_community.agent_toolkits.nla.toolkit import (
NLAToolkit,
)
from langchain_community.agent_toolkits.office365.toolkit import (
O365Toolkit,
)
from langchain_community.agent_toolkits.openapi.base import (
create_openapi_agent,
)
from langchain_community.agent_toolkits.openapi.toolkit import (
OpenAPIToolkit,
)
from langchain_community.agent_toolkits.playwright.toolkit import (
PlayWrightBrowserToolkit,
)
from langchain_community.agent_toolkits.polygon.toolkit import (
PolygonToolkit,
)
from langchain_community.agent_toolkits.powerbi.base import (
create_pbi_agent,
)
from langchain_community.agent_toolkits.powerbi.chat_base import (
create_pbi_chat_agent,
)
from langchain_community.agent_toolkits.powerbi.toolkit import (
PowerBIToolkit,
)
from langchain_community.agent_toolkits.slack.toolkit import (
SlackToolkit,
)
from langchain_community.agent_toolkits.spark_sql.base import (
create_spark_sql_agent,
)
from langchain_community.agent_toolkits.spark_sql.toolkit import (
SparkSQLToolkit,
)
from langchain_community.agent_toolkits.sql.base import (
create_sql_agent,
)
from langchain_community.agent_toolkits.sql.toolkit import (
SQLDatabaseToolkit,
)
from langchain_community.agent_toolkits.steam.toolkit import (
SteamToolkit,
)
from langchain_community.agent_toolkits.zapier.toolkit import (
ZapierToolkit,
)
__all__ = [
"AINetworkToolkit",
"AmadeusToolkit",
"AzureAiServicesToolkit",
"AzureCognitiveServicesToolkit",
"CogniswitchToolkit",
"ConneryToolkit",
"FileManagementToolkit",
"GmailToolkit",
"JiraToolkit",
"JsonToolkit",
"MultionToolkit",
"NLAToolkit",
"NasaToolkit",
"O365Toolkit",
"OpenAPIToolkit",
"PlayWrightBrowserToolkit",
"PolygonToolkit",
"PowerBIToolkit",
"SQLDatabaseToolkit",
"SlackToolkit",
"SparkSQLToolkit",
"SteamToolkit",
"ZapierToolkit",
"create_json_agent",
"create_openapi_agent",
"create_pbi_agent",
"create_pbi_chat_agent",
"create_spark_sql_agent",
"create_sql_agent",
]
_module_lookup = {
"AINetworkToolkit": "langchain_community.agent_toolkits.ainetwork.toolkit",
"AmadeusToolkit": "langchain_community.agent_toolkits.amadeus.toolkit",
"AzureAiServicesToolkit": "langchain_community.agent_toolkits.azure_ai_services",
"AzureCognitiveServicesToolkit": "langchain_community.agent_toolkits.azure_cognitive_services", # noqa: E501
"CogniswitchToolkit": "langchain_community.agent_toolkits.cogniswitch.toolkit",
"ConneryToolkit": "langchain_community.agent_toolkits.connery",
"FileManagementToolkit": "langchain_community.agent_toolkits.file_management.toolkit", # noqa: E501
"GmailToolkit": "langchain_community.agent_toolkits.gmail.toolkit",
"JiraToolkit": "langchain_community.agent_toolkits.jira.toolkit",
"JsonToolkit": "langchain_community.agent_toolkits.json.toolkit",
"MultionToolkit": "langchain_community.agent_toolkits.multion.toolkit",
"NLAToolkit": "langchain_community.agent_toolkits.nla.toolkit",
"NasaToolkit": "langchain_community.agent_toolkits.nasa.toolkit",
"O365Toolkit": "langchain_community.agent_toolkits.office365.toolkit",
"OpenAPIToolkit": "langchain_community.agent_toolkits.openapi.toolkit",
"PlayWrightBrowserToolkit": "langchain_community.agent_toolkits.playwright.toolkit",
"PolygonToolkit": "langchain_community.agent_toolkits.polygon.toolkit",
"PowerBIToolkit": "langchain_community.agent_toolkits.powerbi.toolkit",
"SQLDatabaseToolkit": "langchain_community.agent_toolkits.sql.toolkit",
"SlackToolkit": "langchain_community.agent_toolkits.slack.toolkit",
"SparkSQLToolkit": "langchain_community.agent_toolkits.spark_sql.toolkit",
"SteamToolkit": "langchain_community.agent_toolkits.steam.toolkit",
"ZapierToolkit": "langchain_community.agent_toolkits.zapier.toolkit",
"create_json_agent": "langchain_community.agent_toolkits.json.base",
"create_openapi_agent": "langchain_community.agent_toolkits.openapi.base",
"create_pbi_agent": "langchain_community.agent_toolkits.powerbi.base",
"create_pbi_chat_agent": "langchain_community.agent_toolkits.powerbi.chat_base",
"create_spark_sql_agent": "langchain_community.agent_toolkits.spark_sql.base",
"create_sql_agent": "langchain_community.agent_toolkits.sql.base",
}
def __getattr__(name: str) -> Any:
if name in _module_lookup:
module = importlib.import_module(_module_lookup[name])
return getattr(module, name)
raise AttributeError(f"module {__name__} has no attribute {name}")

View File

@@ -0,0 +1 @@
"""AINetwork toolkit."""

View File

@@ -0,0 +1,70 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any, List, Literal, Optional
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import ConfigDict, model_validator
from langchain_community.tools.ainetwork.app import AINAppOps
from langchain_community.tools.ainetwork.owner import AINOwnerOps
from langchain_community.tools.ainetwork.rule import AINRuleOps
from langchain_community.tools.ainetwork.transfer import AINTransfer
from langchain_community.tools.ainetwork.utils import authenticate
from langchain_community.tools.ainetwork.value import AINValueOps
if TYPE_CHECKING:
from ain.ain import Ain
class AINetworkToolkit(BaseToolkit):
"""Toolkit for interacting with AINetwork Blockchain.
*Security Note*: This toolkit contains tools that can read and modify
the state of a service; e.g., by reading, creating, updating, deleting
data associated with this service.
See https://python.langchain.com/docs/security for more information.
Parameters:
network: Optional. The network to connect to. Default is "testnet".
Options are "mainnet" or "testnet".
interface: Optional. The interface to use. If not provided, will
attempt to authenticate with the network. Default is None.
"""
network: Optional[Literal["mainnet", "testnet"]] = "testnet"
interface: Optional[Ain] = None
@model_validator(mode="before")
@classmethod
def set_interface(cls, values: dict) -> Any:
"""Set the interface if not provided.
If the interface is not provided, attempt to authenticate with the
network using the network value provided.
Args:
values: The values to validate.
Returns:
The validated values.
"""
if not values.get("interface"):
values["interface"] = authenticate(network=values.get("network", "testnet"))
return values
model_config = ConfigDict(
arbitrary_types_allowed=True,
validate_default=True,
)
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
AINAppOps(),
AINOwnerOps(),
AINRuleOps(),
AINTransfer(),
AINValueOps(),
]

View File

@@ -0,0 +1,38 @@
from __future__ import annotations
from typing import TYPE_CHECKING, List, Optional
from langchain_core.language_models import BaseLanguageModel
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import ConfigDict, Field
from langchain_community.tools.amadeus.closest_airport import AmadeusClosestAirport
from langchain_community.tools.amadeus.flight_search import AmadeusFlightSearch
from langchain_community.tools.amadeus.utils import authenticate
if TYPE_CHECKING:
from amadeus import Client
class AmadeusToolkit(BaseToolkit):
"""Toolkit for interacting with Amadeus which offers APIs for travel.
Parameters:
client: Optional. The Amadeus client. Default is None.
llm: Optional. The language model to use. Default is None.
"""
client: Client = Field(default_factory=authenticate)
llm: Optional[BaseLanguageModel] = Field(default=None)
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
AmadeusClosestAirport(llm=self.llm),
AmadeusFlightSearch(),
]

View File

@@ -0,0 +1,31 @@
from __future__ import annotations
from typing import List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.azure_ai_services import (
AzureAiServicesDocumentIntelligenceTool,
AzureAiServicesImageAnalysisTool,
AzureAiServicesSpeechToTextTool,
AzureAiServicesTextAnalyticsForHealthTool,
AzureAiServicesTextToSpeechTool,
)
class AzureAiServicesToolkit(BaseToolkit):
"""Toolkit for Azure AI Services."""
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
tools: List[BaseTool] = [
AzureAiServicesDocumentIntelligenceTool(), # type: ignore[call-arg]
AzureAiServicesImageAnalysisTool(),
AzureAiServicesSpeechToTextTool(), # type: ignore[call-arg]
AzureAiServicesTextToSpeechTool(), # type: ignore[call-arg]
AzureAiServicesTextAnalyticsForHealthTool(), # type: ignore[call-arg]
]
return tools

View File

@@ -0,0 +1,34 @@
from __future__ import annotations
import sys
from typing import List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.azure_cognitive_services import (
AzureCogsFormRecognizerTool,
AzureCogsImageAnalysisTool,
AzureCogsSpeech2TextTool,
AzureCogsText2SpeechTool,
AzureCogsTextAnalyticsHealthTool,
)
class AzureCognitiveServicesToolkit(BaseToolkit):
"""Toolkit for Azure Cognitive Services."""
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
tools: List[BaseTool] = [
AzureCogsFormRecognizerTool(), # type: ignore[call-arg]
AzureCogsSpeech2TextTool(), # type: ignore[call-arg]
AzureCogsText2SpeechTool(), # type: ignore[call-arg]
AzureCogsTextAnalyticsHealthTool(), # type: ignore[call-arg]
]
# TODO: Remove check once azure-ai-vision supports MacOS.
if sys.platform.startswith("linux") or sys.platform.startswith("win"):
tools.append(AzureCogsImageAnalysisTool()) # type: ignore[call-arg]
return tools

View File

@@ -0,0 +1,5 @@
"""Toolkits for agents."""
from langchain_core.tools.base import BaseToolkit
__all__ = ["BaseToolkit"]

View File

@@ -0,0 +1 @@
"""Apache Cassandra Toolkit."""

View File

@@ -0,0 +1,37 @@
"""Apache Cassandra Toolkit."""
from typing import List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import ConfigDict, Field
from langchain_community.tools.cassandra_database.tool import (
GetSchemaCassandraDatabaseTool,
GetTableDataCassandraDatabaseTool,
QueryCassandraDatabaseTool,
)
from langchain_community.utilities.cassandra_database import CassandraDatabase
class CassandraDatabaseToolkit(BaseToolkit):
"""Toolkit for interacting with an Apache Cassandra database.
Parameters:
db: CassandraDatabase. The Cassandra database to interact
with.
"""
db: CassandraDatabase = Field(exclude=True)
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
GetSchemaCassandraDatabaseTool(db=self.db),
QueryCassandraDatabaseTool(db=self.db),
GetTableDataCassandraDatabaseTool(db=self.db),
]

View File

@@ -0,0 +1,120 @@
from typing import Dict, List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.clickup.prompt import (
CLICKUP_FOLDER_CREATE_PROMPT,
CLICKUP_GET_ALL_TEAMS_PROMPT,
CLICKUP_GET_FOLDERS_PROMPT,
CLICKUP_GET_LIST_PROMPT,
CLICKUP_GET_SPACES_PROMPT,
CLICKUP_GET_TASK_ATTRIBUTE_PROMPT,
CLICKUP_GET_TASK_PROMPT,
CLICKUP_LIST_CREATE_PROMPT,
CLICKUP_TASK_CREATE_PROMPT,
CLICKUP_UPDATE_TASK_ASSIGNEE_PROMPT,
CLICKUP_UPDATE_TASK_PROMPT,
)
from langchain_community.tools.clickup.tool import ClickupAction
from langchain_community.utilities.clickup import ClickupAPIWrapper
class ClickupToolkit(BaseToolkit):
"""Clickup Toolkit.
*Security Note*: This toolkit contains tools that can read and modify
the state of a service; e.g., by reading, creating, updating, deleting
data associated with this service.
See https://python.langchain.com/docs/security for more information.
Parameters:
tools: List[BaseTool]. The tools in the toolkit. Default is an empty list.
"""
tools: List[BaseTool] = []
@classmethod
def from_clickup_api_wrapper(
cls, clickup_api_wrapper: ClickupAPIWrapper
) -> "ClickupToolkit":
"""Create a ClickupToolkit from a ClickupAPIWrapper.
Args:
clickup_api_wrapper: ClickupAPIWrapper. The Clickup API wrapper.
Returns:
ClickupToolkit. The Clickup toolkit.
"""
operations: List[Dict] = [
{
"mode": "get_task",
"name": "Get task",
"description": CLICKUP_GET_TASK_PROMPT,
},
{
"mode": "get_task_attribute",
"name": "Get task attribute",
"description": CLICKUP_GET_TASK_ATTRIBUTE_PROMPT,
},
{
"mode": "get_teams",
"name": "Get Teams",
"description": CLICKUP_GET_ALL_TEAMS_PROMPT,
},
{
"mode": "create_task",
"name": "Create Task",
"description": CLICKUP_TASK_CREATE_PROMPT,
},
{
"mode": "create_list",
"name": "Create List",
"description": CLICKUP_LIST_CREATE_PROMPT,
},
{
"mode": "create_folder",
"name": "Create Folder",
"description": CLICKUP_FOLDER_CREATE_PROMPT,
},
{
"mode": "get_list",
"name": "Get all lists in the space",
"description": CLICKUP_GET_LIST_PROMPT,
},
{
"mode": "get_folders",
"name": "Get all folders in the workspace",
"description": CLICKUP_GET_FOLDERS_PROMPT,
},
{
"mode": "get_spaces",
"name": "Get all spaces in the workspace",
"description": CLICKUP_GET_SPACES_PROMPT,
},
{
"mode": "update_task",
"name": "Update task",
"description": CLICKUP_UPDATE_TASK_PROMPT,
},
{
"mode": "update_task_assignees",
"name": "Update task assignees",
"description": CLICKUP_UPDATE_TASK_ASSIGNEE_PROMPT,
},
]
tools = [
ClickupAction(
name=action["name"],
description=action["description"],
mode=action["mode"],
api_wrapper=clickup_api_wrapper,
)
for action in operations
]
return cls(tools=tools) # type: ignore[arg-type]
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return self.tools

View File

@@ -0,0 +1 @@
"""CogniSwitch Toolkit"""

View File

@@ -0,0 +1,45 @@
from typing import List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.cogniswitch.tool import (
CogniswitchKnowledgeRequest,
CogniswitchKnowledgeSourceFile,
CogniswitchKnowledgeSourceURL,
CogniswitchKnowledgeStatus,
)
class CogniswitchToolkit(BaseToolkit):
"""Toolkit for CogniSwitch.
Use the toolkit to get all the tools present in the Cogniswitch and
use them to interact with your knowledge.
Parameters:
cs_token: str. The Cogniswitch token.
OAI_token: str. The OpenAI API token.
apiKey: str. The Cogniswitch OAuth token.
"""
cs_token: str
OAI_token: str
apiKey: str
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
CogniswitchKnowledgeStatus(
cs_token=self.cs_token, OAI_token=self.OAI_token, apiKey=self.apiKey
),
CogniswitchKnowledgeRequest(
cs_token=self.cs_token, OAI_token=self.OAI_token, apiKey=self.apiKey
),
CogniswitchKnowledgeSourceFile(
cs_token=self.cs_token, OAI_token=self.OAI_token, apiKey=self.apiKey
),
CogniswitchKnowledgeSourceURL(
cs_token=self.cs_token, OAI_token=self.OAI_token, apiKey=self.apiKey
),
]

View File

@@ -0,0 +1,7 @@
"""
This module contains the ConneryToolkit.
"""
from .toolkit import ConneryToolkit
__all__ = ["ConneryToolkit"]

View File

@@ -0,0 +1,60 @@
from typing import Any, List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import model_validator
from langchain_community.tools.connery import ConneryService
class ConneryToolkit(BaseToolkit):
"""
Toolkit with a list of Connery Actions as tools.
Parameters:
tools (List[BaseTool]): The list of Connery Actions.
"""
tools: List[BaseTool]
def get_tools(self) -> List[BaseTool]:
"""
Returns the list of Connery Actions.
"""
return self.tools
@model_validator(mode="before")
@classmethod
def validate_attributes(cls, values: dict) -> Any:
"""
Validate the attributes of the ConneryToolkit class.
Args:
values (dict): The arguments to validate.
Returns:
dict: The validated arguments.
Raises:
ValueError: If the 'tools' attribute is not set
"""
if not values.get("tools"):
raise ValueError("The attribute 'tools' must be set.")
return values
@classmethod
def create_instance(cls, connery_service: ConneryService) -> "ConneryToolkit":
"""
Creates a Connery Toolkit using a Connery Service.
Parameters:
connery_service (ConneryService): The Connery Service
to get the list of Connery Actions.
Returns:
ConneryToolkit: The Connery Toolkit.
"""
instance = cls(tools=connery_service.list_actions()) # type: ignore[arg-type]
return instance

View File

@@ -0,0 +1,26 @@
from pathlib import Path
from typing import Any
from langchain_core._api.path import as_import_path
def __getattr__(name: str) -> Any:
"""Get attr name."""
if name == "create_csv_agent":
# Get directory of langchain package
HERE = Path(__file__).parents[3]
here = as_import_path(Path(__file__).parent, relative_to=HERE)
old_path = "langchain." + here + "." + name
new_path = "langchain_experimental." + here + "." + name
raise ImportError(
"This agent has been moved to langchain experiment. "
"This agent relies on python REPL tool under the hood, so to use it "
"safely please sandbox the python REPL. "
"Read https://github.com/langchain-ai/langchain/blob/master/SECURITY.md "
"and https://github.com/langchain-ai/langchain/discussions/11680"
"To keep using this code as is, install langchain experimental and "
f"update your import statement from:\n `{old_path}` to `{new_path}`."
)
raise AttributeError(f"{name} does not exist")

View File

@@ -0,0 +1,7 @@
"""Local file management toolkit."""
from langchain_community.agent_toolkits.file_management.toolkit import (
FileManagementToolkit,
)
__all__ = ["FileManagementToolkit"]

View File

@@ -0,0 +1,88 @@
from __future__ import annotations
from typing import Any, Dict, List, Optional, Type
from langchain_core.tools import BaseTool, BaseToolkit
from langchain_core.utils.pydantic import get_fields
from pydantic import model_validator
from langchain_community.tools.file_management.copy import CopyFileTool
from langchain_community.tools.file_management.delete import DeleteFileTool
from langchain_community.tools.file_management.file_search import FileSearchTool
from langchain_community.tools.file_management.list_dir import ListDirectoryTool
from langchain_community.tools.file_management.move import MoveFileTool
from langchain_community.tools.file_management.read import ReadFileTool
from langchain_community.tools.file_management.write import WriteFileTool
_FILE_TOOLS: List[Type[BaseTool]] = [
CopyFileTool,
DeleteFileTool,
FileSearchTool,
MoveFileTool,
ReadFileTool,
WriteFileTool,
ListDirectoryTool,
]
_FILE_TOOLS_MAP: Dict[str, Type[BaseTool]] = {
get_fields(tool_cls)["name"].default: tool_cls for tool_cls in _FILE_TOOLS
}
class FileManagementToolkit(BaseToolkit):
"""Toolkit for interacting with local files.
*Security Notice*: This toolkit provides methods to interact with local files.
If providing this toolkit to an agent on an LLM, ensure you scope
the agent's permissions to only include the necessary permissions
to perform the desired operations.
By **default** the agent will have access to all files within
the root dir and will be able to Copy, Delete, Move, Read, Write
and List files in that directory.
Consider the following:
- Limit access to particular directories using `root_dir`.
- Use filesystem permissions to restrict access and permissions to only
the files and directories required by the agent.
- Limit the tools available to the agent to only the file operations
necessary for the agent's intended use.
- Sandbox the agent by running it in a container.
See https://python.langchain.com/docs/security for more information.
Parameters:
root_dir: Optional. The root directory to perform file operations.
If not provided, file operations are performed relative to the current
working directory.
selected_tools: Optional. The tools to include in the toolkit. If not
provided, all tools are included.
"""
root_dir: Optional[str] = None
"""If specified, all file operations are made relative to root_dir."""
selected_tools: Optional[List[str]] = None
"""If provided, only provide the selected tools. Defaults to all."""
@model_validator(mode="before")
@classmethod
def validate_tools(cls, values: dict) -> Any:
selected_tools = values.get("selected_tools") or []
for tool_name in selected_tools:
if tool_name not in _FILE_TOOLS_MAP:
raise ValueError(
f"File Tool of name {tool_name} not supported."
f" Permitted tools: {list(_FILE_TOOLS_MAP)}"
)
return values
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
allowed_tools = self.selected_tools or _FILE_TOOLS_MAP
tools: List[BaseTool] = []
for tool in allowed_tools:
tool_cls = _FILE_TOOLS_MAP[tool]
tools.append(tool_cls(root_dir=self.root_dir))
return tools
__all__ = ["FileManagementToolkit"]

View File

@@ -0,0 +1 @@
"""financial datasets toolkit."""

View File

@@ -0,0 +1,44 @@
from __future__ import annotations
from typing import List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import ConfigDict, Field
from langchain_community.tools.financial_datasets.balance_sheets import BalanceSheets
from langchain_community.tools.financial_datasets.cash_flow_statements import (
CashFlowStatements,
)
from langchain_community.tools.financial_datasets.income_statements import (
IncomeStatements,
)
from langchain_community.utilities.financial_datasets import FinancialDatasetsAPIWrapper
class FinancialDatasetsToolkit(BaseToolkit):
"""Toolkit for interacting with financialdatasets.ai.
Parameters:
api_wrapper: The FinancialDatasets API Wrapper.
"""
api_wrapper: FinancialDatasetsAPIWrapper = Field(
default_factory=FinancialDatasetsAPIWrapper
)
def __init__(self, api_wrapper: FinancialDatasetsAPIWrapper):
super().__init__()
self.api_wrapper = api_wrapper
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
BalanceSheets(api_wrapper=self.api_wrapper),
CashFlowStatements(api_wrapper=self.api_wrapper),
IncomeStatements(api_wrapper=self.api_wrapper),
]

View File

@@ -0,0 +1 @@
"""GitHub Toolkit."""

View File

@@ -0,0 +1,479 @@
"""GitHub Toolkit."""
from typing import Dict, List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import BaseModel, Field
from langchain_community.tools.github.prompt import (
COMMENT_ON_ISSUE_PROMPT,
CREATE_BRANCH_PROMPT,
CREATE_FILE_PROMPT,
CREATE_PULL_REQUEST_PROMPT,
CREATE_REVIEW_REQUEST_PROMPT,
DELETE_FILE_PROMPT,
GET_FILES_FROM_DIRECTORY_PROMPT,
GET_ISSUE_PROMPT,
GET_ISSUES_PROMPT,
GET_LATEST_RELEASE_PROMPT,
GET_PR_PROMPT,
GET_RELEASE_PROMPT,
GET_RELEASES_PROMPT,
LIST_BRANCHES_IN_REPO_PROMPT,
LIST_PRS_PROMPT,
LIST_PULL_REQUEST_FILES,
OVERVIEW_EXISTING_FILES_BOT_BRANCH,
OVERVIEW_EXISTING_FILES_IN_MAIN,
READ_FILE_PROMPT,
SEARCH_CODE_PROMPT,
SEARCH_ISSUES_AND_PRS_PROMPT,
SET_ACTIVE_BRANCH_PROMPT,
UPDATE_FILE_PROMPT,
)
from langchain_community.tools.github.tool import GitHubAction
from langchain_community.utilities.github import GitHubAPIWrapper
class NoInput(BaseModel):
"""Schema for operations that do not require any input."""
no_input: str = Field("", description="No input required, e.g. `` (empty string).")
class GetIssue(BaseModel):
"""Schema for operations that require an issue number as input."""
issue_number: int = Field(0, description="Issue number as an integer, e.g. `42`")
class CommentOnIssue(BaseModel):
"""Schema for operations that require a comment as input."""
input: str = Field(..., description="Follow the required formatting.")
class GetPR(BaseModel):
"""Schema for operations that require a PR number as input."""
pr_number: int = Field(0, description="The PR number as an integer, e.g. `12`")
class CreatePR(BaseModel):
"""Schema for operations that require a PR title and body as input."""
formatted_pr: str = Field(..., description="Follow the required formatting.")
class CreateFile(BaseModel):
"""Schema for operations that require a file path and content as input."""
formatted_file: str = Field(..., description="Follow the required formatting.")
class ReadFile(BaseModel):
"""Schema for operations that require a file path as input."""
formatted_filepath: str = Field(
...,
description=(
"The full file path of the file you would like to read where the "
"path must NOT start with a slash, e.g. `some_dir/my_file.py`."
),
)
class UpdateFile(BaseModel):
"""Schema for operations that require a file path and content as input."""
formatted_file_update: str = Field(
..., description="Strictly follow the provided rules."
)
class DeleteFile(BaseModel):
"""Schema for operations that require a file path as input."""
formatted_filepath: str = Field(
...,
description=(
"The full file path of the file you would like to delete"
" where the path must NOT start with a slash, e.g."
" `some_dir/my_file.py`. Only input a string,"
" not the param name."
),
)
class DirectoryPath(BaseModel):
"""Schema for operations that require a directory path as input."""
input: str = Field(
"",
description=(
"The path of the directory, e.g. `some_dir/inner_dir`."
" Only input a string, do not include the parameter name."
),
)
class BranchName(BaseModel):
"""Schema for operations that require a branch name as input."""
branch_name: str = Field(
..., description="The name of the branch, e.g. `my_branch`."
)
class SearchCode(BaseModel):
"""Schema for operations that require a search query as input."""
search_query: str = Field(
...,
description=(
"A keyword-focused natural language search"
"query for code, e.g. `MyFunctionName()`."
),
)
class CreateReviewRequest(BaseModel):
"""Schema for operations that require a username as input."""
username: str = Field(
...,
description="GitHub username of the user being requested, e.g. `my_username`.",
)
class SearchIssuesAndPRs(BaseModel):
"""Schema for operations that require a search query as input."""
search_query: str = Field(
...,
description="Natural language search query, e.g. `My issue title or topic`.",
)
class TagName(BaseModel):
"""Schema for operations that require a tag name as input."""
tag_name: str = Field(
...,
description="The tag name of the release, e.g. `v1.0.0`.",
)
class GitHubToolkit(BaseToolkit):
"""GitHub Toolkit.
*Security Note*: This toolkit contains tools that can read and modify
the state of a service; e.g., by creating, deleting, or updating,
reading underlying data.
For example, this toolkit can be used to create issues, pull requests,
and comments on GitHub.
See [Security](https://python.langchain.com/docs/security) for more information.
Setup:
See detailed installation instructions here:
https://python.langchain.com/docs/integrations/tools/github/#installation
You will need to install ``pygithub`` and set the following environment
variables:
.. code-block:: bash
pip install -U pygithub
export GITHUB_APP_ID="your-app-id"
export GITHUB_APP_PRIVATE_KEY="path-to-private-key"
export GITHUB_REPOSITORY="your-github-repository"
Instantiate:
.. code-block:: python
from langchain_community.agent_toolkits.github.toolkit import GitHubToolkit
from langchain_community.utilities.github import GitHubAPIWrapper
github = GitHubAPIWrapper()
toolkit = GitHubToolkit.from_github_api_wrapper(github)
Tools:
.. code-block:: python
tools = toolkit.get_tools()
for tool in tools:
print(tool.name)
.. code-block:: none
Get Issues
Get Issue
Comment on Issue
List open pull requests (PRs)
Get Pull Request
Overview of files included in PR
Create Pull Request
List Pull Requests' Files
Create File
Read File
Update File
Delete File
Overview of existing files in Main branch
Overview of files in current working branch
List branches in this repository
Set active branch
Create a new branch
Get files from a directory
Search issues and pull requests
Search code
Create review request
Include release tools:
By default, the toolkit does not include release-related tools.
You can include them by setting ``include_release_tools=True`` when
initializing the toolkit:
.. code-block:: python
toolkit = GitHubToolkit.from_github_api_wrapper(
github, include_release_tools=True
)
Setting ``include_release_tools=True`` will include the following tools:
.. code-block:: none
Get latest release
Get releases
Get release
Use within an agent:
.. code-block:: python
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
# Select example tool
tools = [tool for tool in toolkit.get_tools() if tool.name == "Get Issue"]
assert len(tools) == 1
tools[0].name = "get_issue"
llm = ChatOpenAI(model="gpt-4o-mini")
agent_executor = create_react_agent(llm, tools)
example_query = "What is the title of issue 24888?"
events = agent_executor.stream(
{"messages": [("user", example_query)]},
stream_mode="values",
)
for event in events:
event["messages"][-1].pretty_print()
.. code-block:: none
================================[1m Human Message [0m=================================
What is the title of issue 24888?
==================================[1m Ai Message [0m==================================
Tool Calls:
get_issue (call_iSYJVaM7uchfNHOMJoVPQsOi)
Call ID: call_iSYJVaM7uchfNHOMJoVPQsOi
Args:
issue_number: 24888
=================================[1m Tool Message [0m=================================
Name: get_issue
{"number": 24888, "title": "Standardize KV-Store Docs", "body": "..."
==================================[1m Ai Message [0m==================================
The title of issue 24888 is "Standardize KV-Store Docs".
Parameters:
tools: List[BaseTool]. The tools in the toolkit. Default is an empty list.
""" # noqa: E501
tools: List[BaseTool] = []
@classmethod
def from_github_api_wrapper(
cls, github_api_wrapper: GitHubAPIWrapper, include_release_tools: bool = False
) -> "GitHubToolkit":
"""Create a GitHubToolkit from a GitHubAPIWrapper.
Args:
github_api_wrapper: GitHubAPIWrapper. The GitHub API wrapper.
include_release_tools: bool. Whether to include release-related tools.
Defaults to False.
Returns:
GitHubToolkit. The GitHub toolkit.
"""
operations: List[Dict] = [
{
"mode": "get_issues",
"name": "Get Issues",
"description": GET_ISSUES_PROMPT,
"args_schema": NoInput,
},
{
"mode": "get_issue",
"name": "Get Issue",
"description": GET_ISSUE_PROMPT,
"args_schema": GetIssue,
},
{
"mode": "comment_on_issue",
"name": "Comment on Issue",
"description": COMMENT_ON_ISSUE_PROMPT,
"args_schema": CommentOnIssue,
},
{
"mode": "list_open_pull_requests",
"name": "List open pull requests (PRs)",
"description": LIST_PRS_PROMPT,
"args_schema": NoInput,
},
{
"mode": "get_pull_request",
"name": "Get Pull Request",
"description": GET_PR_PROMPT,
"args_schema": GetPR,
},
{
"mode": "list_pull_request_files",
"name": "Overview of files included in PR",
"description": LIST_PULL_REQUEST_FILES,
"args_schema": GetPR,
},
{
"mode": "create_pull_request",
"name": "Create Pull Request",
"description": CREATE_PULL_REQUEST_PROMPT,
"args_schema": CreatePR,
},
{
"mode": "list_pull_request_files",
"name": "List Pull Requests' Files",
"description": LIST_PULL_REQUEST_FILES,
"args_schema": GetPR,
},
{
"mode": "create_file",
"name": "Create File",
"description": CREATE_FILE_PROMPT,
"args_schema": CreateFile,
},
{
"mode": "read_file",
"name": "Read File",
"description": READ_FILE_PROMPT,
"args_schema": ReadFile,
},
{
"mode": "update_file",
"name": "Update File",
"description": UPDATE_FILE_PROMPT,
"args_schema": UpdateFile,
},
{
"mode": "delete_file",
"name": "Delete File",
"description": DELETE_FILE_PROMPT,
"args_schema": DeleteFile,
},
{
"mode": "list_files_in_main_branch",
"name": "Overview of existing files in Main branch",
"description": OVERVIEW_EXISTING_FILES_IN_MAIN,
"args_schema": NoInput,
},
{
"mode": "list_files_in_bot_branch",
"name": "Overview of files in current working branch",
"description": OVERVIEW_EXISTING_FILES_BOT_BRANCH,
"args_schema": NoInput,
},
{
"mode": "list_branches_in_repo",
"name": "List branches in this repository",
"description": LIST_BRANCHES_IN_REPO_PROMPT,
"args_schema": NoInput,
},
{
"mode": "set_active_branch",
"name": "Set active branch",
"description": SET_ACTIVE_BRANCH_PROMPT,
"args_schema": BranchName,
},
{
"mode": "create_branch",
"name": "Create a new branch",
"description": CREATE_BRANCH_PROMPT,
"args_schema": BranchName,
},
{
"mode": "get_files_from_directory",
"name": "Get files from a directory",
"description": GET_FILES_FROM_DIRECTORY_PROMPT,
"args_schema": DirectoryPath,
},
{
"mode": "search_issues_and_prs",
"name": "Search issues and pull requests",
"description": SEARCH_ISSUES_AND_PRS_PROMPT,
"args_schema": SearchIssuesAndPRs,
},
{
"mode": "search_code",
"name": "Search code",
"description": SEARCH_CODE_PROMPT,
"args_schema": SearchCode,
},
{
"mode": "create_review_request",
"name": "Create review request",
"description": CREATE_REVIEW_REQUEST_PROMPT,
"args_schema": CreateReviewRequest,
},
]
release_operations: List[Dict] = [
{
"mode": "get_latest_release",
"name": "Get latest release",
"description": GET_LATEST_RELEASE_PROMPT,
"args_schema": NoInput,
},
{
"mode": "get_releases",
"name": "Get releases",
"description": GET_RELEASES_PROMPT,
"args_schema": NoInput,
},
{
"mode": "get_release",
"name": "Get release",
"description": GET_RELEASE_PROMPT,
"args_schema": TagName,
},
]
operations = operations + (release_operations if include_release_tools else [])
tools = [
GitHubAction(
name=action["name"],
description=action["description"],
mode=action["mode"],
api_wrapper=github_api_wrapper,
args_schema=action.get("args_schema", None),
)
for action in operations
]
return cls(tools=tools) # type: ignore[arg-type]
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return self.tools

View File

@@ -0,0 +1 @@
"""GitLab Toolkit."""

View File

@@ -0,0 +1,170 @@
"""GitLab Toolkit."""
from typing import Dict, List, Optional
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.gitlab.prompt import (
COMMENT_ON_ISSUE_PROMPT,
CREATE_FILE_PROMPT,
CREATE_PULL_REQUEST_PROMPT,
CREATE_REPO_BRANCH,
DELETE_FILE_PROMPT,
GET_ISSUE_PROMPT,
GET_ISSUES_PROMPT,
GET_REPO_FILES_FROM_DIRECTORY,
GET_REPO_FILES_IN_BOT_BRANCH,
GET_REPO_FILES_IN_MAIN,
LIST_REPO_BRANCES,
READ_FILE_PROMPT,
SET_ACTIVE_BRANCH,
UPDATE_FILE_PROMPT,
)
from langchain_community.tools.gitlab.tool import GitLabAction
from langchain_community.utilities.gitlab import GitLabAPIWrapper
# only include a subset of tools by default to avoid a breaking change, where
# new tools are added to the toolkit and the user's code breaks because of
# the new tools
DEFAULT_INCLUDED_TOOLS = [
"get_issues",
"get_issue",
"comment_on_issue",
"create_pull_request",
"create_file",
"read_file",
"update_file",
"delete_file",
]
class GitLabToolkit(BaseToolkit):
"""GitLab Toolkit.
*Security Note*: This toolkit contains tools that can read and modify
the state of a service; e.g., by creating, deleting, or updating,
reading underlying data.
For example, this toolkit can be used to create issues, pull requests,
and comments on GitLab.
See https://python.langchain.com/docs/security for more information.
Parameters:
tools: List[BaseTool]. The tools in the toolkit. Default is an empty list.
"""
tools: List[BaseTool] = []
@classmethod
def from_gitlab_api_wrapper(
cls,
gitlab_api_wrapper: GitLabAPIWrapper,
*,
included_tools: Optional[List[str]] = None,
) -> "GitLabToolkit":
"""Create a GitLabToolkit from a GitLabAPIWrapper.
Args:
gitlab_api_wrapper: GitLabAPIWrapper. The GitLab API wrapper.
Returns:
GitLabToolkit. The GitLab toolkit.
"""
tools_to_include = (
included_tools if included_tools is not None else DEFAULT_INCLUDED_TOOLS
)
operations: List[Dict] = [
{
"mode": "get_issues",
"name": "Get Issues",
"description": GET_ISSUES_PROMPT,
},
{
"mode": "get_issue",
"name": "Get Issue",
"description": GET_ISSUE_PROMPT,
},
{
"mode": "comment_on_issue",
"name": "Comment on Issue",
"description": COMMENT_ON_ISSUE_PROMPT,
},
{
"mode": "create_pull_request",
"name": "Create Pull Request",
"description": CREATE_PULL_REQUEST_PROMPT,
},
{
"mode": "create_file",
"name": "Create File",
"description": CREATE_FILE_PROMPT,
},
{
"mode": "read_file",
"name": "Read File",
"description": READ_FILE_PROMPT,
},
{
"mode": "update_file",
"name": "Update File",
"description": UPDATE_FILE_PROMPT,
},
{
"mode": "delete_file",
"name": "Delete File",
"description": DELETE_FILE_PROMPT,
},
{
"mode": "create_branch",
"name": "Create a new branch",
"description": CREATE_REPO_BRANCH,
},
{
"mode": "list_branches_in_repo",
"name": "Get the list of branches",
"description": LIST_REPO_BRANCES,
},
{
"mode": "set_active_branch",
"name": "Change the active branch",
"description": SET_ACTIVE_BRANCH,
},
{
"mode": "list_files_in_main_branch",
"name": "Overview of existing files in Main branch",
"description": GET_REPO_FILES_IN_MAIN,
},
{
"mode": "list_files_in_bot_branch",
"name": "Overview of files in current working branch",
"description": GET_REPO_FILES_IN_BOT_BRANCH,
},
{
"mode": "list_files_from_directory",
"name": "Overview of files in current working branch from a specific path", # noqa: E501
"description": GET_REPO_FILES_FROM_DIRECTORY,
},
]
operations_filtered = [
operation
for operation in operations
if operation["mode"] in tools_to_include
]
tools = [
GitLabAction(
name=action["name"],
description=action["description"],
mode=action["mode"],
api_wrapper=gitlab_api_wrapper,
)
for action in operations_filtered
]
return cls(tools=tools) # type: ignore[arg-type]
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return self.tools

View File

@@ -0,0 +1 @@
"""Gmail toolkit."""

View File

@@ -0,0 +1,132 @@
from __future__ import annotations
from typing import TYPE_CHECKING, List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import ConfigDict, Field
from langchain_community.tools.gmail.create_draft import GmailCreateDraft
from langchain_community.tools.gmail.get_message import GmailGetMessage
from langchain_community.tools.gmail.get_thread import GmailGetThread
from langchain_community.tools.gmail.search import GmailSearch
from langchain_community.tools.gmail.send_message import GmailSendMessage
from langchain_community.tools.gmail.utils import build_resource_service
if TYPE_CHECKING:
# This is for linting and IDE typehints
from googleapiclient.discovery import Resource
else:
try:
# We do this so pydantic can resolve the types when instantiating
from googleapiclient.discovery import Resource
except ImportError:
pass
SCOPES = ["https://mail.google.com/"]
class GmailToolkit(BaseToolkit):
"""Toolkit for interacting with Gmail.
*Security Note*: This toolkit contains tools that can read and modify
the state of a service; e.g., by reading, creating, updating, deleting
data associated with this service.
For example, this toolkit can be used to send emails on behalf of the
associated account.
See https://python.langchain.com/docs/security for more information.
Setup:
You will need a Google credentials.json file to use this toolkit.
See instructions here: https://python.langchain.com/docs/integrations/tools/gmail/#setup
Key init args:
api_resource: Optional. The Google API resource. Default is None.
Instantiate:
.. code-block:: python
from langchain_google_community import GmailToolkit
toolkit = GmailToolkit()
Tools:
.. code-block:: python
toolkit.get_tools()
.. code-block:: none
[GmailCreateDraft(api_resource=<googleapiclient.discovery.Resource object at 0x1094509d0>),
GmailSendMessage(api_resource=<googleapiclient.discovery.Resource object at 0x1094509d0>),
GmailSearch(api_resource=<googleapiclient.discovery.Resource object at 0x1094509d0>),
GmailGetMessage(api_resource=<googleapiclient.discovery.Resource object at 0x1094509d0>),
GmailGetThread(api_resource=<googleapiclient.discovery.Resource object at 0x1094509d0>)]
Use within an agent:
.. code-block:: python
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(model="gpt-4o-mini")
agent_executor = create_react_agent(llm, tools)
example_query = "Draft an email to fake@fake.com thanking them for coffee."
events = agent_executor.stream(
{"messages": [("user", example_query)]},
stream_mode="values",
)
for event in events:
event["messages"][-1].pretty_print()
.. code-block:: none
================================[1m Human Message [0m=================================
Draft an email to fake@fake.com thanking them for coffee.
==================================[1m Ai Message [0m==================================
Tool Calls:
create_gmail_draft (call_slGkYKZKA6h3Mf1CraUBzs6M)
Call ID: call_slGkYKZKA6h3Mf1CraUBzs6M
Args:
message: Dear Fake,
I wanted to take a moment to thank you for the coffee yesterday. It was a pleasure catching up with you. Let's do it again soon!
Best regards,
[Your Name]
to: ['fake@fake.com']
subject: Thank You for the Coffee
=================================[1m Tool Message [0m=================================
Name: create_gmail_draft
Draft created. Draft Id: r-7233782721440261513
==================================[1m Ai Message [0m==================================
I have drafted an email to fake@fake.com thanking them for the coffee. You can review and send it from your email draft with the subject "Thank You for the Coffee".
Parameters:
api_resource: Optional. The Google API resource. Default is None.
""" # noqa: E501
api_resource: Resource = Field(default_factory=build_resource_service)
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
GmailCreateDraft(api_resource=self.api_resource),
GmailSendMessage(api_resource=self.api_resource),
GmailSearch(api_resource=self.api_resource),
GmailGetMessage(api_resource=self.api_resource),
GmailGetThread(api_resource=self.api_resource),
]

View File

@@ -0,0 +1 @@
"""Jira Toolkit."""

View File

@@ -0,0 +1,83 @@
from typing import Dict, List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.jira.prompt import (
JIRA_CATCH_ALL_PROMPT,
JIRA_CONFLUENCE_PAGE_CREATE_PROMPT,
JIRA_GET_ALL_PROJECTS_PROMPT,
JIRA_ISSUE_CREATE_PROMPT,
JIRA_JQL_PROMPT,
)
from langchain_community.tools.jira.tool import JiraAction
from langchain_community.utilities.jira import JiraAPIWrapper
class JiraToolkit(BaseToolkit):
"""Jira Toolkit.
*Security Note*: This toolkit contains tools that can read and modify
the state of a service; e.g., by creating, deleting, or updating,
reading underlying data.
See https://python.langchain.com/docs/security for more information.
Parameters:
tools: List[BaseTool]. The tools in the toolkit. Default is an empty list.
"""
tools: List[BaseTool] = []
@classmethod
def from_jira_api_wrapper(cls, jira_api_wrapper: JiraAPIWrapper) -> "JiraToolkit":
"""Create a JiraToolkit from a JiraAPIWrapper.
Args:
jira_api_wrapper: JiraAPIWrapper. The Jira API wrapper.
Returns:
JiraToolkit. The Jira toolkit.
"""
operations: List[Dict] = [
{
"mode": "jql",
"name": "jql_query",
"description": JIRA_JQL_PROMPT,
},
{
"mode": "get_projects",
"name": "get_projects",
"description": JIRA_GET_ALL_PROJECTS_PROMPT,
},
{
"mode": "create_issue",
"name": "create_issue",
"description": JIRA_ISSUE_CREATE_PROMPT,
},
{
"mode": "other",
"name": "catch_all_jira_api",
"description": JIRA_CATCH_ALL_PROMPT,
},
{
"mode": "create_page",
"name": "create_confluence_page",
"description": JIRA_CONFLUENCE_PAGE_CREATE_PROMPT,
},
]
tools = [
JiraAction(
name=action["name"],
description=action["description"],
mode=action["mode"],
api_wrapper=jira_api_wrapper,
)
for action in operations
]
return cls(tools=tools) # type: ignore[arg-type]
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return self.tools

View File

@@ -0,0 +1 @@
"""Json agent."""

View File

@@ -0,0 +1,76 @@
"""Json agent."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from langchain_core.callbacks import BaseCallbackManager
from langchain_core.language_models import BaseLanguageModel
from langchain_community.agent_toolkits.json.prompt import JSON_PREFIX, JSON_SUFFIX
from langchain_community.agent_toolkits.json.toolkit import JsonToolkit
if TYPE_CHECKING:
from langchain_classic.agents.agent import AgentExecutor
def create_json_agent(
llm: BaseLanguageModel,
toolkit: JsonToolkit,
callback_manager: Optional[BaseCallbackManager] = None,
prefix: str = JSON_PREFIX,
suffix: str = JSON_SUFFIX,
format_instructions: Optional[str] = None,
input_variables: Optional[List[str]] = None,
verbose: bool = False,
agent_executor_kwargs: Optional[Dict[str, Any]] = None,
**kwargs: Any,
) -> AgentExecutor:
"""Construct a json agent from an LLM and tools.
Args:
llm: The language model to use.
toolkit: The toolkit to use.
callback_manager: The callback manager to use. Default is None.
prefix: The prefix to use. Default is JSON_PREFIX.
suffix: The suffix to use. Default is JSON_SUFFIX.
format_instructions: The format instructions to use. Default is None.
input_variables: The input variables to use. Default is None.
verbose: Whether to print verbose output. Default is False.
agent_executor_kwargs: Optional additional arguments for the agent executor.
kwargs: Additional arguments for the agent.
Returns:
The agent executor.
"""
from langchain_classic.agents.agent import AgentExecutor
from langchain_classic.agents.mrkl.base import ZeroShotAgent
from langchain_classic.chains.llm import LLMChain
tools = toolkit.get_tools()
prompt_params = (
{"format_instructions": format_instructions}
if format_instructions is not None
else {}
)
prompt = ZeroShotAgent.create_prompt(
tools,
prefix=prefix,
suffix=suffix,
input_variables=input_variables,
**prompt_params,
)
llm_chain = LLMChain(
llm=llm,
prompt=prompt,
callback_manager=callback_manager,
)
tool_names = [tool.name for tool in tools]
agent = ZeroShotAgent(llm_chain=llm_chain, allowed_tools=tool_names, **kwargs)
return AgentExecutor.from_agent_and_tools(
agent=agent,
tools=tools,
callback_manager=callback_manager,
verbose=verbose,
**(agent_executor_kwargs or {}),
)

View File

@@ -0,0 +1,25 @@
# flake8: noqa
JSON_PREFIX = """You are an agent designed to interact with JSON.
Your goal is to return a final answer by interacting with the JSON.
You have access to the following tools which help you learn more about the JSON you are interacting with.
Only use the below tools. Only use the information returned by the below tools to construct your final answer.
Do not make up any information that is not contained in the JSON.
Your input to the tools should be in the form of `data["key"][0]` where `data` is the JSON blob you are interacting with, and the syntax used is Python.
You should only use keys that you know for a fact exist. You must validate that a key exists by seeing it previously when calling `json_spec_list_keys`.
If you have not seen a key in one of those responses, you cannot use it.
You should only add one key at a time to the path. You cannot add multiple keys at once.
If you encounter a "KeyError", go back to the previous key, look at the available keys, and try again.
If the question does not seem to be related to the JSON, just return "I don't know" as the answer.
Always begin your interaction with the `json_spec_list_keys` tool with input "data" to see what keys exist in the JSON.
Note that sometimes the value at a given path is large. In this case, you will get an error "Value is a large dictionary, should explore its keys directly".
In this case, you should ALWAYS follow up by using the `json_spec_list_keys` tool to see what keys exist at that path.
Do not simply refer the user to the JSON or a section of the JSON, as this is not a valid answer. Keep digging until you find the answer and explicitly return it.
"""
JSON_SUFFIX = """Begin!"
Question: {input}
Thought: I should look at the keys that exist in data to see what I have access to
{agent_scratchpad}"""

View File

@@ -0,0 +1,29 @@
from __future__ import annotations
from typing import List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.json.tool import (
JsonGetValueTool,
JsonListKeysTool,
JsonSpec,
)
class JsonToolkit(BaseToolkit):
"""Toolkit for interacting with a JSON spec.
Parameters:
spec: The JSON spec.
"""
spec: JsonSpec
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
JsonListKeysTool(spec=self.spec),
JsonGetValueTool(spec=self.spec),
]

View File

@@ -0,0 +1,771 @@
# flake8: noqa
"""Tools provide access to various resources and services.
LangChain has a large ecosystem of integrations with various external resources
like local and remote file systems, APIs and databases.
These integrations allow developers to create versatile applications that combine the
power of LLMs with the ability to access, interact with and manipulate external
resources.
When developing an application, developers should inspect the capabilities and
permissions of the tools that underlie the given agent toolkit, and determine
whether permissions of the given toolkit are appropriate for the application.
See [Security](https://python.langchain.com/docs/security) for more information.
"""
import warnings
from typing import Any, Dict, List, Optional, Callable, Tuple
from mypy_extensions import Arg, KwArg
from langchain_community.tools.arxiv.tool import ArxivQueryRun
from langchain_community.tools.bing_search.tool import BingSearchRun
from langchain_community.tools.dataforseo_api_search import DataForSeoAPISearchResults
from langchain_community.tools.dataforseo_api_search import DataForSeoAPISearchRun
from langchain_community.tools.ddg_search.tool import DuckDuckGoSearchRun
from langchain_community.tools.eleven_labs.text2speech import ElevenLabsText2SpeechTool
from langchain_community.tools.file_management import ReadFileTool
from langchain_community.tools.golden_query.tool import GoldenQueryRun
from langchain_community.tools.google_cloud.texttospeech import (
GoogleCloudTextToSpeechTool,
)
from langchain_community.tools.google_finance.tool import GoogleFinanceQueryRun
from langchain_community.tools.google_jobs.tool import GoogleJobsQueryRun
from langchain_community.tools.google_lens.tool import GoogleLensQueryRun
from langchain_community.tools.google_scholar.tool import GoogleScholarQueryRun
from langchain_community.tools.google_search.tool import (
GoogleSearchResults,
GoogleSearchRun,
)
from langchain_community.tools.google_serper.tool import (
GoogleSerperResults,
GoogleSerperRun,
)
from langchain_community.tools.google_trends.tool import GoogleTrendsQueryRun
from langchain_community.tools.graphql.tool import BaseGraphQLTool
from langchain_community.tools.human.tool import HumanInputRun
from langchain_community.tools.memorize.tool import Memorize
from langchain_community.tools.merriam_webster.tool import MerriamWebsterQueryRun
from langchain_community.tools.metaphor_search.tool import MetaphorSearchResults
from langchain_community.tools.openweathermap.tool import OpenWeatherMapQueryRun
from langchain_community.tools.pubmed.tool import PubmedQueryRun
from langchain_community.tools.reddit_search.tool import RedditSearchRun
from langchain_community.tools.requests.tool import (
RequestsDeleteTool,
RequestsGetTool,
RequestsPatchTool,
RequestsPostTool,
RequestsPutTool,
)
from langchain_community.tools.scenexplain.tool import SceneXplainTool
from langchain_community.tools.searchapi.tool import SearchAPIResults, SearchAPIRun
from langchain_community.tools.searx_search.tool import (
SearxSearchResults,
SearxSearchRun,
)
from langchain_community.tools.shell.tool import ShellTool
from langchain_community.tools.sleep.tool import SleepTool
from langchain_community.tools.stackexchange.tool import StackExchangeTool
from langchain_community.tools.wikipedia.tool import WikipediaQueryRun
from langchain_community.tools.wolfram_alpha.tool import WolframAlphaQueryRun
from langchain_community.utilities.arxiv import ArxivAPIWrapper
from langchain_community.utilities.awslambda import LambdaWrapper
from langchain_community.utilities.bing_search import BingSearchAPIWrapper
from langchain_community.utilities.dalle_image_generator import DallEAPIWrapper
from langchain_community.utilities.dataforseo_api_search import DataForSeoAPIWrapper
from langchain_community.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper
from langchain_community.utilities.golden_query import GoldenQueryAPIWrapper
from langchain_community.utilities.google_books import GoogleBooksAPIWrapper
from langchain_community.utilities.google_finance import GoogleFinanceAPIWrapper
from langchain_community.utilities.google_jobs import GoogleJobsAPIWrapper
from langchain_community.utilities.google_lens import GoogleLensAPIWrapper
from langchain_community.utilities.google_scholar import GoogleScholarAPIWrapper
from langchain_community.utilities.google_search import GoogleSearchAPIWrapper
from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper
from langchain_community.utilities.google_trends import GoogleTrendsAPIWrapper
from langchain_community.utilities.graphql import GraphQLAPIWrapper
from langchain_community.utilities.merriam_webster import MerriamWebsterAPIWrapper
from langchain_community.utilities.metaphor_search import MetaphorSearchAPIWrapper
from langchain_community.utilities.openweathermap import OpenWeatherMapAPIWrapper
from langchain_community.utilities.pubmed import PubMedAPIWrapper
from langchain_community.utilities.reddit_search import RedditSearchAPIWrapper
from langchain_community.utilities.requests import TextRequestsWrapper
from langchain_community.utilities.searchapi import SearchApiAPIWrapper
from langchain_community.utilities.searx_search import SearxSearchWrapper
from langchain_community.utilities.serpapi import SerpAPIWrapper
from langchain_community.utilities.stackexchange import StackExchangeAPIWrapper
from langchain_community.utilities.twilio import TwilioAPIWrapper
from langchain_community.utilities.wikipedia import WikipediaAPIWrapper
from langchain_community.utilities.wolfram_alpha import WolframAlphaAPIWrapper
from langchain_core.callbacks import BaseCallbackManager
from langchain_core.callbacks import Callbacks
from langchain_core.language_models import BaseLanguageModel
from langchain_core.tools import BaseTool, Tool
def _get_tools_requests_get() -> BaseTool:
# Dangerous requests are allowed here, because there's another flag that the user
# has to provide in order to actually opt in.
# This is a private function and should not be used directly.
return RequestsGetTool(
requests_wrapper=TextRequestsWrapper(), allow_dangerous_requests=True
)
def _get_tools_requests_post() -> BaseTool:
# Dangerous requests are allowed here, because there's another flag that the user
# has to provide in order to actually opt in.
# This is a private function and should not be used directly.
return RequestsPostTool(
requests_wrapper=TextRequestsWrapper(), allow_dangerous_requests=True
)
def _get_tools_requests_patch() -> BaseTool:
# Dangerous requests are allowed here, because there's another flag that the user
# has to provide in order to actually opt in.
# This is a private function and should not be used directly.
return RequestsPatchTool(
requests_wrapper=TextRequestsWrapper(), allow_dangerous_requests=True
)
def _get_tools_requests_put() -> BaseTool:
# Dangerous requests are allowed here, because there's another flag that the user
# has to provide in order to actually opt in.
# This is a private function and should not be used directly.
return RequestsPutTool(
requests_wrapper=TextRequestsWrapper(), allow_dangerous_requests=True
)
def _get_tools_requests_delete() -> BaseTool:
# Dangerous requests are allowed here, because there's another flag that the user
# has to provide in order to actually opt in.
# This is a private function and should not be used directly.
return RequestsDeleteTool(
requests_wrapper=TextRequestsWrapper(), allow_dangerous_requests=True
)
def _get_terminal() -> BaseTool:
return ShellTool()
def _get_sleep() -> BaseTool:
return SleepTool()
_BASE_TOOLS: Dict[str, Callable[[], BaseTool]] = {
"sleep": _get_sleep,
}
DANGEROUS_TOOLS = {
# Tools that contain some level of risk.
# Please use with caution and read the documentation of these tools
# to understand the risks and how to mitigate them.
# Refer to https://python.langchain.com/docs/security
# for more information.
"requests": _get_tools_requests_get, # preserved for backwards compatibility
"requests_get": _get_tools_requests_get,
"requests_post": _get_tools_requests_post,
"requests_patch": _get_tools_requests_patch,
"requests_put": _get_tools_requests_put,
"requests_delete": _get_tools_requests_delete,
"terminal": _get_terminal,
}
def _get_llm_math(llm: BaseLanguageModel) -> BaseTool:
try:
from langchain_classic.chains.llm_math.base import LLMMathChain
except ImportError:
raise ImportError(
"LLM Math tools require the library `langchain` to be installed."
" Please install it with `pip install langchain`."
)
return Tool(
name="Calculator",
description="Useful for when you need to answer questions about math.",
func=LLMMathChain.from_llm(llm=llm).run,
coroutine=LLMMathChain.from_llm(llm=llm).arun,
)
def _get_open_meteo_api(llm: BaseLanguageModel) -> BaseTool:
try:
from langchain_classic.chains.api.base import APIChain
from langchain_classic.chains.api import (
open_meteo_docs,
)
except ImportError:
raise ImportError(
"API tools require the library `langchain` to be installed."
" Please install it with `pip install langchain`."
)
chain = APIChain.from_llm_and_api_docs(
llm,
open_meteo_docs.OPEN_METEO_DOCS,
limit_to_domains=["https://api.open-meteo.com/"],
)
return Tool(
name="Open-Meteo-API",
description="Useful for when you want to get weather information from the OpenMeteo API. The input should be a question in natural language that this API can answer.",
func=chain.run,
)
_LLM_TOOLS: Dict[str, Callable[[BaseLanguageModel], BaseTool]] = {
"llm-math": _get_llm_math,
"open-meteo-api": _get_open_meteo_api,
}
def _get_news_api(llm: BaseLanguageModel, **kwargs: Any) -> BaseTool:
news_api_key = kwargs["news_api_key"]
try:
from langchain_classic.chains.api.base import APIChain
from langchain_classic.chains.api import (
news_docs,
)
except ImportError:
raise ImportError(
"API tools require the library `langchain` to be installed."
" Please install it with `pip install langchain`."
)
chain = APIChain.from_llm_and_api_docs(
llm,
news_docs.NEWS_DOCS,
headers={"X-Api-Key": news_api_key},
limit_to_domains=["https://newsapi.org/"],
)
return Tool(
name="News-API",
description="Use this when you want to get information about the top headlines of current news stories. The input should be a question in natural language that this API can answer.",
func=chain.run,
)
def _get_tmdb_api(llm: BaseLanguageModel, **kwargs: Any) -> BaseTool:
tmdb_bearer_token = kwargs["tmdb_bearer_token"]
try:
from langchain_classic.chains.api.base import APIChain
from langchain_classic.chains.api import (
tmdb_docs,
)
except ImportError:
raise ImportError(
"API tools require the library `langchain` to be installed."
" Please install it with `pip install langchain`."
)
chain = APIChain.from_llm_and_api_docs(
llm,
tmdb_docs.TMDB_DOCS,
headers={"Authorization": f"Bearer {tmdb_bearer_token}"},
limit_to_domains=["https://api.themoviedb.org/"],
)
return Tool(
name="TMDB-API",
description="Useful for when you want to get information from The Movie Database. The input should be a question in natural language that this API can answer.",
func=chain.run,
)
def _get_podcast_api(llm: BaseLanguageModel, **kwargs: Any) -> BaseTool:
listen_api_key = kwargs["listen_api_key"]
try:
from langchain_classic.chains.api.base import APIChain
from langchain_classic.chains.api import (
podcast_docs,
)
except ImportError:
raise ImportError(
"API tools require the library `langchain` to be installed."
" Please install it with `pip install langchain`."
)
chain = APIChain.from_llm_and_api_docs(
llm,
podcast_docs.PODCAST_DOCS,
headers={"X-ListenAPI-Key": listen_api_key},
limit_to_domains=["https://listen-api.listennotes.com/"],
)
return Tool(
name="Podcast-API",
description="Use the Listen Notes Podcast API to search all podcasts or episodes. The input should be a question in natural language that this API can answer.",
func=chain.run,
)
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))
def _get_google_search(**kwargs: Any) -> BaseTool:
return GoogleSearchRun(api_wrapper=GoogleSearchAPIWrapper(**kwargs))
def _get_merriam_webster(**kwargs: Any) -> BaseTool:
return MerriamWebsterQueryRun(api_wrapper=MerriamWebsterAPIWrapper(**kwargs))
def _get_wikipedia(**kwargs: Any) -> BaseTool:
return WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper(**kwargs))
def _get_arxiv(**kwargs: Any) -> BaseTool:
return ArxivQueryRun(api_wrapper=ArxivAPIWrapper(**kwargs))
def _get_golden_query(**kwargs: Any) -> BaseTool:
return GoldenQueryRun(api_wrapper=GoldenQueryAPIWrapper(**kwargs))
def _get_pubmed(**kwargs: Any) -> BaseTool:
return PubmedQueryRun(api_wrapper=PubMedAPIWrapper(**kwargs))
def _get_google_books(**kwargs: Any) -> BaseTool:
from langchain_community.tools.google_books import GoogleBooksQueryRun
return GoogleBooksQueryRun(api_wrapper=GoogleBooksAPIWrapper(**kwargs))
def _get_google_jobs(**kwargs: Any) -> BaseTool:
return GoogleJobsQueryRun(api_wrapper=GoogleJobsAPIWrapper(**kwargs))
def _get_google_lens(**kwargs: Any) -> BaseTool:
return GoogleLensQueryRun(api_wrapper=GoogleLensAPIWrapper(**kwargs))
def _get_google_serper(**kwargs: Any) -> BaseTool:
return GoogleSerperRun(api_wrapper=GoogleSerperAPIWrapper(**kwargs))
def _get_google_scholar(**kwargs: Any) -> BaseTool:
return GoogleScholarQueryRun(api_wrapper=GoogleScholarAPIWrapper(**kwargs))
def _get_google_finance(**kwargs: Any) -> BaseTool:
return GoogleFinanceQueryRun(api_wrapper=GoogleFinanceAPIWrapper(**kwargs))
def _get_google_trends(**kwargs: Any) -> BaseTool:
return GoogleTrendsQueryRun(api_wrapper=GoogleTrendsAPIWrapper(**kwargs))
def _get_google_serper_results_json(**kwargs: Any) -> BaseTool:
return GoogleSerperResults(api_wrapper=GoogleSerperAPIWrapper(**kwargs))
def _get_google_search_results_json(**kwargs: Any) -> BaseTool:
return GoogleSearchResults(api_wrapper=GoogleSearchAPIWrapper(**kwargs))
def _get_searchapi(**kwargs: Any) -> BaseTool:
return SearchAPIRun(api_wrapper=SearchApiAPIWrapper(**kwargs))
def _get_searchapi_results_json(**kwargs: Any) -> BaseTool:
return SearchAPIResults(api_wrapper=SearchApiAPIWrapper(**kwargs))
def _get_serpapi(**kwargs: Any) -> BaseTool:
return Tool(
name="Search",
description="A search engine. Useful for when you need to answer questions about current events. Input should be a search query.",
func=SerpAPIWrapper(**kwargs).run,
coroutine=SerpAPIWrapper(**kwargs).arun,
)
def _get_stackexchange(**kwargs: Any) -> BaseTool:
return StackExchangeTool(api_wrapper=StackExchangeAPIWrapper(**kwargs))
def _get_dalle_image_generator(**kwargs: Any) -> Tool:
return Tool(
"Dall-E-Image-Generator",
DallEAPIWrapper(**kwargs).run,
"A wrapper around OpenAI DALL-E API. Useful for when you need to generate images from a text description. Input should be an image description.",
)
def _get_twilio(**kwargs: Any) -> BaseTool:
return Tool(
name="Text-Message",
description="Useful for when you need to send a text message to a provided phone number.",
func=TwilioAPIWrapper(**kwargs).run,
)
def _get_searx_search(**kwargs: Any) -> BaseTool:
return SearxSearchRun(wrapper=SearxSearchWrapper(**kwargs))
def _get_searx_search_results_json(**kwargs: Any) -> BaseTool:
wrapper_kwargs = {k: v for k, v in kwargs.items() if k != "num_results"}
return SearxSearchResults(wrapper=SearxSearchWrapper(**wrapper_kwargs), **kwargs)
def _get_bing_search(**kwargs: Any) -> BaseTool:
return BingSearchRun(api_wrapper=BingSearchAPIWrapper(**kwargs))
def _get_metaphor_search(**kwargs: Any) -> BaseTool:
return MetaphorSearchResults(api_wrapper=MetaphorSearchAPIWrapper(**kwargs))
def _get_ddg_search(**kwargs: Any) -> BaseTool:
return DuckDuckGoSearchRun(api_wrapper=DuckDuckGoSearchAPIWrapper(**kwargs))
def _get_human_tool(**kwargs: Any) -> BaseTool:
return HumanInputRun(**kwargs)
def _get_scenexplain(**kwargs: Any) -> BaseTool:
return SceneXplainTool(**kwargs)
def _get_graphql_tool(**kwargs: Any) -> BaseTool:
return BaseGraphQLTool(graphql_wrapper=GraphQLAPIWrapper(**kwargs))
def _get_openweathermap(**kwargs: Any) -> BaseTool:
return OpenWeatherMapQueryRun(api_wrapper=OpenWeatherMapAPIWrapper(**kwargs))
def _get_dataforseo_api_search(**kwargs: Any) -> BaseTool:
return DataForSeoAPISearchRun(api_wrapper=DataForSeoAPIWrapper(**kwargs))
def _get_dataforseo_api_search_json(**kwargs: Any) -> BaseTool:
return DataForSeoAPISearchResults(api_wrapper=DataForSeoAPIWrapper(**kwargs))
def _get_eleven_labs_text2speech(**kwargs: Any) -> BaseTool:
return ElevenLabsText2SpeechTool(**kwargs)
def _get_memorize(llm: BaseLanguageModel, **kwargs: Any) -> BaseTool:
return Memorize(llm=llm) # type: ignore[arg-type]
def _get_google_cloud_texttospeech(**kwargs: Any) -> BaseTool:
return GoogleCloudTextToSpeechTool(**kwargs)
def _get_file_management_tool(**kwargs: Any) -> BaseTool:
return ReadFileTool(**kwargs)
def _get_reddit_search(**kwargs: Any) -> BaseTool:
return RedditSearchRun(api_wrapper=RedditSearchAPIWrapper(**kwargs))
_EXTRA_LLM_TOOLS: Dict[
str,
Tuple[Callable[[Arg(BaseLanguageModel, "llm"), KwArg(Any)], BaseTool], List[str]],
] = {
"news-api": (_get_news_api, ["news_api_key"]),
"tmdb-api": (_get_tmdb_api, ["tmdb_bearer_token"]),
"podcast-api": (_get_podcast_api, ["listen_api_key"]),
"memorize": (_get_memorize, []),
}
_EXTRA_OPTIONAL_TOOLS: Dict[str, Tuple[Callable[[KwArg(Any)], BaseTool], List[str]]] = {
"wolfram-alpha": (_get_wolfram_alpha, ["wolfram_alpha_appid"]),
"google-search": (_get_google_search, ["google_api_key", "google_cse_id"]),
"google-search-results-json": (
_get_google_search_results_json,
["google_api_key", "google_cse_id", "num_results"],
),
"searx-search-results-json": (
_get_searx_search_results_json,
["searx_host", "engines", "num_results", "aiosession"],
),
"bing-search": (_get_bing_search, ["bing_subscription_key", "bing_search_url"]),
"metaphor-search": (_get_metaphor_search, ["metaphor_api_key"]),
"ddg-search": (_get_ddg_search, []),
"google-books": (_get_google_books, ["google_books_api_key"]),
"google-lens": (_get_google_lens, ["serp_api_key"]),
"google-serper": (_get_google_serper, ["serper_api_key", "aiosession"]),
"google-scholar": (
_get_google_scholar,
["top_k_results", "hl", "lr", "serp_api_key"],
),
"google-finance": (
_get_google_finance,
["serp_api_key"],
),
"google-trends": (
_get_google_trends,
["serp_api_key"],
),
"google-jobs": (
_get_google_jobs,
["serp_api_key"],
),
"google-serper-results-json": (
_get_google_serper_results_json,
["serper_api_key", "aiosession"],
),
"searchapi": (_get_searchapi, ["searchapi_api_key", "aiosession"]),
"searchapi-results-json": (
_get_searchapi_results_json,
["searchapi_api_key", "aiosession"],
),
"serpapi": (_get_serpapi, ["serpapi_api_key", "aiosession"]),
"dalle-image-generator": (_get_dalle_image_generator, ["openai_api_key"]),
"twilio": (_get_twilio, ["account_sid", "auth_token", "from_number"]),
"searx-search": (_get_searx_search, ["searx_host", "engines", "aiosession"]),
"merriam-webster": (_get_merriam_webster, ["merriam_webster_api_key"]),
"wikipedia": (_get_wikipedia, ["top_k_results", "lang"]),
"arxiv": (
_get_arxiv,
["top_k_results", "load_max_docs", "load_all_available_meta"],
),
"golden-query": (_get_golden_query, ["golden_api_key"]),
"pubmed": (_get_pubmed, ["top_k_results"]),
"human": (_get_human_tool, ["prompt_func", "input_func"]),
"awslambda": (
_get_lambda_api,
["awslambda_tool_name", "awslambda_tool_description", "function_name"],
),
"stackexchange": (_get_stackexchange, []),
"sceneXplain": (_get_scenexplain, []),
"graphql": (
_get_graphql_tool,
["graphql_endpoint", "custom_headers", "fetch_schema_from_transport"],
),
"openweathermap-api": (_get_openweathermap, ["openweathermap_api_key"]),
"dataforseo-api-search": (
_get_dataforseo_api_search,
["api_login", "api_password", "aiosession"],
),
"dataforseo-api-search-json": (
_get_dataforseo_api_search_json,
["api_login", "api_password", "aiosession"],
),
"eleven_labs_text2speech": (_get_eleven_labs_text2speech, ["elevenlabs_api_key"]),
"google_cloud_texttospeech": (_get_google_cloud_texttospeech, []),
"read_file": (_get_file_management_tool, []),
"reddit_search": (
_get_reddit_search,
["reddit_client_id", "reddit_client_secret", "reddit_user_agent"],
),
}
def _handle_callbacks(
callback_manager: Optional[BaseCallbackManager], callbacks: Callbacks
) -> Callbacks:
if callback_manager is not None:
warnings.warn(
"callback_manager is deprecated. Please use callbacks instead.",
DeprecationWarning,
)
if callbacks is not None:
raise ValueError(
"Cannot specify both callback_manager and callbacks arguments."
)
return callback_manager
return callbacks
def load_huggingface_tool(
task_or_repo_id: str,
model_repo_id: Optional[str] = None,
token: Optional[str] = None,
remote: bool = False,
**kwargs: Any,
) -> BaseTool:
"""Loads a tool from the HuggingFace Hub.
Args:
task_or_repo_id: Task or model repo id.
model_repo_id: Optional model repo id. Defaults to None.
token: Optional token. Defaults to None.
remote: Optional remote. Defaults to False.
kwargs: Additional keyword arguments.
Returns:
A tool.
Raises:
ImportError: If the required libraries are not installed.
NotImplementedError: If multimodal outputs or inputs are not supported.
"""
try:
from transformers import load_tool
except ImportError:
raise ImportError(
"HuggingFace tools require the libraries `transformers>=4.29.0`"
" and `huggingface_hub>=0.14.1` to be installed."
" Please install it with"
" `pip install --upgrade transformers huggingface_hub`."
)
hf_tool = load_tool(
task_or_repo_id,
model_repo_id=model_repo_id,
token=token,
remote=remote,
**kwargs,
)
outputs = hf_tool.outputs
if set(outputs) != {"text"}:
raise NotImplementedError("Multimodal outputs not supported yet.")
inputs = hf_tool.inputs
if set(inputs) != {"text"}:
raise NotImplementedError("Multimodal inputs not supported yet.")
return Tool.from_function(
hf_tool.__call__, name=hf_tool.name, description=hf_tool.description
)
def raise_dangerous_tools_exception(name: str) -> None:
raise ValueError(
f"{name} is a dangerous tool. You cannot use it without opting in "
"by setting allow_dangerous_tools to True. "
"Most tools have some inherit risk to them merely because they are "
'allowed to interact with the "real world".'
"Please refer to LangChain security guidelines "
"to https://python.langchain.com/docs/security."
"Some tools have been designated as dangerous because they pose "
"risk that is not intuitively obvious. For example, a tool that "
"allows an agent to make requests to the web, can also be used "
"to make requests to a server that is only accessible from the "
"server hosting the code."
"Again, all tools carry some risk, and it's your responsibility to "
"understand which tools you're using and the risks associated with "
"them."
)
def load_tools(
tool_names: List[str],
llm: Optional[BaseLanguageModel] = None,
callbacks: Callbacks = None,
allow_dangerous_tools: bool = False,
**kwargs: Any,
) -> List[BaseTool]:
"""Load tools based on their name.
Tools allow agents to interact with various resources and services like
APIs, databases, file systems, etc.
Please scope the permissions of each tools to the minimum required for the
application.
For example, if an application only needs to read from a database,
the database tool should not be given write permissions. Moreover
consider scoping the permissions to only allow accessing specific
tables and impose user-level quota for limiting resource usage.
Please read the APIs of the individual tools to determine which configuration
they support.
See [Security](https://python.langchain.com/docs/security) for more information.
Args:
tool_names: name of tools to load.
llm: An optional language model may be needed to initialize certain tools.
Defaults to None.
callbacks: Optional callback manager or list of callback handlers.
If not provided, default global callback manager will be used.
allow_dangerous_tools: Optional flag to allow dangerous tools.
Tools that contain some level of risk.
Please use with caution and read the documentation of these tools
to understand the risks and how to mitigate them.
Refer to https://python.langchain.com/docs/security
for more information.
Please note that this list may not be fully exhaustive.
It is your responsibility to understand which tools
you're using and the risks associated with them.
Defaults to False.
kwargs: Additional keyword arguments.
Returns:
List of tools.
Raises:
ValueError: If the tool name is unknown.
ValueError: If the tool requires an LLM to be provided.
ValueError: If the tool requires some parameters that were not provided.
ValueError: If the tool is a dangerous tool and allow_dangerous_tools is False.
"""
tools = []
callbacks = _handle_callbacks(
callback_manager=kwargs.get("callback_manager"), callbacks=callbacks
)
for name in tool_names:
if name in DANGEROUS_TOOLS and not allow_dangerous_tools:
raise_dangerous_tools_exception(name)
if name in {"requests"}:
warnings.warn(
"tool name `requests` is deprecated - "
"please use `requests_all` or specify the requests method"
)
if name == "requests_all":
# expand requests into various methods
if not allow_dangerous_tools:
raise_dangerous_tools_exception(name)
requests_method_tools = [
_tool for _tool in DANGEROUS_TOOLS if _tool.startswith("requests_")
]
tool_names.extend(requests_method_tools)
elif name in _BASE_TOOLS:
tools.append(_BASE_TOOLS[name]())
elif name in DANGEROUS_TOOLS:
tools.append(DANGEROUS_TOOLS[name]())
elif name in _LLM_TOOLS:
if llm is None:
raise ValueError(f"Tool {name} requires an LLM to be provided")
tool = _LLM_TOOLS[name](llm)
tools.append(tool)
elif name in _EXTRA_LLM_TOOLS:
if llm is None:
raise ValueError(f"Tool {name} requires an LLM to be provided")
_get_llm_tool_func, extra_keys = _EXTRA_LLM_TOOLS[name]
missing_keys = set(extra_keys).difference(kwargs)
if missing_keys:
raise ValueError(
f"Tool {name} requires some parameters that were not "
f"provided: {missing_keys}"
)
sub_kwargs = {k: kwargs[k] for k in extra_keys}
tool = _get_llm_tool_func(llm=llm, **sub_kwargs)
tools.append(tool)
elif name in _EXTRA_OPTIONAL_TOOLS:
_get_tool_func, extra_keys = _EXTRA_OPTIONAL_TOOLS[name]
sub_kwargs = {k: kwargs[k] for k in extra_keys if k in kwargs}
tool = _get_tool_func(**sub_kwargs)
tools.append(tool)
else:
raise ValueError(f"Got unknown tool {name}")
if callbacks is not None:
for tool in tools:
tool.callbacks = callbacks
return tools
def get_all_tool_names() -> List[str]:
"""Get a list of all possible tool names."""
return (
list(_BASE_TOOLS)
+ list(_EXTRA_OPTIONAL_TOOLS)
+ list(_EXTRA_LLM_TOOLS)
+ list(_LLM_TOOLS)
+ list(DANGEROUS_TOOLS)
)

View File

@@ -0,0 +1 @@
"""MultiOn Toolkit."""

View File

@@ -0,0 +1,35 @@
"""MultiOn agent."""
from __future__ import annotations
from typing import List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import ConfigDict
from langchain_community.tools.multion.close_session import MultionCloseSession
from langchain_community.tools.multion.create_session import MultionCreateSession
from langchain_community.tools.multion.update_session import MultionUpdateSession
class MultionToolkit(BaseToolkit):
"""Toolkit for interacting with the Browser Agent.
**Security Note**: This toolkit contains tools that interact with the
user's browser via the multion API which grants an agent
access to the user's browser.
Please review the documentation for the multion API to understand
the security implications of using this toolkit.
See https://python.langchain.com/docs/security for more information.
"""
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [MultionCreateSession(), MultionUpdateSession(), MultionCloseSession()]

View File

@@ -0,0 +1 @@
"""NASA Toolkit"""

View File

@@ -0,0 +1,62 @@
from typing import Dict, List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from langchain_community.tools.nasa.prompt import (
NASA_CAPTIONS_PROMPT,
NASA_MANIFEST_PROMPT,
NASA_METADATA_PROMPT,
NASA_SEARCH_PROMPT,
)
from langchain_community.tools.nasa.tool import NasaAction
from langchain_community.utilities.nasa import NasaAPIWrapper
class NasaToolkit(BaseToolkit):
"""Nasa Toolkit.
Parameters:
tools: List[BaseTool]. The tools in the toolkit. Default is an empty list.
"""
tools: List[BaseTool] = []
@classmethod
def from_nasa_api_wrapper(cls, nasa_api_wrapper: NasaAPIWrapper) -> "NasaToolkit":
operations: List[Dict] = [
{
"mode": "search_media",
"name": "Search NASA Image and Video Library media",
"description": NASA_SEARCH_PROMPT,
},
{
"mode": "get_media_metadata_manifest",
"name": "Get NASA Image and Video Library media metadata manifest",
"description": NASA_MANIFEST_PROMPT,
},
{
"mode": "get_media_metadata_location",
"name": "Get NASA Image and Video Library media metadata location",
"description": NASA_METADATA_PROMPT,
},
{
"mode": "get_video_captions_location",
"name": "Get NASA Image and Video Library video captions location",
"description": NASA_CAPTIONS_PROMPT,
},
]
tools = [
NasaAction(
name=action["name"],
description=action["description"],
mode=action["mode"],
api_wrapper=nasa_api_wrapper,
)
for action in operations
]
return cls(tools=tools) # type: ignore[arg-type]
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return self.tools

View File

@@ -0,0 +1,79 @@
"""Tool for interacting with a single API with natural language definition."""
from __future__ import annotations
from typing import Any, Optional
from langchain_core.language_models import BaseLanguageModel
from langchain_core.tools import Tool
from langchain_community.chains.openapi.chain import OpenAPIEndpointChain
from langchain_community.tools.openapi.utils.api_models import APIOperation
from langchain_community.tools.openapi.utils.openapi_utils import OpenAPISpec
from langchain_community.utilities.requests import Requests
class NLATool(Tool):
"""Natural Language API Tool."""
@classmethod
def from_open_api_endpoint_chain(
cls, chain: OpenAPIEndpointChain, api_title: str
) -> "NLATool":
"""Convert an endpoint chain to an API endpoint tool.
Args:
chain: The endpoint chain.
api_title: The title of the API.
Returns:
The API endpoint tool.
"""
expanded_name = (
f"{api_title.replace(' ', '_')}.{chain.api_operation.operation_id}"
)
description = (
f"I'm an AI from {api_title}. Instruct what you want,"
" and I'll assist via an API with description:"
f" {chain.api_operation.description}"
)
return cls(name=expanded_name, func=chain.run, description=description)
@classmethod
def from_llm_and_method(
cls,
llm: BaseLanguageModel,
path: str,
method: str,
spec: OpenAPISpec,
requests: Optional[Requests] = None,
verbose: bool = False,
return_intermediate_steps: bool = False,
**kwargs: Any,
) -> "NLATool":
"""Instantiate the tool from the specified path and method.
Args:
llm: The language model to use.
path: The path of the API.
method: The method of the API.
spec: The OpenAPI spec.
requests: Optional requests object. Default is None.
verbose: Whether to print verbose output. Default is False.
return_intermediate_steps: Whether to return intermediate steps.
Default is False.
kwargs: Additional arguments.
Returns:
The tool.
"""
api_operation = APIOperation.from_openapi_spec(spec, path, method)
chain = OpenAPIEndpointChain.from_api_operation(
api_operation,
llm,
requests=requests,
verbose=verbose,
return_intermediate_steps=return_intermediate_steps,
**kwargs,
)
return cls.from_open_api_endpoint_chain(chain, spec.info.title)

View File

@@ -0,0 +1,150 @@
from __future__ import annotations
from typing import Any, List, Optional, Sequence
from langchain_core.language_models import BaseLanguageModel
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import Field
from langchain_community.agent_toolkits.nla.tool import NLATool
from langchain_community.tools.openapi.utils.openapi_utils import OpenAPISpec
from langchain_community.tools.plugin import AIPlugin
from langchain_community.utilities.requests import Requests
class NLAToolkit(BaseToolkit):
"""Natural Language API Toolkit.
*Security Note*: This toolkit creates tools that enable making calls
to an Open API compliant API.
The tools created by this toolkit may be able to make GET, POST,
PATCH, PUT, DELETE requests to any of the exposed endpoints on
the API.
Control access to who can use this toolkit.
See https://python.langchain.com/docs/security for more information.
"""
nla_tools: Sequence[NLATool] = Field(...)
"""List of API Endpoint Tools."""
def get_tools(self) -> List[BaseTool]:
"""Get the tools for all the API operations."""
return list(self.nla_tools)
@staticmethod
def _get_http_operation_tools(
llm: BaseLanguageModel,
spec: OpenAPISpec,
requests: Optional[Requests] = None,
verbose: bool = False,
**kwargs: Any,
) -> List[NLATool]:
"""Get the tools for all the API operations."""
if not spec.paths:
return []
http_operation_tools = []
for path in spec.paths:
for method in spec.get_methods_for_path(path):
endpoint_tool = NLATool.from_llm_and_method(
llm=llm,
path=path,
method=method,
spec=spec,
requests=requests,
verbose=verbose,
**kwargs,
)
http_operation_tools.append(endpoint_tool)
return http_operation_tools
@classmethod
def from_llm_and_spec(
cls,
llm: BaseLanguageModel,
spec: OpenAPISpec,
requests: Optional[Requests] = None,
verbose: bool = False,
**kwargs: Any,
) -> NLAToolkit:
"""Instantiate the toolkit by creating tools for each operation.
Args:
llm: The language model to use.
spec: The OpenAPI spec.
requests: Optional requests object. Default is None.
verbose: Whether to print verbose output. Default is False.
kwargs: Additional arguments.
Returns:
The toolkit.
"""
http_operation_tools = cls._get_http_operation_tools(
llm=llm, spec=spec, requests=requests, verbose=verbose, **kwargs
)
return cls(nla_tools=http_operation_tools)
@classmethod
def from_llm_and_url(
cls,
llm: BaseLanguageModel,
open_api_url: str,
requests: Optional[Requests] = None,
verbose: bool = False,
**kwargs: Any,
) -> NLAToolkit:
"""Instantiate the toolkit from an OpenAPI Spec URL.
Args:
llm: The language model to use.
open_api_url: The URL of the OpenAPI spec.
requests: Optional requests object. Default is None.
verbose: Whether to print verbose output. Default is False.
kwargs: Additional arguments.
Returns:
The toolkit.
"""
spec = OpenAPISpec.from_url(open_api_url)
return cls.from_llm_and_spec(
llm=llm, spec=spec, requests=requests, verbose=verbose, **kwargs
)
@classmethod
def from_llm_and_ai_plugin(
cls,
llm: BaseLanguageModel,
ai_plugin: AIPlugin,
requests: Optional[Requests] = None,
verbose: bool = False,
**kwargs: Any,
) -> NLAToolkit:
"""Instantiate the toolkit from an OpenAPI Spec URL"""
spec = OpenAPISpec.from_url(ai_plugin.api.url)
# TODO: Merge optional Auth information with the `requests` argument
return cls.from_llm_and_spec(
llm=llm,
spec=spec,
requests=requests,
verbose=verbose,
**kwargs,
)
@classmethod
def from_llm_and_ai_plugin_url(
cls,
llm: BaseLanguageModel,
ai_plugin_url: str,
requests: Optional[Requests] = None,
verbose: bool = False,
**kwargs: Any,
) -> NLAToolkit:
"""Instantiate the toolkit from an OpenAPI Spec URL"""
plugin = AIPlugin.from_url(ai_plugin_url)
return cls.from_llm_and_ai_plugin(
llm=llm, ai_plugin=plugin, requests=requests, verbose=verbose, **kwargs
)

View File

@@ -0,0 +1 @@
"""Office365 toolkit."""

View File

@@ -0,0 +1,55 @@
from __future__ import annotations
from typing import TYPE_CHECKING, List
from langchain_core.tools import BaseTool
from langchain_core.tools.base import BaseToolkit
from pydantic import ConfigDict, Field
from langchain_community.tools.office365.create_draft_message import (
O365CreateDraftMessage,
)
from langchain_community.tools.office365.events_search import O365SearchEvents
from langchain_community.tools.office365.messages_search import O365SearchEmails
from langchain_community.tools.office365.send_event import O365SendEvent
from langchain_community.tools.office365.send_message import O365SendMessage
from langchain_community.tools.office365.utils import authenticate
if TYPE_CHECKING:
from O365 import Account
class O365Toolkit(BaseToolkit):
"""Toolkit for interacting with Office 365.
*Security Note*: This toolkit contains tools that can read and modify
the state of a service; e.g., by reading, creating, updating, deleting
data associated with this service.
For example, this toolkit can be used search through emails and events,
send messages and event invites, and create draft messages.
Please make sure that the permissions given by this toolkit
are appropriate for your use case.
See https://python.langchain.com/docs/security for more information.
Parameters:
account: Optional. The Office 365 account. Default is None.
"""
account: Account = Field(default_factory=authenticate)
model_config = ConfigDict(
arbitrary_types_allowed=True,
)
def get_tools(self) -> List[BaseTool]:
"""Get the tools in the toolkit."""
return [
O365SearchEvents(),
O365CreateDraftMessage(),
O365SearchEmails(),
O365SendEvent(),
O365SendMessage(),
]

View File

@@ -0,0 +1 @@
"""OpenAPI spec agent."""

Some files were not shown because too many files have changed in this diff Show More