diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-06-23 18:37:46 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-06-23 18:37:46 +0900 |
| commit | 21b59cc1d0928dc04dcf5eac24470aaa05013b2d (patch) | |
| tree | 9888aa23aafea3907ce96eb958a06d4369dad86e /src/ollama_web/tools/registry.py | |
| parent | de0513e7cb0593b1aa141e367ff4da7156d6110f (diff) | |
基本機能実装
Diffstat (limited to 'src/ollama_web/tools/registry.py')
| -rw-r--r-- | src/ollama_web/tools/registry.py | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/ollama_web/tools/registry.py b/src/ollama_web/tools/registry.py new file mode 100644 index 0000000..92b321c --- /dev/null +++ b/src/ollama_web/tools/registry.py @@ -0,0 +1,81 @@ +"""Registry of tools exposed to the LLM.""" + +from __future__ import annotations + +import json +from collections.abc import Callable, Sequence +from dataclasses import dataclass, field + +from .scrape import scrape_url +from .search import web_search + + +@dataclass +class ToolRegistry: + """A simple registry mapping tool names to callable implementations.""" + + _tools: dict[str, Callable[..., object]] = field(default_factory=dict) + + def register(self, func: Callable[..., object]) -> Callable[..., object]: + """Register a callable under its ``__name__``.""" + self._tools[func.__name__] = func + return func + + @property + def names(self) -> list[str]: + return list(self._tools.keys()) + + @property + def callables(self) -> list[Callable[..., object]]: + return list(self._tools.values()) + + def get(self, name: str) -> Callable[..., object] | None: + return self._tools.get(name) + + def execute(self, name: str, arguments: dict[str, object] | str) -> str: + """Execute a named tool and return a JSON-encoded string result. + + Args: + name: The tool function name. + arguments: Either a dict of keyword arguments or a JSON string that + decodes to one. + + Returns: + A JSON string representation of the tool's return value, or an error + object when the tool is unknown or raises. + """ + func = self.get(name) + if func is None: + return json.dumps({"error": f"Unknown tool: {name}"}) + + if isinstance(arguments, str): + try: + arguments = json.loads(arguments) if arguments else {} + except json.JSONDecodeError: + return json.dumps({"error": f"Invalid JSON arguments for {name}: {arguments}"}) + + try: + result = func(**arguments) + except Exception as exc: # noqa: BLE001 + return json.dumps({"error": f"{type(exc).__name__}: {exc}"}) + + if isinstance(result, str): + return result + try: + return json.dumps(result, ensure_ascii=False, default=str) + except (TypeError, ValueError): + return str(result) + + +def default_registry() -> ToolRegistry: + """Build a registry pre-loaded with the built-in tools.""" + reg = ToolRegistry() + reg.register(web_search) + reg.register(scrape_url) + return reg + + +def all_tool_callables(registry: ToolRegistry | None = None) -> Sequence[Callable[..., object]]: + """Return the list of callables suitable for ``ollama`` ``tools`` argument.""" + reg = registry or default_registry() + return reg.callables
\ No newline at end of file |
