Skip to content

Commit 32c576d

Browse files
committed
Merge remote-tracking branch 'origin' into Statnett-255
2 parents b2ea531 + 3f6f47c commit 32c576d

File tree

9 files changed

+109
-130
lines changed

9 files changed

+109
-130
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Next release
33

44
* [#255](https://github.com/statnett/Talk2PowerSystem_PM/issues/255): OBO auth flow for Cognite
55
* [#255](https://github.com/statnett/Talk2PowerSystem_PM/issues/255): Update the version of `cognite-sdk` from `7.86.0` to `7.89.0`
6+
* [#256](https://github.com/statnett/Talk2PowerSystem_PM/issues/256): Update the queries for the ontologies and datasets information served from the `__about` endpoint
67
* [#251](https://github.com/statnett/Talk2PowerSystem_PM/issues/251): Change N-Shot tool configuration to default to the base GraphDB
78
* [#251](https://github.com/statnett/Talk2PowerSystem_PM/issues/251): Change N-Shot tool configuration SPARQL query template
89
* [#254](https://github.com/statnett/Talk2PowerSystem_PM/issues/254): Update the version of `ttyg` from `1.9.3` to `1.10.0`, so that the chat bot can run without admin access to GraphDB

src/talk2powersystemllm/agent.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from base64 import b64encode
22
from enum import Enum
33
from pathlib import Path
4+
from typing import Any
45

56
import yaml
67
from langchain_core.language_models import BaseChatModel
@@ -81,17 +82,11 @@ class CogniteSettings(BaseModel):
8182

8283
@model_validator(mode="after")
8384
def check_credentials(self) -> "CogniteSettings":
84-
if self.client_secret:
85-
if self.token_file_path:
86-
raise ValueError("Both token_file_path and client_secret for Cognite are provided. "
87-
"Set only one of them!")
88-
elif self.interactive_client_id:
89-
raise ValueError("Both interactive_client_id and client_secret for Cognite are provided. "
90-
"Set only one of them!")
91-
elif self.token_file_path:
92-
if self.interactive_client_id:
93-
raise ValueError("Both token_file_path and interactive_client_id for Cognite are provided. "
94-
"Set only one of them!")
85+
def exactly_one_is_not_none(*args: Any) -> bool:
86+
return sum(a is not None for a in args) == 1
87+
88+
if not exactly_one_is_not_none(self.client_secret, self.token_file_path, self.interactive_client_id):
89+
raise ValueError("Pass exactly one of 'client_secret', 'token_file_path' or 'interactive_client_id'!")
9590

9691
if self.interactive_client_id and not self.tenant_id:
9792
raise ValueError("Tenant id is required!")

src/talk2powersystemllm/app/server/main.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,17 +410,22 @@ async def get_auth_config(
410410
authority=settings.security.authority,
411411
client_credential=agent_factory.settings.tools.cognite.client_secret,
412412
)
413+
COGNITE_SCOPES = [f"{agent_factory.settings.tools.cognite.base_url}/.default", "offline_access"]
413414

414415

415416
def exchange_obo_for_cognite(user_access_token: str) -> dict:
416-
# Try cache first (MSAL keeps an in-memory cache by default)
417+
result = confidential_app.acquire_token_silent(COGNITE_SCOPES, account=None)
418+
if result:
419+
logging.debug("Cognite token acquired.")
420+
return result["access_token"]
421+
422+
logging.debug("Acquiring token for Cognite using OBO.")
417423
result = confidential_app.acquire_token_on_behalf_of(
418424
user_assertion=user_access_token,
419-
scopes=[f"{agent_factory.settings.tools.cognite.base_url}/.default", "offline_access"],
425+
scopes=COGNITE_SCOPES,
420426
)
421427
if "access_token" not in result:
422-
error_message = (f"Failed to obtain OBO token for Cognite, error: {result.get("error")}, "
423-
f"description: {result.get("error_description")}")
428+
error_message = f"Failed to obtain OBO token for Cognite: {result}"
424429
logging.error(error_message)
425430
raise HTTPException(status_code=401, detail=error_message)
426431
return result
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
PREFIX dcat: <http://www.w3.org/ns/dcat#>
2-
PREFIX onto: <http://www.ontotext.com/>
32
PREFIX dct: <http://purl.org/dc/terms/>
43

5-
SELECT DISTINCT ?uri ?name ?date
6-
FROM onto:explicit {
4+
SELECT ?uri ?name ?date {
75
?uri a dcat:Dataset
6+
OPTIONAL {
7+
?uri dct:description ?name.
8+
FILTER(lang(?name) != "no")
9+
}
10+
OPTIONAL {
11+
?uri dct:title ?name.
12+
}
813
OPTIONAL {
914
SELECT ?uri (SAMPLE(SUBSTR(STR(?dateTime), 1, 10)) AS ?date) {
1015
?uri a dcat:Dataset;
1116
dct:issued ?dateTime
1217
}
1318
GROUP BY ?uri
1419
}
15-
OPTIONAL {
16-
?uri dct:title ?title
17-
}
18-
OPTIONAL {
19-
?uri dct:description ?descr
20-
}
21-
BIND(COALESCE(?title, ?descr) AS ?name)
2220
}
2321
ORDER BY ?name
Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
1-
PREFIX onto: <http://www.ontotext.com/>
21
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
32
PREFIX dct: <http://purl.org/dc/terms/>
43
PREFIX owl: <http://www.w3.org/2002/07/owl#>
54

6-
SELECT ?uri ?name ?version ?date
7-
FROM onto:explicit {
5+
SELECT ?uri ?name ?date ?version {
86
?uri a owl:Ontology.
97
OPTIONAL {
10-
?uri dct:title ?title
8+
?uri rdfs:label ?name
119
}
1210
OPTIONAL {
13-
?uri rdfs:label ?label
11+
?uri dct:title ?name
1412
}
1513
OPTIONAL {
1614
?uri owl:versionInfo ?version
1715
}
1816
OPTIONAL {
1917
?uri dct:modified ?date
2018
}
21-
BIND(COALESCE(?title, ?label) AS ?name)
2219
}
2320
ORDER BY ?name

src/talk2powersystemllm/app/trouble.md

Lines changed: 24 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -536,17 +536,6 @@ Sample Response Body:
536536
"description": "Checks if Redis can be queried.",
537537
"message": "Redis can be queried."
538538
},
539-
{
540-
"status": "OK",
541-
"severity": "HIGH",
542-
"id": "http://talk2powersystem.no/talk2powersystem-api/cognite-healthcheck",
543-
"name": "Cognite Health Check",
544-
"type": "cognite",
545-
"impact": "Chat bot won't be able to query Cognite or tools may not function as expected.",
546-
"troubleshooting": "http://localhost:8000/__trouble#cognite-health-check-status-is-not-ok",
547-
"description": "Checks if Cognite can be queried by listing the time series with limit of 1.",
548-
"message": "Cognite can be queried."
549-
},
550539
{
551540
"status": "OK",
552541
"severity": "HIGH",
@@ -1408,53 +1397,48 @@ Sample Response Body:
14081397
The `ontologies`, `datasets` and `graphdb` sections are updated on a scheduled basis (30 seconds by default). The `agent` and `backend` sections are static and initialized at the start of the application, since the data don't change at run time.
14091398
The SPARQL query, which fetches the `ontologies` data is
14101399
```
1411-
PREFIX onto: <http://www.ontotext.com/>
14121400
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
14131401
PREFIX dct: <http://purl.org/dc/terms/>
14141402
PREFIX owl: <http://www.w3.org/2002/07/owl#>
14151403
1416-
SELECT ?uri ?name ?version ?date
1417-
FROM onto:explicit {
1404+
SELECT ?uri ?name ?date ?version {
14181405
?uri a owl:Ontology.
14191406
OPTIONAL {
1420-
?uri dct:title ?title
1407+
?uri rdfs:label ?name
14211408
}
14221409
OPTIONAL {
1423-
?uri rdfs:label ?label
1410+
?uri dct:title ?name
14241411
}
14251412
OPTIONAL {
14261413
?uri owl:versionInfo ?version
14271414
}
14281415
OPTIONAL {
14291416
?uri dct:modified ?date
14301417
}
1431-
BIND(COALESCE(?title, ?label) AS ?name)
14321418
}
14331419
ORDER BY ?name
14341420
```
14351421
The SPARQL query, which fetches the `datasets` data is
14361422
```
14371423
PREFIX dcat: <http://www.w3.org/ns/dcat#>
1438-
PREFIX onto: <http://www.ontotext.com/>
14391424
PREFIX dct: <http://purl.org/dc/terms/>
14401425
1441-
SELECT DISTINCT ?uri ?name ?date
1442-
FROM onto:explicit {
1426+
SELECT ?uri ?name ?date {
14431427
?uri a dcat:Dataset
1428+
OPTIONAL {
1429+
?uri dct:description ?name.
1430+
FILTER(lang(?name) != "no")
1431+
}
1432+
OPTIONAL {
1433+
?uri dct:title ?name.
1434+
}
14441435
OPTIONAL {
14451436
SELECT ?uri (SAMPLE(SUBSTR(STR(?dateTime), 1, 10)) AS ?date) {
14461437
?uri a dcat:Dataset;
14471438
dct:issued ?dateTime
14481439
}
14491440
GROUP BY ?uri
14501441
}
1451-
OPTIONAL {
1452-
?uri dct:title ?title
1453-
}
1454-
OPTIONAL {
1455-
?uri dct:description ?descr
1456-
}
1457-
BIND(COALESCE(?title, ?descr) AS ?name)
14581442
}
14591443
ORDER BY ?name
14601444
```
@@ -1497,6 +1481,7 @@ experienced with the following:
14971481
* GraphDB
14981482
* Cognite
14991483
* Azure OpenAI
1484+
* OpenID, Microsoft Entra ID
15001485
* Redis
15011486

15021487
## Resolving Known Issues
@@ -1511,10 +1496,6 @@ Most probable cause: ["GraphDB can't be queried or is mis-configured"](#graphdb-
15111496

15121497
Most probable cause: ["GraphDB can't be queried or is mis-configured"](#graphdb-cant-be-queried-or-is-mis-configured)
15131498

1514-
#### Calls made by the LLM agent to the tools `sparql_query`, `autocomplete_search`, `retrieval_search` are failing
1515-
1516-
Most probable cause: ["Cognite can't be queried or is mis-configured"](#cognite-cant-be-queried-or-is-mis-configured)
1517-
15181499
#### Calls made by the LLM agent to the tools `retrieve_time_series`, `retrieve_data_points` are failing
15191500

15201501
Most probable cause: ["Cognite can't be queried or is mis-configured"](#cognite-cant-be-queried-or-is-mis-configured)
@@ -1551,12 +1532,21 @@ This section lists the causes of known issues and provides solutions.
15511532
##### Solution
15521533

15531534
- Make sure Cognite is reachable from the app host.
1554-
- Make sure Cognite credentials are correct.
1535+
- Make sure the application security is enabled, otherwise Cognite won't be accessible.
1536+
- Make sure that in the application configuration in Azure `user impersonation` for Cognite is set under API permissions and is approved.
1537+
- Make sure the property `tools.cognite.client_secret` is set and has a correct value. To create / obtain it you (or your Azure admin) must:
1538+
1. Go to the Azure Portal → Microsoft Entra ID → App registrations → Your FastAPI Backend App
1539+
2. In the left menu, choose Certificates & secrets
1540+
3. Under Client secrets, click ➕ New client secret
1541+
4. Give it a description and choose an expiry (6 months, 12 months, custom)
1542+
5. Click Add
1543+
Azure will show you:
1544+
- Value – this is your actual secret (copy it now → you can’t view it later)
1545+
- Secret ID – an internal reference (not needed in code)
15551546

15561547
##### Verification
15571548

1558-
- Check the response status code of the `__gtg` endpoint, it must be `200`.
1559-
- Check the response body of the `__health` endpoint, Cognite health check must have status `OK`.
1549+
Users no longer report that the calls made by the LLM agent to the tools `retrieve_time_series`, `retrieve_data_points` are failing.
15601550

15611551
#### Redis can't be queried or is mis-configured
15621552

src/talk2powersystemllm/tools/cognite/base.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,7 @@ def __init__(
4343
"""
4444

4545
if obo_token:
46-
credentials = OAuthInteractive(
47-
authority_url=f"https://login.microsoftonline.com/{tenant_id}",
48-
client_id=interactive_client_id,
49-
scopes=[f"{base_url}/.default"],
50-
)
46+
credentials = CredentialProvider.load({"token": obo_token})
5147
elif token_file_path:
5248
self._token_file_path = token_file_path
5349
credentials = self._refresh()

tests/acceptance_tests/docker-compose/statements.ttl

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
@prefix dcat: <http://www.w3.org/ns/dcat#> .
2-
@prefix dct: <http://purl.org/dc/terms/> .
2+
@prefix dct: <http://purl.org/dc/terms/> .
33
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4-
@prefix owl: <http://www.w3.org/2002/07/owl#> .
4+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
5+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
56

67
<urn:uuid:f176961e-9aeb-11e5-91da-b8763fd99c5f> a <https://cim.ucaiug.io/ns#Substation>;
78
<https://cim.ucaiug.io/ns#IdentifiedObject.mRID> "f176961e-9aeb-11e5-91da-b8763fd99c5f";
@@ -11,22 +12,32 @@
1112

1213
<urn:uuid:5b6a8b13-4c20-4147-8ed6-7249e303e647> a dcat:Dataset;
1314
dct:description "State Variable (SV) part of the Nordic 44-bus synthetic test model developed by Statnett SF of the Nordic region.";
14-
dct:issued "2025-02-14"^^<http://www.w3.org/2001/XMLSchema#date> , "2025-06-14"^^<http://www.w3.org/2001/XMLSchema#date> .
15+
dct:issued "2025-02-14"^^xsd:date .
1516

1617
<urn:uuid:5ad50f29-f3e5-4cf9-8519-cef17d71f8de> a dcat:Dataset;
1718
dct:description "DIGIN10 CGMES v3.0 Geographical Region Reference model"@en;
18-
dct:issued "2022-04-01T08:55:55"^^<http://www.w3.org/2001/XMLSchema#date>;
19+
dct:issued "2022-04-01T08:55:55"^^xsd:date;
1920
dct:title "DIGIN10-30-GeographicalRegion_RD" .
2021

2122
<urn:uuid:f1d9a88d-0ff5-4e4b-9d6a-c353fe8232c3> a dcat:Dataset .
2223

24+
<urn:uuid:f4c70c71-77e2-410e-9903-cbd85305cdc4> a dcat:Dataset;
25+
dct:description "DIGIN10 CGMES v3.0 Base Voltage Reference model"@en, "DIGIN10 CGMES v3.0 Medium Voltage 1 (MV1) Low Voltage 1 (LV1) Boundary Model"@en;
26+
dct:issued "2022-04-01T08:55:55"^^xsd:date, "2022-04-06T11:32:55"^^xsd:date;
27+
dct:title "DIGIN10-30-BaseVoltage_RD", "DIGIN10-30-MV1-LV1_BM" .
28+
29+
<urn:uuid:971c4254-5365-4aaf-8fa6-02658b3f8e05> a dcat:Dataset;
30+
dct:description "Geospartial GridCapacity MAS1"@en, "Stedsdata Nettkapasitet MAS1"@no;
31+
dct:issued "2023-02-21T08:08:00.000Z"^^xsd:dateTime;
32+
dct:title "DIGIN10-30-WattApp-GL" .
33+
2334
<https://ap-voc.cim4.eu/AssessedElement#Ontology> a owl:Ontology;
24-
dct:modified "2024-09-07"^^<http://www.w3.org/2001/XMLSchema#date>;
35+
dct:modified "2024-09-07"^^xsd:date;
2536
dct:title "Assessed Element Vocabulary"@en;
2637
owl:versionInfo "2.3.1" .
2738

2839
<https://cim.ucaiug.io/rules#> a owl:Ontology;
29-
dct:modified "2025-08-13"^^<http://www.w3.org/2001/XMLSchema#date>;
40+
dct:modified "2025-08-13"^^xsd:date;
3041
rdfs:label "CIM Inferred Extension Ontology";
3142
owl:versionInfo "1.1" .
3243

0 commit comments

Comments
 (0)