Skip to content

Commit a05bae3

Browse files
authored
Merge pull request #14 from AI4REALNET/main
Merge updates done on AI4RealNet
2 parents 4abc5cc + 4416fcd commit a05bae3

File tree

33 files changed

+488
-199
lines changed

33 files changed

+488
-199
lines changed

.gitattributes

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
* text=auto
2+
*.sh text eol=lf
3+
*.conf text eol=lf
4+
*.bash text eol=lf
5+
*.yml text eol=lf

README.md

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@ The platform uses the project **OperatorFabric** for notification management.
4949
### Prerequisites
5050

5151
- [Git (version 2.40.1)](https://git-scm.com/)
52-
- [Docker (version 24.0.2)](https://www.docker.com/)
53-
- [Docker Compose (version 1.25.0 or later)](https://www.docker.com/)
52+
- [Docker Engine (version 27)](https://www.docker.com/)
53+
- [Docker Compose V2](https://www.docker.com/)
5454

5555

5656
### Setting Up the Environment
5757

5858
Clone the repo of the assistant
5959

6060
```sh
61-
git clone https://github.com/IRT-SystemX/InteractiveAI.git
61+
git clone [repo-url]
6262
```
6363

6464
## Usage
@@ -68,7 +68,7 @@ Below are the steps to start all services. For other methods, please consult the
6868

6969
### Running All Services (Dev Mode)
7070

71-
1. Set-up environement variables
71+
1. **Set-up environement variables**
7272

7373

7474
`VITE_POWERGRID_SIMU`, `VITE_RAILWAY_SIMU` , `VITE_ATM_SIMU` are the simulators' endpoints.
@@ -84,31 +84,34 @@ export VITE_ATM_SIMU=http://[Service url]:[Service port]
8484
> **_NOTE:_** For this step, you should already have a running simulator. If not, you can use the simulator we provided as an example. For this, please follow the tutorial provided in InteractiveAI/usecases_examples/PowerGrid/ then set the VITE_POWERGRID_SIMU variable to http://YOUR_SERVER_ADDRESS:5100/
8585
>
8686
>
87-
2. Run InteractiveAI assistant
87+
2. **Run InteractiveAI assistant**
8888
```sh
8989
cd config/dev/cab-standalone
9090
./docker-compose.sh
9191
```
9292
> **_NOTE:_** You will see the word cab (Cockpit Assistant Bidirectionnel) on most files in the project. Note that it was the initial project name of InteractiveAI. Might be updated later.
9393
94-
3. Setting up Keycloak `Frontend URL`
95-
* **Access Keycloak Interface**:
94+
3. **Setting up Keycloak `Frontend URL`**
95+
* Access Keycloak Interface:
9696
- Ensure that your Keycloak instance is running and accessible.
9797
- Open a web browser and navigate to the Keycloak admin console, typically available at `http://localhost:89/auth/admin`.
98-
* **Login to Keycloak Admin Console**:
98+
* Login to Keycloak Admin Console:
9999
- Log in to the Keycloak admin console using your administrator credentials (`admin:admin` by default)
100-
* **Navigate to Client Settings**:
100+
* Configure frontendUrl:
101+
- On the Keycloak admin console, locate and click on the "Realm Settings" section.
102+
- In the Frontend URL setting, add the URL of your Assistant Platform frontend as a valid redirect URI. This URL is typically where your frontend application is hosted. For example, if your frontend is hosted locally for development purposes, you might add `http://localhost:3200/*`.
103+
- After adding the frontend URL, save the changes to update the client settings.
104+
* Configure Valid Redirect URIs:
101105
- On the Keycloak admin console, locate and click on the "Clients" section.
102106
- Select the client representing your Assistant Platform application.
103-
* **Configure FrontendUrl**:
104107
- Within the client settings, look for the "Valid Redirect URIs" or similar configuration field.
105-
- Add the URL of your Assistant Platform frontend as a valid redirect URI. This URL is typically where your frontend application is hosted. For example, if your frontend is hosted locally for development purposes, you might add `http://localhost:3200/*`.
106-
- Ensure that the frontend URL you specify matches the actual URL where your frontend application is accessible.
107-
* **Save Changes**:
108-
- After adding the frontend URL, save the changes to update the client settings.
108+
- Add the URL of your Assistant Platform frontend, it should match the one used in the frontendUrl setting.
109+
- After adding the Valid Redirect URIs, save the changes to update the client settings.
110+
111+
112+
4. **Load resources**
109113

110-
4. Load resources
111-
**WARINING:** You need to restart the frontend after updating the URL on keycloak do it before loading the resources.
114+
**WARNING:** You need to restart the frontend after updating the URL on keycloak do it before loading the resources.
112115
```sh
113116
docker restart frontend
114117
```

backend/context-service/resources/ATM/schemas.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,35 @@
22

33
from api.schemas import MetadataSchema
44
from apiflask.fields import Dict, String, Float, List, Integer
5-
class MetadataSchemaATM(MetadataSchema):
5+
from apiflask import Schema, fields
6+
from marshmallow import pre_load
7+
class PlaneMetadataSchemaATM(MetadataSchema):
8+
id_plane = String()
69
ApDest = Dict()
710
Current_airspeed = Float()
811
Latitude = Float()
912
Longitude = Float()
1013
wpList = List(Dict())
11-
id_plane = Integer()
14+
15+
class MetadataSchemaATM(MetadataSchema):
16+
airplanes = List(fields.Nested(PlaneMetadataSchemaATM), required=True)
17+
18+
# Backward compatibility: optional fields for the single airplane case
19+
ApDest = Dict(required=False)
20+
Current_airspeed = Float(required=False)
21+
Latitude = Float(required=False)
22+
Longitude = Float(required=False)
23+
wpList = List(Dict(), required=False)
24+
25+
@pre_load
26+
def handle_backward_compatibility(self, data, **kwargs):
27+
# If the new 'airplanes' field is not provided, assume the old format.
28+
if 'airplanes' not in data:
29+
airplane = {}
30+
for field in ['ApDest', 'Current_airspeed', 'Latitude', 'Longitude', 'wpList']:
31+
if field in data:
32+
airplane[field] = data[field]
33+
# Provide a default id_plane if not present.
34+
airplane.setdefault('id_plane', "X")
35+
data['airplanes'] = [airplane]
36+
return data

backend/recommendation-service/resources/PowerGrid/PowerGridgrid2op_poc_simulator/assistant_manager.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def get_parade_info(self, act):
196196
"Redispatch" # pour renvoyer le kpi type_of_the_reco
197197
)
198198
title.append(
199-
"Parade injection: redispatch de source de production"
199+
"Injection recommendation: production source redispatch"
200200
)
201201
cpt = 0
202202
for gen_idx in range(act.n_gen):
@@ -213,9 +213,9 @@ def get_parade_info(self, act):
213213
# storage
214214
if act._modif_storage:
215215
kpis["type_of_the_reco"] = (
216-
"Stockage" # pour renvoyer le kpi type_of_the_reco
216+
"Storage" # pour renvoyer le kpi type_of_the_reco
217217
)
218-
title.append("Parade stockage")
218+
title.append("Storage recommendation")
219219
cpt = 0
220220
for stor_idx in range(act.n_storage):
221221
amount_ = act._storage_power[stor_idx]
@@ -225,8 +225,8 @@ def get_parade_info(self, act):
225225
description.append(", ")
226226
cpt = 1
227227
description.append(
228-
f'Demande à l\'unité "{name_}" de '
229-
f'{"charger" if amount_ > 0.0 else "decharger"} '
228+
f'Ask unit "{name_}" to '
229+
f'{"charge" if amount_ > 0.0 else "discharge"} '
230230
f'{abs(amount_):.2f} MW (setpoint: {amount_:.2f} MW)'
231231
)
232232

@@ -235,7 +235,7 @@ def get_parade_info(self, act):
235235
kpis["type_of_the_reco"] = (
236236
"Injection" # pour renvoyer le kpi type_of_the_reco
237237
)
238-
title.append("Parade injection")
238+
title.append("Injection recommendation")
239239
cpt = 0
240240
for gen_idx in range(act.n_gen):
241241
amount_ = act._curtail[gen_idx]
@@ -245,71 +245,71 @@ def get_parade_info(self, act):
245245
description.append(", ")
246246
cpt = 1
247247
description.append(
248-
f'Limiter l\'unité "{name_}" à '
249-
f'{100.0 * amount_:.1f}% de sa capacité max '
248+
f'Limit unit "{name_}" to '
249+
f'{100.0 * amount_:.1f}% of its maximum capacity '
250250
f'(setpoint: {amount_:.3f})'
251251
)
252252

253253
# force line status
254254
force_line_impact = impact["force_line"]
255255
if force_line_impact["changed"]:
256256
kpis["type_of_the_reco"] = (
257-
"Topologique" # pour renvoyer le kpi type_of_the_reco
257+
"Topological" # pour renvoyer le kpi type_of_the_reco
258258
)
259259
title.append(
260-
"Parade topologique: connection/deconnection de ligne"
260+
"Topological recommendation: connection/disconnection of line"
261261
)
262262
reconnections = force_line_impact["reconnections"]
263263
if reconnections["count"] > 0:
264264
description.append(
265-
f"Reconnection de {reconnections['count']} lignes "
265+
f"Reconnection of {reconnections['count']} lines "
266266
f"({reconnections['powerlines']})"
267267
)
268268

269269
disconnections = force_line_impact["disconnections"]
270270
if disconnections["count"] > 0:
271271
description.append(
272-
f"Déconnection de {disconnections['count']} lignes "
272+
f"Disconnection of {disconnections['count']} lines "
273273
f"({disconnections['powerlines']})"
274274
)
275275

276276
# swtich line status
277277
swith_line_impact = impact["switch_line"]
278278
if swith_line_impact["changed"]:
279279
kpis["type_of_the_reco"] = (
280-
"Topologique" # pour renvoyer le kpi type_of_the_reco
280+
"Topological" # pour renvoyer le kpi type_of_the_reco
281281
)
282-
title.append("Parade topologique: changer l'état d'une ligne")
282+
title.append("Topological: change a line state")
283283
description.append(
284-
f"Changer le statut de {swith_line_impact['count']} lignes "
284+
f"Change the state of {swith_line_impact['count']} lines "
285285
f"({swith_line_impact['powerlines']})"
286286
)
287287

288288
# topology
289289
bus_switch_impact = impact["topology"]["bus_switch"]
290290
if len(bus_switch_impact) > 0:
291291
kpis["type_of_the_reco"] = (
292-
"Topologique" # pour renvoyer le kpi type_of_the_reco
292+
"Topological" # pour renvoyer le kpi type_of_the_reco
293293
)
294294
title.append(
295-
"Parade topologique: prise de schéma au poste "
295+
"Topological recommendation: Schematic acquisition at substation "
296296
+ str(bus_switch_impact["substation"])
297297
)
298-
description.append("Changement de bus:")
298+
description.append("Busbar change:")
299299
for switch in bus_switch_impact:
300300
description.append(
301-
f"\t \t - Switch bus de {switch['object_type']} id "
302-
f"{switch['object_id']} [au poste {switch['substation']}]"
301+
f"\t \t - Switch bus of {switch['object_type']} id "
302+
f"{switch['object_id']} [at station {switch['substation']}]"
303303
)
304304

305305
assigned_bus_impact = impact["topology"]["assigned_bus"]
306306
disconnect_bus_impact = impact["topology"]["disconnect_bus"]
307307
if len(assigned_bus_impact) > 0 or len(disconnect_bus_impact) > 0:
308308
kpis["type_of_the_reco"] = (
309-
"Topologique" # pour renvoyer le kpi type_of_the_reco
309+
"Topological" # pour renvoyer le kpi type_of_the_reco
310310
)
311311
title.append(
312-
"Parade topologique: prise de schéma au poste "
312+
"Topological recommendation: Schematic acquisition at substation "
313313
+ str(assigned_bus_impact[0]["substation"])
314314
)
315315
if assigned_bus_impact:
@@ -320,7 +320,7 @@ def get_parade_info(self, act):
320320
description.append(", ")
321321
cpt = 1
322322
description.append(
323-
f" Assigner le bus {assigned['bus']} à "
323+
f" Assign bus {assigned['bus']} to "
324324
f"{assigned['object_type']} id {assigned['object_id']}"
325325
)
326326
if disconnect_bus_impact:
@@ -331,20 +331,20 @@ def get_parade_info(self, act):
331331
description.append(", ")
332332
cpt = 1
333333
description.append(
334-
f"Déconnecter {disconnected['object_type']} avec l'id "
335-
f"{disconnected['object_id']} [au niveau du poste "
334+
f"Disconnect {disconnected['object_type']} with id "
335+
f"{disconnected['object_id']} [at the substation level "
336336
f"{disconnected['substation']}]"
337337
)
338338

339339
# Any of the above cases,
340340
# then the recommendation is most likely "Do nothing"
341341
if not title and act == self.action_do_nothing:
342342
kpis["type_of_the_reco"] = (
343-
"Ne rien faire" # pour renvoyer le kpi type_of_the_reco
343+
"Do nothing" # pour renvoyer le kpi type_of_the_reco
344344
)
345345
title.append("Poursuivre")
346346
description.append(
347-
"Poursuite du scénario sans intervention extérieur"
347+
"Continuation of the scenario without operator action"
348348
)
349349

350350
title = "".join(title)

backend/recommendation-service/resources/PowerGrid/manager.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ def get_onto_recommendation(self, event_line):
6161
"""
6262
# Default output
6363
output_json = {
64-
"title": "Parade ontologique par defaut",
64+
"title": "Default Ontology Recommendation",
6565
"description": (
66-
"Aucune recommandation n’a pu être générée car cette surcharge "
67-
"n’a jamais été observée dans le passé"
66+
"No recommendation has been found for this overload, because "
67+
"it has not been observed in the past."
6868
),
6969
"use_case": "PowerGrid",
7070
"agent_type": AgentType.onto.name,
@@ -198,7 +198,7 @@ def get_onto_recommendation(self, event_line):
198198
)[0][0]
199199
output_json = {
200200
"title": recommendation,
201-
"description": f"Cette parade a été rencontrée {nb_similar_situations} fois dans le passé.",
201+
"description": f"This pattern has been observed {nb_similar_situations} times in the past.",
202202
"use_case": "PowerGrid",
203203
"agent_type": AgentType.onto.name,
204204
"actions": [action_dict],

backend/recommendation-service/resources/Railway/manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# backend/recommendation-service/resources/RTE/manager.py
1+
# backend/recommendation-service/resources/Railway/manager.py
22

33
from api.manager.base_manager import BaseRecommendationManager
44

config/dev/cab-standalone/docker-compose.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ fi
4444
echo "HOST_IP=${HOST_IP}" >> .env
4545

4646
cat .env
47-
docker-compose up -d
47+
docker compose up -d

config/dev/cab-standalone/nginx-cors-permissive.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# docker-compose DNS used to resolved keycloak services
1+
# docker compose DNS used to resolved keycloak services
22
resolver 127.0.0.11 ipv6=off;
33
server {
44
listen 80;

config/dev/cab-standalone/nginx-kubernetes.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# docker-compose DNS used to resolved users service
1+
# docker compose DNS used to resolved users service
22
# resolver 127.0.0.11 ipv6=off;
33

44
# Log format to have msec in time + request processing time

config/dev/cab-standalone/nginx.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# docker-compose DNS used to resolved users service
1+
# docker compose DNS used to resolved users service
22
resolver 127.0.0.11 ipv6=off;
33

44
# Log format to have msec in time + request processing time

0 commit comments

Comments
 (0)