aurelian 0.3.2__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.
Files changed (254) hide show
  1. aurelian/__init__.py +9 -0
  2. aurelian/agents/__init__.py +0 -0
  3. aurelian/agents/amigo/__init__.py +3 -0
  4. aurelian/agents/amigo/amigo_agent.py +77 -0
  5. aurelian/agents/amigo/amigo_config.py +85 -0
  6. aurelian/agents/amigo/amigo_evals.py +73 -0
  7. aurelian/agents/amigo/amigo_gradio.py +52 -0
  8. aurelian/agents/amigo/amigo_mcp.py +152 -0
  9. aurelian/agents/amigo/amigo_tools.py +152 -0
  10. aurelian/agents/biblio/__init__.py +42 -0
  11. aurelian/agents/biblio/biblio_agent.py +94 -0
  12. aurelian/agents/biblio/biblio_config.py +40 -0
  13. aurelian/agents/biblio/biblio_gradio.py +67 -0
  14. aurelian/agents/biblio/biblio_mcp.py +115 -0
  15. aurelian/agents/biblio/biblio_tools.py +164 -0
  16. aurelian/agents/biblio_agent.py +46 -0
  17. aurelian/agents/checklist/__init__.py +44 -0
  18. aurelian/agents/checklist/checklist_agent.py +85 -0
  19. aurelian/agents/checklist/checklist_config.py +28 -0
  20. aurelian/agents/checklist/checklist_gradio.py +70 -0
  21. aurelian/agents/checklist/checklist_mcp.py +86 -0
  22. aurelian/agents/checklist/checklist_tools.py +141 -0
  23. aurelian/agents/checklist/content/checklists.yaml +7 -0
  24. aurelian/agents/checklist/content/streams.csv +136 -0
  25. aurelian/agents/checklist_agent.py +40 -0
  26. aurelian/agents/chemistry/__init__.py +3 -0
  27. aurelian/agents/chemistry/chemistry_agent.py +46 -0
  28. aurelian/agents/chemistry/chemistry_config.py +71 -0
  29. aurelian/agents/chemistry/chemistry_evals.py +79 -0
  30. aurelian/agents/chemistry/chemistry_gradio.py +50 -0
  31. aurelian/agents/chemistry/chemistry_mcp.py +120 -0
  32. aurelian/agents/chemistry/chemistry_tools.py +121 -0
  33. aurelian/agents/chemistry/image_agent.py +15 -0
  34. aurelian/agents/d4d/__init__.py +30 -0
  35. aurelian/agents/d4d/d4d_agent.py +72 -0
  36. aurelian/agents/d4d/d4d_config.py +46 -0
  37. aurelian/agents/d4d/d4d_gradio.py +58 -0
  38. aurelian/agents/d4d/d4d_mcp.py +71 -0
  39. aurelian/agents/d4d/d4d_tools.py +157 -0
  40. aurelian/agents/d4d_agent.py +64 -0
  41. aurelian/agents/diagnosis/__init__.py +33 -0
  42. aurelian/agents/diagnosis/diagnosis_agent.py +53 -0
  43. aurelian/agents/diagnosis/diagnosis_config.py +48 -0
  44. aurelian/agents/diagnosis/diagnosis_evals.py +76 -0
  45. aurelian/agents/diagnosis/diagnosis_gradio.py +52 -0
  46. aurelian/agents/diagnosis/diagnosis_mcp.py +141 -0
  47. aurelian/agents/diagnosis/diagnosis_tools.py +204 -0
  48. aurelian/agents/diagnosis_agent.py +28 -0
  49. aurelian/agents/draw/__init__.py +3 -0
  50. aurelian/agents/draw/draw_agent.py +39 -0
  51. aurelian/agents/draw/draw_config.py +26 -0
  52. aurelian/agents/draw/draw_gradio.py +50 -0
  53. aurelian/agents/draw/draw_mcp.py +94 -0
  54. aurelian/agents/draw/draw_tools.py +100 -0
  55. aurelian/agents/draw/judge_agent.py +18 -0
  56. aurelian/agents/filesystem/__init__.py +0 -0
  57. aurelian/agents/filesystem/filesystem_config.py +27 -0
  58. aurelian/agents/filesystem/filesystem_gradio.py +49 -0
  59. aurelian/agents/filesystem/filesystem_mcp.py +89 -0
  60. aurelian/agents/filesystem/filesystem_tools.py +95 -0
  61. aurelian/agents/filesystem/py.typed +0 -0
  62. aurelian/agents/github/__init__.py +0 -0
  63. aurelian/agents/github/github_agent.py +83 -0
  64. aurelian/agents/github/github_cli.py +248 -0
  65. aurelian/agents/github/github_config.py +22 -0
  66. aurelian/agents/github/github_gradio.py +152 -0
  67. aurelian/agents/github/github_mcp.py +252 -0
  68. aurelian/agents/github/github_tools.py +408 -0
  69. aurelian/agents/github/github_tools.py.tmp +413 -0
  70. aurelian/agents/goann/__init__.py +13 -0
  71. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.md +1000 -0
  72. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.pdf +0 -0
  73. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.md +693 -0
  74. aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.pdf +0 -0
  75. aurelian/agents/goann/goann_agent.py +90 -0
  76. aurelian/agents/goann/goann_config.py +90 -0
  77. aurelian/agents/goann/goann_evals.py +104 -0
  78. aurelian/agents/goann/goann_gradio.py +62 -0
  79. aurelian/agents/goann/goann_mcp.py +0 -0
  80. aurelian/agents/goann/goann_tools.py +65 -0
  81. aurelian/agents/gocam/__init__.py +43 -0
  82. aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.docx +0 -0
  83. aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.pdf +0 -0
  84. aurelian/agents/gocam/documents/DNA-binding_transcription_factor_activity_annotation_guidelines.md +100 -0
  85. aurelian/agents/gocam/documents/E3 ubiquitin ligases.docx +0 -0
  86. aurelian/agents/gocam/documents/E3 ubiquitin ligases.pdf +0 -0
  87. aurelian/agents/gocam/documents/E3_ubiquitin_ligases.md +134 -0
  88. aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.docx +0 -0
  89. aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.pdf +0 -0
  90. aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.docx +0 -0
  91. aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.pdf +0 -0
  92. aurelian/agents/gocam/documents/GO-CAM_annotation_guidelines_README.md +1 -0
  93. aurelian/agents/gocam/documents/GO-CAM_modelling_guidelines_TO_DO.md +3 -0
  94. aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.docx +0 -0
  95. aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.pdf +0 -0
  96. aurelian/agents/gocam/documents/How to annotate molecular adaptors.docx +0 -0
  97. aurelian/agents/gocam/documents/How to annotate molecular adaptors.pdf +0 -0
  98. aurelian/agents/gocam/documents/How to annotate sequestering proteins.docx +0 -0
  99. aurelian/agents/gocam/documents/How to annotate sequestering proteins.pdf +0 -0
  100. aurelian/agents/gocam/documents/How_to_annotate_complexes_in_GO-CAM.md +29 -0
  101. aurelian/agents/gocam/documents/How_to_annotate_molecular_adaptors.md +31 -0
  102. aurelian/agents/gocam/documents/How_to_annotate_sequestering_proteins.md +42 -0
  103. aurelian/agents/gocam/documents/Molecular adaptor activity.docx +0 -0
  104. aurelian/agents/gocam/documents/Molecular adaptor activity.pdf +0 -0
  105. aurelian/agents/gocam/documents/Molecular carrier activity.docx +0 -0
  106. aurelian/agents/gocam/documents/Molecular carrier activity.pdf +0 -0
  107. aurelian/agents/gocam/documents/Molecular_adaptor_activity.md +51 -0
  108. aurelian/agents/gocam/documents/Molecular_carrier_activity.md +41 -0
  109. aurelian/agents/gocam/documents/Protein sequestering activity.docx +0 -0
  110. aurelian/agents/gocam/documents/Protein sequestering activity.pdf +0 -0
  111. aurelian/agents/gocam/documents/Protein_sequestering_activity.md +50 -0
  112. aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.docx +0 -0
  113. aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.pdf +0 -0
  114. aurelian/agents/gocam/documents/Signaling_receptor_activity_annotation_guidelines.md +187 -0
  115. aurelian/agents/gocam/documents/Transcription coregulator activity.docx +0 -0
  116. aurelian/agents/gocam/documents/Transcription coregulator activity.pdf +0 -0
  117. aurelian/agents/gocam/documents/Transcription_coregulator_activity.md +36 -0
  118. aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.docx +0 -0
  119. aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.pdf +0 -0
  120. aurelian/agents/gocam/documents/Transporter_activity_annotation_annotation_guidelines.md +43 -0
  121. Regulatory Processes in GO-CAM.docx +0 -0
  122. Regulatory Processes in GO-CAM.pdf +0 -0
  123. aurelian/agents/gocam/documents/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +31 -0
  124. aurelian/agents/gocam/documents/md/DNA-binding_transcription_factor_activity_annotation_guidelines.md +131 -0
  125. aurelian/agents/gocam/documents/md/E3_ubiquitin_ligases.md +166 -0
  126. aurelian/agents/gocam/documents/md/GO-CAM_annotation_guidelines_README.md +1 -0
  127. aurelian/agents/gocam/documents/md/GO-CAM_modelling_guidelines_TO_DO.md +5 -0
  128. aurelian/agents/gocam/documents/md/How_to_annotate_complexes_in_GO-CAM.md +28 -0
  129. aurelian/agents/gocam/documents/md/How_to_annotate_molecular_adaptors.md +19 -0
  130. aurelian/agents/gocam/documents/md/How_to_annotate_sequestering_proteins.md +38 -0
  131. aurelian/agents/gocam/documents/md/Molecular_adaptor_activity.md +52 -0
  132. aurelian/agents/gocam/documents/md/Molecular_carrier_activity.md +59 -0
  133. aurelian/agents/gocam/documents/md/Protein_sequestering_activity.md +52 -0
  134. aurelian/agents/gocam/documents/md/Signaling_receptor_activity_annotation_guidelines.md +271 -0
  135. aurelian/agents/gocam/documents/md/Transcription_coregulator_activity.md +54 -0
  136. aurelian/agents/gocam/documents/md/Transporter_activity_annotation_annotation_guidelines.md +38 -0
  137. aurelian/agents/gocam/documents/md/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +39 -0
  138. aurelian/agents/gocam/documents/pandoc_md/Signaling_receptor_activity_annotation_guidelines.md +334 -0
  139. aurelian/agents/gocam/gocam_agent.py +240 -0
  140. aurelian/agents/gocam/gocam_config.py +85 -0
  141. aurelian/agents/gocam/gocam_curator_agent.py +46 -0
  142. aurelian/agents/gocam/gocam_evals.py +67 -0
  143. aurelian/agents/gocam/gocam_gradio.py +89 -0
  144. aurelian/agents/gocam/gocam_mcp.py +224 -0
  145. aurelian/agents/gocam/gocam_tools.py +294 -0
  146. aurelian/agents/linkml/__init__.py +0 -0
  147. aurelian/agents/linkml/linkml_agent.py +62 -0
  148. aurelian/agents/linkml/linkml_config.py +48 -0
  149. aurelian/agents/linkml/linkml_evals.py +66 -0
  150. aurelian/agents/linkml/linkml_gradio.py +45 -0
  151. aurelian/agents/linkml/linkml_mcp.py +186 -0
  152. aurelian/agents/linkml/linkml_tools.py +102 -0
  153. aurelian/agents/literature/__init__.py +3 -0
  154. aurelian/agents/literature/literature_agent.py +55 -0
  155. aurelian/agents/literature/literature_config.py +35 -0
  156. aurelian/agents/literature/literature_gradio.py +52 -0
  157. aurelian/agents/literature/literature_mcp.py +174 -0
  158. aurelian/agents/literature/literature_tools.py +182 -0
  159. aurelian/agents/monarch/__init__.py +25 -0
  160. aurelian/agents/monarch/monarch_agent.py +44 -0
  161. aurelian/agents/monarch/monarch_config.py +45 -0
  162. aurelian/agents/monarch/monarch_gradio.py +51 -0
  163. aurelian/agents/monarch/monarch_mcp.py +65 -0
  164. aurelian/agents/monarch/monarch_tools.py +113 -0
  165. aurelian/agents/oak/__init__.py +0 -0
  166. aurelian/agents/oak/oak_config.py +27 -0
  167. aurelian/agents/oak/oak_gradio.py +57 -0
  168. aurelian/agents/ontology_mapper/__init__.py +31 -0
  169. aurelian/agents/ontology_mapper/ontology_mapper_agent.py +56 -0
  170. aurelian/agents/ontology_mapper/ontology_mapper_config.py +50 -0
  171. aurelian/agents/ontology_mapper/ontology_mapper_evals.py +108 -0
  172. aurelian/agents/ontology_mapper/ontology_mapper_gradio.py +58 -0
  173. aurelian/agents/ontology_mapper/ontology_mapper_mcp.py +81 -0
  174. aurelian/agents/ontology_mapper/ontology_mapper_tools.py +147 -0
  175. aurelian/agents/phenopackets/__init__.py +3 -0
  176. aurelian/agents/phenopackets/phenopackets_agent.py +58 -0
  177. aurelian/agents/phenopackets/phenopackets_config.py +72 -0
  178. aurelian/agents/phenopackets/phenopackets_evals.py +99 -0
  179. aurelian/agents/phenopackets/phenopackets_gradio.py +55 -0
  180. aurelian/agents/phenopackets/phenopackets_mcp.py +178 -0
  181. aurelian/agents/phenopackets/phenopackets_tools.py +127 -0
  182. aurelian/agents/rag/__init__.py +40 -0
  183. aurelian/agents/rag/rag_agent.py +83 -0
  184. aurelian/agents/rag/rag_config.py +80 -0
  185. aurelian/agents/rag/rag_gradio.py +67 -0
  186. aurelian/agents/rag/rag_mcp.py +107 -0
  187. aurelian/agents/rag/rag_tools.py +189 -0
  188. aurelian/agents/rag_agent.py +54 -0
  189. aurelian/agents/robot/__init__.py +0 -0
  190. aurelian/agents/robot/assets/__init__.py +3 -0
  191. aurelian/agents/robot/assets/template.md +384 -0
  192. aurelian/agents/robot/robot_config.py +25 -0
  193. aurelian/agents/robot/robot_gradio.py +46 -0
  194. aurelian/agents/robot/robot_mcp.py +100 -0
  195. aurelian/agents/robot/robot_ontology_agent.py +139 -0
  196. aurelian/agents/robot/robot_tools.py +50 -0
  197. aurelian/agents/talisman/__init__.py +3 -0
  198. aurelian/agents/talisman/talisman_agent.py +126 -0
  199. aurelian/agents/talisman/talisman_config.py +66 -0
  200. aurelian/agents/talisman/talisman_gradio.py +50 -0
  201. aurelian/agents/talisman/talisman_mcp.py +168 -0
  202. aurelian/agents/talisman/talisman_tools.py +720 -0
  203. aurelian/agents/ubergraph/__init__.py +40 -0
  204. aurelian/agents/ubergraph/ubergraph_agent.py +71 -0
  205. aurelian/agents/ubergraph/ubergraph_config.py +79 -0
  206. aurelian/agents/ubergraph/ubergraph_gradio.py +48 -0
  207. aurelian/agents/ubergraph/ubergraph_mcp.py +69 -0
  208. aurelian/agents/ubergraph/ubergraph_tools.py +118 -0
  209. aurelian/agents/uniprot/__init__.py +37 -0
  210. aurelian/agents/uniprot/uniprot_agent.py +43 -0
  211. aurelian/agents/uniprot/uniprot_config.py +43 -0
  212. aurelian/agents/uniprot/uniprot_evals.py +99 -0
  213. aurelian/agents/uniprot/uniprot_gradio.py +48 -0
  214. aurelian/agents/uniprot/uniprot_mcp.py +168 -0
  215. aurelian/agents/uniprot/uniprot_tools.py +136 -0
  216. aurelian/agents/web/__init__.py +0 -0
  217. aurelian/agents/web/web_config.py +27 -0
  218. aurelian/agents/web/web_gradio.py +48 -0
  219. aurelian/agents/web/web_mcp.py +50 -0
  220. aurelian/agents/web/web_tools.py +108 -0
  221. aurelian/chat.py +23 -0
  222. aurelian/cli.py +800 -0
  223. aurelian/dependencies/__init__.py +0 -0
  224. aurelian/dependencies/workdir.py +78 -0
  225. aurelian/mcp/__init__.py +0 -0
  226. aurelian/mcp/amigo_mcp_test.py +86 -0
  227. aurelian/mcp/config_generator.py +123 -0
  228. aurelian/mcp/example_config.json +43 -0
  229. aurelian/mcp/generate_sample_config.py +37 -0
  230. aurelian/mcp/gocam_mcp_test.py +126 -0
  231. aurelian/mcp/linkml_mcp_tools.py +190 -0
  232. aurelian/mcp/mcp_discovery.py +87 -0
  233. aurelian/mcp/mcp_test.py +31 -0
  234. aurelian/mcp/phenopackets_mcp_test.py +103 -0
  235. aurelian/tools/__init__.py +0 -0
  236. aurelian/tools/web/__init__.py +0 -0
  237. aurelian/tools/web/url_download.py +51 -0
  238. aurelian/utils/__init__.py +0 -0
  239. aurelian/utils/async_utils.py +15 -0
  240. aurelian/utils/data_utils.py +32 -0
  241. aurelian/utils/documentation_manager.py +59 -0
  242. aurelian/utils/doi_fetcher.py +238 -0
  243. aurelian/utils/ontology_utils.py +68 -0
  244. aurelian/utils/pdf_fetcher.py +23 -0
  245. aurelian/utils/process_logs.py +100 -0
  246. aurelian/utils/pubmed_utils.py +238 -0
  247. aurelian/utils/pytest_report_to_markdown.py +67 -0
  248. aurelian/utils/robot_ontology_utils.py +112 -0
  249. aurelian/utils/search_utils.py +95 -0
  250. aurelian-0.3.2.dist-info/LICENSE +22 -0
  251. aurelian-0.3.2.dist-info/METADATA +105 -0
  252. aurelian-0.3.2.dist-info/RECORD +254 -0
  253. aurelian-0.3.2.dist-info/WHEEL +4 -0
  254. aurelian-0.3.2.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,102 @@
