tooluniverse 0.1.4__py3-none-any.whl โ 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tooluniverse might be problematic. Click here for more details.
- tooluniverse/__init__.py +340 -4
- tooluniverse/admetai_tool.py +84 -0
- tooluniverse/agentic_tool.py +563 -0
- tooluniverse/alphafold_tool.py +96 -0
- tooluniverse/base_tool.py +129 -6
- tooluniverse/boltz_tool.py +207 -0
- tooluniverse/chem_tool.py +192 -0
- tooluniverse/compose_scripts/__init__.py +1 -0
- tooluniverse/compose_scripts/biomarker_discovery.py +293 -0
- tooluniverse/compose_scripts/comprehensive_drug_discovery.py +186 -0
- tooluniverse/compose_scripts/drug_safety_analyzer.py +89 -0
- tooluniverse/compose_scripts/literature_tool.py +34 -0
- tooluniverse/compose_scripts/output_summarizer.py +279 -0
- tooluniverse/compose_scripts/tool_description_optimizer.py +681 -0
- tooluniverse/compose_scripts/tool_discover.py +705 -0
- tooluniverse/compose_scripts/tool_graph_composer.py +448 -0
- tooluniverse/compose_tool.py +371 -0
- tooluniverse/ctg_tool.py +1002 -0
- tooluniverse/custom_tool.py +81 -0
- tooluniverse/dailymed_tool.py +108 -0
- tooluniverse/data/admetai_tools.json +155 -0
- tooluniverse/data/agentic_tools.json +1156 -0
- tooluniverse/data/alphafold_tools.json +87 -0
- tooluniverse/data/boltz_tools.json +9 -0
- tooluniverse/data/chembl_tools.json +16 -0
- tooluniverse/data/clait_tools.json +108 -0
- tooluniverse/data/clinicaltrials_gov_tools.json +326 -0
- tooluniverse/data/compose_tools.json +202 -0
- tooluniverse/data/dailymed_tools.json +70 -0
- tooluniverse/data/dataset_tools.json +646 -0
- tooluniverse/data/disease_target_score_tools.json +712 -0
- tooluniverse/data/efo_tools.json +17 -0
- tooluniverse/data/embedding_tools.json +319 -0
- tooluniverse/data/enrichr_tools.json +31 -0
- tooluniverse/data/europe_pmc_tools.json +22 -0
- tooluniverse/data/expert_feedback_tools.json +10 -0
- tooluniverse/data/fda_drug_adverse_event_tools.json +491 -0
- tooluniverse/data/fda_drug_labeling_tools.json +544 -168
- tooluniverse/data/fda_drugs_with_brand_generic_names_for_tool.py +76929 -148860
- tooluniverse/data/finder_tools.json +209 -0
- tooluniverse/data/gene_ontology_tools.json +113 -0
- tooluniverse/data/gwas_tools.json +1082 -0
- tooluniverse/data/hpa_tools.json +333 -0
- tooluniverse/data/humanbase_tools.json +47 -0
- tooluniverse/data/idmap_tools.json +74 -0
- tooluniverse/data/mcp_client_tools_example.json +113 -0
- tooluniverse/data/mcpautoloadertool_defaults.json +28 -0
- tooluniverse/data/medlineplus_tools.json +141 -0
- tooluniverse/data/monarch_tools.json +1 -1
- tooluniverse/data/openalex_tools.json +36 -0
- tooluniverse/data/opentarget_tools.json +82 -58
- tooluniverse/data/output_summarization_tools.json +101 -0
- tooluniverse/data/packages/bioinformatics_core_tools.json +1756 -0
- tooluniverse/data/packages/categorized_tools.txt +206 -0
- tooluniverse/data/packages/cheminformatics_tools.json +347 -0
- tooluniverse/data/packages/earth_sciences_tools.json +74 -0
- tooluniverse/data/packages/genomics_tools.json +776 -0
- tooluniverse/data/packages/image_processing_tools.json +38 -0
- tooluniverse/data/packages/machine_learning_tools.json +789 -0
- tooluniverse/data/packages/neuroscience_tools.json +62 -0
- tooluniverse/data/packages/original_tools.txt +0 -0
- tooluniverse/data/packages/physics_astronomy_tools.json +62 -0
- tooluniverse/data/packages/scientific_computing_tools.json +560 -0
- tooluniverse/data/packages/single_cell_tools.json +453 -0
- tooluniverse/data/packages/software_tools.json +4954 -0
- tooluniverse/data/packages/structural_biology_tools.json +396 -0
- tooluniverse/data/packages/visualization_tools.json +399 -0
- tooluniverse/data/pubchem_tools.json +215 -0
- tooluniverse/data/pubtator_tools.json +68 -0
- tooluniverse/data/rcsb_pdb_tools.json +1332 -0
- tooluniverse/data/reactome_tools.json +19 -0
- tooluniverse/data/semantic_scholar_tools.json +26 -0
- tooluniverse/data/special_tools.json +2 -25
- tooluniverse/data/tool_composition_tools.json +88 -0
- tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
- tooluniverse/data/txagent_client_tools.json +9 -0
- tooluniverse/data/uniprot_tools.json +211 -0
- tooluniverse/data/url_fetch_tools.json +94 -0
- tooluniverse/data/uspto_downloader_tools.json +9 -0
- tooluniverse/data/uspto_tools.json +811 -0
- tooluniverse/data/xml_tools.json +3275 -0
- tooluniverse/dataset_tool.py +296 -0
- tooluniverse/default_config.py +165 -0
- tooluniverse/efo_tool.py +42 -0
- tooluniverse/embedding_database.py +630 -0
- tooluniverse/embedding_sync.py +396 -0
- tooluniverse/enrichr_tool.py +266 -0
- tooluniverse/europe_pmc_tool.py +52 -0
- tooluniverse/execute_function.py +1775 -95
- tooluniverse/extended_hooks.py +444 -0
- tooluniverse/gene_ontology_tool.py +194 -0
- tooluniverse/graphql_tool.py +158 -36
- tooluniverse/gwas_tool.py +358 -0
- tooluniverse/hpa_tool.py +1645 -0
- tooluniverse/humanbase_tool.py +389 -0
- tooluniverse/logging_config.py +254 -0
- tooluniverse/mcp_client_tool.py +764 -0
- tooluniverse/mcp_integration.py +413 -0
- tooluniverse/mcp_tool_registry.py +925 -0
- tooluniverse/medlineplus_tool.py +337 -0
- tooluniverse/openalex_tool.py +228 -0
- tooluniverse/openfda_adv_tool.py +283 -0
- tooluniverse/openfda_tool.py +393 -160
- tooluniverse/output_hook.py +1122 -0
- tooluniverse/package_tool.py +195 -0
- tooluniverse/pubchem_tool.py +158 -0
- tooluniverse/pubtator_tool.py +168 -0
- tooluniverse/rcsb_pdb_tool.py +38 -0
- tooluniverse/reactome_tool.py +108 -0
- tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
- tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
- tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
- tooluniverse/remote/expert_feedback/simple_test.py +23 -0
- tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
- tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
- tooluniverse/remote/expert_feedback_mcp/human_expert_mcp_server.py +1611 -0
- tooluniverse/remote/expert_feedback_mcp/simple_test.py +34 -0
- tooluniverse/remote/expert_feedback_mcp/start_web_interface.py +91 -0
- tooluniverse/remote/immune_compass/compass_tool.py +327 -0
- tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
- tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
- tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
- tooluniverse/remote_tool.py +99 -0
- tooluniverse/restful_tool.py +53 -30
- tooluniverse/scripts/generate_tool_graph.py +408 -0
- tooluniverse/scripts/visualize_tool_graph.py +829 -0
- tooluniverse/semantic_scholar_tool.py +62 -0
- tooluniverse/smcp.py +2452 -0
- tooluniverse/smcp_server.py +975 -0
- tooluniverse/test/mcp_server_test.py +0 -0
- tooluniverse/test/test_admetai_tool.py +370 -0
- tooluniverse/test/test_agentic_tool.py +129 -0
- tooluniverse/test/test_alphafold_tool.py +71 -0
- tooluniverse/test/test_chem_tool.py +37 -0
- tooluniverse/test/test_compose_lieraturereview.py +63 -0
- tooluniverse/test/test_compose_tool.py +448 -0
- tooluniverse/test/test_dailymed.py +69 -0
- tooluniverse/test/test_dataset_tool.py +200 -0
- tooluniverse/test/test_disease_target_score.py +56 -0
- tooluniverse/test/test_drugbank_filter_examples.py +179 -0
- tooluniverse/test/test_efo.py +31 -0
- tooluniverse/test/test_enrichr_tool.py +21 -0
- tooluniverse/test/test_europe_pmc_tool.py +20 -0
- tooluniverse/test/test_fda_adv.py +95 -0
- tooluniverse/test/test_fda_drug_labeling.py +91 -0
- tooluniverse/test/test_gene_ontology_tools.py +66 -0
- tooluniverse/test/test_gwas_tool.py +139 -0
- tooluniverse/test/test_hpa.py +625 -0
- tooluniverse/test/test_humanbase_tool.py +20 -0
- tooluniverse/test/test_idmap_tools.py +61 -0
- tooluniverse/test/test_mcp_server.py +211 -0
- tooluniverse/test/test_mcp_tool.py +247 -0
- tooluniverse/test/test_medlineplus.py +220 -0
- tooluniverse/test/test_openalex_tool.py +32 -0
- tooluniverse/test/test_opentargets.py +28 -0
- tooluniverse/test/test_pubchem_tool.py +116 -0
- tooluniverse/test/test_pubtator_tool.py +37 -0
- tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
- tooluniverse/test/test_reactome.py +54 -0
- tooluniverse/test/test_semantic_scholar_tool.py +24 -0
- tooluniverse/test/test_software_tools.py +147 -0
- tooluniverse/test/test_tool_description_optimizer.py +49 -0
- tooluniverse/test/test_tool_finder.py +26 -0
- tooluniverse/test/test_tool_finder_llm.py +252 -0
- tooluniverse/test/test_tools_find.py +195 -0
- tooluniverse/test/test_uniprot_tools.py +74 -0
- tooluniverse/test/test_uspto_tool.py +72 -0
- tooluniverse/test/test_xml_tool.py +113 -0
- tooluniverse/tool_finder_embedding.py +267 -0
- tooluniverse/tool_finder_keyword.py +693 -0
- tooluniverse/tool_finder_llm.py +699 -0
- tooluniverse/tool_graph_web_ui.py +955 -0
- tooluniverse/tool_registry.py +416 -0
- tooluniverse/uniprot_tool.py +155 -0
- tooluniverse/url_tool.py +253 -0
- tooluniverse/uspto_tool.py +240 -0
- tooluniverse/utils.py +369 -41
- tooluniverse/xml_tool.py +369 -0
- tooluniverse-1.0.0.dist-info/METADATA +377 -0
- tooluniverse-1.0.0.dist-info/RECORD +186 -0
- {tooluniverse-0.1.4.dist-info โ tooluniverse-1.0.0.dist-info}/WHEEL +1 -1
- tooluniverse-1.0.0.dist-info/entry_points.txt +9 -0
- tooluniverse-0.1.4.dist-info/METADATA +0 -141
- tooluniverse-0.1.4.dist-info/RECORD +0 -18
- {tooluniverse-0.1.4.dist-info โ tooluniverse-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {tooluniverse-0.1.4.dist-info โ tooluniverse-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test suite for ToolUniverse Software Package Tools
|
|
3
|
+
|
|
4
|
+
This test validates the PackageTool implementations for popular Python packages.
|
|
5
|
+
It follows the same pattern as other test files in the ToolUniverse test directory.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python src/tooluniverse/test/test_software_tools.py
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from tooluniverse.execute_function import ToolUniverse
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main():
|
|
15
|
+
print("๐งช Testing ToolUniverse Software Package Tools")
|
|
16
|
+
print("=" * 60)
|
|
17
|
+
|
|
18
|
+
# Step 1: Initialize ToolUniverse with only software tools to reduce noise
|
|
19
|
+
tooluni = ToolUniverse()
|
|
20
|
+
tooluni.load_tools(tool_type=["software"])
|
|
21
|
+
|
|
22
|
+
# Step 2: Get all software package tools
|
|
23
|
+
software_tools = [
|
|
24
|
+
name
|
|
25
|
+
for name in tooluni.all_tool_dict.keys()
|
|
26
|
+
if "get_" in name and "_info" in name
|
|
27
|
+
]
|
|
28
|
+
print(f"๐ฆ Found {len(software_tools)} software package tools:")
|
|
29
|
+
for tool in software_tools:
|
|
30
|
+
package = tool.replace("get_", "").replace("_info", "").replace("_", "-")
|
|
31
|
+
print(f" โข {package}")
|
|
32
|
+
|
|
33
|
+
# Step 3: Define test queries for the PackageTool-based software tools
|
|
34
|
+
test_queries = [
|
|
35
|
+
# Basic tests with examples
|
|
36
|
+
{"name": "get_numpy_info", "arguments": {"include_examples": True}},
|
|
37
|
+
{"name": "get_pandas_info", "arguments": {"include_examples": True}},
|
|
38
|
+
{"name": "get_requests_info", "arguments": {"include_examples": True}},
|
|
39
|
+
{"name": "get_flask_info", "arguments": {"include_examples": True}},
|
|
40
|
+
{"name": "get_scikit_learn_info", "arguments": {"include_examples": True}},
|
|
41
|
+
{"name": "get_matplotlib_info", "arguments": {"include_examples": True}},
|
|
42
|
+
{"name": "get_pytorch_info", "arguments": {"include_examples": True}},
|
|
43
|
+
# Test without examples
|
|
44
|
+
{"name": "get_numpy_info", "arguments": {"include_examples": False}},
|
|
45
|
+
# Test different source options
|
|
46
|
+
{"name": "get_pandas_info", "arguments": {"include_examples": False}},
|
|
47
|
+
{"name": "get_requests_info", "arguments": {"include_examples": True}},
|
|
48
|
+
{"name": "get_flask_info", "arguments": {"include_examples": False}},
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
print("\n" + "=" * 60)
|
|
52
|
+
|
|
53
|
+
# Step 4: Run all test queries
|
|
54
|
+
successful_tests = 0
|
|
55
|
+
failed_tests = 0
|
|
56
|
+
|
|
57
|
+
for idx, query in enumerate(test_queries):
|
|
58
|
+
try:
|
|
59
|
+
package_name = (
|
|
60
|
+
query["name"].replace("get_", "").replace("_info", "").replace("_", "-")
|
|
61
|
+
)
|
|
62
|
+
print(f"\n[{idx+1}] Testing {package_name}...")
|
|
63
|
+
print(f" Tool: {query['name']}")
|
|
64
|
+
print(f" Args: {query['arguments']}")
|
|
65
|
+
print("-" * 50)
|
|
66
|
+
|
|
67
|
+
result = tooluni.run(query)
|
|
68
|
+
|
|
69
|
+
# Check if the result is successful
|
|
70
|
+
if (
|
|
71
|
+
isinstance(result, dict)
|
|
72
|
+
and "error" not in result
|
|
73
|
+
and result.get("package_name")
|
|
74
|
+
):
|
|
75
|
+
print("โ
SUCCESS")
|
|
76
|
+
successful_tests += 1
|
|
77
|
+
|
|
78
|
+
# Print key information
|
|
79
|
+
print(f" ๐ฆ Package: {result.get('package_name', 'Unknown')}")
|
|
80
|
+
print(
|
|
81
|
+
f" ๐ Description: {result.get('description', 'No description')}..."
|
|
82
|
+
)
|
|
83
|
+
print(f" ๐ง Import: {result.get('import_name', 'Unknown')}")
|
|
84
|
+
print(f" ๐ Category: {result.get('category', 'Unknown')}")
|
|
85
|
+
print(f" ๐พ Source: {result.get('source', 'Unknown')}")
|
|
86
|
+
|
|
87
|
+
if result.get("installation"):
|
|
88
|
+
print(f" ๐ป Install: {result['installation'].get('pip', 'N/A')}")
|
|
89
|
+
|
|
90
|
+
if result.get("documentation"):
|
|
91
|
+
print(f" ๐ Docs: {result['documentation']}")
|
|
92
|
+
|
|
93
|
+
if query["arguments"].get("include_examples", False):
|
|
94
|
+
if result.get("usage_example"):
|
|
95
|
+
print(f" ๐ Example: {len(result['usage_example'])} chars")
|
|
96
|
+
if result.get("quick_start"):
|
|
97
|
+
print(f" ๐ Quick start: {len(result['quick_start'])} steps")
|
|
98
|
+
|
|
99
|
+
elif isinstance(result, dict) and "error" in result:
|
|
100
|
+
print("โ FAILED")
|
|
101
|
+
print(f" Error: {result['error']}")
|
|
102
|
+
failed_tests += 1
|
|
103
|
+
|
|
104
|
+
else:
|
|
105
|
+
print("โ FAILED")
|
|
106
|
+
print(f" Unexpected result type: {type(result)}")
|
|
107
|
+
failed_tests += 1
|
|
108
|
+
|
|
109
|
+
except Exception as e:
|
|
110
|
+
print("โ FAILED")
|
|
111
|
+
print(f" Exception: {str(e)}")
|
|
112
|
+
failed_tests += 1
|
|
113
|
+
|
|
114
|
+
# Step 5: Summary
|
|
115
|
+
print("\n" + "=" * 60)
|
|
116
|
+
print("๐ฏ TEST SUMMARY")
|
|
117
|
+
print(f"โ
Successful: {successful_tests}")
|
|
118
|
+
print(f"โ Failed: {failed_tests}")
|
|
119
|
+
print(
|
|
120
|
+
f"๐ Success Rate: {successful_tests/(successful_tests+failed_tests)*100:.1f}%"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
print(f"\n๐ Tested {len(software_tools)} packages:")
|
|
124
|
+
for tool in software_tools:
|
|
125
|
+
pkg = tool.replace("get_", "").replace("_info", "").replace("_", "-")
|
|
126
|
+
print(f" โข {pkg}")
|
|
127
|
+
|
|
128
|
+
print("\nโน๏ธ Features Tested:")
|
|
129
|
+
print(" - PackageTool implementation for popular Python packages")
|
|
130
|
+
print(" - PyPI API integration with real-time package data")
|
|
131
|
+
print(" - Local information fallback when API unavailable")
|
|
132
|
+
print(" - Different parameter combinations (include_examples, source)")
|
|
133
|
+
print(" - Installation instructions and documentation links")
|
|
134
|
+
print(" - Usage examples and quick start guides")
|
|
135
|
+
|
|
136
|
+
return successful_tests, failed_tests
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
if __name__ == "__main__":
|
|
140
|
+
successful, failed = main()
|
|
141
|
+
|
|
142
|
+
if failed == 0:
|
|
143
|
+
print("\n๐ ALL TESTS PASSED! Software tools are working perfectly.")
|
|
144
|
+
else:
|
|
145
|
+
print(f"\nโ ๏ธ {failed} test(s) failed. Check output above for details.")
|
|
146
|
+
|
|
147
|
+
print("\nโจ Software package tools testing complete!")
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Minimal test for ToolDescriptionOptimizer on FDA tool"""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
from tooluniverse import ToolUniverse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def main():
|
|
9
|
+
"""Run minimal FDA tool tests."""
|
|
10
|
+
# Setup
|
|
11
|
+
tu = ToolUniverse()
|
|
12
|
+
tu.load_tools()
|
|
13
|
+
os.makedirs("temp_test", exist_ok=True)
|
|
14
|
+
|
|
15
|
+
# Get FDA tool
|
|
16
|
+
tool_name = "FDA_get_active_ingredient_info_by_drug_name"
|
|
17
|
+
tool_config = tu.get_tool_description(tool_name)
|
|
18
|
+
|
|
19
|
+
# Test 1: Multi-round optimization
|
|
20
|
+
result = tu.run(
|
|
21
|
+
{
|
|
22
|
+
"name": "ToolDescriptionOptimizer",
|
|
23
|
+
"arguments": {
|
|
24
|
+
"tool_config": tool_config,
|
|
25
|
+
"max_iterations": 3,
|
|
26
|
+
"satisfaction_threshold": 8.0,
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
)
|
|
30
|
+
print(
|
|
31
|
+
f"Multi-round optimization: {result['total_iterations']} rounds, score {result['final_quality_score']}/10"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Test 2: Feedback-driven test generation
|
|
35
|
+
enhanced_config = tool_config.copy()
|
|
36
|
+
enhanced_config["_optimization_feedback"] = (
|
|
37
|
+
"Test with both brand and generic drug names"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
_ = tu.run_one_function(
|
|
41
|
+
{"name": "TestCaseGenerator", "arguments": {"tool_config": enhanced_config}}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
print("Feedback-driven test generation: Complete")
|
|
45
|
+
print("FDA tool optimization tests: PASSED")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
main()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from tooluniverse import ToolUniverse
|
|
2
|
+
|
|
3
|
+
# Step 1: Initialize tool universe
|
|
4
|
+
tooluni = ToolUniverse()
|
|
5
|
+
tooluni.load_tools()
|
|
6
|
+
|
|
7
|
+
#
|
|
8
|
+
test_queries = [
|
|
9
|
+
{
|
|
10
|
+
"name": "Tool_Finder",
|
|
11
|
+
"arguments": {
|
|
12
|
+
"description": "a tool for finding tools related to diseases",
|
|
13
|
+
"limit": 10,
|
|
14
|
+
"return_call_result": False,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{"name": "Tool_Finder_Keyword", "arguments": {"query": "disease", "limit": 5}},
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
for idx, query in enumerate(test_queries):
|
|
21
|
+
print(
|
|
22
|
+
f"\n[{idx+1}] Running tool: {query['name']} with arguments: {query['arguments']}"
|
|
23
|
+
)
|
|
24
|
+
result = tooluni.run(query)
|
|
25
|
+
print("โ
Success. Example output snippet:")
|
|
26
|
+
print(result if isinstance(result, dict) else str(result))
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Compatibility test for ToolFinderLLM - ensuring seamless replacement of original tool_finder.py
|
|
4
|
+
|
|
5
|
+
This script tests that ToolFinderLLM has the same interface and behavior as the original
|
|
6
|
+
ToolFinderEmbedding, making it a drop-in replacement.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
import traceback
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_compatibility():
|
|
14
|
+
"""Test that ToolFinderLLM matches original tool_finder interface."""
|
|
15
|
+
print("๐งช Testing ToolFinderLLM compatibility...")
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from tooluniverse.execute_function import ToolUniverse
|
|
19
|
+
from tooluniverse.tool_finder_llm import ToolFinderLLM
|
|
20
|
+
|
|
21
|
+
# Initialize ToolUniverse
|
|
22
|
+
tooluniverse = ToolUniverse()
|
|
23
|
+
tooluniverse.load_tools()
|
|
24
|
+
|
|
25
|
+
# Configure LLM tool finder
|
|
26
|
+
config = {
|
|
27
|
+
"name": "ToolFinderLLM",
|
|
28
|
+
"type": "ToolFinderLLM",
|
|
29
|
+
"configs": {
|
|
30
|
+
"api_type": "CHATGPT",
|
|
31
|
+
"model_id": "gpt-4o-1120",
|
|
32
|
+
"temperature": 0.1,
|
|
33
|
+
"max_new_tokens": 2048,
|
|
34
|
+
"return_json": True,
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
llm_finder = ToolFinderLLM(config, tooluniverse)
|
|
39
|
+
|
|
40
|
+
# Test 1: Basic find_tools() method
|
|
41
|
+
print("โ Testing find_tools() method...")
|
|
42
|
+
result1 = llm_finder.find_tools(
|
|
43
|
+
message="Find tools for drug safety analysis", rag_num=3
|
|
44
|
+
)
|
|
45
|
+
assert isinstance(result1, list), f"Expected list, got {type(result1)}"
|
|
46
|
+
print(f" Result type: {type(result1)} โ")
|
|
47
|
+
|
|
48
|
+
# Test 2: find_tools() with return_call_result=True
|
|
49
|
+
print("โ Testing find_tools() with return_call_result=True...")
|
|
50
|
+
result2 = llm_finder.find_tools(
|
|
51
|
+
message="Find tools for gene analysis", rag_num=2, return_call_result=True
|
|
52
|
+
)
|
|
53
|
+
assert isinstance(result2, tuple), f"Expected tuple, got {type(result2)}"
|
|
54
|
+
assert len(result2) == 2, f"Expected tuple of length 2, got {len(result2)}"
|
|
55
|
+
prompts, tool_names = result2
|
|
56
|
+
assert isinstance(
|
|
57
|
+
prompts, list
|
|
58
|
+
), f"Expected prompts as list, got {type(prompts)}"
|
|
59
|
+
assert isinstance(
|
|
60
|
+
tool_names, list
|
|
61
|
+
), f"Expected tool_names as list, got {type(tool_names)}"
|
|
62
|
+
print(
|
|
63
|
+
f" Result: ({type(prompts)}, {type(tool_names)}) with {len(tool_names)} tools โ"
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Test 3: run() method compatibility
|
|
67
|
+
print("โ Testing run() method...")
|
|
68
|
+
arguments = {
|
|
69
|
+
"description": "Find tools for protein analysis",
|
|
70
|
+
"limit": 2,
|
|
71
|
+
"return_call_result": False,
|
|
72
|
+
}
|
|
73
|
+
result3 = llm_finder.run(arguments)
|
|
74
|
+
assert isinstance(
|
|
75
|
+
result3, list
|
|
76
|
+
), f"Expected list from run(), got {type(result3)}"
|
|
77
|
+
print(f" Run method result type: {type(result3)} โ")
|
|
78
|
+
|
|
79
|
+
# Test 4: run() with return_call_result=True
|
|
80
|
+
print("โ Testing run() with return_call_result=True...")
|
|
81
|
+
arguments_with_result = {
|
|
82
|
+
"description": "Find tools for clinical trials",
|
|
83
|
+
"limit": 2,
|
|
84
|
+
"return_call_result": True,
|
|
85
|
+
}
|
|
86
|
+
result4 = llm_finder.run(arguments_with_result)
|
|
87
|
+
assert isinstance(
|
|
88
|
+
result4, tuple
|
|
89
|
+
), f"Expected tuple from run(), got {type(result4)}"
|
|
90
|
+
print(f" Run method with return_call_result: {type(result4)} โ")
|
|
91
|
+
|
|
92
|
+
# Test 5: test with picked_tool_names (original interface)
|
|
93
|
+
print("โ Testing find_tools() with picked_tool_names...")
|
|
94
|
+
test_tools = ["EuropePMC_search_articles", "PubChem_get_CID_by_compound_name"]
|
|
95
|
+
result5 = llm_finder.find_tools(
|
|
96
|
+
picked_tool_names=test_tools, return_call_result=False
|
|
97
|
+
)
|
|
98
|
+
assert isinstance(
|
|
99
|
+
result5, list
|
|
100
|
+
), f"Expected list with picked_tool_names, got {type(result5)}"
|
|
101
|
+
print(f" Picked tools result type: {type(result5)} โ")
|
|
102
|
+
|
|
103
|
+
# Test 6: test picked_tool_names with return_call_result=True
|
|
104
|
+
print(
|
|
105
|
+
"โ Testing find_tools() with picked_tool_names and return_call_result=True..."
|
|
106
|
+
)
|
|
107
|
+
result6 = llm_finder.find_tools(
|
|
108
|
+
picked_tool_names=test_tools, return_call_result=True
|
|
109
|
+
)
|
|
110
|
+
assert isinstance(
|
|
111
|
+
result6, tuple
|
|
112
|
+
), f"Expected tuple with picked_tool_names, got {type(result6)}"
|
|
113
|
+
prompts6, names6 = result6
|
|
114
|
+
assert isinstance(
|
|
115
|
+
prompts6, list
|
|
116
|
+
), f"Expected prompts as list, got {type(prompts6)}"
|
|
117
|
+
assert isinstance(names6, list), f"Expected names as list, got {type(names6)}"
|
|
118
|
+
assert len(names6) <= len(
|
|
119
|
+
test_tools
|
|
120
|
+
), f"Expected names count <= input, got {len(names6)} > {len(test_tools)}"
|
|
121
|
+
print(
|
|
122
|
+
f" Picked tools with return_call_result: ({type(prompts6)}, {type(names6)}) โ"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
print("\n๐ All compatibility tests passed!")
|
|
126
|
+
print("โ
ToolFinderLLM interface matches original ToolFinderEmbedding")
|
|
127
|
+
return True
|
|
128
|
+
|
|
129
|
+
except ImportError as e:
|
|
130
|
+
print(f"โ ๏ธ ToolUniverse not available: {e}")
|
|
131
|
+
print("Skipping tests - this is expected in some environments")
|
|
132
|
+
return True
|
|
133
|
+
|
|
134
|
+
except Exception as e:
|
|
135
|
+
print(f"โ Compatibility test failed: {e}")
|
|
136
|
+
traceback.print_exc()
|
|
137
|
+
return False
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_error_handling():
|
|
141
|
+
"""Test error handling and edge cases."""
|
|
142
|
+
print("\n๐งช Testing error handling...")
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
from tooluniverse.execute_function import ToolUniverse
|
|
146
|
+
from tooluniverse.tool_finder_llm import ToolFinderLLM
|
|
147
|
+
|
|
148
|
+
# Initialize ToolUniverse
|
|
149
|
+
tooluniverse = ToolUniverse()
|
|
150
|
+
tooluniverse.load_tools()
|
|
151
|
+
|
|
152
|
+
config = {
|
|
153
|
+
"name": "ToolFinderLLM",
|
|
154
|
+
"type": "ToolFinderLLM",
|
|
155
|
+
"configs": {
|
|
156
|
+
"api_type": "CHATGPT",
|
|
157
|
+
"model_id": "gpt-4o-1120",
|
|
158
|
+
"temperature": 0.1,
|
|
159
|
+
"max_new_tokens": 2048,
|
|
160
|
+
"return_json": True,
|
|
161
|
+
},
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
llm_finder = ToolFinderLLM(config, tooluniverse)
|
|
165
|
+
|
|
166
|
+
# Test with invalid arguments
|
|
167
|
+
print("โ Testing error handling with None arguments...")
|
|
168
|
+
try:
|
|
169
|
+
# This should raise an assertion error
|
|
170
|
+
result = llm_finder.find_tools(message=None, picked_tool_names=None)
|
|
171
|
+
print(f" โ Expected AssertionError but got result: {type(result)}")
|
|
172
|
+
return False
|
|
173
|
+
except AssertionError:
|
|
174
|
+
print(" โ AssertionError raised as expected")
|
|
175
|
+
|
|
176
|
+
# Test with empty picked_tool_names
|
|
177
|
+
print("โ Testing with empty picked_tool_names...")
|
|
178
|
+
result = llm_finder.find_tools(picked_tool_names=[], return_call_result=False)
|
|
179
|
+
assert isinstance(
|
|
180
|
+
result, list
|
|
181
|
+
), f"Expected list with empty picked_tool_names, got {type(result)}"
|
|
182
|
+
assert len(result) == 0, f"Expected empty result, got {len(result)} items"
|
|
183
|
+
print(" โ Empty picked_tool_names handled correctly")
|
|
184
|
+
|
|
185
|
+
# Test run() with missing required arguments
|
|
186
|
+
print("โ Testing run() with empty arguments...")
|
|
187
|
+
try:
|
|
188
|
+
result = llm_finder.run({})
|
|
189
|
+
print(f" โ Expected AssertionError but got result: {type(result)}")
|
|
190
|
+
return False
|
|
191
|
+
except AssertionError:
|
|
192
|
+
print(" โ AssertionError raised as expected for empty arguments")
|
|
193
|
+
|
|
194
|
+
print("โ
Error handling tests passed!")
|
|
195
|
+
return True
|
|
196
|
+
|
|
197
|
+
except ImportError as e:
|
|
198
|
+
print(f"โ ๏ธ ToolUniverse not available: {e}")
|
|
199
|
+
return True
|
|
200
|
+
|
|
201
|
+
except Exception as e:
|
|
202
|
+
print(f"โ Error handling test failed: {e}")
|
|
203
|
+
traceback.print_exc()
|
|
204
|
+
return False
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def main():
|
|
208
|
+
"""Run compatibility tests to ensure seamless replacement of original tool_finder."""
|
|
209
|
+
print("๐ ToolFinderLLM Compatibility Tests")
|
|
210
|
+
print("=" * 60)
|
|
211
|
+
|
|
212
|
+
tests = [
|
|
213
|
+
("Interface Compatibility", test_compatibility),
|
|
214
|
+
("Error Handling", test_error_handling),
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
results = []
|
|
218
|
+
for test_name, test_func in tests:
|
|
219
|
+
try:
|
|
220
|
+
success = test_func()
|
|
221
|
+
results.append((test_name, success))
|
|
222
|
+
except Exception as e:
|
|
223
|
+
print(f"โ {test_name} crashed: {e}")
|
|
224
|
+
results.append((test_name, False))
|
|
225
|
+
|
|
226
|
+
print("\n" + "=" * 60)
|
|
227
|
+
print("๐ Test Results Summary:")
|
|
228
|
+
print("=" * 60)
|
|
229
|
+
|
|
230
|
+
passed = 0
|
|
231
|
+
for test_name, success in results:
|
|
232
|
+
status = "โ
PASS" if success else "โ FAIL"
|
|
233
|
+
print(f"{status} | {test_name}")
|
|
234
|
+
if success:
|
|
235
|
+
passed += 1
|
|
236
|
+
|
|
237
|
+
print(f"\n๐ Tests completed: {passed}/{len(results)} passed")
|
|
238
|
+
|
|
239
|
+
if passed == len(results):
|
|
240
|
+
print("๐ All compatibility tests passed!")
|
|
241
|
+
print(
|
|
242
|
+
"โ
ToolFinderLLM can seamlessly replace the original ToolFinderEmbedding"
|
|
243
|
+
)
|
|
244
|
+
return 0
|
|
245
|
+
else:
|
|
246
|
+
print("โ ๏ธ Some compatibility tests failed.")
|
|
247
|
+
print("โ Interface modifications needed before replacement")
|
|
248
|
+
return 1
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
if __name__ == "__main__":
|
|
252
|
+
sys.exit(main())
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Simplified SMCP tools/find test script
|
|
4
|
+
|
|
5
|
+
Test the new search_method parameter functionality:
|
|
6
|
+
- 'auto': Automatically select the best search method
|
|
7
|
+
- 'llm': Use LLM intelligent search
|
|
8
|
+
- 'embedding': Use embedding vector search
|
|
9
|
+
- 'keyword': Use keyword search
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
import asyncio
|
|
14
|
+
import sys
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
# Add the src directory to the path
|
|
18
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def print_test(title):
|
|
22
|
+
"""Print test title"""
|
|
23
|
+
print(f"\n๐ {title}")
|
|
24
|
+
print("=" * 50)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def print_result(result):
|
|
28
|
+
"""Print results"""
|
|
29
|
+
if isinstance(result, dict):
|
|
30
|
+
# Only show key information
|
|
31
|
+
if "result" in result:
|
|
32
|
+
data = result["result"]
|
|
33
|
+
query = data.get("query", "unknown")
|
|
34
|
+
method = data.get("search_method", "unknown")
|
|
35
|
+
count = data.get("total_matches", 0)
|
|
36
|
+
print(f"โ
Query: '{query}' | Method: {method} | Results: {count}")
|
|
37
|
+
|
|
38
|
+
# Show found tool names
|
|
39
|
+
if "tools" in data and data["tools"]:
|
|
40
|
+
print("๐ Found tools:")
|
|
41
|
+
for i, tool in enumerate(data["tools"][:3], 1): # Only show first 3
|
|
42
|
+
print(f" {i}. {tool.get('name', 'Unknown')}")
|
|
43
|
+
else:
|
|
44
|
+
print("โ No tools found")
|
|
45
|
+
elif "error" in result:
|
|
46
|
+
print(f"โ Error: {result['error']['message']}")
|
|
47
|
+
else:
|
|
48
|
+
print(f"Result: {result}")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
from tooluniverse.smcp import SMCP # noqa: E402
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def test_search_methods():
|
|
55
|
+
"""Test different search methods"""
|
|
56
|
+
print("๐ Starting SMCP search functionality tests...")
|
|
57
|
+
|
|
58
|
+
# Initialize server
|
|
59
|
+
print("\n๐ฆ Initializing SMCP server...")
|
|
60
|
+
server = SMCP(name="Test Server", search_enabled=True)
|
|
61
|
+
print(f"โ
Server initialized, loaded {len(server._exposed_tools)} tools")
|
|
62
|
+
|
|
63
|
+
# Test query
|
|
64
|
+
query = "protein analysis"
|
|
65
|
+
|
|
66
|
+
# Test 1: Auto search method
|
|
67
|
+
print_test("Test 1: Auto search (search_method='auto')")
|
|
68
|
+
request = {
|
|
69
|
+
"jsonrpc": "2.0",
|
|
70
|
+
"id": "test_auto",
|
|
71
|
+
"method": "tools/find",
|
|
72
|
+
"params": {"query": query, "search_method": "auto", "limit": 3},
|
|
73
|
+
}
|
|
74
|
+
result = await server._custom_handle_request(request)
|
|
75
|
+
print_result(result)
|
|
76
|
+
|
|
77
|
+
# Test 2: LLM search method
|
|
78
|
+
print_test("Test 2: LLM intelligent search (search_method='llm')")
|
|
79
|
+
request = {
|
|
80
|
+
"jsonrpc": "2.0",
|
|
81
|
+
"id": "test_llm",
|
|
82
|
+
"method": "tools/find",
|
|
83
|
+
"params": {"query": query, "search_method": "llm", "limit": 3},
|
|
84
|
+
}
|
|
85
|
+
result = await server._custom_handle_request(request)
|
|
86
|
+
print_result(result)
|
|
87
|
+
|
|
88
|
+
# Test 3: Keyword search method
|
|
89
|
+
print_test("Test 3: Keyword search (search_method='keyword')")
|
|
90
|
+
request = {
|
|
91
|
+
"jsonrpc": "2.0",
|
|
92
|
+
"id": "test_keyword",
|
|
93
|
+
"method": "tools/find",
|
|
94
|
+
"params": {"query": "tool", "search_method": "keyword", "limit": 3},
|
|
95
|
+
}
|
|
96
|
+
result = await server._custom_handle_request(request)
|
|
97
|
+
print_result(result)
|
|
98
|
+
|
|
99
|
+
# Test 4: Embedding vector search method
|
|
100
|
+
print_test("Test 4: Embedding vector search (search_method='embedding')")
|
|
101
|
+
request = {
|
|
102
|
+
"jsonrpc": "2.0",
|
|
103
|
+
"id": "test_embedding",
|
|
104
|
+
"method": "tools/find",
|
|
105
|
+
"params": {"query": query, "search_method": "embedding", "limit": 3},
|
|
106
|
+
}
|
|
107
|
+
result = await server._custom_handle_request(request)
|
|
108
|
+
print_result(result)
|
|
109
|
+
|
|
110
|
+
# Test 5: Error handling - invalid search method
|
|
111
|
+
print_test("Test 5: Invalid search method (should fallback)")
|
|
112
|
+
request = {
|
|
113
|
+
"jsonrpc": "2.0",
|
|
114
|
+
"id": "test_invalid",
|
|
115
|
+
"method": "tools/find",
|
|
116
|
+
"params": {"query": query, "search_method": "invalid_method", "limit": 3},
|
|
117
|
+
}
|
|
118
|
+
result = await server._custom_handle_request(request)
|
|
119
|
+
print_result(result)
|
|
120
|
+
|
|
121
|
+
# Test 6: Error handling - missing required parameter
|
|
122
|
+
print_test("Test 6: Missing query parameter (should error)")
|
|
123
|
+
request = {
|
|
124
|
+
"jsonrpc": "2.0",
|
|
125
|
+
"id": "test_error",
|
|
126
|
+
"method": "tools/find",
|
|
127
|
+
"params": {"search_method": "auto", "limit": 3}, # Missing query
|
|
128
|
+
}
|
|
129
|
+
result = await server._custom_handle_request(request)
|
|
130
|
+
print_result(result)
|
|
131
|
+
|
|
132
|
+
print("\nโ
All tests completed!")
|
|
133
|
+
await server.close()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def show_examples():
|
|
137
|
+
"""Show request examples"""
|
|
138
|
+
print("\n๐ MCP Request Examples:")
|
|
139
|
+
|
|
140
|
+
examples = [
|
|
141
|
+
{
|
|
142
|
+
"name": "Auto Search",
|
|
143
|
+
"request": {
|
|
144
|
+
"jsonrpc": "2.0",
|
|
145
|
+
"id": "1",
|
|
146
|
+
"method": "tools/find",
|
|
147
|
+
"params": {
|
|
148
|
+
"query": "protein analysis",
|
|
149
|
+
"search_method": "auto",
|
|
150
|
+
"limit": 5,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"name": "LLM Search",
|
|
156
|
+
"request": {
|
|
157
|
+
"jsonrpc": "2.0",
|
|
158
|
+
"id": "2",
|
|
159
|
+
"method": "tools/find",
|
|
160
|
+
"params": {
|
|
161
|
+
"query": "gene expression",
|
|
162
|
+
"search_method": "llm",
|
|
163
|
+
"limit": 3,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"name": "Keyword Search",
|
|
169
|
+
"request": {
|
|
170
|
+
"jsonrpc": "2.0",
|
|
171
|
+
"id": "3",
|
|
172
|
+
"method": "tools/find",
|
|
173
|
+
"params": {"query": "chemical", "search_method": "keyword", "limit": 3},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
for example in examples:
|
|
179
|
+
print(f"\n{example['name']}:")
|
|
180
|
+
print(json.dumps(example["request"], indent=2, ensure_ascii=False))
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
async def main():
|
|
184
|
+
"""Main test function"""
|
|
185
|
+
print("๐งช Starting SMCP search method functionality tests...")
|
|
186
|
+
|
|
187
|
+
# Show examples
|
|
188
|
+
show_examples()
|
|
189
|
+
|
|
190
|
+
# Run tests
|
|
191
|
+
await test_search_methods()
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
if __name__ == "__main__":
|
|
195
|
+
asyncio.run(main())
|