Source code for langchain_community.tools.shell.tool
import logging
import platform
import warnings
from typing import Any, List, Optional, Type, Union
from langchain_core.callbacks import (
CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import BaseModel, Field, root_validator
from langchain_core.tools import BaseTool
logger = logging.getLogger(__name__)
[docs]class ShellInput(BaseModel):
"""Bash Shell工具的命令。"""
commands: Union[str, List[str]] = Field(
...,
description="需要运行的shell命令列表。 Deserialized using json.loads",
)
"""需要运行的shell命令列表。"""
@root_validator
def _validate_commands(cls, values: dict) -> dict:
"""验证命令。"""
# TODO: Add real validators
commands = values.get("commands")
if not isinstance(commands, list):
values["commands"] = [commands]
# Warn that the bash tool is not safe
warnings.warn(
"The shell tool has no safeguards by default. Use at your own risk."
)
return values
def _get_default_bash_process() -> Any:
"""获取默认的bash进程。"""
try:
from langchain_experimental.llm_bash.bash import BashProcess
except ImportError:
raise ImportError(
"BashProcess has been moved to langchain experimental."
"To use this tool, install langchain-experimental "
"with `pip install langchain-experimental`."
)
return BashProcess(return_err_output=True)
def _get_platform() -> str:
"""获取平台。"""
system = platform.system()
if system == "Darwin":
return "MacOS"
return system
[docs]class ShellTool(BaseTool):
"""用于运行shell命令的工具。"""
process: Any = Field(default_factory=_get_default_bash_process)
"""运行命令的Bash进程。"""
name: str = "terminal"
"""工具的名称。"""
description: str = f"Run shell commands on this {_get_platform()} machine."
"""工具的描述。"""
args_schema: Type[BaseModel] = ShellInput
"""输入参数的模式。"""
ask_human_input: bool = False
"""如果为True,则在bash shell中执行语言模型生成的命令之前,会提示用户确认(y/n)。"""
def _run(
self,
commands: Union[str, List[str]],
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
"""运行命令并返回最终输出。"""
print(f"Executing command:\n {commands}") # noqa: T201
try:
if self.ask_human_input:
user_input = input("Proceed with command execution? (y/n): ").lower()
if user_input == "y":
return self.process.run(commands)
else:
logger.info("Invalid input. User aborted command execution.")
return None # type: ignore[return-value]
else:
return self.process.run(commands)
except Exception as e:
logger.error(f"Error during command execution: {e}")
return None # type: ignore[return-value]