tooluniverse.stitch_tool 源代码
# stitch_tool.py
"""
STITCH (Search Tool for Interacting Chemicals) API tool for ToolUniverse.
STITCH is a database of known and predicted interactions between
chemicals and proteins, combining data from various sources.
API Documentation: http://stitch.embl.de/
"""
import requests
from typing import Dict, Any
from .base_tool import BaseTool
from .tool_registry import register_tool
# Base URL for STITCH REST API (chemical-protein interactions)
# NOTE: stitch.embl.de API endpoints have moved to string-db.org (same API format)
STITCH_BASE_URL = "https://string-db.org/api"
[文档]
@register_tool("STITCHTool")
class STITCHTool(BaseTool):
"""
Tool for querying STITCH database.
STITCH provides chemical-protein interaction data including:
- Known drug-target interactions
- Predicted chemical-protein interactions
- Interaction scores and evidence
- Network analysis data
No authentication required. Free for academic/research use.
"""
[文档]
def __init__(self, tool_config: Dict[str, Any]):
super().__init__(tool_config)
self.timeout = tool_config.get("timeout", 30)
self.operation = tool_config.get("fields", {}).get(
"operation", "get_interactions"
)
[文档]
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""Execute the STITCH API call."""
operation = self.operation
if operation == "get_interactions":
return self._get_interactions(arguments)
elif operation == "get_interactors":
return self._get_interactors(arguments)
elif operation == "resolve":
return self._resolve_identifiers(arguments)
else:
return {"status": "error", "error": f"Unknown operation: {operation}"}
[文档]
def _get_interactions(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""
Get chemical-protein interactions.
Endpoint: GET /json/interactions
"""
# Accept 'chemical' or 'chemicals' as alias for 'identifiers'
identifiers = (
arguments.get("identifiers")
or arguments.get("chemical")
or arguments.get("chemicals")
or []
)
if not identifiers:
return {
"status": "error",
"error": "identifiers parameter is required (chemical names or IDs)",
}
if isinstance(identifiers, str):
identifiers = [identifiers]
# Normalize CID format: CID000002244 → CIDm00002244 (STITCH uses 'm' prefix)
import re
def _normalize_cid(id_str):
m = re.match(r"^CID0*(\d+)$", id_str, re.IGNORECASE)
if m:
return f"CIDm{int(m.group(1)):08d}"
return id_str
identifiers = [_normalize_cid(i) for i in identifiers]
params = {
"identifiers": "%0D".join(identifiers), # URL-encoded newline separator
"species": arguments.get("species", 9606), # Default: human
"limit": arguments.get("limit", 10),
"required_score": arguments.get("required_score", 400), # Medium confidence
}
try:
response = requests.get(
f"{STITCH_BASE_URL}/json/interactions",
params=params,
timeout=self.timeout,
)
if response.status_code == 404:
return {
"status": "error",
"error": f"No interactions found for {identifiers} in STITCH. "
"Try using CID identifiers (e.g., 'CIDm00002244' for aspirin) "
"or check compound names at http://stitch.embl.de/",
}
response.raise_for_status()
return {"status": "success", "data": response.json()}
except requests.RequestException as e:
return {"status": "error", "error": f"STITCH API request failed: {str(e)}"}
[文档]
def _get_interactors(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""
Get interaction partners for a chemical or protein.
Endpoint: GET /json/interactors
"""
identifiers = arguments.get("identifiers", [])
if not identifiers:
return {"status": "error", "error": "identifiers parameter is required"}
if isinstance(identifiers, str):
identifiers = [identifiers]
params = {
"identifiers": "%0D".join(identifiers),
"species": arguments.get("species", 9606),
"limit": arguments.get("limit", 10),
}
try:
response = requests.get(
f"{STITCH_BASE_URL}/json/network",
params=params,
timeout=self.timeout,
)
if response.status_code == 404:
return {
"status": "error",
"error": f"No interactors found for {identifiers} in STITCH. "
"Try using CID identifiers or check compound names at http://stitch.embl.de/",
}
response.raise_for_status()
return {"status": "success", "data": response.json()}
except requests.RequestException as e:
return {"status": "error", "error": f"STITCH API request failed: {str(e)}"}
[文档]
def _resolve_identifiers(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
"""
Resolve chemical/protein names to STITCH identifiers.
Endpoint: GET /json/resolve
"""
identifier = arguments.get("identifier", "")
if not identifier:
return {"status": "error", "error": "identifier parameter is required"}
params = {"identifier": identifier, "species": arguments.get("species", 9606)}
try:
response = requests.get(
f"{STITCH_BASE_URL}/json/resolve",
params=params,
timeout=self.timeout,
)
if response.status_code == 404:
return {
"status": "error",
"error": f"Identifier '{identifier}' not found in STITCH. "
"Try using CID identifiers or check at http://stitch.embl.de/",
}
response.raise_for_status()
return {"status": "success", "data": response.json()}
except requests.RequestException as e:
return {"status": "error", "error": f"STITCH API request failed: {str(e)}"}