parent
20d7ee580f
commit
9f6a71cb24
@ -0,0 +1,113 @@
|
||||
import asyncio
|
||||
import json
|
||||
from typing import Dict
|
||||
|
||||
import requests
|
||||
|
||||
from swarms.structs.aop import AOPCluster
|
||||
from swarms.tools.mcp_client_tools import execute_tool_call_simple
|
||||
|
||||
|
||||
def _select_tools_by_keyword(tools: list, keyword: str) -> list:
|
||||
"""
|
||||
Return tools whose name or description contains the keyword
|
||||
(case-insensitive).
|
||||
"""
|
||||
kw = keyword.lower()
|
||||
selected = []
|
||||
for t in tools:
|
||||
name = t.get("function", {}).get("name", "")
|
||||
desc = t.get("function", {}).get("description", "")
|
||||
if kw in name.lower() or kw in desc.lower():
|
||||
selected.append(t)
|
||||
return selected
|
||||
|
||||
|
||||
def _example_payload_from_schema(tools: list, tool_name: str) -> dict:
|
||||
"""
|
||||
Construct a minimal example payload for a given tool using its JSON schema.
|
||||
Falls back to a generic 'task' if schema not present.
|
||||
"""
|
||||
for t in tools:
|
||||
fn = t.get("function", {})
|
||||
if fn.get("name") == tool_name:
|
||||
schema = fn.get("parameters", {})
|
||||
required = schema.get("required", [])
|
||||
props = schema.get("properties", {})
|
||||
payload = {}
|
||||
for r in required:
|
||||
if r in props:
|
||||
if props[r].get("type") == "string":
|
||||
payload[r] = (
|
||||
"Example patient case: 45M, egfr 59 ml/min/1.73"
|
||||
)
|
||||
elif props[r].get("type") == "boolean":
|
||||
payload[r] = False
|
||||
else:
|
||||
payload[r] = None
|
||||
if not payload:
|
||||
payload = {
|
||||
"task": "Provide ICD-10 suggestions for the case above"
|
||||
}
|
||||
return payload
|
||||
return {"task": "Provide ICD-10 suggestions for the case above"}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
cluster = AOPCluster(
|
||||
urls=["http://localhost:8000/mcp"],
|
||||
transport="streamable-http",
|
||||
)
|
||||
|
||||
tools = cluster.get_tools(output_type="dict")
|
||||
print(f"Tools: {len(tools)}")
|
||||
|
||||
coding_tools = _select_tools_by_keyword(tools, "coder")
|
||||
names = [t.get("function", {}).get("name") for t in coding_tools]
|
||||
print(f"Coding-related tools: {names}")
|
||||
|
||||
# Build a real payload for "Medical Coder" and execute the tool call
|
||||
tool_name = "Medical Coder"
|
||||
payload: Dict[str, object] = _example_payload_from_schema(tools, tool_name)
|
||||
|
||||
# Enrich with public keyless data (epidemiology context via disease.sh)
|
||||
try:
|
||||
epi = requests.get(
|
||||
"https://disease.sh/v3/covid-19/countries/USA?strict=true",
|
||||
timeout=5,
|
||||
)
|
||||
if epi.ok:
|
||||
data = epi.json()
|
||||
epi_summary = (
|
||||
f"US COVID-19 context: cases={data.get('cases')}, "
|
||||
f"todayCases={data.get('todayCases')}, deaths={data.get('deaths')}"
|
||||
)
|
||||
base_task = payload.get("task") or ""
|
||||
payload["task"] = (
|
||||
f"{base_task}\n\nEpidemiology context (no key API): {epi_summary}"
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
print("Calling tool:", tool_name)
|
||||
request = {
|
||||
"function": {
|
||||
"name": tool_name,
|
||||
"arguments": payload,
|
||||
}
|
||||
}
|
||||
result = asyncio.run(
|
||||
execute_tool_call_simple(
|
||||
response=request,
|
||||
server_path="http://localhost:8000/mcp",
|
||||
output_type="json",
|
||||
transport="streamable-http",
|
||||
verbose=False,
|
||||
)
|
||||
)
|
||||
print("Response:")
|
||||
print(result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -0,0 +1,166 @@
|
||||
# Import medical agents defined in the demo module
|
||||
from examples.demos.medical.medical_coder_agent import (chief_medical_officer,
|
||||
internist,
|
||||
medical_coder,
|
||||
synthesizer,
|
||||
virologist)
|
||||
from swarms.structs.aop import AOP
|
||||
|
||||
|
||||
def _enrich_agents_metadata() -> None:
|
||||
"""
|
||||
Add lightweight tags/capabilities/roles to imported agents for
|
||||
better discovery results.
|
||||
"""
|
||||
chief_medical_officer.tags = [
|
||||
"coordination",
|
||||
"diagnosis",
|
||||
"triage",
|
||||
]
|
||||
chief_medical_officer.capabilities = [
|
||||
"case-intake",
|
||||
"differential",
|
||||
"planning",
|
||||
]
|
||||
chief_medical_officer.role = "coordinator"
|
||||
|
||||
virologist.tags = ["virology", "infectious-disease"]
|
||||
virologist.capabilities = ["viral-analysis", "icd10-suggestion"]
|
||||
virologist.role = "specialist"
|
||||
|
||||
internist.tags = ["internal-medicine", "evaluation"]
|
||||
internist.capabilities = [
|
||||
"system-review",
|
||||
"hcc-tagging",
|
||||
"risk-stratification",
|
||||
]
|
||||
internist.role = "specialist"
|
||||
|
||||
medical_coder.tags = ["coding", "icd10", "compliance"]
|
||||
medical_coder.capabilities = [
|
||||
"code-assignment",
|
||||
"documentation-review",
|
||||
]
|
||||
medical_coder.role = "coder"
|
||||
|
||||
synthesizer.tags = ["synthesis", "reporting"]
|
||||
synthesizer.capabilities = [
|
||||
"evidence-reconciliation",
|
||||
"final-report",
|
||||
]
|
||||
synthesizer.role = "synthesizer"
|
||||
|
||||
|
||||
def _medical_input_schema() -> dict:
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"task": {
|
||||
"type": "string",
|
||||
"description": "Patient case or instruction for the agent",
|
||||
},
|
||||
"priority": {
|
||||
"type": "string",
|
||||
"enum": ["low", "normal", "high"],
|
||||
"description": "Processing priority",
|
||||
},
|
||||
"include_images": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to consider linked images if provided",
|
||||
"default": False,
|
||||
},
|
||||
"img": {
|
||||
"type": "string",
|
||||
"description": "Optional image path/URL",
|
||||
},
|
||||
"imgs": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Optional list of images",
|
||||
},
|
||||
},
|
||||
"required": ["task"],
|
||||
"additionalProperties": False,
|
||||
}
|
||||
|
||||
|
||||
def _medical_output_schema() -> dict:
|
||||
return {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"result": {"type": "string"},
|
||||
"success": {"type": "boolean"},
|
||||
"error": {"type": "string"},
|
||||
"confidence": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"maximum": 1,
|
||||
"description": "Optional confidence in the assessment",
|
||||
},
|
||||
"codes": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Optional list of suggested ICD-10 codes",
|
||||
},
|
||||
},
|
||||
"required": ["result", "success"],
|
||||
"additionalProperties": True,
|
||||
}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""
|
||||
Start an AOP MCP server that exposes the medical agents as tools with
|
||||
structured schemas and per-agent settings.
|
||||
"""
|
||||
_enrich_agents_metadata()
|
||||
|
||||
deployer = AOP(
|
||||
server_name="Medical-AOP-Server",
|
||||
port=8000,
|
||||
verbose=False,
|
||||
traceback_enabled=True,
|
||||
log_level="INFO",
|
||||
transport="streamable-http",
|
||||
)
|
||||
|
||||
input_schema = _medical_input_schema()
|
||||
output_schema = _medical_output_schema()
|
||||
|
||||
# Register each agent with a modest, role-appropriate timeout
|
||||
deployer.add_agent(
|
||||
chief_medical_officer,
|
||||
timeout=45,
|
||||
input_schema=input_schema,
|
||||
output_schema=output_schema,
|
||||
)
|
||||
deployer.add_agent(
|
||||
virologist,
|
||||
timeout=40,
|
||||
input_schema=input_schema,
|
||||
output_schema=output_schema,
|
||||
)
|
||||
deployer.add_agent(
|
||||
internist,
|
||||
timeout=40,
|
||||
input_schema=input_schema,
|
||||
output_schema=output_schema,
|
||||
)
|
||||
deployer.add_agent(
|
||||
medical_coder,
|
||||
timeout=50,
|
||||
input_schema=input_schema,
|
||||
output_schema=output_schema,
|
||||
)
|
||||
deployer.add_agent(
|
||||
synthesizer,
|
||||
timeout=45,
|
||||
input_schema=input_schema,
|
||||
output_schema=output_schema,
|
||||
)
|
||||
|
||||
deployer.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in new issue