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.

Files changed (187) hide show
  1. tooluniverse/__init__.py +340 -4
  2. tooluniverse/admetai_tool.py +84 -0
  3. tooluniverse/agentic_tool.py +563 -0
  4. tooluniverse/alphafold_tool.py +96 -0
  5. tooluniverse/base_tool.py +129 -6
  6. tooluniverse/boltz_tool.py +207 -0
  7. tooluniverse/chem_tool.py +192 -0
  8. tooluniverse/compose_scripts/__init__.py +1 -0
  9. tooluniverse/compose_scripts/biomarker_discovery.py +293 -0
  10. tooluniverse/compose_scripts/comprehensive_drug_discovery.py +186 -0
  11. tooluniverse/compose_scripts/drug_safety_analyzer.py +89 -0
  12. tooluniverse/compose_scripts/literature_tool.py +34 -0
  13. tooluniverse/compose_scripts/output_summarizer.py +279 -0
  14. tooluniverse/compose_scripts/tool_description_optimizer.py +681 -0
  15. tooluniverse/compose_scripts/tool_discover.py +705 -0
  16. tooluniverse/compose_scripts/tool_graph_composer.py +448 -0
  17. tooluniverse/compose_tool.py +371 -0
  18. tooluniverse/ctg_tool.py +1002 -0
  19. tooluniverse/custom_tool.py +81 -0
  20. tooluniverse/dailymed_tool.py +108 -0
  21. tooluniverse/data/admetai_tools.json +155 -0
  22. tooluniverse/data/agentic_tools.json +1156 -0
  23. tooluniverse/data/alphafold_tools.json +87 -0
  24. tooluniverse/data/boltz_tools.json +9 -0
  25. tooluniverse/data/chembl_tools.json +16 -0
  26. tooluniverse/data/clait_tools.json +108 -0
  27. tooluniverse/data/clinicaltrials_gov_tools.json +326 -0
  28. tooluniverse/data/compose_tools.json +202 -0
  29. tooluniverse/data/dailymed_tools.json +70 -0
  30. tooluniverse/data/dataset_tools.json +646 -0
  31. tooluniverse/data/disease_target_score_tools.json +712 -0
  32. tooluniverse/data/efo_tools.json +17 -0
  33. tooluniverse/data/embedding_tools.json +319 -0
  34. tooluniverse/data/enrichr_tools.json +31 -0
  35. tooluniverse/data/europe_pmc_tools.json +22 -0
  36. tooluniverse/data/expert_feedback_tools.json +10 -0
  37. tooluniverse/data/fda_drug_adverse_event_tools.json +491 -0
  38. tooluniverse/data/fda_drug_labeling_tools.json +544 -168
  39. tooluniverse/data/fda_drugs_with_brand_generic_names_for_tool.py +76929 -148860
  40. tooluniverse/data/finder_tools.json +209 -0
  41. tooluniverse/data/gene_ontology_tools.json +113 -0
  42. tooluniverse/data/gwas_tools.json +1082 -0
  43. tooluniverse/data/hpa_tools.json +333 -0
  44. tooluniverse/data/humanbase_tools.json +47 -0
  45. tooluniverse/data/idmap_tools.json +74 -0
  46. tooluniverse/data/mcp_client_tools_example.json +113 -0
  47. tooluniverse/data/mcpautoloadertool_defaults.json +28 -0
  48. tooluniverse/data/medlineplus_tools.json +141 -0
  49. tooluniverse/data/monarch_tools.json +1 -1
  50. tooluniverse/data/openalex_tools.json +36 -0
  51. tooluniverse/data/opentarget_tools.json +82 -58
  52. tooluniverse/data/output_summarization_tools.json +101 -0
  53. tooluniverse/data/packages/bioinformatics_core_tools.json +1756 -0
  54. tooluniverse/data/packages/categorized_tools.txt +206 -0
  55. tooluniverse/data/packages/cheminformatics_tools.json +347 -0
  56. tooluniverse/data/packages/earth_sciences_tools.json +74 -0
  57. tooluniverse/data/packages/genomics_tools.json +776 -0
  58. tooluniverse/data/packages/image_processing_tools.json +38 -0
  59. tooluniverse/data/packages/machine_learning_tools.json +789 -0
  60. tooluniverse/data/packages/neuroscience_tools.json +62 -0
  61. tooluniverse/data/packages/original_tools.txt +0 -0
  62. tooluniverse/data/packages/physics_astronomy_tools.json +62 -0
  63. tooluniverse/data/packages/scientific_computing_tools.json +560 -0
  64. tooluniverse/data/packages/single_cell_tools.json +453 -0
  65. tooluniverse/data/packages/software_tools.json +4954 -0
  66. tooluniverse/data/packages/structural_biology_tools.json +396 -0
  67. tooluniverse/data/packages/visualization_tools.json +399 -0
  68. tooluniverse/data/pubchem_tools.json +215 -0
  69. tooluniverse/data/pubtator_tools.json +68 -0
  70. tooluniverse/data/rcsb_pdb_tools.json +1332 -0
  71. tooluniverse/data/reactome_tools.json +19 -0
  72. tooluniverse/data/semantic_scholar_tools.json +26 -0
  73. tooluniverse/data/special_tools.json +2 -25
  74. tooluniverse/data/tool_composition_tools.json +88 -0
  75. tooluniverse/data/toolfinderkeyword_defaults.json +34 -0
  76. tooluniverse/data/txagent_client_tools.json +9 -0
  77. tooluniverse/data/uniprot_tools.json +211 -0
  78. tooluniverse/data/url_fetch_tools.json +94 -0
  79. tooluniverse/data/uspto_downloader_tools.json +9 -0
  80. tooluniverse/data/uspto_tools.json +811 -0
  81. tooluniverse/data/xml_tools.json +3275 -0
  82. tooluniverse/dataset_tool.py +296 -0
  83. tooluniverse/default_config.py +165 -0
  84. tooluniverse/efo_tool.py +42 -0
  85. tooluniverse/embedding_database.py +630 -0
  86. tooluniverse/embedding_sync.py +396 -0
  87. tooluniverse/enrichr_tool.py +266 -0
  88. tooluniverse/europe_pmc_tool.py +52 -0
  89. tooluniverse/execute_function.py +1775 -95
  90. tooluniverse/extended_hooks.py +444 -0
  91. tooluniverse/gene_ontology_tool.py +194 -0
  92. tooluniverse/graphql_tool.py +158 -36
  93. tooluniverse/gwas_tool.py +358 -0
  94. tooluniverse/hpa_tool.py +1645 -0
  95. tooluniverse/humanbase_tool.py +389 -0
  96. tooluniverse/logging_config.py +254 -0
  97. tooluniverse/mcp_client_tool.py +764 -0
  98. tooluniverse/mcp_integration.py +413 -0
  99. tooluniverse/mcp_tool_registry.py +925 -0
  100. tooluniverse/medlineplus_tool.py +337 -0
  101. tooluniverse/openalex_tool.py +228 -0
  102. tooluniverse/openfda_adv_tool.py +283 -0
  103. tooluniverse/openfda_tool.py +393 -160
  104. tooluniverse/output_hook.py +1122 -0
  105. tooluniverse/package_tool.py +195 -0
  106. tooluniverse/pubchem_tool.py +158 -0
  107. tooluniverse/pubtator_tool.py +168 -0
  108. tooluniverse/rcsb_pdb_tool.py +38 -0
  109. tooluniverse/reactome_tool.py +108 -0
  110. tooluniverse/remote/boltz/boltz_mcp_server.py +50 -0
  111. tooluniverse/remote/depmap_24q2/depmap_24q2_mcp_tool.py +442 -0
  112. tooluniverse/remote/expert_feedback/human_expert_mcp_tools.py +2013 -0
  113. tooluniverse/remote/expert_feedback/simple_test.py +23 -0
  114. tooluniverse/remote/expert_feedback/start_web_interface.py +188 -0
  115. tooluniverse/remote/expert_feedback/web_only_interface.py +0 -0
  116. tooluniverse/remote/expert_feedback_mcp/human_expert_mcp_server.py +1611 -0
  117. tooluniverse/remote/expert_feedback_mcp/simple_test.py +34 -0
  118. tooluniverse/remote/expert_feedback_mcp/start_web_interface.py +91 -0
  119. tooluniverse/remote/immune_compass/compass_tool.py +327 -0
  120. tooluniverse/remote/pinnacle/pinnacle_tool.py +328 -0
  121. tooluniverse/remote/transcriptformer/transcriptformer_tool.py +586 -0
  122. tooluniverse/remote/uspto_downloader/uspto_downloader_mcp_server.py +61 -0
  123. tooluniverse/remote/uspto_downloader/uspto_downloader_tool.py +120 -0
  124. tooluniverse/remote_tool.py +99 -0
  125. tooluniverse/restful_tool.py +53 -30
  126. tooluniverse/scripts/generate_tool_graph.py +408 -0
  127. tooluniverse/scripts/visualize_tool_graph.py +829 -0
  128. tooluniverse/semantic_scholar_tool.py +62 -0
  129. tooluniverse/smcp.py +2452 -0
  130. tooluniverse/smcp_server.py +975 -0
  131. tooluniverse/test/mcp_server_test.py +0 -0
  132. tooluniverse/test/test_admetai_tool.py +370 -0
  133. tooluniverse/test/test_agentic_tool.py +129 -0
  134. tooluniverse/test/test_alphafold_tool.py +71 -0
  135. tooluniverse/test/test_chem_tool.py +37 -0
  136. tooluniverse/test/test_compose_lieraturereview.py +63 -0
  137. tooluniverse/test/test_compose_tool.py +448 -0
  138. tooluniverse/test/test_dailymed.py +69 -0
  139. tooluniverse/test/test_dataset_tool.py +200 -0
  140. tooluniverse/test/test_disease_target_score.py +56 -0
  141. tooluniverse/test/test_drugbank_filter_examples.py +179 -0
  142. tooluniverse/test/test_efo.py +31 -0
  143. tooluniverse/test/test_enrichr_tool.py +21 -0
  144. tooluniverse/test/test_europe_pmc_tool.py +20 -0
  145. tooluniverse/test/test_fda_adv.py +95 -0
  146. tooluniverse/test/test_fda_drug_labeling.py +91 -0
  147. tooluniverse/test/test_gene_ontology_tools.py +66 -0
  148. tooluniverse/test/test_gwas_tool.py +139 -0
  149. tooluniverse/test/test_hpa.py +625 -0
  150. tooluniverse/test/test_humanbase_tool.py +20 -0
  151. tooluniverse/test/test_idmap_tools.py +61 -0
  152. tooluniverse/test/test_mcp_server.py +211 -0
  153. tooluniverse/test/test_mcp_tool.py +247 -0
  154. tooluniverse/test/test_medlineplus.py +220 -0
  155. tooluniverse/test/test_openalex_tool.py +32 -0
  156. tooluniverse/test/test_opentargets.py +28 -0
  157. tooluniverse/test/test_pubchem_tool.py +116 -0
  158. tooluniverse/test/test_pubtator_tool.py +37 -0
  159. tooluniverse/test/test_rcsb_pdb_tool.py +86 -0
  160. tooluniverse/test/test_reactome.py +54 -0
  161. tooluniverse/test/test_semantic_scholar_tool.py +24 -0
  162. tooluniverse/test/test_software_tools.py +147 -0
  163. tooluniverse/test/test_tool_description_optimizer.py +49 -0
  164. tooluniverse/test/test_tool_finder.py +26 -0
  165. tooluniverse/test/test_tool_finder_llm.py +252 -0
  166. tooluniverse/test/test_tools_find.py +195 -0
  167. tooluniverse/test/test_uniprot_tools.py +74 -0
  168. tooluniverse/test/test_uspto_tool.py +72 -0
  169. tooluniverse/test/test_xml_tool.py +113 -0
  170. tooluniverse/tool_finder_embedding.py +267 -0
  171. tooluniverse/tool_finder_keyword.py +693 -0
  172. tooluniverse/tool_finder_llm.py +699 -0
  173. tooluniverse/tool_graph_web_ui.py +955 -0
  174. tooluniverse/tool_registry.py +416 -0
  175. tooluniverse/uniprot_tool.py +155 -0
  176. tooluniverse/url_tool.py +253 -0
  177. tooluniverse/uspto_tool.py +240 -0
  178. tooluniverse/utils.py +369 -41
  179. tooluniverse/xml_tool.py +369 -0
  180. tooluniverse-1.0.0.dist-info/METADATA +377 -0
  181. tooluniverse-1.0.0.dist-info/RECORD +186 -0
  182. {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/WHEEL +1 -1
  183. tooluniverse-1.0.0.dist-info/entry_points.txt +9 -0
  184. tooluniverse-0.1.4.dist-info/METADATA +0 -141
  185. tooluniverse-0.1.4.dist-info/RECORD +0 -18
  186. {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/licenses/LICENSE +0 -0
  187. {tooluniverse-0.1.4.dist-info → tooluniverse-1.0.0.dist-info}/top_level.txt +0 -0
@@ -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 'properties' in current_dict[level]:
19
- current_dict = current_dict[level]['properties']
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 != 'openfda' and key !='generic_name' and key !='brand_name':
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['search_fields'] = mapped_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(params=None, endpoint_url=None, api_key=None, sort=None, limit=5,
112
- skip=None, count=None, exists=None, return_fields=None,
113
- exist_option='OR', search_keyword_option='AND', keywords_filter=True):
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=='ALL':
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('search_fields', {})
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 keywords_filter and field !='openfda.brand_name' and field !='openfda.generic_name':
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 == 'openfda.generic_name':
131
- value = value.upper() # all generic names are in uppercase
132
- value = value.replace(" and ", " ") # remove 'and' in the search query
133
- value = value.replace(" AND ", " ") # remove 'AND' in the search query
134
- value = ' '.join(value.split())
135
- if search_keyword_option=='AND':
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=='OR':
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['search_fields']
158
+ del params["search_fields"]
142
159
  if search_query:
143
- params['search'] = "+".join(search_query)
144
- params['search'] = '(' + params['search'] + ')'
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 (params.get('search') or params.get('count') or params.get('sort') or search_fields):
147
- return {"error": "You must provide at least one of 'search', 'count', or 'sort' parameters."}
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['limit'] = params.get('limit', limit)
151
- params['sort'] = params.get('sort', sort)
152
- params['skip'] = params.get('skip', skip)
153
- params['count'] = params.get('count', count)
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 'search' in params:
158
- if exist_option == 'AND':
159
- params['search'] += "+AND+(" + "+AND+".join(
160
- [f"_exists_:{keyword}" for keyword in exists])+")"
161
- elif exist_option == 'OR':
162
- params['search'] += "+AND+(" + "+".join(
163
- [f"_exists_:{keyword}" for keyword in exists])+")"
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 == 'AND':
166
- params['search'] = "+AND+".join(
167
- [f"_exists_:{keyword}" for keyword in exists])
168
- elif exist_option == 'OR':
169
- params['search'] = "+".join(
170
- [f"_exists_:{keyword}" for keyword in exists])
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['search'] += "+AND+(" + "+".join(
173
- [f"_exists_:{field}" for field in search_fields.keys()]) +")"
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 'error' in response_data:
190
- print("Invalid Query: ", response_data['error'])
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('meta', {})
195
- meta_info = meta_info.get('results', {})
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('results', [])
199
- if return_fields == 'ALL':
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
- results, required_fields, keywords_list)
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['fields']
217
- self.search_fields = fields.get('search_fields', {})
218
- self.return_fields = fields.get('return_fields', [])
219
- self.exists = fields.get('exists', None)
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('FDA_API_KEY')
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
- return search_openfda(mapped_arguments,
230
- endpoint_url=self.endpoint_url,
231
- api_key=self.api_key,
232
- exists=self.exists,
233
- return_fields=self.return_fields, exist_option='OR')
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 = 'https://api.fda.gov/drug/label.json'
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": ['ALL', 'abuse', 'accessories', 'active_ingredient', 'adverse_reactions', 'alarms', 'animal_pharmacology_and_or_toxicology', 'ask_doctor', 'ask_doctor_or_pharmacist', 'assembly_or_installation_instructions', 'boxed_warning', 'calibration_instructions', 'carcinogenesis_and_mutagenesis_and_impairment_of_fertility', 'cleaning', 'clinical_pharmacology', 'clinical_studies', 'compatible_accessories', 'components', 'contraindications', 'controlled_substance', 'dependence', 'description', 'diagram_of_device', 'disposal_and_waste_handling', 'do_not_use', 'dosage_and_administration', 'dosage_forms_and_strengths', 'drug_abuse_and_dependence', 'drug_and_or_laboratory_test_interactions', 'drug_interactions', 'effective_time', 'environmental_warning', 'food_safety_warning', 'general_precautions', 'geriatric_use', 'guaranteed_analysis_of_feed', 'health_care_provider_letter', 'health_claim', 'how_supplied', 'id', 'inactive_ingredient', 'indications_and_usage', 'information_for_owners_or_caregivers', 'information_for_patients', 'instructions_for_use', 'intended_use_of_the_device', 'keep_out_of_reach_of_children', 'labor_and_delivery', 'laboratory_tests', 'mechanism_of_action', 'microbiology', 'nonclinical_toxicology', 'nonteratogenic_effects', 'nursing_mothers', 'openfda', 'other_safety_information', 'overdosage', 'package_label_principal_display_panel', 'patient_medication_information', 'pediatric_use', 'pharmacodynamics', 'pharmacogenomics', 'pharmacokinetics', 'precautions', 'pregnancy', 'pregnancy_or_breast_feeding', 'purpose', 'questions', 'recent_major_changes', 'references', 'residue_warning', 'risks', 'route', 'safe_handling_warning', 'set_id', 'spl_indexing_data_elements', 'spl_medguide', 'spl_patient_package_insert', 'spl_product_data_elements', 'spl_unclassified_section', 'statement_of_identity', 'stop_use', 'storage_and_handling', 'summary_of_safety_and_effectiveness', 'teratogenic_effects', 'troubleshooting', 'use_in_specific_populations', 'user_safety_warnings', 'version', 'warnings', 'warnings_and_cautions', 'when_using', 'meta'],
262
- "description": "Searchable field."
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 = 'https://api.fda.gov/drug/label.json'
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
- return_fields = arguments['return_fields']
293
- del arguments['return_fields']
294
- return search_openfda(mapped_arguments,
295
- endpoint_url=self.endpoint_url,
296
- api_key=self.api_key,
297
- return_fields=return_fields, exists=return_fields, exist_option='OR')
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": ['ALL', 'abuse', 'accessories', 'active_ingredient', 'adverse_reactions', 'alarms', 'animal_pharmacology_and_or_toxicology', 'ask_doctor', 'ask_doctor_or_pharmacist', 'assembly_or_installation_instructions', 'boxed_warning', 'calibration_instructions', 'carcinogenesis_and_mutagenesis_and_impairment_of_fertility', 'cleaning', 'clinical_pharmacology', 'clinical_studies', 'compatible_accessories', 'components', 'contraindications', 'controlled_substance', 'dependence', 'description', 'diagram_of_device', 'disposal_and_waste_handling', 'do_not_use', 'dosage_and_administration', 'dosage_forms_and_strengths', 'drug_abuse_and_dependence', 'drug_and_or_laboratory_test_interactions', 'drug_interactions', 'effective_time', 'environmental_warning', 'food_safety_warning', 'general_precautions', 'geriatric_use', 'guaranteed_analysis_of_feed', 'health_care_provider_letter', 'health_claim', 'how_supplied', 'id', 'inactive_ingredient', 'indications_and_usage', 'information_for_owners_or_caregivers', 'information_for_patients', 'instructions_for_use', 'intended_use_of_the_device', 'keep_out_of_reach_of_children', 'labor_and_delivery', 'laboratory_tests', 'mechanism_of_action', 'microbiology', 'nonclinical_toxicology', 'nonteratogenic_effects', 'nursing_mothers', 'openfda', 'other_safety_information', 'overdosage', 'package_label_principal_display_panel', 'patient_medication_information', 'pediatric_use', 'pharmacodynamics', 'pharmacogenomics', 'pharmacokinetics', 'precautions', 'pregnancy', 'pregnancy_or_breast_feeding', 'purpose', 'questions', 'recent_major_changes', 'references', 'residue_warning', 'risks', 'route', 'safe_handling_warning', 'set_id', 'spl_indexing_data_elements', 'spl_medguide', 'spl_patient_package_insert', 'spl_product_data_elements', 'spl_unclassified_section', 'statement_of_identity', 'stop_use', 'storage_and_handling', 'summary_of_safety_and_effectiveness', 'teratogenic_effects', 'troubleshooting', 'use_in_specific_populations', 'user_safety_warnings', 'version', 'warnings', 'warnings_and_cautions', 'when_using', 'meta'],
319
- "description": "Searchable field."
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
- "query": ['id']
339
- },
340
- }
568
+ "search_fields": {"query": ["id"]},
569
+ },
341
570
  }
