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.
- aurelian/__init__.py +9 -0
- aurelian/agents/__init__.py +0 -0
- aurelian/agents/amigo/__init__.py +3 -0
- aurelian/agents/amigo/amigo_agent.py +77 -0
- aurelian/agents/amigo/amigo_config.py +85 -0
- aurelian/agents/amigo/amigo_evals.py +73 -0
- aurelian/agents/amigo/amigo_gradio.py +52 -0
- aurelian/agents/amigo/amigo_mcp.py +152 -0
- aurelian/agents/amigo/amigo_tools.py +152 -0
- aurelian/agents/biblio/__init__.py +42 -0
- aurelian/agents/biblio/biblio_agent.py +94 -0
- aurelian/agents/biblio/biblio_config.py +40 -0
- aurelian/agents/biblio/biblio_gradio.py +67 -0
- aurelian/agents/biblio/biblio_mcp.py +115 -0
- aurelian/agents/biblio/biblio_tools.py +164 -0
- aurelian/agents/biblio_agent.py +46 -0
- aurelian/agents/checklist/__init__.py +44 -0
- aurelian/agents/checklist/checklist_agent.py +85 -0
- aurelian/agents/checklist/checklist_config.py +28 -0
- aurelian/agents/checklist/checklist_gradio.py +70 -0
- aurelian/agents/checklist/checklist_mcp.py +86 -0
- aurelian/agents/checklist/checklist_tools.py +141 -0
- aurelian/agents/checklist/content/checklists.yaml +7 -0
- aurelian/agents/checklist/content/streams.csv +136 -0
- aurelian/agents/checklist_agent.py +40 -0
- aurelian/agents/chemistry/__init__.py +3 -0
- aurelian/agents/chemistry/chemistry_agent.py +46 -0
- aurelian/agents/chemistry/chemistry_config.py +71 -0
- aurelian/agents/chemistry/chemistry_evals.py +79 -0
- aurelian/agents/chemistry/chemistry_gradio.py +50 -0
- aurelian/agents/chemistry/chemistry_mcp.py +120 -0
- aurelian/agents/chemistry/chemistry_tools.py +121 -0
- aurelian/agents/chemistry/image_agent.py +15 -0
- aurelian/agents/d4d/__init__.py +30 -0
- aurelian/agents/d4d/d4d_agent.py +72 -0
- aurelian/agents/d4d/d4d_config.py +46 -0
- aurelian/agents/d4d/d4d_gradio.py +58 -0
- aurelian/agents/d4d/d4d_mcp.py +71 -0
- aurelian/agents/d4d/d4d_tools.py +157 -0
- aurelian/agents/d4d_agent.py +64 -0
- aurelian/agents/diagnosis/__init__.py +33 -0
- aurelian/agents/diagnosis/diagnosis_agent.py +53 -0
- aurelian/agents/diagnosis/diagnosis_config.py +48 -0
- aurelian/agents/diagnosis/diagnosis_evals.py +76 -0
- aurelian/agents/diagnosis/diagnosis_gradio.py +52 -0
- aurelian/agents/diagnosis/diagnosis_mcp.py +141 -0
- aurelian/agents/diagnosis/diagnosis_tools.py +204 -0
- aurelian/agents/diagnosis_agent.py +28 -0
- aurelian/agents/draw/__init__.py +3 -0
- aurelian/agents/draw/draw_agent.py +39 -0
- aurelian/agents/draw/draw_config.py +26 -0
- aurelian/agents/draw/draw_gradio.py +50 -0
- aurelian/agents/draw/draw_mcp.py +94 -0
- aurelian/agents/draw/draw_tools.py +100 -0
- aurelian/agents/draw/judge_agent.py +18 -0
- aurelian/agents/filesystem/__init__.py +0 -0
- aurelian/agents/filesystem/filesystem_config.py +27 -0
- aurelian/agents/filesystem/filesystem_gradio.py +49 -0
- aurelian/agents/filesystem/filesystem_mcp.py +89 -0
- aurelian/agents/filesystem/filesystem_tools.py +95 -0
- aurelian/agents/filesystem/py.typed +0 -0
- aurelian/agents/github/__init__.py +0 -0
- aurelian/agents/github/github_agent.py +83 -0
- aurelian/agents/github/github_cli.py +248 -0
- aurelian/agents/github/github_config.py +22 -0
- aurelian/agents/github/github_gradio.py +152 -0
- aurelian/agents/github/github_mcp.py +252 -0
- aurelian/agents/github/github_tools.py +408 -0
- aurelian/agents/github/github_tools.py.tmp +413 -0
- aurelian/agents/goann/__init__.py +13 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.md +1000 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines.pdf +0 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.md +693 -0
- aurelian/agents/goann/documents/Transcription_Factors_Annotation_Guidelines_Paper.pdf +0 -0
- aurelian/agents/goann/goann_agent.py +90 -0
- aurelian/agents/goann/goann_config.py +90 -0
- aurelian/agents/goann/goann_evals.py +104 -0
- aurelian/agents/goann/goann_gradio.py +62 -0
- aurelian/agents/goann/goann_mcp.py +0 -0
- aurelian/agents/goann/goann_tools.py +65 -0
- aurelian/agents/gocam/__init__.py +43 -0
- aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.docx +0 -0
- aurelian/agents/gocam/documents/DNA-binding transcription factor activity annotation guidelines.pdf +0 -0
- aurelian/agents/gocam/documents/DNA-binding_transcription_factor_activity_annotation_guidelines.md +100 -0
- aurelian/agents/gocam/documents/E3 ubiquitin ligases.docx +0 -0
- aurelian/agents/gocam/documents/E3 ubiquitin ligases.pdf +0 -0
- aurelian/agents/gocam/documents/E3_ubiquitin_ligases.md +134 -0
- aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.docx +0 -0
- aurelian/agents/gocam/documents/GO-CAM annotation guidelines README.pdf +0 -0
- aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.docx +0 -0
- aurelian/agents/gocam/documents/GO-CAM modelling guidelines TO DO.pdf +0 -0
- aurelian/agents/gocam/documents/GO-CAM_annotation_guidelines_README.md +1 -0
- aurelian/agents/gocam/documents/GO-CAM_modelling_guidelines_TO_DO.md +3 -0
- aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.docx +0 -0
- aurelian/agents/gocam/documents/How to annotate complexes in GO-CAM.pdf +0 -0
- aurelian/agents/gocam/documents/How to annotate molecular adaptors.docx +0 -0
- aurelian/agents/gocam/documents/How to annotate molecular adaptors.pdf +0 -0
- aurelian/agents/gocam/documents/How to annotate sequestering proteins.docx +0 -0
- aurelian/agents/gocam/documents/How to annotate sequestering proteins.pdf +0 -0
- aurelian/agents/gocam/documents/How_to_annotate_complexes_in_GO-CAM.md +29 -0
- aurelian/agents/gocam/documents/How_to_annotate_molecular_adaptors.md +31 -0
- aurelian/agents/gocam/documents/How_to_annotate_sequestering_proteins.md +42 -0
- aurelian/agents/gocam/documents/Molecular adaptor activity.docx +0 -0
- aurelian/agents/gocam/documents/Molecular adaptor activity.pdf +0 -0
- aurelian/agents/gocam/documents/Molecular carrier activity.docx +0 -0
- aurelian/agents/gocam/documents/Molecular carrier activity.pdf +0 -0
- aurelian/agents/gocam/documents/Molecular_adaptor_activity.md +51 -0
- aurelian/agents/gocam/documents/Molecular_carrier_activity.md +41 -0
- aurelian/agents/gocam/documents/Protein sequestering activity.docx +0 -0
- aurelian/agents/gocam/documents/Protein sequestering activity.pdf +0 -0
- aurelian/agents/gocam/documents/Protein_sequestering_activity.md +50 -0
- aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.docx +0 -0
- aurelian/agents/gocam/documents/Signaling receptor activity annotation guidelines.pdf +0 -0
- aurelian/agents/gocam/documents/Signaling_receptor_activity_annotation_guidelines.md +187 -0
- aurelian/agents/gocam/documents/Transcription coregulator activity.docx +0 -0
- aurelian/agents/gocam/documents/Transcription coregulator activity.pdf +0 -0
- aurelian/agents/gocam/documents/Transcription_coregulator_activity.md +36 -0
- aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.docx +0 -0
- aurelian/agents/gocam/documents/Transporter activity annotation annotation guidelines.pdf +0 -0
- aurelian/agents/gocam/documents/Transporter_activity_annotation_annotation_guidelines.md +43 -0
- Regulatory Processes in GO-CAM.docx +0 -0
- Regulatory Processes in GO-CAM.pdf +0 -0
- aurelian/agents/gocam/documents/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +31 -0
- aurelian/agents/gocam/documents/md/DNA-binding_transcription_factor_activity_annotation_guidelines.md +131 -0
- aurelian/agents/gocam/documents/md/E3_ubiquitin_ligases.md +166 -0
- aurelian/agents/gocam/documents/md/GO-CAM_annotation_guidelines_README.md +1 -0
- aurelian/agents/gocam/documents/md/GO-CAM_modelling_guidelines_TO_DO.md +5 -0
- aurelian/agents/gocam/documents/md/How_to_annotate_complexes_in_GO-CAM.md +28 -0
- aurelian/agents/gocam/documents/md/How_to_annotate_molecular_adaptors.md +19 -0
- aurelian/agents/gocam/documents/md/How_to_annotate_sequestering_proteins.md +38 -0
- aurelian/agents/gocam/documents/md/Molecular_adaptor_activity.md +52 -0
- aurelian/agents/gocam/documents/md/Molecular_carrier_activity.md +59 -0
- aurelian/agents/gocam/documents/md/Protein_sequestering_activity.md +52 -0
- aurelian/agents/gocam/documents/md/Signaling_receptor_activity_annotation_guidelines.md +271 -0
- aurelian/agents/gocam/documents/md/Transcription_coregulator_activity.md +54 -0
- aurelian/agents/gocam/documents/md/Transporter_activity_annotation_annotation_guidelines.md +38 -0
- aurelian/agents/gocam/documents/md/WIP_-_Regulation_and_Regulatory_Processes_in_GO-CAM.md +39 -0
- aurelian/agents/gocam/documents/pandoc_md/Signaling_receptor_activity_annotation_guidelines.md +334 -0
- aurelian/agents/gocam/gocam_agent.py +240 -0
- aurelian/agents/gocam/gocam_config.py +85 -0
- aurelian/agents/gocam/gocam_curator_agent.py +46 -0
- aurelian/agents/gocam/gocam_evals.py +67 -0
- aurelian/agents/gocam/gocam_gradio.py +89 -0
- aurelian/agents/gocam/gocam_mcp.py +224 -0
- aurelian/agents/gocam/gocam_tools.py +294 -0
- aurelian/agents/linkml/__init__.py +0 -0
- aurelian/agents/linkml/linkml_agent.py +62 -0
- aurelian/agents/linkml/linkml_config.py +48 -0
- aurelian/agents/linkml/linkml_evals.py +66 -0
- aurelian/agents/linkml/linkml_gradio.py +45 -0
- aurelian/agents/linkml/linkml_mcp.py +186 -0
- aurelian/agents/linkml/linkml_tools.py +102 -0
- aurelian/agents/literature/__init__.py +3 -0
- aurelian/agents/literature/literature_agent.py +55 -0
- aurelian/agents/literature/literature_config.py +35 -0
- aurelian/agents/literature/literature_gradio.py +52 -0
- aurelian/agents/literature/literature_mcp.py +174 -0
- aurelian/agents/literature/literature_tools.py +182 -0
- aurelian/agents/monarch/__init__.py +25 -0
- aurelian/agents/monarch/monarch_agent.py +44 -0
- aurelian/agents/monarch/monarch_config.py +45 -0
- aurelian/agents/monarch/monarch_gradio.py +51 -0
- aurelian/agents/monarch/monarch_mcp.py +65 -0
- aurelian/agents/monarch/monarch_tools.py +113 -0
- aurelian/agents/oak/__init__.py +0 -0
- aurelian/agents/oak/oak_config.py +27 -0
- aurelian/agents/oak/oak_gradio.py +57 -0
- aurelian/agents/ontology_mapper/__init__.py +31 -0
- aurelian/agents/ontology_mapper/ontology_mapper_agent.py +56 -0
- aurelian/agents/ontology_mapper/ontology_mapper_config.py +50 -0
- aurelian/agents/ontology_mapper/ontology_mapper_evals.py +108 -0
- aurelian/agents/ontology_mapper/ontology_mapper_gradio.py +58 -0
- aurelian/agents/ontology_mapper/ontology_mapper_mcp.py +81 -0
- aurelian/agents/ontology_mapper/ontology_mapper_tools.py +147 -0
- aurelian/agents/phenopackets/__init__.py +3 -0
- aurelian/agents/phenopackets/phenopackets_agent.py +58 -0
- aurelian/agents/phenopackets/phenopackets_config.py +72 -0
- aurelian/agents/phenopackets/phenopackets_evals.py +99 -0
- aurelian/agents/phenopackets/phenopackets_gradio.py +55 -0
- aurelian/agents/phenopackets/phenopackets_mcp.py +178 -0
- aurelian/agents/phenopackets/phenopackets_tools.py +127 -0
- aurelian/agents/rag/__init__.py +40 -0
- aurelian/agents/rag/rag_agent.py +83 -0
- aurelian/agents/rag/rag_config.py +80 -0
- aurelian/agents/rag/rag_gradio.py +67 -0
- aurelian/agents/rag/rag_mcp.py +107 -0
- aurelian/agents/rag/rag_tools.py +189 -0
- aurelian/agents/rag_agent.py +54 -0
- aurelian/agents/robot/__init__.py +0 -0
- aurelian/agents/robot/assets/__init__.py +3 -0
- aurelian/agents/robot/assets/template.md +384 -0
- aurelian/agents/robot/robot_config.py +25 -0
- aurelian/agents/robot/robot_gradio.py +46 -0
- aurelian/agents/robot/robot_mcp.py +100 -0
- aurelian/agents/robot/robot_ontology_agent.py +139 -0
- aurelian/agents/robot/robot_tools.py +50 -0
- aurelian/agents/talisman/__init__.py +3 -0
- aurelian/agents/talisman/talisman_agent.py +126 -0
- aurelian/agents/talisman/talisman_config.py +66 -0
- aurelian/agents/talisman/talisman_gradio.py +50 -0
- aurelian/agents/talisman/talisman_mcp.py +168 -0
- aurelian/agents/talisman/talisman_tools.py +720 -0
- aurelian/agents/ubergraph/__init__.py +40 -0
- aurelian/agents/ubergraph/ubergraph_agent.py +71 -0
- aurelian/agents/ubergraph/ubergraph_config.py +79 -0
- aurelian/agents/ubergraph/ubergraph_gradio.py +48 -0
- aurelian/agents/ubergraph/ubergraph_mcp.py +69 -0
- aurelian/agents/ubergraph/ubergraph_tools.py +118 -0
- aurelian/agents/uniprot/__init__.py +37 -0
- aurelian/agents/uniprot/uniprot_agent.py +43 -0
- aurelian/agents/uniprot/uniprot_config.py +43 -0
- aurelian/agents/uniprot/uniprot_evals.py +99 -0
- aurelian/agents/uniprot/uniprot_gradio.py +48 -0
- aurelian/agents/uniprot/uniprot_mcp.py +168 -0
- aurelian/agents/uniprot/uniprot_tools.py +136 -0
- aurelian/agents/web/__init__.py +0 -0
- aurelian/agents/web/web_config.py +27 -0
- aurelian/agents/web/web_gradio.py +48 -0
- aurelian/agents/web/web_mcp.py +50 -0
- aurelian/agents/web/web_tools.py +108 -0
- aurelian/chat.py +23 -0
- aurelian/cli.py +800 -0
- aurelian/dependencies/__init__.py +0 -0
- aurelian/dependencies/workdir.py +78 -0
- aurelian/mcp/__init__.py +0 -0
- aurelian/mcp/amigo_mcp_test.py +86 -0
- aurelian/mcp/config_generator.py +123 -0
- aurelian/mcp/example_config.json +43 -0
- aurelian/mcp/generate_sample_config.py +37 -0
- aurelian/mcp/gocam_mcp_test.py +126 -0
- aurelian/mcp/linkml_mcp_tools.py +190 -0
- aurelian/mcp/mcp_discovery.py +87 -0
- aurelian/mcp/mcp_test.py +31 -0
- aurelian/mcp/phenopackets_mcp_test.py +103 -0
- aurelian/tools/__init__.py +0 -0
- aurelian/tools/web/__init__.py +0 -0
- aurelian/tools/web/url_download.py +51 -0
- aurelian/utils/__init__.py +0 -0
- aurelian/utils/async_utils.py +15 -0
- aurelian/utils/data_utils.py +32 -0
- aurelian/utils/documentation_manager.py +59 -0
- aurelian/utils/doi_fetcher.py +238 -0
- aurelian/utils/ontology_utils.py +68 -0
- aurelian/utils/pdf_fetcher.py +23 -0
- aurelian/utils/process_logs.py +100 -0
- aurelian/utils/pubmed_utils.py +238 -0
- aurelian/utils/pytest_report_to_markdown.py +67 -0
- aurelian/utils/robot_ontology_utils.py +112 -0
- aurelian/utils/search_utils.py +95 -0
- aurelian-0.3.2.dist-info/LICENSE +22 -0
- aurelian-0.3.2.dist-info/METADATA +105 -0
- aurelian-0.3.2.dist-info/RECORD +254 -0
- aurelian-0.3.2.dist-info/WHEEL +4 -0
- aurelian-0.3.2.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,204 @@
|
|
1
|
+
"""
|
2
|
+
Tools for the Diagnosis agent.
|
3
|
+
"""
|
4
|
+
import asyncio
|
5
|
+
from functools import lru_cache
|
6
|
+
from typing import Dict, List, Optional
|
7
|
+
|
8
|
+
from oaklib import get_adapter
|
9
|
+
from pydantic_ai import RunContext, ModelRetry
|
10
|
+
|
11
|
+
from aurelian.utils.data_utils import obj_to_dict
|
12
|
+
from aurelian.utils.ontology_utils import search_ontology
|
13
|
+
from aurelian.utils.search_utils import web_search, retrieve_web_page as fetch_web_page
|
14
|
+
from .diagnosis_config import DiagnosisDependencies, get_config, HAS_PHENOTYPE
|
15
|
+
|
16
|
+
|
17
|
+
@lru_cache
|
18
|
+
def get_mondo_adapter():
|
19
|
+
"""
|
20
|
+
Get the MONDO ontology adapter.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
The MONDO ontology adapter from OAK
|
24
|
+
"""
|
25
|
+
return get_adapter("sqlite:obo:mondo")
|
26
|
+
|
27
|
+
|
28
|
+
async def find_disease_id(
|
29
|
+
ctx: RunContext[DiagnosisDependencies],
|
30
|
+
query: str
|
31
|
+
) -> List[Dict]:
|
32
|
+
"""
|
33
|
+
Finds the disease ID for a given search term.
|
34
|
+
|
35
|
+
OAK search term syntax is used; the default strategy is to match
|
36
|
+
labels:
|
37
|
+
|
38
|
+
```
|
39
|
+
find_disease_id("Dravet syndrome")
|
40
|
+
```
|
41
|
+
|
42
|
+
You can use OAK expressions, e.g, all labels
|
43
|
+
that start with "Peroxisomal biogenesis disorder":
|
44
|
+
|
45
|
+
```
|
46
|
+
find_disease_id("l^Peroxisomal biogenesis disorder")
|
47
|
+
```
|
48
|
+
|
49
|
+
Args:
|
50
|
+
ctx: The run context
|
51
|
+
query: The label search term to use
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
List of matching disease IDs and names
|
55
|
+
"""
|
56
|
+
print(f"Disease Search: {query}")
|
57
|
+
|
58
|
+
try:
|
59
|
+
config = ctx.deps or get_config()
|
60
|
+
adapter = get_mondo_adapter()
|
61
|
+
|
62
|
+
# Execute the potentially blocking operation in a thread pool
|
63
|
+
results = await asyncio.to_thread(
|
64
|
+
search_ontology,
|
65
|
+
adapter,
|
66
|
+
query,
|
67
|
+
limit=config.max_search_results
|
68
|
+
)
|
69
|
+
|
70
|
+
if not results:
|
71
|
+
print(f"No results for query: {query} using {adapter}")
|
72
|
+
raise ModelRetry(
|
73
|
+
f"No disease IDs found for query: {query}. Try a different search term."
|
74
|
+
)
|
75
|
+
print(f"Got {len(results)} results for {query}")
|
76
|
+
|
77
|
+
return results
|
78
|
+
except Exception as e:
|
79
|
+
if "ModelRetry" in str(type(e)):
|
80
|
+
raise e
|
81
|
+
raise ModelRetry(f"Error finding disease ID: {str(e)}")
|
82
|
+
|
83
|
+
|
84
|
+
async def find_disease_phenotypes(
|
85
|
+
ctx: RunContext[DiagnosisDependencies],
|
86
|
+
query: str
|
87
|
+
) -> List[Dict]:
|
88
|
+
"""
|
89
|
+
Finds the phenotypes for a disease ID.
|
90
|
+
|
91
|
+
Example:
|
92
|
+
|
93
|
+
```
|
94
|
+
find_disease_phenotypes("MONDO:0007947")
|
95
|
+
```
|
96
|
+
|
97
|
+
Args:
|
98
|
+
ctx: The run context
|
99
|
+
query: The disease ID to search for (should be an ID but can be a name)
|
100
|
+
|
101
|
+
Returns:
|
102
|
+
List of phenotypes for the disease
|
103
|
+
"""
|
104
|
+
print(f"Phenotype query: {query}")
|
105
|
+
|
106
|
+
try:
|
107
|
+
config = ctx.deps or get_config()
|
108
|
+
|
109
|
+
# Determine if we have a disease ID or need to search for one
|
110
|
+
if ":" in query:
|
111
|
+
query_ids = [query]
|
112
|
+
else:
|
113
|
+
# Find the disease ID from the name
|
114
|
+
disease_results = await find_disease_id(ctx, query)
|
115
|
+
if not disease_results:
|
116
|
+
raise ModelRetry(f"Could not find disease for query: {query}")
|
117
|
+
|
118
|
+
# Extract just the IDs from the results
|
119
|
+
query_ids = [result.get("id") for result in disease_results if "id" in result]
|
120
|
+
if not query_ids:
|
121
|
+
raise ModelRetry(f"Could not find valid disease IDs for query: {query}")
|
122
|
+
|
123
|
+
# Get the phenotype associations
|
124
|
+
monarch_adapter = config.monarch_adapter
|
125
|
+
|
126
|
+
# Execute the potentially blocking operation in a thread pool
|
127
|
+
assocs = await asyncio.to_thread(
|
128
|
+
monarch_adapter.associations,
|
129
|
+
subjects=query_ids,
|
130
|
+
predicates=[HAS_PHENOTYPE]
|
131
|
+
)
|
132
|
+
|
133
|
+
# Convert to dictionaries
|
134
|
+
results = []
|
135
|
+
for assoc in assocs:
|
136
|
+
dict_assoc = await asyncio.to_thread(obj_to_dict, assoc)
|
137
|
+
results.append(dict_assoc)
|
138
|
+
|
139
|
+
if not results:
|
140
|
+
disease_label = query
|
141
|
+
if query_ids and query_ids[0] != query:
|
142
|
+
disease_label = f"{query} ({query_ids[0]})"
|
143
|
+
raise ModelRetry(f"No phenotypes found for disease: {disease_label}")
|
144
|
+
|
145
|
+
print(f"Results[{query_ids}]: {results}")
|
146
|
+
return results
|
147
|
+
except Exception as e:
|
148
|
+
if "ModelRetry" in str(type(e)):
|
149
|
+
raise e
|
150
|
+
raise ModelRetry(f"Error finding disease phenotypes: {str(e)}")
|
151
|
+
|
152
|
+
|
153
|
+
async def search_web(query: str) -> str:
|
154
|
+
"""
|
155
|
+
Search the web using a text query.
|
156
|
+
|
157
|
+
Note: This will not retrieve the full content. For that, use `retrieve_web_page`.
|
158
|
+
|
159
|
+
Args:
|
160
|
+
query: The search query
|
161
|
+
|
162
|
+
Returns:
|
163
|
+
Matching web pages plus summaries
|
164
|
+
"""
|
165
|
+
print(f"Web Search: {query}")
|
166
|
+
|
167
|
+
try:
|
168
|
+
# Execute the potentially blocking operation in a thread pool
|
169
|
+
results = await asyncio.to_thread(web_search, query)
|
170
|
+
|
171
|
+
if not results or results.strip() == "":
|
172
|
+
raise ModelRetry(f"No web search results found for query: {query}")
|
173
|
+
|
174
|
+
return results
|
175
|
+
except Exception as e:
|
176
|
+
if "ModelRetry" in str(type(e)):
|
177
|
+
raise e
|
178
|
+
raise ModelRetry(f"Error searching the web: {str(e)}")
|
179
|
+
|
180
|
+
|
181
|
+
async def retrieve_web_page(url: str) -> str:
|
182
|
+
"""
|
183
|
+
Fetch the contents of a web page.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
url: The URL of the web page to retrieve
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
The contents of the web page
|
190
|
+
"""
|
191
|
+
print(f"Fetch URL: {url}")
|
192
|
+
|
193
|
+
try:
|
194
|
+
# Execute the potentially blocking operation in a thread pool
|
195
|
+
content = await asyncio.to_thread(fetch_web_page, url)
|
196
|
+
|
197
|
+
if not content or content.strip() == "":
|
198
|
+
raise ModelRetry(f"No content found at URL: {url}")
|
199
|
+
|
200
|
+
return content
|
201
|
+
except Exception as e:
|
202
|
+
if "ModelRetry" in str(type(e)):
|
203
|
+
raise e
|
204
|
+
raise ModelRetry(f"Error retrieving web page: {str(e)}")
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"""
|
2
|
+
Agent for performing diagnoses, validated against Monarch KG - DEPRECATED
|
3
|
+
|
4
|
+
This module is maintained for backward compatibility.
|
5
|
+
Please use aurelian.agents.diagnosis.diagnosis_agent instead.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from aurelian.agents.diagnosis.diagnosis_agent import diagnosis_agent
|
9
|
+
from aurelian.agents.diagnosis.diagnosis_config import DiagnosisDependencies, get_config
|
10
|
+
from aurelian.agents.diagnosis.diagnosis_gradio import chat
|
11
|
+
from aurelian.agents.diagnosis.diagnosis_tools import (
|
12
|
+
find_disease_id,
|
13
|
+
find_disease_phenotypes,
|
14
|
+
search_web,
|
15
|
+
retrieve_web_page,
|
16
|
+
get_mondo_adapter,
|
17
|
+
)
|
18
|
+
|
19
|
+
__all__ = [
|
20
|
+
"diagnosis_agent",
|
21
|
+
"DiagnosisDependencies",
|
22
|
+
"chat",
|
23
|
+
"find_disease_id",
|
24
|
+
"find_disease_phenotypes",
|
25
|
+
"search_web",
|
26
|
+
"retrieve_web_page",
|
27
|
+
"get_mondo_adapter",
|
28
|
+
]
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""
|
2
|
+
Agent for creating SVG drawings based on text descriptions.
|
3
|
+
"""
|
4
|
+
from pydantic import BaseModel
|
5
|
+
|
6
|
+
from aurelian.agents.draw.draw_config import DrawDependencies
|
7
|
+
from aurelian.agents.draw.draw_tools import (
|
8
|
+
judge_drawing, DrawingFeedback
|
9
|
+
)
|
10
|
+
from pydantic_ai import Agent, Tool
|
11
|
+
|
12
|
+
SYSTEM = """
|
13
|
+
You are an expert scientific artist specializing in creating clear illustrations and figures.
|
14
|
+
|
15
|
+
When creating SVG drawings:
|
16
|
+
1. Focus on clarity and simplicity over excessive detail
|
17
|
+
2. Use appropriate shapes, lines, and basic colors
|
18
|
+
3. Ensure the drawing is recognizable and representative of the description
|
19
|
+
4. Use valid SVG syntax with width and height attributes
|
20
|
+
|
21
|
+
ALWAYS `judge_drawing` to get feedback on your drawings, iterate on them, and improve clarity.
|
22
|
+
Even if you think you have the correct drawing, you MUST call this AT LEAST once to get a second
|
23
|
+
opinion and to make sure it renders OK.
|
24
|
+
"""
|
25
|
+
|
26
|
+
class SVGDrawing(BaseModel):
|
27
|
+
svg_content: str
|
28
|
+
legend: str
|
29
|
+
feedback: DrawingFeedback
|
30
|
+
|
31
|
+
draw_agent = Agent(
|
32
|
+
model="openai:gpt-4o",
|
33
|
+
deps_type=DrawDependencies,
|
34
|
+
system_prompt=SYSTEM,
|
35
|
+
result_type=SVGDrawing,
|
36
|
+
tools=[
|
37
|
+
Tool(judge_drawing),
|
38
|
+
]
|
39
|
+
)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
"""
|
2
|
+
Configuration classes for the draw agent.
|
3
|
+
"""
|
4
|
+
from dataclasses import dataclass
|
5
|
+
from typing import Optional
|
6
|
+
|
7
|
+
from aurelian.dependencies.workdir import HasWorkdir
|
8
|
+
|
9
|
+
|
10
|
+
@dataclass
|
11
|
+
class DrawDependencies(HasWorkdir):
|
12
|
+
"""
|
13
|
+
Configuration for the draw agent.
|
14
|
+
"""
|
15
|
+
max_svg_size: int = 1024 * 1024 # 1MB max SVG size
|
16
|
+
judge_feedback: bool = True # Whether to get judge feedback
|
17
|
+
|
18
|
+
|
19
|
+
def get_config() -> DrawDependencies:
|
20
|
+
"""
|
21
|
+
Get the Draw agent configuration.
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
DrawDependencies: The draw dependencies
|
25
|
+
"""
|
26
|
+
return DrawDependencies()
|
@@ -0,0 +1,50 @@
|
|
1
|
+
"""
|
2
|
+
Gradio UI for the draw agent.
|
3
|
+
"""
|
4
|
+
from typing import List, Optional
|
5
|
+
|
6
|
+
import gradio as gr
|
7
|
+
|
8
|
+
from aurelian.agents.draw.draw_agent import draw_agent
|
9
|
+
from aurelian.agents.draw.draw_config import DrawDependencies
|
10
|
+
from aurelian.utils.async_utils import run_sync
|
11
|
+
|
12
|
+
|
13
|
+
def chat(deps: Optional[DrawDependencies] = None, workdir: str = None, **kwargs):
|
14
|
+
"""
|
15
|
+
Initialize a chat interface for the draw 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 = DrawDependencies()
|
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: draw_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="Drawing AI Assistant",
|
45
|
+
examples=[
|
46
|
+
["Draw a simple cat face"],
|
47
|
+
["Create an SVG of a tree with birds"],
|
48
|
+
["Draw a basic house with a chimney"]
|
49
|
+
]
|
50
|
+
)
|
@@ -0,0 +1,94 @@
|
|
1
|
+
"""
|
2
|
+
MCP tools for creating SVG drawings.
|
3
|
+
"""
|
4
|
+
import os
|
5
|
+
from typing import Dict, List
|
6
|
+
|
7
|
+
from mcp.server.fastmcp import FastMCP
|
8
|
+
|
9
|
+
import aurelian.agents.draw.draw_tools as dt
|
10
|
+
from aurelian.agents.draw.draw_agent import SYSTEM
|
11
|
+
from aurelian.agents.draw.draw_config import DrawDependencies
|
12
|
+
from pydantic_ai import RunContext
|
13
|
+
|
14
|
+
# Initialize FastMCP server
|
15
|
+
mcp = FastMCP("draw", instructions=SYSTEM)
|
16
|
+
|
17
|
+
|
18
|
+
from aurelian.dependencies.workdir import WorkDir
|
19
|
+
|
20
|
+
def deps() -> DrawDependencies:
|
21
|
+
deps = DrawDependencies()
|
22
|
+
# Set the location from environment variable or default
|
23
|
+
loc = os.getenv("AURELIAN_WORKDIR", "/tmp/aurelian")
|
24
|
+
deps.workdir = WorkDir(loc)
|
25
|
+
return deps
|
26
|
+
|
27
|
+
def ctx() -> RunContext[DrawDependencies]:
|
28
|
+
rc: RunContext[DrawDependencies] = RunContext[DrawDependencies](
|
29
|
+
deps=deps(),
|
30
|
+
model=None, usage=None, prompt=None,
|
31
|
+
)
|
32
|
+
return rc
|
33
|
+
|
34
|
+
|
35
|
+
@mcp.tool()
|
36
|
+
async def create_svg_drawing(description: str) -> str:
|
37
|
+
"""
|
38
|
+
Create an SVG drawing based on a text description.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
description: Detailed description of what to draw
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
SVG markup of the drawing
|
45
|
+
"""
|
46
|
+
return await dt.create_svg_drawing(ctx(), description)
|
47
|
+
|
48
|
+
|
49
|
+
@mcp.tool()
|
50
|
+
async def convert_svg_to_png(svg_content: str) -> bytes:
|
51
|
+
"""
|
52
|
+
Convert SVG content to PNG image.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
svg_content: SVG markup as a string
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
PNG image data as bytes
|
59
|
+
"""
|
60
|
+
return await dt.convert_svg_to_png(ctx(), svg_content)
|
61
|
+
|
62
|
+
|
63
|
+
@mcp.tool()
|
64
|
+
async def svg_to_data_url(svg_content: str) -> str:
|
65
|
+
"""
|
66
|
+
Convert SVG content to a data URL for embedding in HTML.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
svg_content: SVG markup as a string
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
Data URL representation of the SVG
|
73
|
+
"""
|
74
|
+
return await dt.svg_to_data_url(ctx(), svg_content)
|
75
|
+
|
76
|
+
|
77
|
+
@mcp.tool()
|
78
|
+
async def judge_drawing(svg_content: str, description: str) -> str:
|
79
|
+
"""
|
80
|
+
Judge the quality of an SVG drawing based on the description.
|
81
|
+
|
82
|
+
Args:
|
83
|
+
svg_content: SVG markup as a string
|
84
|
+
description: The original description of what to draw
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
Feedback on the drawing's clarity and simplicity
|
88
|
+
"""
|
89
|
+
return await dt.judge_drawing(ctx(), svg_content, description)
|
90
|
+
|
91
|
+
|
92
|
+
if __name__ == "__main__":
|
93
|
+
# Initialize and run the server
|
94
|
+
mcp.run(transport='stdio')
|
@@ -0,0 +1,100 @@
|
|
1
|
+
"""
|
2
|
+
Tools for the draw agent.
|
3
|
+
"""
|
4
|
+
import base64
|
5
|
+
from typing import Optional
|
6
|
+
import cairosvg
|
7
|
+
from pydantic import BaseModel
|
8
|
+
|
9
|
+
from pydantic_ai import RunContext, BinaryContent, ModelRetry
|
10
|
+
|
11
|
+
from aurelian.agents.draw.draw_config import DrawDependencies
|
12
|
+
|
13
|
+
|
14
|
+
class DrawingFeedback(BaseModel):
|
15
|
+
"""
|
16
|
+
Feedback on the drawing's clarity and simplicity.
|
17
|
+
"""
|
18
|
+
feedback: str
|
19
|
+
necessary_changes: Optional[str] = None
|
20
|
+
optional_changes: Optional[str] = None
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
async def convert_svg_to_png(ctx: RunContext[DrawDependencies], svg_content: str) -> bytes:
|
26
|
+
"""
|
27
|
+
Convert SVG content to PNG image.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
ctx: The run context
|
31
|
+
svg_content: SVG markup as a string
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
bytes: PNG image data
|
35
|
+
"""
|
36
|
+
print("Converting SVG to PNG")
|
37
|
+
|
38
|
+
# Check size limits
|
39
|
+
if len(svg_content.encode('utf-8')) > ctx.deps.max_svg_size:
|
40
|
+
raise ValueError(f"SVG content exceeds maximum size of {ctx.deps.max_svg_size} bytes")
|
41
|
+
|
42
|
+
# Convert SVG to PNG using cairosvg
|
43
|
+
png_bytes = cairosvg.svg2png(bytestring=svg_content.encode('utf-8'))
|
44
|
+
return png_bytes
|
45
|
+
|
46
|
+
|
47
|
+
async def svg_to_data_url(ctx: RunContext[DrawDependencies], svg_content: str) -> str:
|
48
|
+
"""
|
49
|
+
Convert SVG content to a data URL for embedding in HTML.
|
50
|
+
|
51
|
+
Args:
|
52
|
+
ctx: The run context
|
53
|
+
svg_content: SVG markup as a string
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
str: Data URL representation of the SVG
|
57
|
+
"""
|
58
|
+
print("Converting SVG to data URL")
|
59
|
+
|
60
|
+
# Check size limits
|
61
|
+
if len(svg_content.encode('utf-8')) > ctx.deps.max_svg_size:
|
62
|
+
raise ValueError(f"SVG content exceeds maximum size of {ctx.deps.max_svg_size} bytes")
|
63
|
+
|
64
|
+
# Encode as base64 and create data URL
|
65
|
+
b64_svg = base64.b64encode(svg_content.encode('utf-8')).decode('ascii')
|
66
|
+
return f"data:image/svg+xml;base64,{b64_svg}"
|
67
|
+
|
68
|
+
|
69
|
+
async def judge_drawing(ctx: RunContext[DrawDependencies],
|
70
|
+
svg_content: str,
|
71
|
+
description: str,
|
72
|
+
attempt_number: int = 1) -> DrawingFeedback:
|
73
|
+
"""
|
74
|
+
Judge the readability of an SVG drawing based on the description.
|
75
|
+
|
76
|
+
In particular, make sure that text is readable and contained within boxes
|
77
|
+
|
78
|
+
Args:
|
79
|
+
ctx: The run context
|
80
|
+
svg_content: SVG markup as a string
|
81
|
+
description: Simple natural language narrative summary of the drawing
|
82
|
+
attempt_number: The attempt number for the drawing
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
DrawingFeedback: Feedback on the drawing's readability
|
86
|
+
"""
|
87
|
+
print(f"Judging drawing for: {description}")
|
88
|
+
|
89
|
+
from aurelian.agents.draw.judge_agent import drawing_judge_agent
|
90
|
+
|
91
|
+
# Convert to PNG for the judge to see
|
92
|
+
png_bytes = await convert_svg_to_png(ctx, svg_content)
|
93
|
+
img = BinaryContent(data=png_bytes, media_type='image/png')
|
94
|
+
|
95
|
+
# Get feedback from judge
|
96
|
+
feedback = await drawing_judge_agent.run(
|
97
|
+
[f"Please evaluate this drawing based on this description: {description} (this is attempt #{attempt_number})", img],
|
98
|
+
deps=ctx.deps)
|
99
|
+
|
100
|
+
return feedback.data
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"""
|
2
|
+
Agent specifically for judging the quality of drawings.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from pydantic_ai import Agent
|
6
|
+
|
7
|
+
from aurelian.agents.draw.draw_tools import DrawingFeedback
|
8
|
+
|
9
|
+
# Separate agent for judging drawings
|
10
|
+
drawing_judge_agent = Agent(
|
11
|
+
model='openai:gpt-4o',
|
12
|
+
system_prompt="""You role is to judge the simplicity and clarity of drawings and figures.
|
13
|
+
|
14
|
+
Specifically, in addition to correctness, you should focus on mistakes made, overlapping
|
15
|
+
or unclear text, etc
|
16
|
+
""",
|
17
|
+
result_type=DrawingFeedback,
|
18
|
+
)
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"""
|
2
|
+
Configuration for the Filesystem agent.
|
3
|
+
"""
|
4
|
+
import os
|
5
|
+
|
6
|
+
from aurelian.dependencies.workdir import HasWorkdir, WorkDir
|
7
|
+
|
8
|
+
|
9
|
+
class FilesystemDependencies(HasWorkdir):
|
10
|
+
"""
|
11
|
+
Filesystem 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() -> FilesystemDependencies:
|
19
|
+
"""Get a default configuration for the Filesystem agent.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
FilesystemDependencies 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 FilesystemDependencies(workdir=workdir)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"""
|
2
|
+
Gradio UI for the Filesystem 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.filesystem.filesystem_tools import inspect_file, download_url_as_markdown
|
10
|
+
from aurelian.agents.filesystem.filesystem_mcp import mcp
|
11
|
+
from aurelian.utils.async_utils import run_sync
|
12
|
+
|
13
|
+
|
14
|
+
def chat(deps: Optional[HasWorkdir] = None, **kwargs):
|
15
|
+
"""
|
16
|
+
Initialize a chat interface for the Filesystem agent.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
deps: Optional dependencies configuration
|
20
|
+
**kwargs: Additional arguments to pass to the agent
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
A Gradio chat interface
|
24
|
+
"""
|
25
|
+
if deps is None:
|
26
|
+
from aurelian.agents.filesystem.filesystem_mcp import deps as get_deps
|
27
|
+
deps = get_deps()
|
28
|
+
|
29
|
+
def get_info(query: str, history: List[str]) -> str:
|
30
|
+
print(f"QUERY: {query}")
|
31
|
+
print(f"HISTORY: {history}")
|
32
|
+
if history:
|
33
|
+
query += "## History"
|
34
|
+
for h in history:
|
35
|
+
query += f"\n{h}"
|
36
|
+
# Use MCP for the agent
|
37
|
+
result = run_sync(lambda: mcp.query(query))
|
38
|
+
return result
|
39
|
+
|
40
|
+
return gr.ChatInterface(
|
41
|
+
fn=get_info,
|
42
|
+
type="messages",
|
43
|
+
title="Filesystem AI Assistant",
|
44
|
+
examples=[
|
45
|
+
["List all files in the working directory"],
|
46
|
+
["Download https://example.com and save as example.md"],
|
47
|
+
["Show me the contents of the file example.md"]
|
48
|
+
]
|
49
|
+
)
|