-
-
Notifications
You must be signed in to change notification settings - Fork 207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: allow to load tools from external modules #336
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Looks good to me! Reviewed everything up to 8c06068 in 1 minute and 13 seconds
More details
- Looked at
415
lines of code in9
files - Skipped
0
files when reviewing. - Skipped posting
4
drafted comments based on config settings.
1. gptme/tools/__init__.py:75
- Draft comment:
Consider providing a default value forTOOL_MODULES
in case the environment variable is not set to avoid unexpected behavior. - Reason this comment was not posted:
Comment looked like it was already resolved.
2. gptme/cli.py:192
- Draft comment:
Ensure that theinit_tools
function is called with thetool_modules
parameter to maintain consistent tool loading behavior. - Reason this comment was not posted:
Comment did not seem useful.
3. gptme/chat.py:78
- Draft comment:
Ensure that theinit_tools
function is called with thetool_modules
parameter to maintain consistent tool loading behavior. - Reason this comment was not posted:
Marked as duplicate.
4. gptme/tools/__init__.py:64
- Draft comment:
Consider providing a default value forTOOL_MODULES
in case the environment variable is not set to avoid unexpected behavior. - Reason this comment was not posted:
Marked as duplicate.
Workflow ID: wflow_FahKdYWbNHfz9C4F
You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet
mode, and more.
7cfed4f
to
3c8d8ed
Compare
Ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❌ Changes requested. Reviewed everything up to 3c8d8ed in 1 minute and 27 seconds
More details
- Looked at
1172
lines of code in22
files - Skipped
0
files when reviewing. - Skipped posting
5
drafted comments based on config settings.
1. gptme/tools/__init__.py:87
- Draft comment:
Store the result ofget_available_tools()
in a variable and reuse it to avoid multiple calls. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable:
The comment suggests an optimization that is already effectively implemented via the global _available_tools cache. The function get_available_tools() only computes the tools once when _available_tools is None, and returns the cached value afterward. Storing the result in a local variable would not provide any additional performance benefit.
Maybe there could be thread safety concerns with the global variable that would make local caching beneficial? Or maybe the global could be modified between loop iterations?
The code is using a simple global cache pattern that is appropriate for this use case. The global is only modified in clear_tools() which is not called during the loop execution. Thread safety would be a separate concern requiring different solutions.
The comment should be deleted because it suggests an optimization that is already effectively implemented through the global _available_tools cache.
2. gptme/tools/python.py:227
- Draft comment:
Add a type hint for theloaded_tools
parameter in theinit
function for better readability and maintainability. - Reason this comment was not posted:
Confidence changes required:50%
Theinit
function ingptme/tools/python.py
is missing a type hint for its parameterloaded_tools
. Adding a type hint would improve code readability and maintainability.
3. gptme/tools/rag.py:115
- Draft comment:
Add a type hint for theargs
parameter in theinit
function for better readability and maintainability. - Reason this comment was not posted:
Confidence changes required:50%
Theinit
function ingptme/tools/rag.py
is missing a type hint for its parameterargs
. Adding a type hint would improve code readability and maintainability.
4. gptme/tools/subagent.py:163
- Draft comment:
Add a type hint for thetool_format
parameter in theexamples
function for better readability and maintainability. - Reason this comment was not posted:
Confidence changes required:50%
Theinit
function ingptme/tools/subagent.py
is missing a type hint for its parametertool_format
. Adding a type hint would improve code readability and maintainability.
5. gptme/tools/rag.py:112
- Draft comment:
Add a type hint for theargs
parameter in theinit
function for better readability and maintainability. - Reason this comment was not posted:
Confidence changes required:50%
Theinit
function ingptme/tools/rag.py
is missing a type hint for its parameterargs
. Adding a type hint would improve code readability and maintainability.
Workflow ID: wflow_7AZWSEbuwoLaaiIM
Want Ellipsis to fix these issues? Tag @ellipsis-dev
in a comment. You can customize Ellipsis with 👍 / 👎 feedback, review rules, user-specific overrides, quiet
mode, and more.
gptme/tools/__init__.py
Outdated
if tool.name in loaded_tool_names: | ||
|
||
config = get_config() | ||
print(config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the print statement as it seems to be a leftover debug statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Removed.
3c8d8ed
to
7c65f0d
Compare
This MR:
|
84995a5
to
3992661
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice, I had something just like this in mind!
Lots of nice improvements in this PR, happy to try it and merge it once the conflicts are resolved :)
# Also test special use cases | ||
assert (tool_save := get_tool_for_langtag("test.txt")) | ||
assert tool_save.name == "save" | ||
|
||
assert (tool_save := get_tool_for_langtag("/src/test")) | ||
assert tool_save.name == "save" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens here? Implicit save?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
3992661
to
46f2863
Compare
46f2863
to
860157b
Compare
Great! Thanks. I've resolved the conflicts. |
I made my first useful contributed tool today using a gptme-agent and the import os
import requests
from gptme.tools import ToolSpec, Parameter, ToolUse
from gptme.message import Message
PUSHOVER_USER_KEY = os.getenv('PUSHOVER_USER_KEY')
PUSHOVER_API_TOKEN = os.getenv('PUSHOVER_API_TOKEN')
def execute(content: str | None, args: list[str] | None, kwargs: dict[str, str] | None, confirm):
if not PUSHOVER_USER_KEY or not PUSHOVER_API_TOKEN:
return Message('system', "PUSHOVER_USER_KEY or PUSHOVER_API_TOKEN env variables are not set")
if content is not None and args is not None:
title = args[0]
message = content
elif kwargs is not None:
title = kwargs.get('title', 'No title')
message = kwargs.get('message', 'No message')
else:
return Message('system', "Tool call failed")
url = "https://api.pushover.net/1/messages.json"
payload = {
"token": PUSHOVER_API_TOKEN,
"user": PUSHOVER_USER_KEY,
"message": message,
"title": title,
}
try:
response = requests.post(url, data=payload, timeout=30)
if response.status_code == 200:
return Message('system', "Notification sent successfully")
else:
return Message('system', "The notification couldn't be sent")
except Exception as e:
return Message('system', f"Something went wrong while sending the notification: {e}")
def examples(tool_format):
return f"""
> User: Send me a notification.
> Assistant:
{ToolUse("send_notification", ["This is a test notification!"], "Success").to_output(tool_format)}
> System: Notification sent successfully.
> Assistant: The notification has been sent.
""".strip()
tool = ToolSpec(
name="notification",
desc="Sends a notification via Pushover.",
instructions="Use this tool to send notifications to the user's Pushover account.",
examples=examples,
execute=execute,
block_types=["notification"],
parameters=[
Parameter(
name="message",
type="string",
description="The message to send in the notification.",
required=True,
),
Parameter(
name="title",
type="string",
description="The title of the notification.",
required=False,
),
],
) So great!!!! |
@ErikBjare this MR is ready for review. It allows to load contributed tools from any python module. Read the added documentation for more information. Let me know what you think.
Important
This pull request enables loading tools from external Python modules by updating configuration and tool initialization logic.
TOOL_MODULES
inconfig.rst
.chat.py
andcli.py
to useTOOL_FORMAT
andTOOL_MODULES
from configuration.init_tools()
intools/__init__.py
to discover tools from specified modules using_discover_tools()
.disabled_by_default
andload_priority
attributes toToolSpec
intools/base.py
.computer.py
,python.py
,rag.py
, andsubagent.py
to use new tool initialization logic.config.rst
.This description was created by for 8c06068. It will automatically update as commits are pushed.