Skip to content

Commit

Permalink
chore: LLM tools update
Browse files Browse the repository at this point in the history
  • Loading branch information
phil65 committed Dec 10, 2024
1 parent e7546a4 commit b854016
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 91 deletions.
73 changes: 27 additions & 46 deletions src/llmling/config/llm_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@


if TYPE_CHECKING:
from collections.abc import Callable, Sequence

from llmling.config.runtime import RuntimeConfig


Expand All @@ -23,55 +21,48 @@ def __init__(self, runtime: RuntimeConfig):
self.runtime = runtime

async def load_resource(self, name: str) -> dict[str, Any]:
"""Load the content of a resource by its name.
"""Load the content of a resource to use in the current interaction.
Use this tool to load the actual content of a resource. First use
get_resources() to see what's available, then provide the resource name
from that list.
Use this to access content from available resources that you want
to analyze or work with.
Args:
name: Name of the resource to load (must match a name from get_resources())
name: Name of an available resource to load
Returns:
The loaded resource including its content and metadata.
Raises:
ResourceError: If the resource doesn't exist or can't be loaded.
The resource content and metadata
"""
resource = await self.runtime.load_resource(name)
return resource.model_dump()

def get_resources(self) -> list[dict]:
"""List all available resources and their metadata.
"""List all resources that are available for loading.
This tool returns information about all resources that can be loaded, including:
- name: The identifier to use with load_resource
- description: What the resource contains
- mimeType: The type of content (e.g., text/markdown, application/json)
Use this to discover what resources you can access using load_resource().
Returns:
List of resources with their complete metadata.
List of available resources with their descriptions
"""
return [i.model_dump(exclude={"uri"}) for i in self.runtime.get_resources()]

async def register_tool(
self,
name: str,
function: str | Callable[..., Any],
function: str,
description: str | None = None,
) -> str:
"""Register a new tool from a function or import path.
"""Register an importable function as a tool for future interactions.
This tool can register a callable from an import path as string
(e.g. "webbrowser.open")
IMPORTANT: The registered tool will NOT be available in this current
interaction. It can only be used in future requests.
Args:
name: Name for the new tool
function: Function to register (callable or import path)
description: Optional description override (uses function docstring if None)
function: Import path to the function (e.g. "json.dumps")
name: Optional custom name for the tool (uses function name if not provided)
description: What the tool does and how to use it
Returns:
Message confirming the tool registration
Confirmation message about the registration
"""
return await self.runtime.register_tool(function, name, description)

Expand All @@ -81,41 +72,32 @@ async def register_code_tool(
code: str,
description: str | None = None,
) -> str:
"""Register a new tool from Python code.
"""Register new tool functionality for future interactions.
The provided code should define a function that will be converted into a tool.
The function's docstring will be used as the tool's description if no description
is provided.
IMPORTANT: The registered tool will NOT be available in this current
interaction. It can only be used in future requests.
Args:
name: Name for the new tool
code: Python code defining the tool function
description: Optional description override (uses function docstring if None)
name: Identifying name for the new tool
code: Python code that implements the tool
description: What the tool does and how to use it
Returns:
Message confirming the tool registration
Confirmation message about the registration
"""
return await self.runtime.register_code_tool(name, code, description)

def get_tools(self) -> Sequence[LLMCallableTool]:
"""Get all registered tools.
Returns:
List of all tools
"""
return self.runtime.get_tools()

async def install_package(
self,
package: str,
) -> str:
"""Install a Python package.
"""Install a Python package for future tool functionality.
This allows installing packages needed for tool functionality.
Package specifications follow PIP format (e.g. "requests>=2.28.0").
NOTE: Installed packages will only be available for tools in future requests,
not in the current interaction.
Args:
package: Package specification to install (e.g. "requests", "pillow>=10.0.0")
package: Package specification to install (e.g. "requests>=2.28.0")
Returns:
Message confirming the installation
Expand All @@ -130,7 +112,6 @@ def get_llm_tool_management_tools(self) -> list[LLMCallableTool]:
fns = [
self.register_tool,
self.register_code_tool,
self.get_tools,
self.install_package,
]
return [LLMCallableTool.from_callable(fn) for fn in fns] # type: ignore
72 changes: 27 additions & 45 deletions src/llmling/config/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,20 +397,16 @@ async def shutdown(self) -> None:

