Skip to content

Commit c79c9b9

Browse files
Teeeioxiaow190
andauthored
feat: Add intelligent tool matcher with semantic embeddings (#67)
- Implement ToolMatcher class using sentence transformers for semantic similarity - Add fallback mechanisms: TF-IDF vectorization and simple keyword matching - Support configurable similarity thresholds and maximum tool results - Provide methods for tool matching, similarity calculation, and tool management - Enable intelligent task-tool matching based on names and descriptions Co-authored-by: guowei <[email protected]>
1 parent ee1e0d4 commit c79c9b9

File tree

4 files changed

+393
-2
lines changed

4 files changed

+393
-2
lines changed

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ packaging==25.0
4848
pandas==2.2.3
4949
pillow==11.2.1
5050
psutil==7.0.0
51+
sentence-transformers==2.5.1
52+
scikit-learn==1.5.2
5153
pycparser==2.22
5254
pydantic==2.11.3
5355
pydantic-settings==2.10.1

slaver/config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
tool:
22
# Has the model undergone targeted training on tool_calls
33
support_tool_calls: false
4+
# Tool matching configuration
5+
matching:
6+
# Maximum number of tools to match for each task
7+
max_tools: 3
8+
# Minimum similarity score threshold (0.0 to 1.0)
9+
min_similarity: 0.1
410

511
# Cloud Server Infos
612
model:

slaver/run.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from mcp.client.stdio import stdio_client
2020
from mcp.client.streamable_http import streamablehttp_client
2121
from tools.utils import Config
22+
from tools.tool_matcher import ToolMatcher
2223

2324
config = Config.load_config()
2425
collaborator = Collaborator.from_config(config=config["collaborator"])
@@ -39,6 +40,12 @@ def __init__(self):
3940
self.threads = []
4041
self.loop = asyncio.get_event_loop()
4142
self.robot_name = None
43+
44+
# Initialize tool matcher with configuration
45+
self.tool_matcher = ToolMatcher(
46+
max_tools=config["tool"]["matching"]["max_tools"],
47+
min_similarity=config["tool"]["matching"]["min_similarity"]
48+
)
4249

4350
signal.signal(signal.SIGINT, self._handle_signal)
4451
signal.signal(signal.SIGTERM, self._handle_signal)
@@ -108,8 +115,21 @@ async def _execute_task(self, task_data: Dict) -> None:
108115
return
109116

110117
os.makedirs("./.log", exist_ok=True)
118+
119+
# Use tool matcher to find relevant tools for the task
120+
task = task_data["task"]
121+
matched_tools = self.tool_matcher.match_tools(task)
122+
123+
# Filter tools based on matching results
124+
if matched_tools:
125+
matched_tool_names = [tool_name for tool_name, _ in matched_tools]
126+
filtered_tools = [tool for tool in self.tools
127+
if tool.get("function", {}).get("name") in matched_tool_names]
128+
else:
129+
filtered_tools = self.tools
130+
111131
agent = ToolCallingAgent(
112-
tools=self.tools,
132+
tools=filtered_tools,
113133
verbosity_level=2,
114134
model=self.model,
115135
model_path=self.model_path,
@@ -118,7 +138,7 @@ async def _execute_task(self, task_data: Dict) -> None:
118138
collaborator=self.collaborator,
119139
tool_executor=self.session.call_tool,
120140
)
121-
task = task_data["task"]
141+
122142
result = await agent.run(task)
123143
self._send_result(
124144
robot_name=self.robot_name,
@@ -200,6 +220,9 @@ async def connect_to_robot(self):
200220
for tool in response.tools
201221
]
202222
print("Connected to robot with tools:", str(self.tools))
223+
224+
# Train the tool matcher with the available tools
225+
self.tool_matcher.fit(self.tools)
203226

204227
"""Complete robot registration with thread management"""
205228
robot_name = config["robot"]["name"]

0 commit comments

Comments
 (0)