mirror of
https://github.com/Hopiu/llm.git
synced 2026-05-16 09:43:12 +00:00
parent
1efb14f294
commit
a880c123bd
4 changed files with 39 additions and 18 deletions
11
docs/help.md
11
docs/help.md
|
|
@ -127,8 +127,8 @@ Options:
|
|||
Attachment with explicit mimetype,
|
||||
--at image.jpg image/jpeg
|
||||
-T, --tool TEXT Name of a tool to make available to the model
|
||||
--tools TEXT Python code block defining functions to
|
||||
register as tools
|
||||
--functions TEXT Python code block or file path defining
|
||||
functions to register as tools
|
||||
--td, --tools-debug Show full details of tool executions
|
||||
--ta, --tools-approve Manually approve every tool execution
|
||||
-o, --option <TEXT TEXT>... key/value options for the model
|
||||
|
|
@ -628,9 +628,10 @@ Usage: llm tools list [OPTIONS]
|
|||
List available tools that have been provided by plugins
|
||||
|
||||
Options:
|
||||
--json Output as JSON
|
||||
--tools TEXT Python code block defining functions to register as tools
|
||||
--help Show this message and exit.
|
||||
--json Output as JSON
|
||||
--functions TEXT Python code block or file path defining functions to
|
||||
register as tools
|
||||
--help Show this message and exit.
|
||||
```
|
||||
|
||||
(help-aliases)=
|
||||
|
|
|
|||
|
|
@ -20,4 +20,4 @@ In LLM every tool is a defined as a Python function. The function can take any n
|
|||
|
||||
Tool functions should include a docstring that describes what the function does. This docstring will become the description that is passed to the model.
|
||||
|
||||
The Python API can accept functions directly. The command-line interface has two ways for tools to be defined: via plugins that implement the {ref}`register_tools() plugin hook <plugin-hooks-register-tools>`, or directly on the command-line using the `--tools` argument to specify a block of Python code defining one or more functions.
|
||||
The Python API can accept functions directly. The command-line interface has two ways for tools to be defined: via plugins that implement the {ref}`register_tools() plugin hook <plugin-hooks-register-tools>`, or directly on the command-line using the `--functions` argument to specify a block of Python code defining one or more functions - or a path to a Python file containing the same.
|
||||
29
llm/cli.py
29
llm/cli.py
|
|
@ -344,8 +344,9 @@ def cli():
|
|||
)
|
||||
@click.option(
|
||||
"python_tools",
|
||||
"--tools",
|
||||
help="Python code block defining functions to register as tools",
|
||||
"--functions",
|
||||
help="Python code block or file path defining functions to register as tools",
|
||||
multiple=True,
|
||||
)
|
||||
@click.option(
|
||||
"tools_debug",
|
||||
|
|
@ -757,7 +758,8 @@ def prompt(
|
|||
|
||||
extra_tools = []
|
||||
if python_tools:
|
||||
extra_tools = _tools_from_code(python_tools)
|
||||
for code_or_path in python_tools:
|
||||
extra_tools = _tools_from_code(code_or_path)
|
||||
|
||||
if tools or python_tools:
|
||||
prompt_method = conversation.chain
|
||||
|
|
@ -2286,15 +2288,17 @@ def tools():
|
|||
@click.option("json_", "--json", is_flag=True, help="Output as JSON")
|
||||
@click.option(
|
||||
"python_tools",
|
||||
"--tools",
|
||||
help="Python code block defining functions to register as tools",
|
||||
"--functions",
|
||||
help="Python code block or file path defining functions to register as tools",
|
||||
multiple=True,
|
||||
)
|
||||
def tools_list(json_, python_tools):
|
||||
"List available tools that have been provided by plugins"
|
||||
tools = get_tools()
|
||||
if python_tools:
|
||||
for tool in _tools_from_code(python_tools):
|
||||
tools[tool.name] = tool
|
||||
for code_or_path in python_tools:
|
||||
for tool in _tools_from_code(code_or_path):
|
||||
tools[tool.name] = tool
|
||||
if json_:
|
||||
click.echo(
|
||||
json.dumps(
|
||||
|
|
@ -3565,16 +3569,21 @@ def load_template(name: str) -> Template:
|
|||
return _parse_yaml_template(name, content)
|
||||
|
||||
|
||||
def _tools_from_code(code: str) -> List[Tool]:
|
||||
def _tools_from_code(code_or_path: str) -> List[Tool]:
|
||||
"""
|
||||
Treat all Python functions in the code as tools
|
||||
"""
|
||||
if "\n" not in code_or_path and code_or_path.endswith(".py"):
|
||||
try:
|
||||
code_or_path = pathlib.Path(code_or_path).read_text()
|
||||
except FileNotFoundError:
|
||||
raise click.ClickException("File not found: {}".format(code_or_path))
|
||||
globals = {}
|
||||
tools = []
|
||||
try:
|
||||
exec(code, globals)
|
||||
exec(code_or_path, globals)
|
||||
except SyntaxError as ex:
|
||||
raise click.ClickException("Error in --tools definition: {}".format(ex))
|
||||
raise click.ClickException("Error in --functions definition: {}".format(ex))
|
||||
# Register all callables in the locals dict:
|
||||
for name, value in globals.items():
|
||||
if callable(value) and not name.startswith("_"):
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ def test_register_fragment_loaders(logs_db, httpx_mock):
|
|||
]
|
||||
|
||||
|
||||
def test_register_tools():
|
||||
def test_register_tools(tmpdir):
|
||||
def upper(text: str) -> str:
|
||||
"""Convert text to uppercase."""
|
||||
return text.upper()
|
||||
|
|
@ -271,11 +271,22 @@ def test_register_tools():
|
|||
},
|
||||
}
|
||||
# And test the --tools option
|
||||
functions_path = str(tmpdir / "functions.py")
|
||||
with open(functions_path, "w") as fp:
|
||||
fp.write("def example(s: str, i: int):\n return s + '-' + str(i)")
|
||||
result3 = runner.invoke(
|
||||
cli.cli, ["tools", "--tools", "def reverse(s: str): return s[::-1]"]
|
||||
cli.cli,
|
||||
[
|
||||
"tools",
|
||||
"--functions",
|
||||
"def reverse(s: str): return s[::-1]",
|
||||
"--functions",
|
||||
functions_path,
|
||||
],
|
||||
)
|
||||
assert result3.exit_code == 0
|
||||
assert "reverse(s: str)" in result3.output
|
||||
assert "example(s: str, i: int)" in result3.output
|
||||
finally:
|
||||
plugins.pm.unregister(name="ToolsPlugin")
|
||||
assert llm.get_tools() == {}
|
||||
|
|
|
|||
Loading…
Reference in a new issue