Here you can find a Python script that automatically handles the uploading of data, defining the project, triggering the simulation, and getting the results.
flowchart TB
upload(Upload the event log file) --> set(Set the columns definition)
set --> create(Create the project)
create --> get(Get the project status)
get --> start(Start the simulation)
start --> read(Read the simulation result)
Prerequisites
Before you start, make sure you have the following packages installed:
According to the script, uploaded event log should be this one, unless you manually modify the columns definition, etc.
Please change the EVENT_LOG_FILE to get the correct path to your local event log file.
Warning
The outcome and treatment of the project defined in exmaple script is only for demonstration purposes. They don’t represent the actual outcome and treatment of the domain, so you can modify them to fit your needs.
importjsonimportpprintimportrequestsimportsseclientfromrequestsimportResponsefromtimeimportsleep# Change this to your own event log fileEVENT_LOG_FILE="./bpic2012-CSV.zip"BASE_URL="http***********"# Please change this to your local instance addressAPI_TOKEN="UaJW0QvkMA1cVnOXB89E0NbLf3JRRoHwv2wWmaY5v=QYpaxr1UD9/FupeZ85sa2r"HEADERS={"Authorization":f"Bearer {API_TOKEN}"}REQUEST_HEADERS={"Authorization":f"Bearer {API_TOKEN}","Content-Type":"application/json"}PROJECT_ID=Nonedefupload_file(file_path)->Response:# Upload a file to the server.url=f"{BASE_URL}/event_log"files=[("file",("bpic2012-CSV.zip",open(file_path,"rb"),"application/zip"))]response=requests.post(url,files=files,headers=HEADERS,data={"separator":","})returnresponsedefset_columns_definition(event_log_id)->Response:# Set the columns definition for the uploaded file.url=f"{BASE_URL}/event_log/{event_log_id}"data={"columns_definition":{"Case ID":"CASE_ID","start_time":"START_TIMESTAMP","end_time":"END_TIMESTAMP","AMOUNT_REQ":"NUMBER","REG_DATE":"DATETIME","Activity":"ACTIVITY","Resource":"RESOURCE"}}response=requests.put(url,json=data,headers=REQUEST_HEADERS)returnresponsedefcreate_project(event_log_id)->Response:# Create a project with the definitionurl=f"{BASE_URL}/project"data={"event_log_id":event_log_id,"positive_outcome":[[{"column":"Activity","operator":"EQUAL","value":"A_APPROVED"}]],"treatment":[[{"column":"Activity","operator":"EQUAL","value":"O_SENT_BACK"}]],"additional_info":{"plugin-causallift-resource-allocation":{"available_resources":["Resource_A","Resource_B","Resource_C","Resource_D","Resource_E","Resource_F","Resource_G","Resource_H","Resource_I","Resource_J","Resource_K","Resource_L","Resource_M","Resource_N","Resource_O","Resource_P","Resource_Q","Resource_R","Resource_S","Resource_T","Resource_U","Resource_V","Resource_W","Resource_X","Resource_Y","Resource_Z"],"treatment_duration":"1h"}}}response=requests.post(url,json=data,headers=REQUEST_HEADERS)returnresponsedefget_project(project_id)->Response:# Get the project definitionurl=f"{BASE_URL}/project/{project_id}"response=requests.get(url,headers=HEADERS)returnresponsedefstart_simulation(project_id)->Response:# Start the simulationurl=f"{BASE_URL}/project/{project_id}/stream/start/simulating"response=requests.put(url,headers=HEADERS)returnresponsedefstop_simulation(project_id)->Response:# Stop the simulationurl=f"{BASE_URL}/project/{project_id}/stream/stop"response=requests.put(url,headers=HEADERS)response.raise_for_status()print("The simulation has been stopped!")returnresponsedefprinting_streaming_response(project_id):# Get a streaming response for the given event feed using sseclient.response=requests.get(f"{BASE_URL}/project/{project_id}/stream/result",stream=True,headers=HEADERS)client=sseclient.SSEClient(response)print("Waiting for events...")foreventinclient.events():ifevent.event!="message":continueevent_data=json.loads(event.data)first_event=event_data[0]prescriptions=first_event["prescriptions"]prescriptions_with_output=[prescriptions[p]forpinprescriptionsifprescriptions[p]["output"]]ifnotprescriptions_with_output:continueprint(f"Received message: {event.event}")print(f"ID: {event.id}")pprint.pprint(prescriptions_with_output,width=120)print("-"*24)defmain():print("\nStaring the client...\n")try:# Upload the event log fileprint("Uploading the event log file...")response=upload_file(EVENT_LOG_FILE)response.raise_for_status()event_log_id=response.json()["event_log_id"]print(f"Event log {event_log_id} has been uploaded!\n")# Set the columns definitionprint("Setting the columns definition...")response=set_columns_definition(event_log_id)response.raise_for_status()print("The columns definition has been set!\n")# Create the projectprint("Creating the project...")response=create_project(event_log_id)response.raise_for_status()project_id=response.json()["project"]["id"]PROJECT_ID=project_idprint(f"Project {project_id} has been created!\n")# Get the project statusprint("Getting the project status...")i=1whileTrue:response=get_project(project_id)project_status=response.json()["project"]["status"]ifproject_status=="TRAINED":breakplugins=response.json()["project"]["plugins"]ifplugins:plugin_statuses=", ".join([plugin["status"]forplugininplugins])print(f"[{i:03d}] Now the project status is {project_status}, and its plugins have statuses {plugin_statuses}")else:print(f"[{i:03d}] Now the project status is {project_status}")sleep(1)i+=1print("The project has been trained!\n")# Start the simulationprint("Starting the simulation...")response=start_simulation(project_id)response.raise_for_status()print("The simulation has been started!\n")# Get the streaming responseprint("Now we are going to get the streaming response...")printing_streaming_response(project_id)exceptKeyboardInterrupt:print("Interrupted by user\n")exceptExceptionase:print(f"Error: {e}\n")finally:PROJECT_IDandstop_simulation(PROJECT_ID)print("Done!\n")if__name__=="__main__":main()
Running the script
To run the script, simply execute the following command:
./venv/bin/python workflow-example.py
Example output
Here is an snippet of the output of the script:
Staring the client...
Uploading the event log file...
Event log 17 has been uploaded!
Setting the columns definition...
The columns definition has been set!
Creating the project...
Project 16 has been created!
Getting the project status...
Now the project status is PREPROCESSING. Waiting for 5 seconds...
Now the project status is PREPROCESSING. Waiting for 5 seconds...
Now the project status is PREPROCESSING. Waiting for 5 seconds...
Now the project status is PREPROCESSING. Waiting for 5 seconds...
Now the project status is PREPROCESSING. It's plugins have status PREPROCESSING, PREPROCESSING, TRAINED. Waiting for 5 seconds...
Now the project status is PREPROCESSING. It's plugins have status PREPROCESSING, PREPROCESSING, TRAINED. Waiting for 5 seconds...
Now the project status is PREPROCESSING. It's plugins have status PREPROCESSING, TRAINED, TRAINED. Waiting for 5 seconds...
Now the project status is PREPROCESSING. It's plugins have status PREPROCESSING, TRAINED, TRAINED. Waiting for 5 seconds...
Now the project status is TRAINING. It's plugins have status TRAINING, TRAINED, TRAINED. Waiting for 5 seconds...
Now the project status is TRAINING. It's plugins have status TRAINING, TRAINED, TRAINED. Waiting for 5 seconds...
The project has been trained!
Starting the simulation...
The simulation has been started!
Now we are going to get the streaming response...
Waiting for events...
Received message: NEW_RESULT
ID: 365
[{'date': '2023-02-14T10:03:25.053610',
'output': 'W_Completeren aanvraag',
'plugin': {'accuracy': 0.5669,
'f1_score': 0.5115,
'model': 3,
'name': 'KNN next activity prediction',
'precision': 0.936,
'recall': 0.5669},
'type': 'NEXT_ACTIVITY'},
{'date': '2023-02-14T10:03:25.064882',
'output': 0.6355,
'plugin': {'accuracy': 0.6527,
'f1_score': 0.5155,
'model': 3,
'name': 'Random forest negative outcome probability',
'precision': 0.7733,
'recall': 0.6527},
'type': 'ALARM'},
{'date': '2023-02-14T10:03:25.682665',
'output': {'cate': 0.6872,
'proba_if_treated': 0.6873,
'proba_if_untreated': 0.0001,
'treatment': [[{'column': 'Activity', 'operator': 'EQUAL', 'value': 'O_SENT_BACK'}]]},
'plugin': {'model': 3, 'name': 'CasualLift treatment effect'},
'type': 'TREATMENT_EFFECT'}]
------------------------
Received message: NEW_RESULT
ID: 371
[{'date': '2023-02-14T10:03:55.610696',
'output': 'W_Afhandelen leads',
'plugin': {'accuracy': 0.5669,
'f1_score': 0.5115,
'model': 3,
'name': 'KNN next activity prediction',
'precision': 0.936,
'recall': 0.5669},
'type': 'NEXT_ACTIVITY'},
{'date': '2023-02-14T10:03:55.622616',
'output': 0.6406,
'plugin': {'accuracy': 0.6527,
'f1_score': 0.5155,
'model': 3,
'name': 'Random forest negative outcome probability',
'precision': 0.7733,
'recall': 0.6527},
'type': 'ALARM'},
{'date': '2023-02-14T10:03:56.230732',
'output': {'cate': 0.6828,
'proba_if_treated': 0.6829,
'proba_if_untreated': 0.0001,
'treatment': [[{'column': 'Activity', 'operator': 'EQUAL', 'value': 'O_SENT_BACK'}]]},
'plugin': {'model': 3, 'name': 'CasualLift treatment effect'},
'type': 'TREATMENT_EFFECT'}]
------------------------
Received message: NEW_RESULT
ID: 372
[{'date': '2023-02-14T10:04:00.686650',
'output': 'W_Completeren aanvraag',
'plugin': {'accuracy': 0.6769,
'f1_score': 0.555,
'model': 4,
'name': 'KNN next activity prediction',
'precision': 0.782,
'recall': 0.6769},
'type': 'NEXT_ACTIVITY'},
{'date': '2023-02-14T10:04:00.700571',
'output': 0.6455,
'plugin': {'accuracy': 0.6468,
'f1_score': 0.5081,
'model': 4,
'name': 'Random forest negative outcome probability',
'precision': 0.7716,
'recall': 0.6468},
'type': 'ALARM'},
{'date': '2023-02-14T10:04:01.397980',
'output': {'cate': 0.679,
'proba_if_treated': 0.6791,
'proba_if_untreated': 0.0001,
'treatment': [[{'column': 'Activity', 'operator': 'EQUAL', 'value': 'O_SENT_BACK'}]]},
'plugin': {'model': 4, 'name': 'CasualLift treatment effect'},
'type': 'TREATMENT_EFFECT'}]
------------------------
Received message: NEW_RESULT
ID: 373
[{'date': '2023-02-14T10:04:05.760306',
'output': 'W_Completeren aanvraag',
'plugin': {'accuracy': 0.6769,
'f1_score': 0.555,
'model': 4,
'name': 'KNN next activity prediction',
'precision': 0.782,
'recall': 0.6769},
'type': 'NEXT_ACTIVITY'},
{'date': '2023-02-14T10:04:05.771450',
'output': 0.63,
'plugin': {'accuracy': 0.6468,
'f1_score': 0.5081,
'model': 4,
'name': 'Random forest negative outcome probability',
'precision': 0.7716,
'recall': 0.6468},
'type': 'ALARM'},
{'date': '2023-02-14T10:04:06.475218',
'output': {'cate': 0.6873,
'proba_if_treated': 0.6874,
'proba_if_untreated': 0.0001,
'treatment': [[{'column': 'Activity', 'operator': 'EQUAL', 'value': 'O_SENT_BACK'}]]},
'plugin': {'model': 4, 'name': 'CasualLift treatment effect'},
'type': 'TREATMENT_EFFECT'}]
------------------------
Interrupted by user
Done!
The example above is tested with the BPI Challenge 2012 dataset.