# Resource Management
async def load_resource(self, name: str) -> LoadedResource:
"""Load the content of a resource by its name.
Use this tool to load the actual content of a resource. First use
get_resources() to see what's available, then provide the resource name
from that list.
"""Load a resource by its registered name.
Args:
name: Name of the resource to load (must match a name from get_resources())
name: Name of the resource as registered in configuration
Returns:
The loaded resource including its content and metadata.
LoadedResource containing content and metadata
Raises:
ResourceError: If the resource doesn't exist or can't be loaded.
ResourceError: If resource doesn't exist or cannot be loaded
"""
return await self._resource_registry.load(name)

Expand Down Expand Up @@ -530,16 +526,10 @@ def get_resource(self, name: str) -> BaseResource:
return self._resource_registry[name]

def get_resources(self) -> Sequence[BaseResource]:
"""List all available resources and their metadata.
This tool returns information about all resources that can be loaded, including:
- name: The identifier to use with load_resource
- description: What the resource contains
- uri: The resource's location
- mimeType: The type of content (e.g., text/markdown, application/json)
"""Get all registered resource configurations.
Returns:
List of resources with their complete metadata.
List of all resource configurations
"""
return list(self._resource_registry.values())

Expand Down Expand Up @@ -641,21 +631,19 @@ async def install_package(
) -> str:
"""Install a Python package using the dependency manager.
This allows installing packages needed for tool functionality.
Package specifications follow PIP format (e.g. "requests>=2.28.0").
Args:
package: Package specification to install (e.g. "requests", "pillow>=10.0.0")
package: Package specification to install
Returns:
Message confirming the installation
Raises:
ToolError: If installation fails or package spec is invalid
Examples:
>>> await install_package("requests")
>>> await install_package("pillow>=10.0.0")
Example:
>>> await runtime.install_package("requests>=2.28.0")
"""
try:
await self._dep_manager.install_dependency(package)
Expand All @@ -672,24 +660,20 @@ async def register_tool(
) -> str:
"""Register a new tool from a function or import path.
This tool can register a callable either from:
- A direct callable object (function/method)
- An import path as string (e.g. "webbrowser.open")
Args:
function: Function to register (callable or import path)
name: Name for the new tool (if None, function name is used)
description: Optional description override (uses function docstring if None)
name: Optional name override (uses function name if None)
description: Optional description override (uses docstring if None)
Returns:
Message confirming the tool registration
Message confirming the registration
Raises:
ToolError: If registration fails (e.g. invalid import path, invalid function)
ToolError: If registration fails
Examples:
>>> await register_tool("webbrowser.open", "open_url")
>>> await register_tool(my_function)
Example:
>>> await runtime.register_tool("webbrowser.open", "open_url")
>>> await runtime.register_tool(my_function)
"""
try:
tool = LLMCallableTool.from_callable(
Expand Down Expand Up @@ -718,23 +702,21 @@ async def register_code_tool(
Args:
name: Name for the new tool
code: Python code defining the tool function
description: Optional description override (uses function docstring if None)
description: Optional description override
Returns:
Message confirming the tool registration
Message confirming the registration
Raises:
ToolError: If registration fails (e.g. invalid code, no callable found)
Examples:
>>> await register_code_tool(
... name="word_count",
... code='''
... async def count_words(text: str) -> dict[str, int]:
... words = text.split()
... return {"total": len(words)}
... '''
... )
ToolError: If registration fails
Example:
>>> code = '''
... async def count_words(text: str) -> dict[str, int]:
... words = text.split()
... return {"total": len(words)}
... '''
>>> await runtime.register_code_tool("word_count", code)
"""
try:
namespace: dict[str, Any] = {}
Expand Down

0 comments on commit b854016

Please sign in to comment.