Source code for langchain_prolog.tool
from inspect import signature
from typing import (
Any,
Dict,
Optional,
Union,
)
from langchain_core.callbacks import (
AsyncCallbackManagerForToolRun,
CallbackManagerForToolRun,
)
from langchain_core.runnables import RunnableConfig
from langchain_core.tools import (
BaseTool,
Tool,
)
from langchain_core.tools.base import _get_runnable_config_param
from pydantic import (
BaseModel,
Field,
)
from langchain_prolog import (
PrologConfig,
PrologInput,
PrologRunnable,
)
from .exceptions import PrologToolException
class _PrologRunnableWrapper(PrologRunnable):
pass
[docs]
class PrologTool(Tool):
"""Tool for executing Prolog queries."""
prolog: PrologRunnable = Field( # type: ignore
default=None,
exclude=True,
description="PrologRunnable instance to be used for invoking Prolog queries",
)
[docs]
def __init__(
self,
name: str,
description: str,
prolog_config: Optional[Union[PrologConfig, Dict]] = None,
prolog_kwargs: Optional[Dict] = None,
**kwargs: Any,
) -> None:
"""Initialize the Prolog tool.
Args:
name (str): The name of the tool.
description (str): A description of what the tool does.
prolog_config (PrologConfig | dict): Configuration for the Prolog interpreter.
return_direct (bool): Whether to return the output directly. Defaults to False.
verbose (bool): Whether to enable verbose output. Defaults to False.
callbacks (Callbacks, optional): Callback functions to be called during tool execution.
tags (list[str], optional): Optional list of tags.
metadata (dict, optional): Optional metadata dictionary.
handle_tool_error(bool | str | Callable, optional): How to handle tool execution errors.
handle_validation_error (bool | str | Callable, optional): How to handle input validation errors.
response_format ("content" | "content_and_artifact"): Format of the tool's response.
**kwargs: Additional arguments passed to BaseTool.
"""
# Initialize the PrologRunnable
prolog_kwargs = prolog_kwargs or {}
prolog = _PrologRunnableWrapper(
prolog_config=prolog_config,
**prolog_kwargs,
)
# Call Tool initializer
super().__init__(
name=name,
description=description,
func=prolog.invoke,
args_schema=prolog.prolog_config.query_schema,
**kwargs,
)
self.prolog = prolog
def _to_args_and_kwargs(self, tool_input: Union[str, dict], tool_call_id: Optional[str]) -> tuple[tuple, dict]:
"""Handle tool input for function calling."""
args, kwargs = BaseTool._to_args_and_kwargs(self, tool_input, tool_call_id) # pylint: disable=protected-access
args = args if isinstance(args, tuple) else () if args is None else (args,)
kwargs = kwargs if isinstance(kwargs, dict) else {} if kwargs is None else {"__arg1": kwargs}
all_args = list(args) + list(kwargs.values())
if len(args) != 0 or "__arg1" in kwargs:
return tuple(all_args), {}
return (kwargs,), {}
[docs]
def run( # type: ignore[override]
self,
tool_input: PrologInput,
**kwargs: Any,
) -> Any:
if isinstance(tool_input, BaseModel):
tool_input = tool_input.model_dump()
return super().run(tool_input, **kwargs) # type: ignore
def _run(
self,
*args: Any,
config: RunnableConfig,
run_manager: Optional[CallbackManagerForToolRun] = None,
**kwargs: Any,
) -> Any:
"""Execute the Prolog query.
Args:
args: Args for the Prolog query to execute
config (RunnableConfig, optional): Optional langchain runnable configuration
run_manager (CallbackManagerForToolRun, optional): Optional callback manager for then tool run
**kwargs: Additional arguments for Prolog query execution.
Supported keyword arguments by janus-swi: inputs, truth_vals
Returns:
Prolog query result. True, False or list of dictionaries
Raises:
PrologToolException: If the query execution fails
"""
try:
if run_manager and signature(self.prolog.invoke).parameters.get("callbacks"):
kwargs["callbacks"] = run_manager.get_child()
if config_param := _get_runnable_config_param(self.prolog.invoke):
kwargs[config_param] = config
return self.prolog.invoke(*args, **kwargs)
except Exception as e:
raise PrologToolException(f"Unexpected error during Prolog tool execution: {str(e)}")
async def _arun(
self,
*args: Any,
config: RunnableConfig,
run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
**kwargs: Any,
) -> Any:
"""Execute the Prolog query asynchronously.
Args:
args: Args for the Prolog query to execute
config (RunnableConfig, optional): Optional langchain runnable configuration
run_manager (CallbackManagerForToolRun, optional): Optional callback manager for then tool run
**kwargs: Additional arguments for Prolog query execution.
Supported keyword arguments by janus-swi: inputs, truth_vals
Returns:
Prolog query result. True, False or list of dictionaries
Raises:
PrologToolException: If the query execution fails
"""
if run_manager:
run_manager = run_manager.get_sync() # type: ignore
return self._run(*args, config=config, run_manager=run_manager, **kwargs) # type: ignore