1
+ from typing import Optional
2
+
3
+ import yaml
4
+ from linkml.generators import JsonSchemaGenerator
5
+ from linkml_runtime.linkml_model import SchemaDefinition
6
+ from linkml_runtime.loaders import yaml_loader
7
+ from pydantic import BaseModel
8
+ from pydantic_ai import RunContext, ModelRetry
9
+
10
+ from aurelian.agents.linkml.linkml_config import LinkMLDependencies
11
+ from aurelian.dependencies.workdir import WorkDir, HasWorkdir
12
+
13
+
14
+ class LinkMLError(ModelRetry):
15
+ pass
16
+
17
+ class SchemaValidationError(LinkMLError):
18
+ """Base exception for all schema validation errors."""
19
+ def __init__(self, message="Schema validation failed", details=None):
20
+ self.details = details or {}
21
+ super().__init__(message)
22
+
23
+
24
+ class ValidationResult(BaseModel):
25
+ valid: bool
26
+ info_messages: Optional[list[str]] = None
27
+
28
+
29
+ async def validate_then_save_schema(ctx: RunContext[HasWorkdir], schema_as_str: str, save_to_file: str= "schema.yaml") -> ValidationResult:
30
+ """
31
+ Validate a LinkML schema.
32
+
33
+ Args:
34
+ ctx: context
35
+ schema_as_str: linkml schema (as yaml) to validate. Do not truncate, always pass the whole schema.
36
+ save_to_file: file name to save the schema to. Defaults to schema.yaml
37
+
38
+ Returns:
39
+
40
+ """
41
+ print(f"Validating schema: {schema_as_str}")
42
+ msgs = []
43
+ try:
44
+ schema_dict = yaml.safe_load(schema_as_str)
45
+ print("YAML is valid")
46
+ except Exception as e:
47
+ raise SchemaValidationError(f"Schema is not valid yaml: {e}")
48
+ if "id" not in schema_dict:
49
+ raise SchemaValidationError("Schema does not have a top level id")
50
+ if "name" not in schema_dict:
51
+ raise SchemaValidationError("Schema does not have a top level name")
52
+ try:
53
+ schema_obj = yaml_loader.loads(schema_as_str, target_class=SchemaDefinition)
54
+ except Exception as e:
55
+ raise ModelRetry(f"Schema does not validate: {e} // {schema_as_str}")
56
+ try:
57
+ gen = JsonSchemaGenerator(schema_obj)
58
+ gen.serialize()
59
+ except Exception as e:
60
+ raise ModelRetry(f"Schema does not convert to JSON-Schema: {e} // {schema_as_str}")
61
+ try:
62
+ if save_to_file and schema_as_str:
63
+ msgs.append(f"Writing schema to {save_to_file}")
64
+ workdir = ctx.deps.workdir
65
+ workdir.write_file(save_to_file, schema_as_str)
66
+ except Exception as e:
67
+ raise ModelRetry(f"Schema does not validate: {e} // {schema_as_str}")
68
+ return ValidationResult(valid=True, info_messages=msgs)
69
+
70
+
71
+ async def validate_data(ctx: RunContext[LinkMLDependencies], schema: str, data_file: str) -> str:
72
+ """
73
+ Validate data file against a schema.
74
+
75
+ This assumes the data file is present in the working directory.
76
+ You can write data to the working directory using the `write_to_file` tool.
77
+
78
+ Args:
79
+ ctx:
80
+ schema: the schema (as a YAML string)
81
+ data_file: the name of the data file in the working directory
82
+
83
+ Returns:
84
+
85
+ """
86
+ print(f"Validating data file: {data_file} using schema: {schema}")
87
+ try:
88
+ schema = yaml_loader.loads(schema, target_class=SchemaDefinition)
89
+ except Exception as e:
90
+ return f"Schema does not validate: {e}"
91
+ try:
92
+ from linkml.validator import validate
93
+ instances = ctx.deps.parse_objects_from_file(data_file)
94
+ for instance in instances:
95
+ print(f"Validating {instance}")
96
+ rpt = validate(instance, schema)
97
+ print(f"Validation report: {rpt}")
98
+ if rpt.results:
99
+ return f"Data does not validate:\n{rpt.results}"
100
+ return f"{len(instances)} instances all validate successfully"
101
+ except Exception as e:
102
+ raise ModelRetry(f"Data does not validate: {e}")
@@ -0,0 +1,3 @@
1
+ """
2
+ Literature agent module for working with scientific literature, publications, and references.
3
+ """
@@ -0,0 +1,55 @@
1
+ """
2
+ Agent for working with scientific literature and publications.
3
+ """
4
+ from aurelian.agents.literature.literature_config import LiteratureDependencies
5
+ from aurelian.agents.literature.literature_tools import (
6
+ lookup_pmid,
7
+ lookup_doi,
8
+ convert_pmid_to_doi,
9
+ convert_doi_to_pmid,
10
+ get_article_abstract,
11
+ extract_text_from_pdf_url,
12
+ search_literature_web,
13
+ retrieve_literature_page
14
+ )
15
+ from aurelian.agents.filesystem.filesystem_tools import inspect_file, list_files
16
+ from pydantic_ai import Agent, Tool
17
+
18
+ SYSTEM = """
19
+ You are an expert scientific literature assistant that helps users access and analyze scientific publications.
20
+
21
+ You can help with:
22
+ - Finding and retrieving full text of articles using PubMed IDs or DOIs
23
+ - Converting between PubMed IDs and DOIs
24
+ - Extracting text from PDF articles
25
+ - Searching for scientific literature on specific topics
26
+ - Analyzing and summarizing scientific papers
27
+
28
+ Always provide accurate citations for any scientific information, including:
29
+ - Article titles
30
+ - Authors
31
+ - Journal names
32
+ - Publication dates
33
+ - DOIs and/or PubMed IDs
34
+
35
+ When quoting or referencing a specific part of a paper, always indicate which section it comes from
36
+ (e.g., abstract, methods, results, discussion).
37
+ """
38
+
39
+ literature_agent = Agent(
40
+ model="openai:gpt-4o",
41
+ deps_type=LiteratureDependencies,
42
+ system_prompt=SYSTEM,
43
+ tools=[
44
+ Tool(lookup_pmid),
45
+ Tool(lookup_doi),
46
+ Tool(convert_pmid_to_doi),
47
+ Tool(convert_doi_to_pmid),
48
+ Tool(get_article_abstract),
49
+ Tool(extract_text_from_pdf_url),
50
+ Tool(search_literature_web),
51
+ Tool(retrieve_literature_page),
52
+ Tool(inspect_file),
53
+ Tool(list_files),
54
+ ]
55
+ )
@@ -0,0 +1,35 @@
1
+ """
2
+ Configuration classes for the literature agent.
3
+ """
4
+ from dataclasses import dataclass
5
+ import os
6
+ from typing import Optional
7
+
8
+ from aurelian.dependencies.workdir import HasWorkdir, WorkDir
9
+
10
+
11
+ @dataclass
12
+ class LiteratureDependencies(HasWorkdir):
13
+ """
14
+ Configuration for the literature agent.
15
+ """
16
+ max_results: int = 10
17
+
18
+ def __post_init__(self):
19
+ """Initialize the config with default values."""
20
+ # Initialize workdir if not provided
21
+ if self.workdir is None:
22
+ self.workdir = WorkDir()
23
+
24
+
25
+ def get_config() -> LiteratureDependencies:
26
+ """
27
+ Get the Literature agent configuration from environment variables or defaults.
28
+
29
+ Returns:
30
+ LiteratureDependencies: The literature dependencies
31
+ """
32
+ workdir_path = os.environ.get("AURELIAN_WORKDIR", None)
33
+ workdir = WorkDir(location=workdir_path) if workdir_path else None
34
+
35
+ return LiteratureDependencies(workdir=workdir)
@@ -0,0 +1,52 @@
1
+ """
2
+ Gradio UI for the literature agent.
3
+ """
4
+ from typing import List, Optional
5
+
6
+ import gradio as gr
7
+
8
+ from aurelian.agents.literature.literature_agent import literature_agent
9
+ from aurelian.agents.literature.literature_config import LiteratureDependencies
10
+ from aurelian.utils.async_utils import run_sync
11
+
12
+
13
+ def chat(deps: Optional[LiteratureDependencies] = None, workdir: str = None, **kwargs):
14
+ """
15
+ Initialize a chat interface for the literature agent.
16
+
17
+ Args:
18
+ deps: Optional dependencies configuration
19
+ workdir: Optional working directory path
20
+ **kwargs: Additional arguments to pass to the agent
21
+
22
+ Returns:
23
+ A Gradio chat interface
24
+ """
25
+ if deps is None:
26
+ deps = LiteratureDependencies()
27
+
28
+ if workdir:
29
+ deps.workdir.location = workdir
30
+
31
+ def get_info(query: str, history: List[str]) -> str:
32
+ print(f"QUERY: {query}")
33
+ print(f"HISTORY: {history}")
34
+ if history:
35
+ query += "## History"
36
+ for h in history:
37
+ query += f"\n{h}"
38
+ result = run_sync(lambda: literature_agent.run_sync(query, deps=deps, **kwargs))
39
+ return result.data
40
+
41
+ return gr.ChatInterface(
42
+ fn=get_info,
43
+ type="messages",
44
+ title="Scientific Literature Assistant",
45
+ examples=[
46
+ ["Look up this article: PMID:31653696"],
47
+ ["Find information about Alzheimer's disease genetics in recent papers"],
48
+ ["What is the DOI for PMID:27629041?"],
49
+ ["Get the abstract of PMID:30478089"],
50
+ ["Convert this DOI to a PMID: 10.1038/nature12373"]
51
+ ]
52
+ )
@@ -0,0 +1,174 @@
1
+ """
2
+ MCP tools for working with scientific literature and publications.
3
+ """
4
+ import os
5
+ from typing import Optional
6
+
7
+ from mcp.server.fastmcp import FastMCP
8
+
9
+ import aurelian.agents.literature.literature_tools as lt
10
+ import aurelian.agents.filesystem.filesystem_tools as fst
11
+ from aurelian.agents.literature.literature_agent import SYSTEM
12
+ from aurelian.agents.literature.literature_config import LiteratureDependencies
13
+ from pydantic_ai import RunContext
14
+
15
+ # Initialize FastMCP server
16
+ mcp = FastMCP("literature", instructions=SYSTEM)
17
+
18
+
19
+ from aurelian.dependencies.workdir import WorkDir
20
+
21
+ def deps() -> LiteratureDependencies:
22
+ deps = LiteratureDependencies()
23
+ # Set the location from environment variable or default
24
+ loc = os.getenv("AURELIAN_WORKDIR", "/tmp/aurelian")
25
+ deps.workdir = WorkDir(loc)
26
+ return deps
27
+
28
+ def ctx() -> RunContext[LiteratureDependencies]:
29
+ rc: RunContext[LiteratureDependencies] = RunContext[LiteratureDependencies](
30
+ deps=deps(),
31
+ model=None, usage=None, prompt=None,
32
+ )
33
+ return rc
34
+
35
+
36
+ @mcp.tool()
37
+ async def lookup_pmid(pmid: str) -> str:
38
+ """
39
+ Lookup the text of a PubMed article by its PMID.
40
+
41
+ Args:
42
+ pmid: The PubMed ID to look up (format: "PMID:nnnnnnn")
43
+
44
+ Returns:
45
+ Full text if available, otherwise abstract
46
+ """
47
+ return await lt.lookup_pmid(ctx(), pmid)
48
+
49
+ @mcp.tool()
50
+ async def lookup_doi(doi: str) -> str:
51
+ """
52
+ Lookup the text of an article by its DOI.
53
+
54
+ Args:
55
+ doi: The DOI to look up
56
+
57
+ Returns:
58
+ Full text if available, otherwise abstract
59
+ """
60
+ return await lt.lookup_doi(doi)
61
+
62
+
63
+ @mcp.tool()
64
+ async def convert_pmid_to_doi(pmid: str) -> str:
65
+ """
66
+ Convert a PubMed ID (PMID) to a DOI.
67
+
68
+ Args:
69
+ pmid: The PubMed ID to convert
70
+
71
+ Returns:
72
+ The corresponding DOI
73
+ """
74
+ return await lt.convert_pmid_to_doi(pmid)
75
+
76
+
77
+ @mcp.tool()
78
+ async def convert_doi_to_pmid(doi: str) -> str:
79
+ """
80
+ Convert a DOI to a PubMed ID (PMID).
81
+
82
+ Args:
83
+ doi: The DOI to convert
84
+
85
+ Returns:
86
+ The corresponding PubMed ID
87
+ """
88
+ return await lt.convert_doi_to_pmid(doi)
89
+
90
+
91
+ @mcp.tool()
92
+ async def get_article_abstract(identifier: str) -> str:
93
+ """
94
+ Get the abstract of an article by its PMID or DOI.
95
+
96
+ Args:
97
+ identifier: PMID or DOI of the article
98
+
99
+ Returns:
100
+ The article abstract
101
+ """
102
+ return await lt.get_article_abstract(identifier)
103
+
104
+
105
+ @mcp.tool()
106
+ async def extract_text_from_pdf_url(url: str) -> str:
107
+ """
108
+ Extract text from a PDF at the given URL.
109
+
110
+ Args:
111
+ url: URL to the PDF file
112
+
113
+ Returns:
114
+ Extracted text from the PDF
115
+ """
116
+ return await lt.extract_text_from_pdf_url(url)
117
+
118
+
119
+ @mcp.tool()
120
+ async def search_literature_web(query: str) -> str:
121
+ """
122
+ Search the web for scientific literature.
123
+
124
+ Args:
125
+ query: The search query
126
+
127
+ Returns:
128
+ Search results with summaries
129
+ """
130
+ return await lt.search_literature_web(query)
131
+
132
+
133
+ @mcp.tool()
134
+ async def retrieve_literature_page(url: str) -> str:
135
+ """
136
+ Fetch the contents of a web page related to scientific literature.
137
+
138
+ Args:
139
+ url: The URL to fetch
140
+
141
+ Returns:
142
+ The contents of the web page
143
+ """
144
+ return await lt.retrieve_literature_page(url)
145
+
146
+
147
+ @mcp.tool()
148
+ async def inspect_file(data_file: str) -> str:
149
+ """
150
+ Inspect a file in the working directory.
151
+
152
+ Args:
153
+ data_file: name of file
154
+
155
+ Returns:
156
+ Contents of the file
157
+ """
158
+ return await fst.inspect_file(ctx(), data_file)
159
+
160
+
161
+ @mcp.tool()
162
+ async def list_files() -> str:
163
+ """
164
+ List files in the working directory.
165
+
166
+ Returns:
167
+ List of files in the working directory
168
+ """
169
+ return await fst.list_files(ctx())
170
+
171
+
172
+ if __name__ == "__main__":
173
+ # Initialize and run the server
174
+ mcp.run(transport='stdio')
@@ -0,0 +1,182 @@
1
+ """
2
+ Tools for the literature agent.
3
+ """
4
+ from typing import Optional, List, Dict
5
+
6
+ from pydantic_ai import RunContext, ModelRetry
7
+
8
+ from aurelian.agents.literature.literature_config import LiteratureDependencies
9
+ from aurelian.utils.doi_fetcher import DOIFetcher
10
+ from aurelian.utils.pubmed_utils import (
11
+ get_pmid_text,
12
+ get_doi_text,
13
+ pmid_to_doi,
14
+ doi_to_pmid,
15
+ get_abstract_from_pubmed,
16
+ )
17
+ from aurelian.utils.pdf_fetcher import extract_text_from_pdf
18
+ from aurelian.utils.search_utils import web_search, retrieve_web_page
19
+
20
+
21
+ async def lookup_pmid(pmid: str) -> str:
22
+ """
23
+ Lookup the text of a PubMed article by its PMID.
24
+
25
+ A PMID should be of the form "PMID:nnnnnnn" (no underscores).
26
+
27
+ Args:
28
+ pmid: The PubMed ID to look up
29
+
30
+ Returns:
31
+ str: Full text if available, otherwise abstract
32
+ """
33
+ print(f"LOOKUP PMID: {pmid}")
34
+ try:
35
+ result = get_pmid_text(pmid)
36
+ print(f"RESULT LENGTH: {len(result)} // {result[:100]}")
37
+ if not result or "Error" in result:
38
+ raise ModelRetry(f"Could not retrieve text for PMID: {pmid}. Try using the abstract only or a different identifier.")
39
+ return result
40
+ except Exception as e:
41
+ raise ModelRetry(f"Error retrieving PMID {pmid}: {str(e)}. Try using the abstract only or a different identifier.")
42
+
43
+
44
+ async def lookup_doi(doi: str) -> str:
45
+ """
46
+ Lookup the text of an article by its DOI.
47
+
48
+ Args:
49
+ doi: The DOI to look up (e.g., "10.1038/nature12373")
50
+
51
+ Returns:
52
+ str: Full text if available, otherwise abstract
53
+ """
54
+ print(f"LOOKUP DOI: {doi}")
55
+ try:
56
+ result = get_doi_text(doi)
57
+ if not result or "Error" in result or "not available" in result.lower():
58
+ raise ModelRetry(f"Could not retrieve text for DOI: {doi}. Try using a PubMed ID or a different approach.")
59
+ return result
60
+ except Exception as e:
61
+ raise ModelRetry(f"Error retrieving DOI {doi}: {str(e)}. Try using a PubMed ID or a different approach.")
62
+
63
+
64
+ async def convert_pmid_to_doi(pmid: str) -> Optional[str]:
65
+ """
66
+ Convert a PubMed ID to a DOI.
67
+
68
+ Args:
69
+ pmid: The PubMed ID to convert
70
+
71
+ Returns:
72
+ str: The corresponding DOI, or None if not found
73
+ """
74
+ print(f"CONVERT PMID TO DOI: {pmid}")
75
+ try:
76
+ result = pmid_to_doi(pmid)
77
+ if not result:
78
+ raise ModelRetry(f"Could not convert PMID {pmid} to DOI. This article may not have a DOI assigned.")
79
+ return result
80
+ except Exception as e:
81
+ raise ModelRetry(f"Error converting PMID {pmid} to DOI: {str(e)}")
82
+
83
+
84
+ async def convert_doi_to_pmid(doi: str) -> Optional[str]:
85
+ """
86
+ Convert a DOI to a PubMed ID.
87
+
88
+ Args:
89
+ doi: The DOI to convert
90
+
91
+ Returns:
92
+ str: The corresponding PubMed ID, or None if not found
93
+ """
94
+ print(f"CONVERT DOI TO PMID: {doi}")
95
+ try:
96
+ result = doi_to_pmid(doi)
97
+ if not result:
98
+ raise ModelRetry(f"Could not convert DOI {doi} to PMID. This article may not be indexed in PubMed.")
99
+ return result
100
+ except Exception as e:
101
+ raise ModelRetry(f"Error converting DOI {doi} to PMID: {str(e)}")
102
+
103
+
104
+ async def get_article_abstract(pmid: str) -> str:
105
+ """
106
+ Get only the abstract of an article by its PubMed ID.
107
+
108
+ Args:
109
+ pmid: The PubMed ID to look up
110
+
111
+ Returns:
112
+ str: The article abstract
113
+ """
114
+ print(f"GET ABSTRACT: {pmid}")
115
+ try:
116
+ result = get_abstract_from_pubmed(pmid)
117
+ if not result or result.endswith("No abstract available"):
118
+ raise ModelRetry(f"No abstract available for PMID {pmid}. This article may not have an abstract or the PMID may be incorrect.")
119
+ return result
120
+ except Exception as e:
121
+ raise ModelRetry(f"Error retrieving abstract for PMID {pmid}: {str(e)}")
122
+
123
+
124
+ async def extract_text_from_pdf_url(ctx: RunContext[LiteratureDependencies], pdf_url: str) -> str:
125
+ """
126
+ Extract text from a PDF at the given URL.
127
+
128
+ Args:
129
+ ctx: The run context
130
+ pdf_url: URL to the PDF file
131
+
132
+ Returns:
133
+ str: The extracted text content
134
+ """
135
+ print(f"EXTRACT PDF: {pdf_url}")
136
+ try:
137
+ result = extract_text_from_pdf(pdf_url)
138
+ if not result or "Error" in result:
139
+ raise ModelRetry(f"Could not extract text from PDF at {pdf_url}. The URL may be invalid or the PDF may be password-protected.")
140
+ return result
141
+ except Exception as e:
142
+ raise ModelRetry(f"Error extracting text from PDF {pdf_url}: {str(e)}")
143
+
144
+
145
+ async def search_literature_web(query: str) -> str:
146
+ """
147
+ Search the web for scientific literature using a text query.
148
+
149
+ Args:
150
+ query: The search query (e.g., "alzheimer's disease genetics 2023")
151
+
152
+ Returns:
153
+ str: Search results with summaries
154
+ """
155
+ print(f"LITERATURE WEB SEARCH: {query}")
156
+ try:
157
+ result = web_search(query)
158
+ if not result:
159
+ raise ModelRetry(f"No search results found for query: {query}. Try using different keywords.")
160
+ return result
161
+ except Exception as e:
162
+ raise ModelRetry(f"Error searching the web for '{query}': {str(e)}")
163
+
164
+
165
+ async def retrieve_literature_page(url: str) -> str:
166
+ """
167
+ Fetch the contents of a literature webpage.
168
+
169
+ Args:
170
+ url: The URL to fetch
171
+
172
+ Returns:
173
+ str: The contents of the webpage
174
+ """
175
+ print(f"FETCH LITERATURE URL: {url}")
176
+ try:
177
+ result = retrieve_web_page(url)
178
+ if not result or len(result.strip()) < 20:
179
+ raise ModelRetry(f"Could not retrieve meaningful content from {url}. The URL may be invalid or require authentication.")
180
+ return result
181
+ except Exception as e:
182
+ raise ModelRetry(f"Error retrieving webpage {url}: {str(e)}")
@@ -0,0 +1,25 @@
1
+ """
2
+ Monarch agent package for interacting with the Monarch Knowledge Base.
3
+ """
4
+
5
+ from .monarch_agent import monarch_agent, MONARCH_SYSTEM_PROMPT
6
+ from .monarch_config import MonarchDependencies, get_config
7
+ from .monarch_gradio import chat
8
+ from .monarch_tools import find_gene_associations, find_disease_associations
9
+
10
+ __all__ = [
11
+ # Agent
12
+ "monarch_agent",
13
+ "MONARCH_SYSTEM_PROMPT",
14
+
15
+ # Config
16
+ "MonarchDependencies",
17
+ "get_config",
18
+
19
+ # Tools
20
+ "find_gene_associations",
21
+ "find_disease_associations",
22
+
23
+ # Gradio
24
+ "chat",
25
+ ]
@@ -0,0 +1,44 @@
1
+ """
2
+ Agent for interacting with the Monarch knowledge base.
3
+ """
4
+ from pydantic_ai import Agent
5
+
6
+ from .monarch_config import MonarchDependencies, get_config
7
+ from .monarch_tools import find_gene_associations, find_disease_associations
8
+
9
+ # System prompt for the Monarch agent
10
+ MONARCH_SYSTEM_PROMPT = """
11
+ You are a helpful assistant specializing in biomedical data from the Monarch Knowledge Base.
12
+ You can help researchers find relationships between genes, diseases, phenotypes, and other biomedical entities.
13
+
14
+ The Monarch Knowledge Base integrates data from multiple biomedical databases and provides a unified interface
15
+ for querying associations between different biological entities.
16
+
17
+ You can:
18
+ - Find associations for genes, including what diseases they're linked to
19
+ - Find associations for diseases, including what genes and phenotypes they're linked to
20
+ - Provide information about biological relationships in a structured way
21
+
22
+ When working with identifiers:
23
+ - Gene symbols should be specified as HGNC or MGI symbols (e.g. "BRCA1")
24
+ - Disease IDs can be specified as MONDO, OMIM, or Orphanet IDs (e.g. "MONDO:0007254")
25
+ - Phenotype IDs can be specified as HP terms (e.g. "HP:0000118")
26
+
27
+ Present your findings in a clear, organized manner that helps researchers understand the biological significance
28
+ of the associations. Include relevant details about:
29
+ - Source of the associations
30
+ - Strength of evidence
31
+ - Type of relationship (causal, correlative, etc.)
32
+ - Relevant literature references when available
33
+ """
34
+
35
+ # Create the agent with the system prompt
36
+ monarch_agent = Agent(
37
+ model="openai:gpt-4o",
38
+ system_prompt=MONARCH_SYSTEM_PROMPT,
39
+ deps_type=MonarchDependencies,
40
+ )
41
+
42
+ # Register the tools with the agent
43
+ monarch_agent.tool(find_gene_associations)
44
+ monarch_agent.tool(find_disease_associations)