community[patch]: Basic Logging and Human input to ShellTool (#15932)

- **Description:** As Shell tool is very versatile, while integrating it
into applications as openai functions, developers have no clue about
what command is being executed using the ShellTool. All one can see is:

![image](https://github.com/langchain-ai/langchain/assets/60742358/540e274a-debc-4564-9027-046b91424df3)

Summarising my feature request:
1. There's no visibility about what command was executed.
2. There's no mechanism to prevent a command to be executed using
ShellTool, like a y/n human input which can be accepted from user to
proceed with executing the command.,
  - **Issue:** the issue #15931 it fixes if applicable,
  - **Dependencies:** There isn't any dependancy,
  - **Twitter handle:** @krishnashed
This commit is contained in:
Krishna Shedbalkar
2024-01-18 02:27:51 +05:30
committed by GitHub
parent 2af813c7eb
commit f238217cea
2 changed files with 53 additions and 1 deletions

View File

@@ -1,3 +1,4 @@
import logging
import platform
import warnings
from typing import Any, List, Optional, Type, Union
@@ -8,6 +9,8 @@ from langchain_core.callbacks import (
from langchain_core.pydantic_v1 import BaseModel, Field, root_validator
from langchain_core.tools import BaseTool
logger = logging.getLogger(__name__)
class ShellInput(BaseModel):
"""Commands for the Bash Shell tool."""
@@ -68,10 +71,32 @@ class ShellTool(BaseTool):
args_schema: Type[BaseModel] = ShellInput
"""Schema for input arguments."""
ask_human_input: bool = False
"""
If True, prompts the user for confirmation (y/n) before executing
a command generated by the language model in the bash shell.
"""
def _run(
self,
commands: Union[str, List[str]],
run_manager: Optional[CallbackManagerForToolRun] = None,
) -> str:
"""Run commands and return final output."""
return self.process.run(commands)
print(f"Executing command:\n {commands}")
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
else:
return self.process.run(commands)
except Exception as e:
logger.error(f"Error during command execution: {e}")
return None