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,48 @@
1
+ """
2
+ Gradio interface for the UniProt agent.
3
+ """
4
+ from typing import List, Optional
5
+
6
+ import gradio as gr
7
+
8
+ from aurelian.agents.uniprot.uniprot_agent import uniprot_agent
9
+ from aurelian.agents.uniprot.uniprot_config import UniprotConfig
10
+ from aurelian.utils.async_utils import run_sync
11
+
12
+
13
+ def chat(deps: Optional[UniprotConfig] = None, **kwargs):
14
+ """
15
+ Initialize a chat interface for the UniProt agent.
16
+
17
+ Args:
18
+ deps: Optional dependencies configuration
19
+ **kwargs: Additional arguments to pass to the agent
20
+
21
+ Returns:
22
+ A Gradio chat interface
23
+ """
24
+ if deps is None:
25
+ deps = UniprotConfig()
26
+
27
+ def get_info(query: str, history: List[str]) -> str:
28
+ print(f"QUERY: {query}")
29
+ print(f"HISTORY: {history}")
30
+ if history:
31
+ query += "## History"
32
+ for h in history:
33
+ query += f"\n{h}"
34
+ result = run_sync(lambda: uniprot_agent.run_sync(query, deps=deps, **kwargs))
35
+ return result.data
36
+
37
+ return gr.ChatInterface(
38
+ fn=get_info,
39
+ type="messages",
40
+ title="UniProt AI Assistant",
41
+ examples=[
42
+ ["Search for human insulin protein"],
43
+ ["Look up UniProt entry P01308"],
44
+ ["Map UniProt IDs P01308,P01009 to PDB database"],
45
+ ["What domains are present in UniProt entry P53_HUMAN?"],
46
+ ["Find all proteins related to Alzheimer's disease"]
47
+ ]
48
+ )
@@ -0,0 +1,168 @@
1
+ """
2
+ MCP integration for the UniProt agent.
3
+ """
4
+ import json
5
+ import os
6
+ from typing import Dict, Any, List, Optional
7
+
8
+ from anthropic import Anthropic
9
+ from pydantic_ai import Agent
10
+
11
+ # Import directly from the MCP module
12
+ from .uniprot_agent import uniprot_agent, UNIPROT_SYSTEM_PROMPT
13
+ from .uniprot_config import UniprotConfig, get_config
14
+
15
+
16
+ def tools_to_anthropic_tools(agent: Agent) -> List[Dict[str, Any]]:
17
+ """Convert pydantic-ai Agent tools to Anthropic tools format.
18
+
19
+ Args:
20
+ agent: The pydantic-ai Agent with tools
21
+
22
+ Returns:
23
+ A list of tools in the Anthropic format
24
+ """
25
+ anthropic_tools = []
26
+ for tool in agent.tools:
27
+ anthropic_tool = {
28
+ "name": tool.name,
29
+ "description": tool.description,
30
+ "input_schema": {
31
+ "type": "object",
32
+ "properties": {},
33
+ "required": []
34
+ }
35
+ }
36
+
37
+ for param_name, param in tool.params.items():
38
+ if param_name == "ctx":
39
+ continue
40
+
41
+ param_schema = {"type": "string"}
42
+ if param.annotation.__origin__ == list:
43
+ param_schema = {
44
+ "type": "array",
45
+ "items": {"type": "string"}
46
+ }
47
+
48
+ anthropic_tool["input_schema"]["properties"][param_name] = param_schema
49
+ if param.default == param.empty:
50
+ anthropic_tool["input_schema"]["required"].append(param_name)
51
+
52
+ anthropic_tools.append(anthropic_tool)
53
+
54
+ return anthropic_tools
55
+
56
+
57
+ def create_bedrock_compatible_resp(
58
+ response_id: str,
59
+ model: str,
60
+ role: str,
61
+ content: List[Dict[str, Any]]
62
+ ) -> Dict[str, Any]:
63
+ """Create a response compatible with the Bedrock format.
64
+
65
+ Args:
66
+ response_id: The response ID
67
+ model: The model name
68
+ role: The role (usually 'assistant')
69
+ content: The content from the Anthropic response
70
+
71
+ Returns:
72
+ A response in the Bedrock format
73
+ """
74
+ return {
75
+ "id": response_id,
76
+ "model": model,
77
+ "choices": [
78
+ {
79
+ "message": {
80
+ "role": role,
81
+ "content": content
82
+ }
83
+ }
84
+ ]
85
+ }
86
+
87
+
88
+ def get_uniprot_mcp_tools() -> List[Dict[str, Any]]:
89
+ """Get the MCP tools for the UniProt agent.
90
+
91
+ Returns:
92
+ A list of tools in the MCP format
93
+ """
94
+ return tools_to_anthropic_tools(uniprot_agent)
95
+
96
+
97
+ def get_uniprot_mcp_messages(
98
+ messages: Optional[List[Dict[str, Any]]] = None,
99
+ system: Optional[str] = None,
100
+ ) -> List[Dict[str, Any]]:
101
+ """Get MCP messages for the UniProt agent.
102
+
103
+ Args:
104
+ messages: Previous messages
105
+ system: System message override
106
+
107
+ Returns:
108
+ List of MCP messages
109
+ """
110
+ if messages is None:
111
+ messages = []
112
+
113
+ if system is None:
114
+ system = UNIPROT_SYSTEM_PROMPT
115
+
116
+ if not messages or messages[0].get("role") != "system":
117
+ messages = [{"role": "system", "content": system}] + messages
118
+
119
+ return messages
120
+
121
+
122
+ def handle_uniprot_mcp_request(
123
+ messages: List[Dict[str, Any]],
124
+ config: Optional[UniprotConfig] = None,
125
+ model: str = "claude-3-5-sonnet-20240620",
126
+ max_tokens: int = 4096,
127
+ temperature: float = 0.0,
128
+ ) -> Dict[str, Any]:
129
+ """Handle an MCP request for the UniProt agent.
130
+
131
+ Args:
132
+ messages: The messages from the client
133
+ config: The UniProt configuration (optional)
134
+ model: The model to use
135
+ max_tokens: The maximum number of tokens to generate
136
+ temperature: The temperature to use for generation
137
+
138
+ Returns:
139
+ An MCP response
140
+ """
141
+ config = config or get_config()
142
+
143
+ api_key = os.environ.get("ANTHROPIC_API_KEY")
144
+ if not api_key:
145
+ raise ValueError("ANTHROPIC_API_KEY environment variable is required for MCP")
146
+
147
+ client = Anthropic(api_key=api_key)
148
+
149
+ # Prepare the messages and tools
150
+ mcp_messages = get_uniprot_mcp_messages(messages)
151
+ mcp_tools = get_uniprot_mcp_tools()
152
+
153
+ # Send the request to Anthropic
154
+ response = client.messages.create(
155
+ model=model,
156
+ messages=mcp_messages,
157
+ tools=mcp_tools,
158
+ max_tokens=max_tokens,
159
+ temperature=temperature,
160
+ )
161
+
162
+ # Return the response in a format compatible with the MCP protocol
163
+ return create_bedrock_compatible_resp(
164
+ response_id=response.id,
165
+ model=model,
166
+ role="assistant",
167
+ content=response.content,
168
+ )
@@ -0,0 +1,136 @@
1
+ """
2
+ Tools for interacting with the UniProt database.
3
+ """
4
+ from typing import Dict, List, Optional
5
+
6
+ from pydantic_ai import RunContext, ModelRetry
7
+
8
+ from .uniprot_config import UniprotConfig, get_config
9
+
10
+
11
+ def normalize_uniprot_id(uniprot_id: str) -> str:
12
+ """Normalize a Uniprot ID by removing any version number.
13
+
14
+ Args:
15
+ uniprot_id: The Uniprot ID
16
+
17
+ Returns:
18
+ The normalized Uniprot ID
19
+ """
20
+ if ":" in uniprot_id:
21
+ return uniprot_id.split(":")[-1]
22
+ return uniprot_id
23
+
24
+
25
+ def search(ctx: RunContext[UniprotConfig], query: str) -> str:
26
+ """Search UniProt with a query string.
27
+
28
+ Args:
29
+ ctx: The run context with access to the config
30
+ query: The search query
31
+
32
+ Returns:
33
+ The search results in TSV format
34
+ """
35
+ config = ctx.deps or get_config()
36
+ u = config.get_uniprot_client()
37
+
38
+ try:
39
+ results = u.search(query, frmt="tsv", columns="accession,id,gene_names")
40
+ if not results or results.strip() == "":
41
+ raise ModelRetry(f"No results found for query: {query}")
42
+ return results
43
+ except Exception as e:
44
+ if "ModelRetry" in str(type(e)):
45
+ raise e
46
+ raise ModelRetry(f"Error searching UniProt: {str(e)}")
47
+
48
+
49
+ def lookup_uniprot_entry(ctx: RunContext[UniprotConfig], uniprot_acc: str) -> str:
50
+ """Lookup the Uniprot entry for a given Uniprot accession number.
51
+
52
+ Args:
53
+ ctx: The run context with access to the config
54
+ uniprot_acc: The Uniprot accession
55
+
56
+ Returns:
57
+ The UniProt entry in text format
58
+ """
59
+ config = ctx.deps or get_config()
60
+ u = config.get_uniprot_client()
61
+
62
+ try:
63
+ uniprot_acc = normalize_uniprot_id(uniprot_acc)
64
+ result = u.retrieve(uniprot_acc, frmt="txt")
65
+ if not result or result.strip() == "":
66
+ raise ModelRetry(f"No entry found for accession: {uniprot_acc}")
67
+ return result
68
+ except Exception as e:
69
+ if "ModelRetry" in str(type(e)):
70
+ raise e
71
+ raise ModelRetry(f"Error looking up UniProt entry: {str(e)}")
72
+
73
+
74
+ def uniprot_mapping(
75
+ ctx: RunContext[UniprotConfig],
76
+ target_database: str,
77
+ uniprot_accs: List[str]
78
+ ) -> Dict:
79
+ """Perform a mapping of Uniprot accessions to another database.
80
+
81
+ Args:
82
+ ctx: The run context with access to the config
83
+ target_database: The target database (e.g., KEGG, PDB)
84
+ uniprot_accs: The Uniprot accessions
85
+
86
+ Returns:
87
+ A dictionary mapping UniProt accessions to entries in the target database
88
+ """
89
+ config = ctx.deps or get_config()
90
+ u = config.get_uniprot_client()
91
+
92
+ try:
93
+ if not uniprot_accs:
94
+ raise ModelRetry("No UniProt accessions provided for mapping")
95
+
96
+ normalized_accs = [normalize_uniprot_id(x) for x in uniprot_accs]
97
+ result = u.mapping("UniProtKB_AC-ID", target_database, ",".join(normalized_accs))
98
+
99
+ if not result:
100
+ raise ModelRetry(f"No mappings found for accessions to {target_database}")
101
+ return result
102
+ except Exception as e:
103
+ if "ModelRetry" in str(type(e)):
104
+ raise e
105
+ raise ModelRetry(f"Error mapping UniProt entries: {str(e)}")
106
+
107
+ def map_to_uniprot(ctx: RunContext[UniprotConfig], external_ids: List[str]) -> Dict:
108
+ """Map Uniprot accessions to UniProt IDs.
109
+
110
+ Args:
111
+ ctx: The run context with access to the config
112
+ external_ids: The external IDs, as prefixed IDs
113
+
114
+ Returns:
115
+ A dictionary mapping external IDs to UniProt IDs
116
+ """
117
+ config = ctx.deps or get_config()
118
+ u = config.get_uniprot_client()
119
+ results = {}
120
+ # split the external IDs by prefix
121
+ ids_by_prefix = {}
122
+ for external_id in external_ids:
123
+ prefix, id = external_id.split(":")
124
+ if prefix not in ids_by_prefix:
125
+ ids_by_prefix[prefix] = []
126
+ ids_by_prefix[prefix].append(id)
127
+ for prefix, ids in ids_by_prefix.items():
128
+ result = u.mapping(prefix, "UniProtKB_AC-ID", ",".join(ids))
129
+ if 'results' in result:
130
+ print(result)
131
+ uniprot_ids = [entry['to'] for entry in result['results']]
132
+ results[prefix] = uniprot_ids
133
+ else:
134
+ print("No mapping found.")
135
+ return results
136
+
File without changes
@@ -0,0 +1,27 @@
1
+ """
2
+ Configuration for the Web agent.
3
+ """
4
+ import os
5
+
6
+ from aurelian.dependencies.workdir import HasWorkdir, WorkDir
7
+
8
+
9
+ class WebDependencies(HasWorkdir):
10
+ """
11
+ Web agent dependencies that include a working directory.
12
+
13
+ This allows the agent to maintain state and access files on the local filesystem.
14
+ """
15
+ pass
16
+
17
+
18
+ def get_config() -> WebDependencies:
19
+ """Get a default configuration for the Web agent.
20
+
21
+ Returns:
22
+ WebDependencies object with default settings
23
+ """
24
+ workdir_path = os.environ.get("AURELIAN_WORKDIR", None)
25
+ workdir = WorkDir(location=workdir_path) if workdir_path else None
26
+
27
+ return WebDependencies(workdir=workdir)
@@ -0,0 +1,48 @@
1
+ """
2
+ Gradio UI for the Web agent.
3
+ """
4
+ from typing import List, Optional
5
+
6
+ import gradio as gr
7
+
8
+ from aurelian.dependencies.workdir import HasWorkdir
9
+ from aurelian.agents.web.web_mcp import mcp
10
+ from aurelian.utils.async_utils import run_sync
11
+
12
+
13
+ def chat(deps: Optional[HasWorkdir] = None, **kwargs):
14
+ """
15
+ Initialize a chat interface for the Web agent.
16
+
17
+ Args:
18
+ deps: Optional dependencies configuration
19
+ **kwargs: Additional arguments to pass to the agent
20
+
21
+ Returns:
22
+ A Gradio chat interface
23
+ """
24
+ if deps is None:
25
+ from aurelian.agents.web.web_mcp import deps as get_deps
26
+ deps = get_deps()
27
+
28
+ def get_info(query: str, history: List[str]) -> str:
29
+ print(f"QUERY: {query}")
30
+ print(f"HISTORY: {history}")
31
+ if history:
32
+ query += "## History"
33
+ for h in history:
34
+ query += f"\n{h}"
35
+ # Use MCP for the agent
36
+ result = run_sync(lambda: mcp.query(query))
37
+ return result
38
+
39
+ return gr.ChatInterface(
40
+ fn=get_info,
41
+ type="messages",
42
+ title="Web Search AI Assistant",
43
+ examples=[
44
+ ["Search for information about gene ontology"],
45
+ ["Find recent research papers on CRISPR"],
46
+ ["Look up information about linkML data modeling"]
47
+ ]
48
+ )
@@ -0,0 +1,50 @@
1
+ """
2
+ MCP tools for web search operations.
3
+ """
4
+ import os
5
+
6
+ from mcp.server.fastmcp import FastMCP
7
+
8
+ import aurelian.agents.web.web_tools as wt
9
+ from aurelian.dependencies.workdir import WorkDir, HasWorkdir
10
+ from pydantic_ai import RunContext
11
+
12
+ # Initialize FastMCP server
13
+ mcp = FastMCP("web", instructions="Web search operations")
14
+
15
+
16
+ def deps() -> HasWorkdir:
17
+ deps = HasWorkdir()
18
+ # Set the location from environment variable or default
19
+ loc = os.getenv("AURELIAN_WORKDIR", "/tmp/aurelian")
20
+ deps.workdir = WorkDir(loc)
21
+ return deps
22
+
23
+ def ctx() -> RunContext[HasWorkdir]:
24
+ rc: RunContext[HasWorkdir] = RunContext[HasWorkdir](
25
+ deps=deps(),
26
+ model=None, usage=None, prompt=None,
27
+ )
28
+ return rc
29
+
30
+
31
+ @mcp.tool()
32
+ async def search_web(query: str) -> str:
33
+ """
34
+ Search the web using a text query.
35
+
36
+ Note, this will not retrieve the full content, for that you
37
+ should use retrieve_web_page tool.
38
+
39
+ Args:
40
+ query: Text query
41
+
42
+ Returns:
43
+ Matching web pages plus summaries
44
+ """
45
+ return await wt.search_web(query)
46
+
47
+
48
+ if __name__ == "__main__":
49
+ # Initialize and run the server
50
+ mcp.run(transport='stdio')
@@ -0,0 +1,108 @@
1
+ from typing import List, Optional
2
+ import os
3
+ import xml.etree.ElementTree as ET
4
+ from pydantic import BaseModel, Field
5
+
6
+ from aurelian.utils.search_utils import web_search
7
+ from pydantic_ai import Agent
8
+ from pydantic_ai.models.openai import OpenAIModel
9
+
10
+
11
+ class Citation(BaseModel):
12
+ """Citation model for query results with citations."""
13
+
14
+ citation_number: str = Field(description="Citation number or identifier")
15
+ url: str = Field(description="URL source of the citation")
16
+ timestamp: Optional[str] = Field(
17
+ default=None, description="Timestamp of the citation, if available"
18
+ )
19
+
20
+
21
+ class ResultWithCitations(BaseModel):
22
+ """Generic result model for queries that return content with citations."""
23
+
24
+ content: str = Field(description="Content of the response")
25
+ citations: List[Citation] = Field(
26
+ default_factory=list, description="List of citations referenced in the content"
27
+ )
28
+
29
+
30
+ async def search_web(query: str) -> str:
31
+ """
32
+ Search the web using a text query.
33
+
34
+ Note, this will not retrieve the full content, for that you
35
+ should use `retrieve_web_page`.
36
+
37
+ Args:
38
+ query: Text query
39
+
40
+ Returns: matching web pages plus summaries
41
+ """
42
+ print(f"Web Search: {query}")
43
+ return web_search(query)
44
+
45
+
46
+ async def perplexity_query(query: str, model_name: str = "sonar") -> ResultWithCitations:
47
+ """
48
+ Query the Perplexity API and return structured results with citations.
49
+
50
+ Args:
51
+ query: The query to send to Perplexity
52
+ model_name: The Perplexity model to use (default: "sonar"). Options include "sonar", "sonar-pro", etc.
53
+
54
+ Returns:
55
+ ResultWithCitations: A structured response with content and citations
56
+
57
+ Raises:
58
+ ValueError: If the Perplexity API key is not set
59
+ RuntimeError: If the response parsing fails
60
+ """
61
+ perplexity_api_key = os.environ.get("PERPLEXITY_API_KEY")
62
+ if not perplexity_api_key:
63
+ raise ValueError("PERPLEXITY_API_KEY environment variable is not set")
64
+
65
+ sonar_model = OpenAIModel(
66
+ model_name=model_name,
67
+ base_url='https://api.perplexity.ai',
68
+ api_key=perplexity_api_key,
69
+ )
70
+
71
+ agent = Agent(sonar_model,
72
+ system_prompt=("Return the response with xml tags <answer> and <citations>,"
73
+ "where citations includes a list with the citation_number, url,"
74
+ " and timestamp for the retrieved citations"))
75
+ result = agent.run_sync(query)
76
+
77
+ try:
78
+ # Parse the XML response
79
+ xml_string = f"<root>{result.data}</root>"
80
+ root = ET.fromstring(xml_string)
81
+
82
+ # Extract answer content
83
+ answer_element = root.find("answer")
84
+ content = answer_element.text.strip() if answer_element is not None and answer_element.text else ""
85
+
86
+ # Extract citations
87
+ citations_list = []
88
+ citations_element = root.find("citations")
89
+ if citations_element is not None:
90
+ for citation in citations_element.findall(".//citation"):
91
+ citation_number = citation.find("citation_number")
92
+ if citation_number is None:
93
+ citation_number = citation.find("number")
94
+
95
+ url_element = citation.find("url")
96
+ timestamp_element = citation.find("timestamp")
97
+
98
+ citations_list.append(
99
+ Citation(
100
+ citation_number=citation_number.text if citation_number is not None and citation_number.text else "",
101
+ url=url_element.text if url_element is not None and url_element.text else "",
102
+ timestamp=timestamp_element.text if timestamp_element is not None and timestamp_element.text else None
103
+ )
104
+ )
105
+
106
+ return ResultWithCitations(content=content, citations=citations_list)
107
+ except ET.ParseError as e:
108
+ raise RuntimeError(f"Failed to parse Perplexity response: {e}")
aurelian/chat.py ADDED
@@ -0,0 +1,23 @@
1
+ from typing import Callable
2
+
3
+ from aurelian.utils.async_utils import run_sync
4
+
5
+
6
+ def get_chatbot(query_func: Callable, **kwargs):
7
+ import gradio as gr
8
+
9
+ def get_info(query: str, history: List[str]) -> str:
10
+ print(f"QUERY: {query}")
11
+ print(f"HISTORY: {history}")
12
+ if history:
13
+ query += "## History"
14
+ for h in history:
15
+ query += f"\n{h}"
16
+ result = run_sync(query_func)
17
+ return result.data
18
+
19
+ return gr.ChatInterface(
20
+ fn=get_info,
21
+ type="messages",
22
+ **kwargs,
23
+ )