tooluniverse.immport_tool 源代码
"""
ImmPort immunology database search tool for ToolUniverse.
Provides search for ImmPort studies (vaccine trials, flow cytometry, ELISPOT,
RNA-seq, clinical immunology data) using the public Elasticsearch-based API.
API: https://www.immport.org/data/query/api/search/study
No authentication required for study search.
"""
import requests
from typing import Any
from .base_tool import BaseTool
from .tool_registry import register_tool
IMMPORT_SEARCH_URL = "https://www.immport.org/data/query/api/search/study"
[文档]
@register_tool("ImmPortTool")
class ImmPortTool(BaseTool):
"""
Tool for searching ImmPort, the NIAID-funded immunology database with
900+ open studies covering vaccine trials, flow cytometry, ELISPOT,
RNA-seq, and clinical immunology data.
No authentication required for study search.
"""
[文档]
def __init__(self, tool_config: dict[str, Any]):
super().__init__(tool_config)
self.timeout = tool_config.get("timeout", 30)
fields = tool_config.get("fields", {})
self.operation = fields.get("operation", "search_studies")
[文档]
def run(self, arguments: dict[str, Any]) -> dict[str, Any]:
try:
if self.operation == "search_studies":
return self._search_studies(arguments)
return {
"status": "error",
"error": f"Unknown operation: {self.operation}",
}
except requests.exceptions.Timeout:
return {
"status": "error",
"error": f"ImmPort API timed out after {self.timeout}s",
}
except requests.exceptions.ConnectionError:
return {
"status": "error",
"error": "Failed to connect to ImmPort API",
}
except Exception as e:
return {"status": "error", "error": str(e)}
[文档]
def _search_studies(self, arguments: dict[str, Any]) -> dict[str, Any]:
"""Search ImmPort studies by keyword with optional filters."""
query = arguments.get("query") or arguments.get("term", "")
if not query:
return {"status": "error", "error": "query parameter is required"}
condition = arguments.get("condition_or_disease")
assay = arguments.get("assay_method")
focus = arguments.get("research_focus")
species = arguments.get("species")
limit = min(int(arguments.get("limit", 10)), 100)
pageSize = limit * 3 if (condition or assay or focus) else limit
params = {"term": query, "pageSize": pageSize}
if species:
params["species"] = species
resp = requests.get(
IMMPORT_SEARCH_URL,
params=params,
headers={"Accept": "application/json"},
timeout=self.timeout,
)
resp.raise_for_status()
data = resp.json()
hits_data = data.get("hits", {})
total = hits_data.get("total", {}).get("value", 0)
raw_hits = hits_data.get("hits", [])
filtered = []
for hit in raw_hits:
src = hit.get("_source", {})
if condition:
conds = [c.lower() for c in (src.get("condition_or_disease") or [])]
if not any(condition.lower() in c for c in conds):
continue
if assay:
assays = [a.lower() for a in (src.get("assay_method") or [])]
if not any(assay.lower() in a for a in assays):
continue
if focus:
focuses = [f.lower() for f in (src.get("research_focus") or [])]
if not any(focus.lower() in f for f in focuses):
continue
filtered.append(src)
if len(filtered) >= limit:
break
studies = [
{
"study_accession": src.get("study_accession"),
"title": src.get("brief_title"),
"brief_description": src.get("brief_description"),
"condition_or_disease": src.get("condition_or_disease"),
"research_focus": src.get("research_focus"),
"species": src.get("species"),
"assay_methods": src.get("assay_method"),
"assay_method_counts": src.get("assay_method_count"),
"biosample_types": src.get("biosample_type"),
"actual_enrollment": src.get("actual_enrollment"),
"age_range": src.get("age_range"),
"gender_included": src.get("gender_included"),
"pubmed_ids": src.get("pubmed_id"),
"doi": src.get("doi"),
"program_name": src.get("program_name"),
"study_pi": src.get("study_pi"),
"clinical_trial": src.get("clinical_trial"),
"latest_data_release_date": src.get("latest_data_release_date"),
}
for src in filtered
]
return {
"status": "success",
"data": studies,
"metadata": {
"total_matches": total,
"returned": len(studies),
"query": query,
"filters_applied": {
k: v
for k, v in {
"condition_or_disease": condition,
"assay_method": assay,
"research_focus": focus,
"species": species,
}.items()
if v
},
"source": "ImmPort (www.immport.org)",
},
}