Skip to content

Commit a7d3d35

Browse files
committed
Updated readme
Signed-off-by: M Q <mingmelvinq@nvidia.com>
1 parent 6d9b380 commit a7d3d35

File tree

1 file changed

+111
-12
lines changed

1 file changed

+111
-12
lines changed

platforms/aidoc/README.md

Lines changed: 111 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,100 @@
1-
# RESTful Wrapper Application for MONAI Deploy
1+
# Creating REST Service with MONAI Deploy Application
22

3-
This application provides a RESTful web interface to run MONAI Deploy applications.
3+
This application provides an example of how to make a MONAI Deploy app run as a REST service on [Aidoc](https://www.aidoc.com/) platform. It is compliant with its [third party integration API](https://ai-partner-sdk.aidoc-cloud.com/prod/api/third-parties/doc/#), and the results [callback message schema](https://ai-partner-sdk.aidoc-cloud.com/prod/api/aidoc-callback/doc/#).
44

5-
It allows you to start a processing job, check the status, and receive a callback when the job is complete.
5+
This example uses a subset of the callback message attributes, covering only the required ones as well as some common attributes. For the full message definition, please contact Aidoc directly.
66

7-
As it stands now, the callback message content is stubbed/generated in the wrapper app, and this will change to the design
8-
where the wrapper app will pass a static callback function to the MONAI Deploy app which will have a reporter operator
9-
that gathers the operations and domain specific info in the app's pipeline and then reports back the content via
10-
this callback. The wrapper app will then have a mapping function to transform the reported data to that expected by
11-
the external callback endpoint.
7+
## High Level Design
128

13-
Also, the whole Restful application can be packaged into a container image using MONAI Deploy app packager, but not doner here.
9+
The high-level design of this REST service involves a few key components:
10+
11+
1. **MONAI Deploy Application**: The core AI logic is encapsulated in a standard MONAI Deploy application (e.g., `AISpleenSegApp`), which is built and tested as a regular containerized workload.
12+
2. **RESTful Service**: A lightweight RESTful application, built using Flask, acts as the front-end. It exposes endpoints to start and check the status of a processing job.
13+
3. **Request Handling**:
14+
- When the RESTful service receives a request to process data, it handles only one request at a time, as per the API specification.
15+
- It creates an instance of the MONAI Deploy application.
16+
- It sets the necessary environment variables for the input and output folders.
17+
- Crucially, it delegates the execution of the MONAI Deploy application to a separate background thread to avoid blocking the web server.
18+
4. **Callback Mechanism**:
19+
- The callback message, which includes the AI results and a list of output files, is generated within the MONAI Deploy application at the end of its run.
20+
- This message is then passed to a callback function that was provided by the REST service during the creation of the MONAI Deploy app instance.
21+
- The REST service, upon receiving the callback, is then responsible for making the final `POST` request to the external callback endpoint specified by the original caller.
22+
23+
This design separates the core AI application from the web-serving logic, allowing each to be developed and tested independently.
24+
25+
## Diagrams
26+
27+
### Component Diagram
28+
29+
This diagram shows the static components of the system and their relationships using the C4 model.
30+
31+
```mermaid
32+
C4Component
33+
title Component Diagram for MONAI Deploy REST Service
34+
35+
Person(client, "External Client", "e.g., Aidoc Platform")
36+
37+
Container_Boundary(rest_service_container, "RESTful Service") {
38+
Component(flask, "Flask App", "Python, Flask", "Handles HTTP requests, manages processing threads, and sends callbacks.")
39+
}
40+
41+
Container_Boundary(monai_app_container, "MONAI Deploy Application") {
42+
Component(monai_app, "AISpleenSegApp", "Python, MONAI Deploy SDK", "Orchestrates the AI inference pipeline and prepares the result message.")
43+
Component(operators, "MONAI Deploy Operators", "Python, MONAI Deploy SDK", "Perform tasks like data loading, inference, and writing results.")
44+
}
45+
46+
System_Ext(fs, "Filesystem", "Stores input/output data.")
47+
48+
Rel(client, flask, "1. Sends processing request", "JSON/HTTPS")
49+
Rel(flask, client, "2. Responds 202 Accepted")
50+
Rel(flask, monai_app, "3. Instantiates & runs in background thread")
51+
Rel(monai_app, operators, "4. Uses operators to process data")
52+
Rel(monai_app, fs, "5. Reads from & Writes to")
53+
Rel(monai_app, flask, "6. Invokes callback on completion")
54+
Rel(flask, client, "7. Sends final results", "JSON/HTTPS")
55+
```
56+
57+
### Sequence Diagram
58+
59+
This diagram illustrates the sequence of interactions for a processing job, including status checks.
60+
61+
```mermaid
62+
sequenceDiagram
63+
actor Client
64+
participant RESTful Service
65+
participant "MONAI Deploy App Thread" as AppThread
66+
participant AISpleenSegApp
67+
68+
Client->>+RESTful Service: POST /process (payload)
69+
RESTful Service-->>-Client: HTTP 202 Accepted
70+
RESTful Service->>+AppThread: Spawn thread(run_processing)
71+
72+
opt While processing is busy
73+
Client->>+RESTful Service: POST /process (payload)
74+
RESTful Service-->>-Client: HTTP 409 Conflict
75+
76+
Client->>+RESTful Service: GET /status
77+
RESTful Service-->>-Client: HTTP 200 OK ("status": "BUSY")
78+
end
79+
80+
AppThread->>+AISpleenSegApp: Create instance(status_callback)
81+
AppThread->>AISpleenSegApp: run()
82+
Note over AISpleenSegApp: Executes processing pipeline...
83+
AISpleenSegApp->>AISpleenSegApp: Formats success message
84+
AISpleenSegApp->>AppThread: status_callback (message)
85+
86+
AISpleenSegApp-->>AppThread: run() completes successfully
87+
deactivate AISpleenSegApp
88+
AppThread->>AppThread: Formats final message
89+
AppThread->>+Client: POST callback_url (Final Results)
90+
Client-->>-AppThread: HTTP 200 OK
91+
92+
Note over RESTful Service: Processing status set to IDLE.
93+
deactivate AppThread
94+
95+
Client->>+RESTful Service: GET /status
96+
RESTful Service-->>-Client: HTTP 200 OK ("status": "IDLE")
97+
```
1498

1599
## How to Run
16100

@@ -131,10 +215,25 @@ When processing is complete, the application will send a `POST` request to the `
131215
```json
132216
{
133217
"run_success": true,
134-
"result": "Processing completed successfully.",
135-
"output_files": ["test.json", "seg.com"],
218+
"output_files": ["output_spleen/1.2.826.0.1.3680043.10.511.3.13787585732573161684951883631909444.dcm", "output_spleen/stl/spleen.stl"],
136219
"error_message": null,
137-
"error_code": null
220+
"error_code": null,
221+
"result": {
222+
"aggregated_results": {
223+
"name": "Spleen Segmentation",
224+
"algorithm_class": ["Measurement"]
225+
},
226+
"detailed_results":{
227+
"Spleen Segmentation": {
228+
"detection": null,
229+
"measurement": {
230+
"measurements_text": "Spleen segmentation completed successfully.", "key_slice_instance_uid": null,
231+
"key_measurement": null
232+
},
233+
"classification": null
234+
}
235+
}
236+
}
138237
}
139238
```
140239

0 commit comments

Comments
 (0)