342
- endpoint_url = 'https://api.fda.gov/drug/label.json'
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
- return_fields = arguments['return_fields']
350
- del arguments['return_fields']
351
- return search_openfda(mapped_arguments,
352
- endpoint_url=self.endpoint_url,
353
- api_key=self.api_key,
354
- return_fields=return_fields, exists=return_fields, exist_option='OR')
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
- "drug_name": {
368
- "type": "string",
369
- "description": "The generic or brand name of the drug.",
370
- "required": True
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
- "drug_name": [
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
- "FDADrugLabel",
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 = {drug['brand_name']: drug['generic_name'] for drug in drug_list}
397
- self.generic_to_brand = {drug['generic_name']: drug['brand_name'] for drug in drug_list}
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('drug_name')
406
- if '-' in drug_name:
407
- drug_name = drug_name.split('-')[0] # to handle some drug names such as tarlatamab-dlle
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['openfda.generic_name'] = self.brand_to_generic[drug_name]
410
- drug_info['openfda.brand_name'] = drug_name
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['openfda.brand_name'] = self.generic_to_brand[drug_name]
413
- drug_info['openfda.generic_name'] = drug_name
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['openfda.generic_name'] = results['results'][0]['openfda.generic_name'][0]
418
- drug_info['openfda.brand_name'] = results['results'][0]['openfda.brand_name'][0]
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