|
|
"""Tool functions for Magentic agents. |
|
|
|
|
|
These functions are decorated with @ai_function to be callable by the ChatAgent's internal LLM. |
|
|
They also interact with the thread-safe MagenticState to persist evidence. |
|
|
""" |
|
|
|
|
|
from agent_framework import ai_function |
|
|
|
|
|
from src.agents.state import get_magentic_state |
|
|
from src.tools.clinicaltrials import ClinicalTrialsTool |
|
|
from src.tools.europepmc import EuropePMCTool |
|
|
from src.tools.pubmed import PubMedTool |
|
|
|
|
|
|
|
|
_pubmed = PubMedTool() |
|
|
_clinicaltrials = ClinicalTrialsTool() |
|
|
_europepmc = EuropePMCTool() |
|
|
|
|
|
|
|
|
@ai_function |
|
|
async def search_pubmed(query: str, max_results: int = 10) -> str: |
|
|
"""Search PubMed for biomedical research papers. |
|
|
|
|
|
Use this tool to find peer-reviewed scientific literature about |
|
|
drugs, diseases, mechanisms of action, and clinical studies. |
|
|
|
|
|
Args: |
|
|
query: Search keywords (e.g., "testosterone libido mechanism") |
|
|
max_results: Maximum results to return (default 10) |
|
|
|
|
|
Returns: |
|
|
Formatted list of papers with titles, abstracts, and citations |
|
|
""" |
|
|
state = get_magentic_state() |
|
|
|
|
|
|
|
|
results = await _pubmed.search(query, max_results) |
|
|
if not results: |
|
|
return f"No PubMed results found for: {query}" |
|
|
|
|
|
|
|
|
|
|
|
new_ids = await state.memory.store_evidence(results) |
|
|
new_count = len(new_ids) |
|
|
|
|
|
|
|
|
|
|
|
display_results = list(results) |
|
|
|
|
|
|
|
|
related = await state.memory.get_relevant_evidence(n=3) |
|
|
|
|
|
|
|
|
current_urls = {r.citation.url for r in display_results} |
|
|
for item in related: |
|
|
if item.citation.url not in current_urls: |
|
|
display_results.append(item) |
|
|
|
|
|
|
|
|
output = [f"Found {len(results)} results ({new_count} new stored):\n"] |
|
|
|
|
|
|
|
|
limit = min(len(display_results), max_results + 3) |
|
|
|
|
|
for i, r in enumerate(display_results[:limit], 1): |
|
|
title = r.citation.title |
|
|
date = r.citation.date |
|
|
source = r.citation.source |
|
|
content_clean = r.content[:300].replace("\n", " ") |
|
|
url = r.citation.url |
|
|
|
|
|
output.append(f"{i}. **{title}** ({date})") |
|
|
output.append(f" Source: {source} | {url}") |
|
|
output.append(f" {content_clean}...") |
|
|
output.append("") |
|
|
|
|
|
return "\n".join(output) |
|
|
|
|
|
|
|
|
@ai_function |
|
|
async def search_clinical_trials(query: str, max_results: int = 10) -> str: |
|
|
"""Search ClinicalTrials.gov for clinical studies. |
|
|
|
|
|
Use this tool to find ongoing and completed clinical trials |
|
|
for potential interventions. |
|
|
|
|
|
Args: |
|
|
query: Search terms (e.g., "sildenafil phase 3") |
|
|
max_results: Maximum results to return (default 10) |
|
|
|
|
|
Returns: |
|
|
Formatted list of clinical trials with status and details |
|
|
""" |
|
|
state = get_magentic_state() |
|
|
|
|
|
results = await _clinicaltrials.search(query, max_results) |
|
|
if not results: |
|
|
return f"No clinical trials found for: {query}" |
|
|
|
|
|
|
|
|
new_ids = await state.memory.store_evidence(results) |
|
|
new_count = len(new_ids) |
|
|
|
|
|
output = [f"Found {len(results)} clinical trials ({new_count} new stored):\n"] |
|
|
for i, r in enumerate(results[:max_results], 1): |
|
|
title = r.citation.title |
|
|
date = r.citation.date |
|
|
source = r.citation.source |
|
|
content_clean = r.content[:300].replace("\n", " ") |
|
|
url = r.citation.url |
|
|
|
|
|
output.append(f"{i}. **{title}**") |
|
|
output.append(f" Status: {source} | Date: {date}") |
|
|
output.append(f" {content_clean}...") |
|
|
output.append(f" URL: {url}\n") |
|
|
|
|
|
return "\n".join(output) |
|
|
|
|
|
|
|
|
@ai_function |
|
|
async def search_preprints(query: str, max_results: int = 10) -> str: |
|
|
"""Search Europe PMC for preprints and papers. |
|
|
|
|
|
Use this tool to find the latest research including preprints |
|
|
from bioRxiv, medRxiv, and peer-reviewed papers. |
|
|
|
|
|
Args: |
|
|
query: Search terms (e.g., "flibanserin HSDD preprint") |
|
|
max_results: Maximum results to return (default 10) |
|
|
|
|
|
Returns: |
|
|
Formatted list of papers with abstracts and links |
|
|
""" |
|
|
state = get_magentic_state() |
|
|
|
|
|
results = await _europepmc.search(query, max_results) |
|
|
if not results: |
|
|
return f"No papers found for: {query}" |
|
|
|
|
|
|
|
|
new_ids = await state.memory.store_evidence(results) |
|
|
new_count = len(new_ids) |
|
|
|
|
|
output = [f"Found {len(results)} papers ({new_count} new stored):\n"] |
|
|
for i, r in enumerate(results[:max_results], 1): |
|
|
title = r.citation.title |
|
|
date = r.citation.date |
|
|
source = r.citation.source |
|
|
content_clean = r.content[:300].replace("\n", " ") |
|
|
url = r.citation.url |
|
|
|
|
|
output.append(f"{i}. **{title}**") |
|
|
output.append(f" Source: {source} | Date: {date}") |
|
|
output.append(f" {content_clean}...") |
|
|
output.append(f" URL: {url}\n") |
|
|
|
|
|
return "\n".join(output) |
|
|
|
|
|
|
|
|
@ai_function |
|
|
async def get_bibliography() -> str: |
|
|
"""Get the full list of collected evidence for the bibliography. |
|
|
|
|
|
Use this tool when generating the final report to get the complete |
|
|
list of references. |
|
|
|
|
|
Returns: |
|
|
Formatted bibliography string. |
|
|
""" |
|
|
state = get_magentic_state() |
|
|
all_evidence = state.memory.get_all_evidence() |
|
|
|
|
|
if not all_evidence: |
|
|
return "No evidence collected." |
|
|
|
|
|
output = ["## References"] |
|
|
for i, ev in enumerate(all_evidence, 1): |
|
|
output.append(f"{i}. {ev.citation.formatted}") |
|
|
output.append(f" URL: {ev.citation.url}") |
|
|
|
|
|
return "\n".join(output) |
|
|
|