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
tooluniverse/openfda_tool.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
from .base_tool import BaseTool
|
|
3
|
+
from .tool_registry import register_tool
|
|
3
4
|
import copy
|
|
4
5
|
import re
|
|
5
|
-
import json
|
|
6
6
|
import os
|
|
7
7
|
|
|
8
|
+
|
|
8
9
|
def check_keys_present(api_capabilities_dict, keys):
|
|
9
10
|
for key in keys:
|
|
10
|
-
levels = key.split(
|
|
11
|
+
levels = key.split(".")
|
|
11
12
|
current_dict = api_capabilities_dict
|
|
12
13
|
key_present = True
|
|
13
14
|
for level in levels:
|
|
@@ -15,8 +16,8 @@ def check_keys_present(api_capabilities_dict, keys):
|
|
|
15
16
|
print(f"Key '{level}' not found in dictionary.")
|
|
16
17
|
key_present = False
|
|
17
18
|
break
|
|
18
|
-
if
|
|
19
|
-
current_dict = current_dict[level][
|
|
19
|
+
if "properties" in current_dict[level]:
|
|
20
|
+
current_dict = current_dict[level]["properties"]
|
|
20
21
|
else:
|
|
21
22
|
current_dict = current_dict[level]
|
|
22
23
|
return key_present
|
|
@@ -35,14 +36,14 @@ def extract_nested_fields(records, fields, keywords=None):
|
|
|
35
36
|
for record in records:
|
|
36
37
|
extracted_record = {}
|
|
37
38
|
for field in fields:
|
|
38
|
-
keys = field.split(
|
|
39
|
+
keys = field.split(".")
|
|
39
40
|
# print("keys", keys)
|
|
40
41
|
value = record
|
|
41
42
|
try:
|
|
42
43
|
for key in keys:
|
|
43
44
|
value = value[key]
|
|
44
|
-
if key !=
|
|
45
|
-
if len(keywords)>0:
|
|
45
|
+
if key != "openfda" and key != "generic_name" and key != "brand_name":
|
|
46
|
+
if len(keywords) > 0:
|
|
46
47
|
# print("key words:", keywords)
|
|
47
48
|
# print(value)
|
|
48
49
|
# print(type(value))
|
|
@@ -54,6 +55,7 @@ def extract_nested_fields(records, fields, keywords=None):
|
|
|
54
55
|
extracted_records.append(extracted_record)
|
|
55
56
|
return extracted_records
|
|
56
57
|
|
|
58
|
+
|
|
57
59
|
def map_properties_to_openfda_fields(arguments, search_fields):
|
|
58
60
|
"""
|
|
59
61
|
Maps the provided arguments to the corresponding openFDA fields based on the search_fields mapping.
|
|
@@ -75,107 +77,141 @@ def map_properties_to_openfda_fields(arguments, search_fields):
|
|
|
75
77
|
else:
|
|
76
78
|
mapped_arguments[openfda_fields] = value
|
|
77
79
|
del arguments[key]
|
|
78
|
-
arguments[
|
|
80
|
+
arguments["search_fields"] = mapped_arguments
|
|
79
81
|
return arguments
|
|
80
82
|
|
|
83
|
+
|
|
81
84
|
def extract_sentences_with_keywords(text_list, keywords):
|
|
82
85
|
"""
|
|
83
86
|
Extracts sentences containing any of the specified keywords from the text.
|
|
84
|
-
|
|
87
|
+
|
|
85
88
|
Parameters:
|
|
86
89
|
- text (str): The input text from which to extract sentences.
|
|
87
90
|
- keywords (list): A list of keywords to search for in the text.
|
|
88
|
-
|
|
91
|
+
|
|
89
92
|
Returns:
|
|
90
93
|
- list: A list of sentences containing any of the keywords.
|
|
91
94
|
"""
|
|
92
95
|
sentences_with_keywords = []
|
|
93
96
|
for text in text_list:
|
|
94
97
|
# Compile a regular expression pattern for sentence splitting
|
|
95
|
-
sentence_pattern = re.compile(r
|
|
98
|
+
sentence_pattern = re.compile(r"(?<=[.!?]) +")
|
|
96
99
|
# Split the text into sentences
|
|
97
100
|
sentences = sentence_pattern.split(text)
|
|
98
101
|
# Initialize a list to hold sentences with keywords
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
|
|
101
103
|
# Iterate through each sentence
|
|
102
104
|
for sentence in sentences:
|
|
103
105
|
# Check if any of the keywords are present in the sentence
|
|
104
106
|
if any(keyword.lower() in sentence.lower() for keyword in keywords):
|
|
105
107
|
# If a keyword is found, add the sentence to the list
|
|
106
108
|
sentences_with_keywords.append(sentence)
|
|
107
|
-
|
|
109
|
+
|
|
108
110
|
return "......".join(sentences_with_keywords)
|
|
109
111
|
|
|
110
112
|
|
|
111
|
-
def search_openfda(
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
def search_openfda(
|
|
114
|
+
params=None,
|
|
115
|
+
endpoint_url=None,
|
|
116
|
+
api_key=None,
|
|
117
|
+
sort=None,
|
|
118
|
+
limit=5,
|
|
119
|
+
skip=None,
|
|
120
|
+
count=None,
|
|
121
|
+
exists=None,
|
|
122
|
+
return_fields=None,
|
|
123
|
+
exist_option="OR",
|
|
124
|
+
search_keyword_option="AND",
|
|
125
|
+
keywords_filter=True,
|
|
126
|
+
):
|
|
114
127
|
# Initialize params if not provided
|
|
115
128
|
if params is None:
|
|
116
129
|
params = {}
|
|
117
|
-
|
|
118
|
-
if return_fields==
|
|
130
|
+
|
|
131
|
+
if return_fields == "ALL":
|
|
119
132
|
exists = None
|
|
120
133
|
|
|
121
134
|
# Initialize search fields and construct search query
|
|
122
|
-
search_fields = params.get(
|
|
135
|
+
search_fields = params.get("search_fields", {})
|
|
123
136
|
search_query = []
|
|
124
137
|
keywords_list = []
|
|
125
138
|
if search_fields:
|
|
126
139
|
for field, value in search_fields.items():
|
|
127
140
|
# Merge multiple continuous black spaces into one and use one '+'
|
|
128
|
-
if
|
|
141
|
+
if (
|
|
142
|
+
keywords_filter
|
|
143
|
+
and field != "openfda.brand_name"
|
|
144
|
+
and field != "openfda.generic_name"
|
|
145
|
+
):
|
|
129
146
|
keywords_list.extend(value.split())
|
|
130
|
-
if field ==
|
|
131
|
-
value = value.upper()
|
|
132
|
-
value = value.replace(" and ", " ")
|
|
133
|
-
value = value.replace(" AND ", " ")
|
|
134
|
-
value =
|
|
135
|
-
if search_keyword_option==
|
|
147
|
+
if field == "openfda.generic_name":
|
|
148
|
+
value = value.upper() # all generic names are in uppercase
|
|
149
|
+
value = value.replace(" and ", " ") # remove 'and' in the search query
|
|
150
|
+
value = value.replace(" AND ", " ") # remove 'AND' in the search query
|
|
151
|
+
value = " ".join(value.split())
|
|
152
|
+
if search_keyword_option == "AND":
|
|
136
153
|
search_query.append(f'{field}:({value.replace(" ", "+AND+")})')
|
|
137
|
-
elif search_keyword_option==
|
|
154
|
+
elif search_keyword_option == "OR":
|
|
138
155
|
search_query.append(f'{field}:({value.replace(" ", "+")})')
|
|
139
156
|
else:
|
|
140
157
|
print("Invalid search_keyword_option. Please use 'AND' or 'OR'.")
|
|
141
|
-
del params[
|
|
158
|
+
del params["search_fields"]
|
|
142
159
|
if search_query:
|
|
143
|
-
params[
|
|
144
|
-
params[
|
|
160
|
+
params["search"] = "+".join(search_query)
|
|
161
|
+
params["search"] = "(" + params["search"] + ")"
|
|
145
162
|
# Validate the presence of at least one of search, count, or sort
|
|
146
|
-
if not (
|
|
147
|
-
|
|
163
|
+
if not (
|
|
164
|
+
params.get("search")
|
|
165
|
+
or params.get("count")
|
|
166
|
+
or params.get("sort")
|
|
167
|
+
or search_fields
|
|
168
|
+
):
|
|
169
|
+
return {
|
|
170
|
+
"error": "You must provide at least one of 'search', 'count', or 'sort' parameters."
|
|
171
|
+
}
|
|
148
172
|
|
|
149
173
|
# Set additional query parameters
|
|
150
|
-
params[
|
|
151
|
-
params[
|
|
152
|
-
params[
|
|
153
|
-
params[
|
|
174
|
+
params["limit"] = params.get("limit", limit)
|
|
175
|
+
params["sort"] = params.get("sort", sort)
|
|
176
|
+
params["skip"] = params.get("skip", skip)
|
|
177
|
+
params["count"] = params.get("count", count)
|
|
154
178
|
if exists is not None:
|
|
155
179
|
if isinstance(exists, str):
|
|
156
180
|
exists = [exists]
|
|
157
|
-
if
|
|
158
|
-
if exist_option ==
|
|
159
|
-
params[
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
181
|
+
if "search" in params:
|
|
182
|
+
if exist_option == "AND":
|
|
183
|
+
params["search"] += (
|
|
184
|
+
"+AND+("
|
|
185
|
+
+ "+AND+".join([f"_exists_:{keyword}" for keyword in exists])
|
|
186
|
+
+ ")"
|
|
187
|
+
)
|
|
188
|
+
elif exist_option == "OR":
|
|
189
|
+
params["search"] += (
|
|
190
|
+
"+AND+("
|
|
191
|
+
+ "+".join([f"_exists_:{keyword}" for keyword in exists])
|
|
192
|
+
+ ")"
|
|
193
|
+
)
|
|
164
194
|
else:
|
|
165
|
-
if exist_option ==
|
|
166
|
-
params[
|
|
167
|
-
[f"_exists_:{keyword}" for keyword in exists]
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
195
|
+
if exist_option == "AND":
|
|
196
|
+
params["search"] = "+AND+".join(
|
|
197
|
+
[f"_exists_:{keyword}" for keyword in exists]
|
|
198
|
+
)
|
|
199
|
+
elif exist_option == "OR":
|
|
200
|
+
params["search"] = "+".join(
|
|
201
|
+
[f"_exists_:{keyword}" for keyword in exists]
|
|
202
|
+
)
|
|
171
203
|
# Ensure that at least one of the search fields exists
|
|
172
|
-
params[
|
|
173
|
-
|
|
204
|
+
params["search"] += (
|
|
205
|
+
"+AND+("
|
|
206
|
+
+ "+".join([f"_exists_:{field}" for field in search_fields.keys()])
|
|
207
|
+
+ ")"
|
|
208
|
+
)
|
|
174
209
|
# params['search']+="+AND+_exists_:openfda"
|
|
175
210
|
|
|
176
211
|
# Construct full query with additional parameters
|
|
177
212
|
query = "&".join(
|
|
178
|
-
[f"{key}={value}" for key, value in params.items() if value is not None]
|
|
213
|
+
[f"{key}={value}" for key, value in params.items() if value is not None]
|
|
214
|
+
)
|
|
179
215
|
full_url = f"{endpoint_url}?{query}"
|
|
180
216
|
if api_key:
|
|
181
217
|
full_url += f"&api_key={api_key}"
|
|
@@ -186,59 +222,59 @@ def search_openfda(params=None, endpoint_url=None, api_key=None, sort=None, limi
|
|
|
186
222
|
|
|
187
223
|
# Get the JSON response
|
|
188
224
|
response_data = response.json()
|
|
189
|
-
if
|
|
190
|
-
print("Invalid Query: ", response_data[
|
|
225
|
+
if "error" in response_data:
|
|
226
|
+
print("Invalid Query: ", response_data["error"])
|
|
191
227
|
return None
|
|
192
228
|
|
|
193
229
|
# Extract meta information
|
|
194
|
-
meta_info = response_data.get(
|
|
195
|
-
meta_info = meta_info.get(
|
|
230
|
+
meta_info = response_data.get("meta", {})
|
|
231
|
+
meta_info = meta_info.get("results", {})
|
|
196
232
|
|
|
197
233
|
# Extract results and return only the specified return fields
|
|
198
|
-
results = response_data.get(
|
|
199
|
-
if return_fields ==
|
|
200
|
-
return {
|
|
201
|
-
'meta': meta_info,
|
|
202
|
-
'results': results
|
|
203
|
-
}
|
|
234
|
+
results = response_data.get("results", [])
|
|
235
|
+
if return_fields == "ALL":
|
|
236
|
+
return {"meta": meta_info, "results": results}
|
|
204
237
|
required_fields = list(search_fields.keys()) + return_fields
|
|
205
|
-
extracted_results = extract_nested_fields(
|
|
206
|
-
|
|
207
|
-
return {
|
|
208
|
-
'meta': meta_info,
|
|
209
|
-
'results': extracted_results
|
|
210
|
-
}
|
|
238
|
+
extracted_results = extract_nested_fields(results, required_fields, keywords_list)
|
|
239
|
+
return {"meta": meta_info, "results": extracted_results}
|
|
211
240
|
|
|
212
241
|
|
|
242
|
+
@register_tool("FDATool")
|
|
213
243
|
class FDATool(BaseTool):
|
|
214
244
|
def __init__(self, tool_config, endpoint_url, api_key=None):
|
|
215
245
|
super().__init__(tool_config)
|
|
216
|
-
fields = tool_config[
|
|
217
|
-
self.search_fields = fields.get(
|
|
218
|
-
self.return_fields = fields.get(
|
|
219
|
-
self.exists = fields.get(
|
|
246
|
+
fields = tool_config["fields"]
|
|
247
|
+
self.search_fields = fields.get("search_fields", {})
|
|
248
|
+
self.return_fields = fields.get("return_fields", [])
|
|
249
|
+
self.exists = fields.get("exists", None)
|
|
220
250
|
if self.exists is None:
|
|
221
251
|
self.exists = self.return_fields
|
|
222
252
|
self.endpoint_url = endpoint_url
|
|
223
|
-
self.api_key = api_key or os.getenv(
|
|
253
|
+
self.api_key = api_key or os.getenv("FDA_API_KEY")
|
|
224
254
|
|
|
225
255
|
def run(self, arguments):
|
|
226
256
|
arguments = copy.deepcopy(arguments)
|
|
227
257
|
mapped_arguments = map_properties_to_openfda_fields(
|
|
228
|
-
arguments, self.search_fields
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
258
|
+
arguments, self.search_fields
|
|
259
|
+
)
|
|
260
|
+
return search_openfda(
|
|
261
|
+
mapped_arguments,
|
|
262
|
+
endpoint_url=self.endpoint_url,
|
|
263
|
+
api_key=self.api_key,
|
|
264
|
+
exists=self.exists,
|
|
265
|
+
return_fields=self.return_fields,
|
|
266
|
+
exist_option="OR",
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@register_tool("FDADrugLabel")
|
|
236
271
|
class FDADrugLabelTool(FDATool):
|
|
237
272
|
def __init__(self, tool_config, api_key=None):
|
|
238
|
-
endpoint_url =
|
|
273
|
+
endpoint_url = "https://api.fda.gov/drug/label.json"
|
|
239
274
|
super().__init__(tool_config, endpoint_url, api_key)
|
|
240
275
|
|
|
241
276
|
|
|
277
|
+
@register_tool("FDADrugLabelSearchTool")
|
|
242
278
|
class FDADrugLabelSearchTool(FDATool):
|
|
243
279
|
def __init__(self, tool_config=None, api_key=None):
|
|
244
280
|
self.tool_config = {
|
|
@@ -252,50 +288,151 @@ class FDADrugLabelSearchTool(FDATool):
|
|
|
252
288
|
"drug_name": {
|
|
253
289
|
"type": "string",
|
|
254
290
|
"description": "The name of the drug.",
|
|
255
|
-
"required": True
|
|
291
|
+
"required": True,
|
|
256
292
|
},
|
|
257
293
|
"return_fields": {
|
|
258
294
|
"type": "array",
|
|
259
295
|
"items": {
|
|
260
296
|
"type": "string",
|
|
261
|
-
"enum": [
|
|
262
|
-
|
|
297
|
+
"enum": [
|
|
298
|
+
"ALL",
|
|
299
|
+
"abuse",
|
|
300
|
+
"accessories",
|
|
301
|
+
"active_ingredient",
|
|
302
|
+
"adverse_reactions",
|
|
303
|
+
"alarms",
|
|
304
|
+
"animal_pharmacology_and_or_toxicology",
|
|
305
|
+
"ask_doctor",
|
|
306
|
+
"ask_doctor_or_pharmacist",
|
|
307
|
+
"assembly_or_installation_instructions",
|
|
308
|
+
"boxed_warning",
|
|
309
|
+
"calibration_instructions",
|
|
310
|
+
"carcinogenesis_and_mutagenesis_and_impairment_of_fertility",
|
|
311
|
+
"cleaning",
|
|
312
|
+
"clinical_pharmacology",
|
|
313
|
+
"clinical_studies",
|
|
314
|
+
"compatible_accessories",
|
|
315
|
+
"components",
|
|
316
|
+
"contraindications",
|
|
317
|
+
"controlled_substance",
|
|
318
|
+
"dependence",
|
|
319
|
+
"description",
|
|
320
|
+
"diagram_of_device",
|
|
321
|
+
"disposal_and_waste_handling",
|
|
322
|
+
"do_not_use",
|
|
323
|
+
"dosage_and_administration",
|
|
324
|
+
"dosage_forms_and_strengths",
|
|
325
|
+
"drug_abuse_and_dependence",
|
|
326
|
+
"drug_and_or_laboratory_test_interactions",
|
|
327
|
+
"drug_interactions",
|
|
328
|
+
"effective_time",
|
|
329
|
+
"environmental_warning",
|
|
330
|
+
"food_safety_warning",
|
|
331
|
+
"general_precautions",
|
|
332
|
+
"geriatric_use",
|
|
333
|
+
"guaranteed_analysis_of_feed",
|
|
334
|
+
"health_care_provider_letter",
|
|
335
|
+
"health_claim",
|
|
336
|
+
"how_supplied",
|
|
337
|
+
"id",
|
|
338
|
+
"inactive_ingredient",
|
|
339
|
+
"indications_and_usage",
|
|
340
|
+
"information_for_owners_or_caregivers",
|
|
341
|
+
"information_for_patients",
|
|
342
|
+
"instructions_for_use",
|
|
343
|
+
"intended_use_of_the_device",
|
|
344
|
+
"keep_out_of_reach_of_children",
|
|
345
|
+
"labor_and_delivery",
|
|
346
|
+
"laboratory_tests",
|
|
347
|
+
"mechanism_of_action",
|
|
348
|
+
"microbiology",
|
|
349
|
+
"nonclinical_toxicology",
|
|
350
|
+
"nonteratogenic_effects",
|
|
351
|
+
"nursing_mothers",
|
|
352
|
+
"openfda",
|
|
353
|
+
"other_safety_information",
|
|
354
|
+
"overdosage",
|
|
355
|
+
"package_label_principal_display_panel",
|
|
356
|
+
"patient_medication_information",
|
|
357
|
+
"pediatric_use",
|
|
358
|
+
"pharmacodynamics",
|
|
359
|
+
"pharmacogenomics",
|
|
360
|
+
"pharmacokinetics",
|
|
361
|
+
"precautions",
|
|
362
|
+
"pregnancy",
|
|
363
|
+
"pregnancy_or_breast_feeding",
|
|
364
|
+
"purpose",
|
|
365
|
+
"questions",
|
|
366
|
+
"recent_major_changes",
|
|
367
|
+
"references",
|
|
368
|
+
"residue_warning",
|
|
369
|
+
"risks",
|
|
370
|
+
"route",
|
|
371
|
+
"safe_handling_warning",
|
|
372
|
+
"set_id",
|
|
373
|
+
"spl_indexing_data_elements",
|
|
374
|
+
"spl_medguide",
|
|
375
|
+
"spl_patient_package_insert",
|
|
376
|
+
"spl_product_data_elements",
|
|
377
|
+
"spl_unclassified_section",
|
|
378
|
+
"statement_of_identity",
|
|
379
|
+
"stop_use",
|
|
380
|
+
"storage_and_handling",
|
|
381
|
+
"summary_of_safety_and_effectiveness",
|
|
382
|
+
"teratogenic_effects",
|
|
383
|
+
"troubleshooting",
|
|
384
|
+
"use_in_specific_populations",
|
|
385
|
+
"user_safety_warnings",
|
|
386
|
+
"version",
|
|
387
|
+
"warnings",
|
|
388
|
+
"warnings_and_cautions",
|
|
389
|
+
"when_using",
|
|
390
|
+
"meta",
|
|
391
|
+
],
|
|
392
|
+
"description": "Searchable field.",
|
|
263
393
|
},
|
|
264
394
|
"description": "Fields to search within drug labels.",
|
|
265
|
-
"required": True
|
|
395
|
+
"required": True,
|
|
266
396
|
},
|
|
267
397
|
"limit": {
|
|
268
398
|
"type": "integer",
|
|
269
399
|
"description": "The number of records to return.",
|
|
270
|
-
"required": False
|
|
400
|
+
"required": False,
|
|
271
401
|
},
|
|
272
402
|
"skip": {
|
|
273
403
|
"type": "integer",
|
|
274
404
|
"description": "The number of records to skip.",
|
|
275
|
-
"required": False
|
|
276
|
-
}
|
|
277
|
-
}
|
|
405
|
+
"required": False,
|
|
406
|
+
},
|
|
407
|
+
},
|
|
278
408
|
},
|
|
279
409
|
"fields": {
|
|
280
410
|
"search_fields": {
|
|
281
411
|
"drug_name": ["openfda.brand_name", "openfda.generic_name"]
|
|
282
412
|
},
|
|
283
|
-
}
|
|
413
|
+
},
|
|
284
414
|
}
|
|
285
|
-
endpoint_url =
|
|
415
|
+
endpoint_url = "https://api.fda.gov/drug/label.json"
|
|
286
416
|
super().__init__(self.tool_config, endpoint_url, api_key)
|
|
287
417
|
|
|
288
418
|
def run(self, arguments):
|
|
289
419
|
arguments = copy.deepcopy(arguments)
|
|
290
420
|
mapped_arguments = map_properties_to_openfda_fields(
|
|
291
|
-
arguments, self.search_fields
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
421
|
+
arguments, self.search_fields
|
|
422
|
+
)
|
|
423
|
+
return_fields = arguments["return_fields"]
|
|
424
|
+
del arguments["return_fields"]
|
|
425
|
+
return search_openfda(
|
|
426
|
+
mapped_arguments,
|
|
427
|
+
endpoint_url=self.endpoint_url,
|
|
428
|
+
api_key=self.api_key,
|
|
429
|
+
return_fields=return_fields,
|
|
430
|
+
exists=return_fields,
|
|
431
|
+
exist_option="OR",
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
@register_tool("FDADrugLabelSearchIDTool")
|
|
299
436
|
class FDADrugLabelSearchIDTool(FDATool):
|
|
300
437
|
def __init__(self, tool_config=None, api_key=None):
|
|
301
438
|
self.tool_config = {
|
|
@@ -309,54 +446,151 @@ class FDADrugLabelSearchIDTool(FDATool):
|
|
|
309
446
|
"query": {
|
|
310
447
|
"type": "string",
|
|
311
448
|
"description": "key words need to be searched.",
|
|
312
|
-
"required": True
|
|
449
|
+
"required": True,
|
|
313
450
|
},
|
|
314
451
|
"return_fields": {
|
|
315
452
|
"type": "array",
|
|
316
453
|
"items": {
|
|
317
454
|
"type": "string",
|
|
318
|
-
"enum": [
|
|
319
|
-
|
|
455
|
+
"enum": [
|
|
456
|
+
"ALL",
|
|
457
|
+
"abuse",
|
|
458
|
+
"accessories",
|
|
459
|
+
"active_ingredient",
|
|
460
|
+
"adverse_reactions",
|
|
461
|
+
"alarms",
|
|
462
|
+
"animal_pharmacology_and_or_toxicology",
|
|
463
|
+
"ask_doctor",
|
|
464
|
+
"ask_doctor_or_pharmacist",
|
|
465
|
+
"assembly_or_installation_instructions",
|
|
466
|
+
"boxed_warning",
|
|
467
|
+
"calibration_instructions",
|
|
468
|
+
"carcinogenesis_and_mutagenesis_and_impairment_of_fertility",
|
|
469
|
+
"cleaning",
|
|
470
|
+
"clinical_pharmacology",
|
|
471
|
+
"clinical_studies",
|
|
472
|
+
"compatible_accessories",
|
|
473
|
+
"components",
|
|
474
|
+
"contraindications",
|
|
475
|
+
"controlled_substance",
|
|
476
|
+
"dependence",
|
|
477
|
+
"description",
|
|
478
|
+
"diagram_of_device",
|
|
479
|
+
"disposal_and_waste_handling",
|
|
480
|
+
"do_not_use",
|
|
481
|
+
"dosage_and_administration",
|
|
482
|
+
"dosage_forms_and_strengths",
|
|
483
|
+
"drug_abuse_and_dependence",
|
|
484
|
+
"drug_and_or_laboratory_test_interactions",
|
|
485
|
+
"drug_interactions",
|
|
486
|
+
"effective_time",
|
|
487
|
+
"environmental_warning",
|
|
488
|
+
"food_safety_warning",
|
|
489
|
+
"general_precautions",
|
|
490
|
+
"geriatric_use",
|
|
491
|
+
"guaranteed_analysis_of_feed",
|
|
492
|
+
"health_care_provider_letter",
|
|
493
|
+
"health_claim",
|
|
494
|
+
"how_supplied",
|
|
495
|
+
"id",
|
|
496
|
+
"inactive_ingredient",
|
|
497
|
+
"indications_and_usage",
|
|
498
|
+
"information_for_owners_or_caregivers",
|
|
499
|
+
"information_for_patients",
|
|
500
|
+
"instructions_for_use",
|
|
501
|
+
"intended_use_of_the_device",
|
|
502
|
+
"keep_out_of_reach_of_children",
|
|
503
|
+
"labor_and_delivery",
|
|
504
|
+
"laboratory_tests",
|
|
505
|
+
"mechanism_of_action",
|
|
506
|
+
"microbiology",
|
|
507
|
+
"nonclinical_toxicology",
|
|
508
|
+
"nonteratogenic_effects",
|
|
509
|
+
"nursing_mothers",
|
|
510
|
+
"openfda",
|
|
511
|
+
"other_safety_information",
|
|
512
|
+
"overdosage",
|
|
513
|
+
"package_label_principal_display_panel",
|
|
514
|
+
"patient_medication_information",
|
|
515
|
+
"pediatric_use",
|
|
516
|
+
"pharmacodynamics",
|
|
517
|
+
"pharmacogenomics",
|
|
518
|
+
"pharmacokinetics",
|
|
519
|
+
"precautions",
|
|
520
|
+
"pregnancy",
|
|
521
|
+
"pregnancy_or_breast_feeding",
|
|
522
|
+
"purpose",
|
|
523
|
+
"questions",
|
|
524
|
+
"recent_major_changes",
|
|
525
|
+
"references",
|
|
526
|
+
"residue_warning",
|
|
527
|
+
"risks",
|
|
528
|
+
"route",
|
|
529
|
+
"safe_handling_warning",
|
|
530
|
+
"set_id",
|
|
531
|
+
"spl_indexing_data_elements",
|
|
532
|
+
"spl_medguide",
|
|
533
|
+
"spl_patient_package_insert",
|
|
534
|
+
"spl_product_data_elements",
|
|
535
|
+
"spl_unclassified_section",
|
|
536
|
+
"statement_of_identity",
|
|
537
|
+
"stop_use",
|
|
538
|
+
"storage_and_handling",
|
|
539
|
+
"summary_of_safety_and_effectiveness",
|
|
540
|
+
"teratogenic_effects",
|
|
541
|
+
"troubleshooting",
|
|
542
|
+
"use_in_specific_populations",
|
|
543
|
+
"user_safety_warnings",
|
|
544
|
+
"version",
|
|
545
|
+
"warnings",
|
|
546
|
+
"warnings_and_cautions",
|
|
547
|
+
"when_using",
|
|
548
|
+
"meta",
|
|
549
|
+
],
|
|
550
|
+
"description": "Searchable field.",
|
|
320
551
|
},
|
|
321
552
|
"description": "Fields to search within drug labels.",
|
|
322
|
-
"required": True
|
|
553
|
+
"required": True,
|
|
323
554
|
},
|
|
324
555
|
"limit": {
|
|
325
556
|
"type": "integer",
|
|
326
557
|
"description": "The number of records to return.",
|
|
327
|
-
"required": False
|
|
558
|
+
"required": False,
|
|
328
559
|
},
|
|
329
560
|
"skip": {
|
|
330
561
|
"type": "integer",
|
|
331
562
|
"description": "The number of records to skip.",
|
|
332
|
-
"required": False
|
|
333
|
-
}
|
|
334
|
-
}
|
|
563
|
+
"required": False,
|
|
564
|
+
},
|
|
565
|
+
},
|
|
335
566
|
},
|
|
336
567
|
"fields": {
|
|
337
|
-
"search_fields": {
|
|
338
|
-
|
|
339
|
-
},
|
|
340
|
-
}
|
|
568
|
+
"search_fields": {"query": ["id"]},
|
|
569
|
+
},
|
|
341
570
|
}
|
|
342
|
-
endpoint_url =
|
|
571
|
+
endpoint_url = "https://api.fda.gov/drug/label.json"
|
|
343
572
|
super().__init__(self.tool_config, endpoint_url, api_key)
|
|
344
573
|
|
|
345
574
|
def run(self, arguments):
|
|
346
575
|
arguments = copy.deepcopy(arguments)
|
|
347
576
|
mapped_arguments = map_properties_to_openfda_fields(
|
|
348
|
-
arguments, self.search_fields
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
577
|
+
arguments, self.search_fields
|
|
578
|
+
)
|
|
579
|
+
return_fields = arguments["return_fields"]
|
|
580
|
+
del arguments["return_fields"]
|
|
581
|
+
return search_openfda(
|
|
582
|
+
mapped_arguments,
|
|
583
|
+
endpoint_url=self.endpoint_url,
|
|
584
|
+
api_key=self.api_key,
|
|
585
|
+
return_fields=return_fields,
|
|
586
|
+
exists=return_fields,
|
|
587
|
+
exist_option="OR",
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
@register_tool("FDADrugLabelGetDrugGenericNameTool")
|
|
357
592
|
class FDADrugLabelGetDrugGenericNameTool(FDADrugLabelTool):
|
|
358
593
|
def __init__(self, tool_config=None, api_key=None):
|
|
359
|
-
|
|
360
594
|
if tool_config is None:
|
|
361
595
|
tool_config = {
|
|
362
596
|
"name": "get_drug_generic_name",
|
|
@@ -364,59 +598,58 @@ class FDADrugLabelGetDrugGenericNameTool(FDADrugLabelTool):
|
|
|
364
598
|
"parameter": {
|
|
365
599
|
"type": "object",
|
|
366
600
|
"properties": {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
}
|
|
601
|
+
"drug_name": {
|
|
602
|
+
"type": "string",
|
|
603
|
+
"description": "The generic or brand name of the drug.",
|
|
604
|
+
"required": True,
|
|
605
|
+
}
|
|
606
|
+
},
|
|
373
607
|
},
|
|
374
608
|
"fields": {
|
|
375
609
|
"search_fields": {
|
|
376
|
-
|
|
377
|
-
"openfda.brand_name",
|
|
378
|
-
"openfda.generic_name"
|
|
379
|
-
]
|
|
610
|
+
"drug_name": ["openfda.brand_name", "openfda.generic_name"]
|
|
380
611
|
},
|
|
381
|
-
"return_fields": [
|
|
382
|
-
"openfda.generic_name"
|
|
383
|
-
]
|
|
612
|
+
"return_fields": ["openfda.generic_name"],
|
|
384
613
|
},
|
|
385
614
|
"type": "FDADrugLabelGetDrugGenericNameTool",
|
|
386
|
-
"label": [
|
|
387
|
-
|
|
388
|
-
"purpose",
|
|
389
|
-
"FDA"
|
|
390
|
-
]
|
|
391
|
-
}
|
|
392
|
-
|
|
615
|
+
"label": ["FDADrugLabel", "purpose", "FDA"],
|
|
616
|
+
}
|
|
393
617
|
|
|
394
618
|
from .data.fda_drugs_with_brand_generic_names_for_tool import drug_list
|
|
395
|
-
|
|
396
|
-
self.brand_to_generic = {
|
|
397
|
-
|
|
398
|
-
|
|
619
|
+
|
|
620
|
+
self.brand_to_generic = {
|
|
621
|
+
drug["brand_name"]: drug["generic_name"] for drug in drug_list
|
|
622
|
+
}
|
|
623
|
+
self.generic_to_brand = {
|
|
624
|
+
drug["generic_name"]: drug["brand_name"] for drug in drug_list
|
|
625
|
+
}
|
|
626
|
+
|
|
399
627
|
super().__init__(tool_config, api_key)
|
|
400
628
|
|
|
401
629
|
def run(self, arguments):
|
|
402
|
-
|
|
403
630
|
drug_info = {}
|
|
404
|
-
|
|
405
|
-
drug_name = arguments.get(
|
|
406
|
-
if
|
|
407
|
-
drug_name = drug_name.split(
|
|
631
|
+
|
|
632
|
+
drug_name = arguments.get("drug_name")
|
|
633
|
+
if "-" in drug_name:
|
|
634
|
+
drug_name = drug_name.split("-")[
|
|
635
|
+
0
|
|
636
|
+
] # to handle some drug names such as tarlatamab-dlle
|
|
408
637
|
if drug_name in self.brand_to_generic:
|
|
409
|
-
drug_info[
|
|
410
|
-
drug_info[
|
|
638
|
+
drug_info["openfda.generic_name"] = self.brand_to_generic[drug_name]
|
|
639
|
+
drug_info["openfda.brand_name"] = drug_name
|
|
411
640
|
elif drug_name in self.generic_to_brand:
|
|
412
|
-
drug_info[
|
|
413
|
-
drug_info[
|
|
641
|
+
drug_info["openfda.brand_name"] = self.generic_to_brand[drug_name]
|
|
642
|
+
drug_info["openfda.generic_name"] = drug_name
|
|
414
643
|
else:
|
|
415
644
|
results = super().run(arguments)
|
|
416
645
|
if results is not None:
|
|
417
|
-
drug_info[
|
|
418
|
-
|
|
646
|
+
drug_info["openfda.generic_name"] = results["results"][0][
|
|
647
|
+
"openfda.generic_name"
|
|
648
|
+
][0]
|
|
649
|
+
drug_info["openfda.brand_name"] = results["results"][0][
|
|
650
|
+
"openfda.brand_name"
|
|
651
|
+
][0]
|
|
419
652
|
print("drug_info", drug_info)
|
|
420
653
|
else:
|
|
421
654
|
drug_info = None
|
|
422
|
-
return drug_info
|
|
655
|
+
return drug_info
|