Metadata-Version: 2.4
Name: memu-medical
Version: 2.2.0
Summary: MeMu SDK — Python client for the MeMu medical AI platform (FHIR-ready)
Author-email: MeMu <juan.c.lavieri@memu.life>
License-Expression: MIT
Project-URL: Homepage, https://memu.life
Project-URL: Repository, https://github.com/Medical-Multimodal/memu-next
Keywords: medical,healthcare,fhir,ehr,transcription,ai
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Classifier: Intended Audience :: Healthcare Industry
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.25
Requires-Dist: websockets>=13.0
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Dynamic: license-file

# MeMu Python SDK

Python client library for the MeMu medical AI platform.

See the [changelog](CHANGELOG.md) for release history and
[license](LICENSE) for usage terms.

## Documentation

Complete documentation — every module with request and response examples, the
full SDK reference, the REST API, billing, limits, and errors — lives at
<https://memu.life/docs>. The same content is available as one Markdown
document for AI agents and tooling at <https://memu.life/llms-full.txt>
(index: <https://memu.life/llms.txt>).

## Installation

```bash
pip install memu-medical
```

From a checkout of this repository: `pip install -e ./sdk`.

## Quick Start

```python
from memu import MeMuClient, MedicalEntityExtractor

# Option 1: Cognito client_credentials (recommended for server-to-server)
client = MeMuClient(
    base_url="https://your-api.execute-api.us-east-1.amazonaws.com",
    client_id="<cognito-client-id>",
    client_secret="<cognito-client-secret>",
    token_url="https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/token",
)

# Option 2: Pre-obtained Bearer token
client = MeMuClient(
    base_url="https://your-api.execute-api.us-east-1.amazonaws.com",
    token="<access-token>",
)

# Extract medical entities
extractor = MedicalEntityExtractor(client)
result = extractor.extract_medical_entities(
    transcript="Patient takes Lisinopril 10mg daily for hypertension",
)
print(result)

client.close()
```

## Available Services

| Class | Method | Description |
|-------|--------|-------------|
| `MedicalEntityExtractor` | `extract_medical_entities()` | Extract medications, diseases, procedures |
| `MedicalEntityExtractorFHIR` | `extract_medical_entities()` | FHIR Bundle output |
| `DrugInteractionChecker` | `orchestrate_interaction_check()` | Check drug-drug interactions |
| `DrugInteractionCheckerFHIR` | `orchestrate_interaction_check_fhir()` | FHIR DetectedIssue output |
| `HCPCSCodeOrchestrator` | `suggest_hcpcs_code()` | Suggest HCPCS codes |
| `HCPCSCodeOrchestratorFHIR` | `orchestrate_hcpcs_fhir()` | FHIR Procedure output |
| `ICD10CodeOrchestrator` | `suggest_icd10_code()` | Suggest ICD-10 codes |
| `ICD10CodeOrchestratorFHIR` | `orchestrate_icd10_fhir()` | FHIR Condition output |
| `MedicalSummarizer` | `summarize_medical_info()` | Summarize clinical notes |
| `MedicalSummarizerFHIR` | `summarize_medical_info_fhir()` | FHIR Composition output |
| `Audio` | `transcribe_audio_file()` | Transcribe audio files |
| `AudioFHIR` | `transcribe_audio_file()` | FHIR DocumentReference output |

## Async client

`AsyncMeMuClient` mirrors `MeMuClient` for asyncio apps (e.g. FastAPI), so
long-running submit-and-poll never blocks the event loop:

```python
import asyncio

from memu import AsyncMeMuClient


async def main():
    async with AsyncMeMuClient.from_env() as client:
        result = await client.submit_and_poll(
            "/summarization/summarize_medical_info",
            {"transcript": "…", "medical_records": []},
        )
        print(result)


asyncio.run(main())
```

Both clients share the same resilience: retries with backoff/`Retry-After`,
idempotency-safe POST (never double-creates a task), single 401 re-auth, and
`base_url` validation.

## Exactly-once submissions

Pass `idempotency_key` (your encounter or document identifier) to any helper
method, `submit_and_poll`, or `post`. The API creates at most one task per
clinic for that key and replays the original `202` on repeats, so the SDK can
retry the submission after a timeout or a 5xx without double billing:

```python
summary = MedicalSummarizer(client).summarize_medical_info(
    transcript=text,
    idempotency_key=f"encounter-{encounter_id}-summary",
)
```

## Errors

| Exception | When |
|---|---|
| `InsufficientBalanceError` (402) | The clinic wallet is empty, or a finished task's result is withheld until funds arrive |
| `RateLimitError` (429) | Rate limit or the 10-tasks-in-flight clinic limit after every retry; `retry_after` in seconds |
| `TaskError` | The task finished `FAILED` |
| `TaskTimeoutError` | The task did not finish within the timeout (outcome unknown; poll again before resubmitting) |
| `AuthError` | Missing credentials or the token request failed |
| `MeMuError` | Any other HTTP failure (`status_code`, `detail`) or exhausted network retries |

## Running Tests

```bash
cd sdk
export MEMU_BASE_URL="https://your-api.execute-api.us-east-1.amazonaws.com"
export MEMU_CLIENT_ID="<cognito-client-id>"
export MEMU_CLIENT_SECRET="<cognito-client-secret>"
export MEMU_TOKEN_URL="https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/token"

python3 -m pytest tests/ -v
```
