From 9f6a71cb247025901fad79ec4af7a070d8cf642a Mon Sep 17 00:00:00 2001 From: CI-DEV <154627941+IlumCI@users.noreply.github.com> Date: Mon, 6 Oct 2025 20:30:07 +0300 Subject: [PATCH] Add files via upload --- examples/aop_examples/medical_aop/client.py | 113 +++++++++++++ examples/aop_examples/medical_aop/server.py | 166 ++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 examples/aop_examples/medical_aop/client.py create mode 100644 examples/aop_examples/medical_aop/server.py diff --git a/examples/aop_examples/medical_aop/client.py b/examples/aop_examples/medical_aop/client.py new file mode 100644 index 00000000..e6b91c0f --- /dev/null +++ b/examples/aop_examples/medical_aop/client.py @@ -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() diff --git a/examples/aop_examples/medical_aop/server.py b/examples/aop_examples/medical_aop/server.py new file mode 100644 index 00000000..b74059e9 --- /dev/null +++ b/examples/aop_examples/medical_aop/server.py @@ -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()