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,45 @@
|
|
1
|
+
"""
|
2
|
+
Configuration for the Monarch agent.
|
3
|
+
"""
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
import os
|
6
|
+
from typing import Dict, List, Optional
|
7
|
+
|
8
|
+
from oaklib import get_adapter
|
9
|
+
from oaklib.interfaces import OboGraphInterface
|
10
|
+
|
11
|
+
from aurelian.dependencies.workdir import HasWorkdir, WorkDir
|
12
|
+
|
13
|
+
|
14
|
+
@dataclass
|
15
|
+
class MonarchDependencies(HasWorkdir):
|
16
|
+
"""Configuration for the Monarch agent."""
|
17
|
+
|
18
|
+
# Default taxon ID for humans
|
19
|
+
taxon: str = "9606"
|
20
|
+
|
21
|
+
def __post_init__(self):
|
22
|
+
"""Initialize the config with default values."""
|
23
|
+
# HasWorkdir doesn't have a __post_init__ method, so we don't call super()
|
24
|
+
if self.workdir is None:
|
25
|
+
self.workdir = WorkDir()
|
26
|
+
|
27
|
+
def get_monarch_adapter(self) -> OboGraphInterface:
|
28
|
+
"""Get a configured Monarch adapter."""
|
29
|
+
return get_adapter("monarch:")
|
30
|
+
|
31
|
+
def get_mondo_adapter(self) -> OboGraphInterface:
|
32
|
+
"""Get a configured Mondo adapter."""
|
33
|
+
return get_adapter("sqlite:obo:mondo")
|
34
|
+
|
35
|
+
|
36
|
+
def get_config() -> MonarchDependencies:
|
37
|
+
"""Get the Monarch configuration from environment variables or defaults."""
|
38
|
+
workdir_path = os.environ.get("AURELIAN_WORKDIR", None)
|
39
|
+
workdir = WorkDir(location=workdir_path) if workdir_path else None
|
40
|
+
taxon = os.environ.get("MONARCH_TAXON", "9606")
|
41
|
+
|
42
|
+
return MonarchDependencies(
|
43
|
+
workdir=workdir,
|
44
|
+
taxon=taxon
|
45
|
+
)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
"""
|
2
|
+
Gradio interface for the Monarch agent.
|
3
|
+
"""
|
4
|
+
from typing import List, Optional
|
5
|
+
|
6
|
+
import gradio as gr
|
7
|
+
|
8
|
+
from aurelian.utils.async_utils import run_sync
|
9
|
+
from .monarch_agent import monarch_agent
|
10
|
+
from .monarch_config import MonarchDependencies
|
11
|
+
|
12
|
+
|
13
|
+
def chat(deps: Optional[MonarchDependencies] = None, taxon: Optional[str] = None, **kwargs):
|
14
|
+
"""
|
15
|
+
Initialize a chat interface for the Monarch agent.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
deps: Optional dependencies configuration
|
19
|
+
taxon: Optional taxon ID to use, defaults to human (9606)
|
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 = MonarchDependencies()
|
27
|
+
|
28
|
+
if taxon:
|
29
|
+
deps.taxon = taxon
|
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: monarch_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="Monarch Knowledge Base AI Assistant",
|
45
|
+
examples=[
|
46
|
+
["Find associations for gene BRCA1"],
|
47
|
+
["What diseases are associated with the APOE gene?"],
|
48
|
+
["Find information about disease MONDO:0007254"],
|
49
|
+
["What genes are associated with Alzheimer's disease?"]
|
50
|
+
]
|
51
|
+
)
|
@@ -0,0 +1,65 @@
|
|
1
|
+
"""
|
2
|
+
MCP tools for interacting with the Monarch Knowledge Base.
|
3
|
+
"""
|
4
|
+
import os
|
5
|
+
from typing import Dict, List, Optional
|
6
|
+
|
7
|
+
from mcp.server.fastmcp import FastMCP
|
8
|
+
|
9
|
+
import aurelian.agents.monarch.monarch_tools as mt
|
10
|
+
from aurelian.agents.monarch.monarch_agent import MONARCH_SYSTEM_PROMPT
|
11
|
+
from aurelian.agents.monarch.monarch_config import MonarchDependencies, get_config
|
12
|
+
from pydantic_ai import RunContext
|
13
|
+
|
14
|
+
# Initialize FastMCP server
|
15
|
+
mcp = FastMCP("monarch", instructions=MONARCH_SYSTEM_PROMPT)
|
16
|
+
|
17
|
+
|
18
|
+
from aurelian.dependencies.workdir import WorkDir
|
19
|
+
|
20
|
+
def deps() -> MonarchDependencies:
|
21
|
+
deps = get_config()
|
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[MonarchDependencies]:
|
28
|
+
rc: RunContext[MonarchDependencies] = RunContext[MonarchDependencies](
|
29
|
+
deps=deps(),
|
30
|
+
model=None, usage=None, prompt=None,
|
31
|
+
)
|
32
|
+
return rc
|
33
|
+
|
34
|
+
|
35
|
+
@mcp.tool()
|
36
|
+
async def find_gene_associations(gene_id: str) -> List[Dict]:
|
37
|
+
"""
|
38
|
+
Find associations for a given gene or gene product.
|
39
|
+
|
40
|
+
Args:
|
41
|
+
gene_id: Gene identifier (e.g., HGNC symbol like "BRCA1")
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
List of association objects containing subject, predicate, object details
|
45
|
+
"""
|
46
|
+
return await mt.find_gene_associations(ctx(), gene_id)
|
47
|
+
|
48
|
+
|
49
|
+
@mcp.tool()
|
50
|
+
async def find_disease_associations(disease_id: str) -> List[Dict]:
|
51
|
+
"""
|
52
|
+
Find associations for a given disease.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
disease_id: Disease identifier (e.g., MONDO:0007254)
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
List of association objects containing subject, predicate, object details
|
59
|
+
"""
|
60
|
+
return await mt.find_disease_associations(ctx(), disease_id)
|
61
|
+
|
62
|
+
|
63
|
+
if __name__ == "__main__":
|
64
|
+
# Initialize and run the server
|
65
|
+
mcp.run(transport='stdio')
|
@@ -0,0 +1,113 @@
|
|
1
|
+
"""
|
2
|
+
Tools for interacting with the Monarch Knowledge Base.
|
3
|
+
"""
|
4
|
+
import asyncio
|
5
|
+
from typing import Dict, List, Optional
|
6
|
+
|
7
|
+
from pydantic_ai import RunContext, ModelRetry
|
8
|
+
|
9
|
+
from aurelian.utils.data_utils import obj_to_dict
|
10
|
+
from aurelian.utils.async_utils import run_sync
|
11
|
+
from .monarch_config import MonarchDependencies, get_config
|
12
|
+
|
13
|
+
|
14
|
+
def get_gene_id(ctx: RunContext[MonarchDependencies], gene_term: str) -> str:
|
15
|
+
"""
|
16
|
+
Normalize a gene identifier.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
ctx: Run context with dependencies
|
20
|
+
gene_term: The gene term to normalize
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
Normalized gene ID
|
24
|
+
"""
|
25
|
+
# Currently just a pass-through, but could be enhanced with ID normalization
|
26
|
+
return gene_term
|
27
|
+
|
28
|
+
|
29
|
+
async def find_gene_associations(ctx: RunContext[MonarchDependencies], gene_id: str) -> List[Dict]:
|
30
|
+
"""
|
31
|
+
Find associations for a given gene ID.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
ctx: Run context with dependencies
|
35
|
+
gene_id: The gene ID to find associations for
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
List of associations for the gene
|
39
|
+
"""
|
40
|
+
config = ctx.deps or get_config()
|
41
|
+
adapter = config.get_monarch_adapter()
|
42
|
+
|
43
|
+
try:
|
44
|
+
normalized_gene_id = get_gene_id(ctx, gene_id)
|
45
|
+
|
46
|
+
# Execute the potentially blocking operation in a thread pool
|
47
|
+
associations = await asyncio.to_thread(adapter.associations, [normalized_gene_id])
|
48
|
+
|
49
|
+
if not associations:
|
50
|
+
raise ModelRetry(f"No gene associations found for {gene_id}. Try a different gene identifier.")
|
51
|
+
|
52
|
+
# Convert associations to dictionaries asynchronously
|
53
|
+
result = []
|
54
|
+
for assoc in associations:
|
55
|
+
dict_assoc = await asyncio.to_thread(obj_to_dict, assoc)
|
56
|
+
result.append(dict_assoc)
|
57
|
+
|
58
|
+
return result
|
59
|
+
except Exception as e:
|
60
|
+
if "ModelRetry" in str(type(e)):
|
61
|
+
raise e
|
62
|
+
raise ModelRetry(f"Error retrieving gene associations: {str(e)}")
|
63
|
+
|
64
|
+
|
65
|
+
def get_disease_id(ctx: RunContext[MonarchDependencies], term: str) -> str:
|
66
|
+
"""
|
67
|
+
Normalize a disease identifier.
|
68
|
+
|
69
|
+
Args:
|
70
|
+
ctx: Run context with dependencies
|
71
|
+
term: The disease term to normalize
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
Normalized disease ID
|
75
|
+
"""
|
76
|
+
# Currently just a pass-through, but could be enhanced with ID normalization
|
77
|
+
return term
|
78
|
+
|
79
|
+
|
80
|
+
async def find_disease_associations(ctx: RunContext[MonarchDependencies], disease_id: str) -> List[Dict]:
|
81
|
+
"""
|
82
|
+
Find associations for a given disease ID.
|
83
|
+
|
84
|
+
Args:
|
85
|
+
ctx: Run context with dependencies
|
86
|
+
disease_id: The disease ID to find associations for
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
List of associations for the disease
|
90
|
+
"""
|
91
|
+
config = ctx.deps or get_config()
|
92
|
+
adapter = config.get_monarch_adapter()
|
93
|
+
|
94
|
+
try:
|
95
|
+
normalized_disease_id = get_disease_id(ctx, disease_id)
|
96
|
+
|
97
|
+
# Execute the potentially blocking operation in a thread pool
|
98
|
+
associations = await asyncio.to_thread(adapter.associations, [normalized_disease_id])
|
99
|
+
|
100
|
+
if not associations:
|
101
|
+
raise ModelRetry(f"No disease associations found for {disease_id}. Try a different disease identifier.")
|
102
|
+
|
103
|
+
# Convert associations to dictionaries asynchronously
|
104
|
+
result = []
|
105
|
+
for assoc in associations:
|
106
|
+
dict_assoc = await asyncio.to_thread(obj_to_dict, assoc)
|
107
|
+
result.append(dict_assoc)
|
108
|
+
|
109
|
+
return result
|
110
|
+
except Exception as e:
|
111
|
+
if "ModelRetry" in str(type(e)):
|
112
|
+
raise e
|
113
|
+
raise ModelRetry(f"Error retrieving disease associations: {str(e)}")
|
File without changes
|
@@ -0,0 +1,27 @@
|
|
1
|
+
"""
|
2
|
+
Configuration for the OAK agent.
|
3
|
+
"""
|
4
|
+
import os
|
5
|
+
|
6
|
+
from aurelian.dependencies.workdir import HasWorkdir, WorkDir
|
7
|
+
|
8
|
+
|
9
|
+
class OakDependencies(HasWorkdir):
|
10
|
+
"""
|
11
|
+
OAK 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() -> OakDependencies:
|
19
|
+
"""Get a default configuration for the OAK agent.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
OakDependencies 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 OakDependencies(workdir=workdir)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
"""
|
2
|
+
Gradio UI for the OAK 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.utils.async_utils import run_sync
|
10
|
+
from pydantic_ai import Agent, Tool
|
11
|
+
|
12
|
+
# Create an Agent
|
13
|
+
oak_agent = Agent(
|
14
|
+
model="openai:gpt-4o",
|
15
|
+
deps_type=HasWorkdir,
|
16
|
+
system_prompt="""
|
17
|
+
You are an expert OAK (Ontology Access Kit) assistant. You can help users interact with ontology databases,
|
18
|
+
search ontologies, and perform common ontology operations.
|
19
|
+
Always provide clear explanations of what you're doing.
|
20
|
+
""",
|
21
|
+
tools=[] # OAK tools would be added here
|
22
|
+
)
|
23
|
+
|
24
|
+
def chat(deps: Optional[HasWorkdir] = None, **kwargs):
|
25
|
+
"""
|
26
|
+
Initialize a chat interface for the OAK agent.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
deps: Optional dependencies configuration
|
30
|
+
**kwargs: Additional arguments to pass to the agent
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
A Gradio chat interface
|
34
|
+
"""
|
35
|
+
if deps is None:
|
36
|
+
deps = HasWorkdir()
|
37
|
+
|
38
|
+
def get_info(query: str, history: List[str]) -> str:
|
39
|
+
print(f"QUERY: {query}")
|
40
|
+
print(f"HISTORY: {history}")
|
41
|
+
if history:
|
42
|
+
query += "## History"
|
43
|
+
for h in history:
|
44
|
+
query += f"\n{h}"
|
45
|
+
result = run_sync(lambda: oak_agent.run_sync(query, deps=deps, **kwargs))
|
46
|
+
return result.data
|
47
|
+
|
48
|
+
return gr.ChatInterface(
|
49
|
+
fn=get_info,
|
50
|
+
type="messages",
|
51
|
+
title="OAK AI Assistant",
|
52
|
+
examples=[
|
53
|
+
["Search for 'diabetes' in the Human Phenotype Ontology"],
|
54
|
+
["Find terms related to 'heart' in GO"],
|
55
|
+
["Get information about the term 'HP:0001250'"]
|
56
|
+
]
|
57
|
+
)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
"""
|
2
|
+
Ontology Mapper agent package for working with ontology term mappings.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from .ontology_mapper_agent import ontology_mapper_agent, add_ontologies
|
6
|
+
from .ontology_mapper_config import OntologyMapperDependencies
|
7
|
+
from .ontology_mapper_gradio import chat
|
8
|
+
from .ontology_mapper_tools import (
|
9
|
+
search_terms,
|
10
|
+
search_web,
|
11
|
+
retrieve_web_page,
|
12
|
+
get_ontology_adapter,
|
13
|
+
)
|
14
|
+
|
15
|
+
__all__ = [
|
16
|
+
# Agent
|
17
|
+
"ontology_mapper_agent",
|
18
|
+
"add_ontologies",
|
19
|
+
|
20
|
+
# Config
|
21
|
+
"OntologyMapperDependencies",
|
22
|
+
|
23
|
+
# Tools
|
24
|
+
"search_terms",
|
25
|
+
"search_web",
|
26
|
+
"retrieve_web_page",
|
27
|
+
"get_ontology_adapter",
|
28
|
+
|
29
|
+
# Gradio
|
30
|
+
"chat",
|
31
|
+
]
|
@@ -0,0 +1,56 @@
|
|
1
|
+
"""
|
2
|
+
Agent for creating ontology mappings.
|
3
|
+
"""
|
4
|
+
from pydantic_ai import Agent, RunContext
|
5
|
+
|
6
|
+
from .ontology_mapper_config import OntologyMapperDependencies, get_config
|
7
|
+
from .ontology_mapper_tools import (
|
8
|
+
search_terms,
|
9
|
+
search_web,
|
10
|
+
retrieve_web_page,
|
11
|
+
)
|
12
|
+
|
13
|
+
# System prompt for the ontology mapper agent
|
14
|
+
ONTOLOGY_MAPPER_SYSTEM_PROMPT = (
|
15
|
+
"You are an expert on OBO ontologies."
|
16
|
+
" Your task is to assist the user in finding the relevant ontology terms,"
|
17
|
+
" given inputs such as search queries, lists of terms to map, alternate ontology classes, etc."
|
18
|
+
" You have access to a limited set of ontologies, which you can search using the `search_terms` function."
|
19
|
+
" This uses embedding-based search, so you can use partial terms, alternate names, etc."
|
20
|
+
" You can also expand the users search terms as appropriate, making use of any context provided."
|
21
|
+
" You should show your reasoning, and your candidate list (as many as appropriate)."
|
22
|
+
" Do not be completely literal in the task of matching ontology terms. If something seems out of scope"
|
23
|
+
" for an ontology, give the appropriate response and recommendation. "
|
24
|
+
" If a term is in scope and can't be found, suggest a term request."
|
25
|
+
" Give detailed provenance chains in <details> tags."
|
26
|
+
" Show ontology term IDs together with labels whenever possible."
|
27
|
+
" IMPORTANT: precision is important. If a user makes a query for a term then you should only return terms"
|
28
|
+
" that represent the SAME CONCEPT. Sometimes this will not be possible, and only close concepts can be found."
|
29
|
+
" Here you can report the close terms, but make it clear these are NOT THE SAME. Before doing this, you should"
|
30
|
+
" try strategies like varying your search term, based on your knowledge of that ontology"
|
31
|
+
" You must NEVER guess ontology term IDs, the query results should always be the source of truth."
|
32
|
+
"Stick to markdown, and all prefixed IDs should by hyperlinked with bioregistry,"
|
33
|
+
" i.e https://bioregistry.io/{curie}."
|
34
|
+
)
|
35
|
+
|
36
|
+
# Create the agent with the system prompt
|
37
|
+
ontology_mapper_agent = Agent(
|
38
|
+
model="openai:gpt-4o",
|
39
|
+
deps_type=OntologyMapperDependencies,
|
40
|
+
result_type=str,
|
41
|
+
system_prompt=ONTOLOGY_MAPPER_SYSTEM_PROMPT,
|
42
|
+
)
|
43
|
+
|
44
|
+
# Register the tools with the agent
|
45
|
+
ontology_mapper_agent.tool(search_terms)
|
46
|
+
ontology_mapper_agent.tool_plain(search_web)
|
47
|
+
ontology_mapper_agent.tool_plain(retrieve_web_page)
|
48
|
+
|
49
|
+
|
50
|
+
@ontology_mapper_agent.system_prompt
|
51
|
+
def add_ontologies(ctx: RunContext[OntologyMapperDependencies]) -> str:
|
52
|
+
"""Add the list of allowed ontologies to the system prompt."""
|
53
|
+
allowed_ontologies = ctx.deps.ontologies
|
54
|
+
if allowed_ontologies:
|
55
|
+
return f"Allowed ontologies: {allowed_ontologies}"
|
56
|
+
return "Use any ontology (ideally in OBO repository)"
|
@@ -0,0 +1,50 @@
|
|
1
|
+
"""
|
2
|
+
Configuration for the Ontology Mapper agent.
|
3
|
+
"""
|
4
|
+
from dataclasses import dataclass, field
|
5
|
+
import os
|
6
|
+
from typing import List, Optional
|
7
|
+
|
8
|
+
from aurelian.dependencies.workdir import HasWorkdir, WorkDir
|
9
|
+
|
10
|
+
|
11
|
+
@dataclass
|
12
|
+
class OntologyMapperDependencies(HasWorkdir):
|
13
|
+
"""
|
14
|
+
Configuration for the ontology mapper agent.
|
15
|
+
|
16
|
+
We include a default set of ontologies because the initial text embedding index is slow..
|
17
|
+
this can easily be changed e.g. in command line
|
18
|
+
"""
|
19
|
+
max_search_results: int = 30
|
20
|
+
ontologies: List[str] = field(
|
21
|
+
default_factory=lambda: ["mondo", "hp", "go", "uberon", "cl", "mp", "envo", "obi"]
|
22
|
+
)
|
23
|
+
|
24
|
+
def __post_init__(self):
|
25
|
+
"""Initialize the config with default values."""
|
26
|
+
# HasWorkdir doesn't have a __post_init__ method, so we don't call super()
|
27
|
+
if self.workdir is None:
|
28
|
+
self.workdir = WorkDir()
|
29
|
+
|
30
|
+
|
31
|
+
def get_config(ontologies: Optional[List[str]] = None) -> OntologyMapperDependencies:
|
32
|
+
"""Get the Ontology Mapper configuration from environment variables or defaults."""
|
33
|
+
workdir_path = os.environ.get("AURELIAN_WORKDIR", None)
|
34
|
+
workdir = WorkDir(location=workdir_path) if workdir_path else None
|
35
|
+
|
36
|
+
config = OntologyMapperDependencies(workdir=workdir)
|
37
|
+
|
38
|
+
# Set ontologies if specified
|
39
|
+
if ontologies:
|
40
|
+
config.ontologies = ontologies
|
41
|
+
|
42
|
+
# Allow environment variable to override max search results
|
43
|
+
max_results_env = os.environ.get("MAX_SEARCH_RESULTS")
|
44
|
+
if max_results_env:
|
45
|
+
try:
|
46
|
+
config.max_search_results = int(max_results_env)
|
47
|
+
except ValueError:
|
48
|
+
pass
|
49
|
+
|
50
|
+
return config
|
@@ -0,0 +1,108 @@
|
|
1
|
+
"""
|
2
|
+
Evaluation module for the Ontology Mapper agent.
|
3
|
+
|
4
|
+
This module implements evaluations for the Ontology Mapper agent using the pydantic-ai-evals framework.
|
5
|
+
"""
|
6
|
+
import asyncio
|
7
|
+
import sys
|
8
|
+
from typing import Optional, Any, Dict, Callable, Awaitable
|
9
|
+
|
10
|
+
from aurelian.evaluators.model import MetadataDict, metadata
|
11
|
+
from aurelian.evaluators.substring_evaluator import SubstringEvaluator
|
12
|
+
from pydantic_evals import Case, Dataset
|
13
|
+
from pydantic_evals.evaluators import LLMJudge
|
14
|
+
|
15
|
+
from aurelian.agents.ontology_mapper.ontology_mapper_agent import ontology_mapper_agent
|
16
|
+
from aurelian.agents.ontology_mapper.ontology_mapper_config import OntologyMapperDependencies, get_config
|
17
|
+
|
18
|
+
class OntologyMapperMetadata(Dict[str, Any]):
|
19
|
+
"""Simple metadata dictionary for Ontology Mapper evaluations."""
|
20
|
+
pass
|
21
|
+
|
22
|
+
# Define individual evaluation cases
|
23
|
+
case1 = Case(
|
24
|
+
name="cell_ontology_neuron",
|
25
|
+
inputs="Find the term in the cell ontology for neuron",
|
26
|
+
expected_output="CL:0000540", # Neuron ID in Cell Ontology
|
27
|
+
metadata=metadata("easy", "basic_term_lookup")
|
28
|
+
)
|
29
|
+
|
30
|
+
case2 = Case(
|
31
|
+
name="middle_fingers_terms",
|
32
|
+
inputs="Best terms to use for the middle 3 fingers",
|
33
|
+
expected_output="digit", # Should mention digit terms
|
34
|
+
metadata=metadata("medium", "anatomical_term_suggestion"),
|
35
|
+
evaluators=[
|
36
|
+
LLMJudge(
|
37
|
+
rubric="""
|
38
|
+
Answer should:
|
39
|
+
1. Identify appropriate anatomical terms for index, middle, and ring fingers
|
40
|
+
2. Include ontology IDs where possible
|
41
|
+
3. Explain why these terms are appropriate
|
42
|
+
""",
|
43
|
+
include_input=True
|
44
|
+
)
|
45
|
+
]
|
46
|
+
)
|
47
|
+
|
48
|
+
case3 = Case(
|
49
|
+
name="go_cell_division",
|
50
|
+
inputs="What is the term for the process of cell division in GO?",
|
51
|
+
expected_output="GO:0051301", # Cell division GO term
|
52
|
+
metadata=metadata("easy", "go_term_lookup")
|
53
|
+
)
|
54
|
+
|
55
|
+
case4 = Case(
|
56
|
+
name="mp_term_mapping",
|
57
|
+
inputs="""
|
58
|
+
Find good MP terms for the following. If no matches can be found, suggest appropriate action
|
59
|
+
|
60
|
+
* CA1 TBS Reduced
|
61
|
+
* CA1 TBS Increased
|
62
|
+
* Surface righting Reduced
|
63
|
+
* Contextual fear conditioning (shock context/context shock) Reduced
|
64
|
+
* Morris water maze Reduced
|
65
|
+
* Rotarod Increased
|
66
|
+
* Rotarod Reduced
|
67
|
+
""",
|
68
|
+
expected_output="MP:", # Should provide MP IDs
|
69
|
+
metadata=metadata("hard", "complex_term_mapping")
|
70
|
+
)
|
71
|
+
|
72
|
+
case5 = Case(
|
73
|
+
name="cross_ontology_mapping",
|
74
|
+
inputs="Map the Human Phenotype Ontology term for 'Seizure' (HP:0001250) to Mouse Phenotype Ontology",
|
75
|
+
expected_output="MP:0002064", # Seizure in MP
|
76
|
+
metadata=metadata("medium", "cross_ontology_mapping")
|
77
|
+
)
|
78
|
+
|
79
|
+
def create_eval_dataset() -> Dataset[str, str, MetadataDict]:
|
80
|
+
"""
|
81
|
+
Create a dataset for evaluating the Ontology Mapper agent.
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
Dataset of Ontology Mapper evaluation cases with appropriate evaluators
|
85
|
+
"""
|
86
|
+
# Collect all cases
|
87
|
+
cases = [case1, case2, case3, case4, case5]
|
88
|
+
|
89
|
+
# Dataset-level evaluators
|
90
|
+
evaluators = [
|
91
|
+
SubstringEvaluator(),
|
92
|
+
LLMJudge(
|
93
|
+
rubric="""
|
94
|
+
Evaluate the answer based on:
|
95
|
+
1. Accuracy of ontology term identification
|
96
|
+
2. Correctness of ontology IDs provided
|
97
|
+
3. Appropriateness of term selection for the given context
|
98
|
+
4. Clear explanation of term selection logic and relationships
|
99
|
+
5. Suitable handling of cases where no exact match exists
|
100
|
+
""",
|
101
|
+
model="anthropic:claude-3-7-sonnet-latest"
|
102
|
+
)
|
103
|
+
]
|
104
|
+
|
105
|
+
return Dataset(
|
106
|
+
cases=cases,
|
107
|
+
evaluators=evaluators
|
108
|
+
)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
"""
|
2
|
+
Gradio interface for the Ontology Mapper agent.
|
3
|
+
"""
|
4
|
+
import os
|
5
|
+
from typing import List, Optional
|
6
|
+
|
7
|
+
import gradio as gr
|
8
|
+
|
9
|
+
from aurelian.utils.async_utils import run_sync
|
10
|
+
from .ontology_mapper_agent import ontology_mapper_agent
|
11
|
+
from .ontology_mapper_config import OntologyMapperDependencies, get_config
|
12
|
+
|
13
|
+
|
14
|
+
def chat(deps: Optional[OntologyMapperDependencies] = None, **kwargs):
|
15
|
+
"""
|
16
|
+
Initialize a chat interface for the Ontology Mapper 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
|
+
deps = get_config()
|
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
|
+
result = run_sync(lambda: ontology_mapper_agent.run_sync(query, deps=deps, **kwargs))
|
36
|
+
return result.data
|
37
|
+
|
38
|
+
return gr.ChatInterface(
|
39
|
+
fn=get_info,
|
40
|
+
type="messages",
|
41
|
+
title="Ontology Mapper AI Assistant",
|
42
|
+
examples=[
|
43
|
+
"Find the term in the cell ontology for neuron",
|
44
|
+
"Best terms to use for the middle 3 fingers",
|
45
|
+
"What is the term for the process of cell division in GO?",
|
46
|
+
"""
|
47
|
+
Find good MP terms for the following. If no matches can be found, suggest appropriate action
|
48
|
+
|
49
|
+
* CA1 TBS Reduced
|
50
|
+
* CA1 TBS Increased
|
51
|
+
* Surface righting Reduced
|
52
|
+
* Contextual fear conditioning (shock context/context shock) Reduced
|
53
|
+
* Morris water maze Reduced
|
54
|
+
* Rotarod Increased
|
55
|
+
* Rotarod Reduced
|
56
|
+
""",
|
57
|
+
]
|
58
|
+
)
|