naas-abi 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- naas_abi/__init__.py +35 -0
- naas_abi/agents/AbiAgent.py +442 -0
- naas_abi/agents/AbiAgent_test.py +157 -0
- naas_abi/agents/EntitytoSPARQLAgent.py +952 -0
- naas_abi/agents/EntitytoSPARQLAgent_test.py +66 -0
- naas_abi/agents/KnowledgeGraphBuilderAgent.py +321 -0
- naas_abi/agents/KnowledgeGraphBuilderAgent_test.py +86 -0
- naas_abi/agents/OntologyEngineerAgent.py +115 -0
- naas_abi/agents/OntologyEngineerAgent_test.py +42 -0
- naas_abi/apps/oxigraph_admin/main.py +392 -0
- naas_abi/apps/oxigraph_admin/terminal_style.py +151 -0
- naas_abi/apps/sparql_terminal/main.py +68 -0
- naas_abi/apps/sparql_terminal/terminal_style.py +236 -0
- naas_abi/apps/terminal_agent/main.py +553 -0
- naas_abi/apps/terminal_agent/terminal_style.py +175 -0
- naas_abi/cli.py +714 -0
- naas_abi/mappings.py +83 -0
- naas_abi/models/airgap_gemma.py +220 -0
- naas_abi/models/airgap_qwen.py +24 -0
- naas_abi/models/default.py +23 -0
- naas_abi/models/gpt_4_1.py +25 -0
- naas_abi/pipelines/AIAgentOntologyGenerationPipeline.py +635 -0
- naas_abi/pipelines/AIAgentOntologyGenerationPipeline_test.py +133 -0
- naas_abi/pipelines/AddIndividualPipeline.py +215 -0
- naas_abi/pipelines/AddIndividualPipeline_test.py +66 -0
- naas_abi/pipelines/InsertDataSPARQLPipeline.py +197 -0
- naas_abi/pipelines/InsertDataSPARQLPipeline_test.py +96 -0
- naas_abi/pipelines/MergeIndividualsPipeline.py +245 -0
- naas_abi/pipelines/MergeIndividualsPipeline_test.py +98 -0
- naas_abi/pipelines/RemoveIndividualPipeline.py +166 -0
- naas_abi/pipelines/RemoveIndividualPipeline_test.py +58 -0
- naas_abi/pipelines/UpdateCommercialOrganizationPipeline.py +198 -0
- naas_abi/pipelines/UpdateDataPropertyPipeline.py +175 -0
- naas_abi/pipelines/UpdateLegalNamePipeline.py +107 -0
- naas_abi/pipelines/UpdateLinkedInPagePipeline.py +179 -0
- naas_abi/pipelines/UpdatePersonPipeline.py +184 -0
- naas_abi/pipelines/UpdateSkillPipeline.py +118 -0
- naas_abi/pipelines/UpdateTickerPipeline.py +104 -0
- naas_abi/pipelines/UpdateWebsitePipeline.py +106 -0
- naas_abi/triggers.py +131 -0
- naas_abi/workflows/AgentRecommendationWorkflow.py +321 -0
- naas_abi/workflows/AgentRecommendationWorkflow_test.py +160 -0
- naas_abi/workflows/ArtificialAnalysisWorkflow.py +337 -0
- naas_abi/workflows/ArtificialAnalysisWorkflow_test.py +57 -0
- naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow.py +210 -0
- naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow_test.py +78 -0
- naas_abi/workflows/CreateClassOntologyYamlWorkflow.py +208 -0
- naas_abi/workflows/CreateClassOntologyYamlWorkflow_test.py +65 -0
- naas_abi/workflows/CreateIndividualOntologyYamlWorkflow.py +183 -0
- naas_abi/workflows/CreateIndividualOntologyYamlWorkflow_test.py +86 -0
- naas_abi/workflows/ExportGraphInstancesToExcelWorkflow.py +450 -0
- naas_abi/workflows/ExportGraphInstancesToExcelWorkflow_test.py +33 -0
- naas_abi/workflows/GetObjectPropertiesFromClassWorkflow.py +385 -0
- naas_abi/workflows/GetObjectPropertiesFromClassWorkflow_test.py +57 -0
- naas_abi/workflows/GetSubjectGraphWorkflow.py +84 -0
- naas_abi/workflows/GetSubjectGraphWorkflow_test.py +71 -0
- naas_abi/workflows/SearchIndividualWorkflow.py +190 -0
- naas_abi/workflows/SearchIndividualWorkflow_test.py +98 -0
- naas_abi-1.0.0.dist-info/METADATA +9 -0
- naas_abi-1.0.0.dist-info/RECORD +62 -0
- naas_abi-1.0.0.dist-info/WHEEL +5 -0
- naas_abi-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter
|
|
6
|
+
from langchain_core.tools import BaseTool, StructuredTool
|
|
7
|
+
from naas_abi_core.pipeline import Pipeline, PipelineConfiguration, PipelineParameters
|
|
8
|
+
from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStoreService
|
|
9
|
+
from naas_abi_core.utils.Graph import ABI, URI_REGEX
|
|
10
|
+
from pydantic import Field
|
|
11
|
+
from rdflib import XSD, Graph, Literal, URIRef
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class UpdatePersonPipelineConfiguration(PipelineConfiguration):
|
|
16
|
+
"""Configuration for UpdatePersonPipeline.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
triple_store (ITripleStoreService): The triple store service to use
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
triple_store: ITripleStoreService
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UpdatePersonPipelineParameters(PipelineParameters):
|
|
26
|
+
individual_uri: Annotated[
|
|
27
|
+
str,
|
|
28
|
+
Field(
|
|
29
|
+
description="URI of the person.",
|
|
30
|
+
pattern=URI_REGEX,
|
|
31
|
+
example="https://www.commoncoreontologies.org/ont00001262/Florent_Ravenel",
|
|
32
|
+
),
|
|
33
|
+
]
|
|
34
|
+
first_name: Annotated[
|
|
35
|
+
Optional[str], Field(None, description="First name of the person.")
|
|
36
|
+
]
|
|
37
|
+
last_name: Annotated[
|
|
38
|
+
Optional[str], Field(None, description="Last name of the person.")
|
|
39
|
+
]
|
|
40
|
+
date_of_birth: Annotated[
|
|
41
|
+
Optional[str],
|
|
42
|
+
Field(
|
|
43
|
+
None,
|
|
44
|
+
description="Date of birth of the person. It must be in the format 'YYYY-MM-DD' (e.g. '1990-01-01').",
|
|
45
|
+
pattern=r"^\d{4}-\d{2}-\d{2}$",
|
|
46
|
+
),
|
|
47
|
+
]
|
|
48
|
+
linkedin_page_uri: Annotated[
|
|
49
|
+
Optional[str],
|
|
50
|
+
Field(
|
|
51
|
+
None,
|
|
52
|
+
description="LinkedIn Page URI of the person from class: http://ontology.naas.ai/abi/LinkedInProfilePage or http://ontology.naas.ai/abi/LinkedInCompanyPage or http://ontology.naas.ai/abi/LinkedInSchoolPage.",
|
|
53
|
+
pattern=URI_REGEX,
|
|
54
|
+
),
|
|
55
|
+
]
|
|
56
|
+
skill_uri: Annotated[
|
|
57
|
+
str,
|
|
58
|
+
Field(
|
|
59
|
+
None,
|
|
60
|
+
description="Skill URI of the person from class: https://www.commoncoreontologies.org/ont00000089",
|
|
61
|
+
pattern=URI_REGEX,
|
|
62
|
+
),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class UpdatePersonPipeline(Pipeline):
|
|
67
|
+
"""Pipeline for updating a person in the ontology."""
|
|
68
|
+
|
|
69
|
+
__configuration: UpdatePersonPipelineConfiguration
|
|
70
|
+
|
|
71
|
+
def __init__(self, configuration: UpdatePersonPipelineConfiguration):
|
|
72
|
+
super().__init__(configuration)
|
|
73
|
+
self.__configuration = configuration
|
|
74
|
+
|
|
75
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
76
|
+
if not isinstance(parameters, UpdatePersonPipelineParameters):
|
|
77
|
+
raise ValueError(
|
|
78
|
+
"Parameters must be of type UpdatePersonPipelineParameters"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Initialize graphs
|
|
82
|
+
graph_insert = Graph()
|
|
83
|
+
|
|
84
|
+
# Get subject URI & graph
|
|
85
|
+
individual_uri = URIRef(parameters.individual_uri)
|
|
86
|
+
graph = self.__configuration.triple_store.get_subject_graph(individual_uri)
|
|
87
|
+
|
|
88
|
+
# Update properties
|
|
89
|
+
if parameters.linkedin_page_uri:
|
|
90
|
+
check_linkedin_page = list(
|
|
91
|
+
graph.triples(
|
|
92
|
+
(
|
|
93
|
+
individual_uri,
|
|
94
|
+
ABI.hasLinkedInPage,
|
|
95
|
+
URIRef(parameters.linkedin_page_uri),
|
|
96
|
+
)
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
if len(check_linkedin_page) == 0:
|
|
100
|
+
graph_insert.add(
|
|
101
|
+
(
|
|
102
|
+
individual_uri,
|
|
103
|
+
ABI.hasLinkedInPage,
|
|
104
|
+
URIRef(parameters.linkedin_page_uri),
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
if parameters.skill_uri:
|
|
108
|
+
check_skill = list(
|
|
109
|
+
graph.triples(
|
|
110
|
+
(individual_uri, ABI.hasSkill, URIRef(parameters.skill_uri))
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
if len(check_skill) == 0:
|
|
114
|
+
graph_insert.add(
|
|
115
|
+
(individual_uri, ABI.hasSkill, URIRef(parameters.skill_uri))
|
|
116
|
+
)
|
|
117
|
+
if parameters.first_name:
|
|
118
|
+
check_first_name = list(
|
|
119
|
+
graph.triples(
|
|
120
|
+
(individual_uri, ABI.first_name, Literal(parameters.first_name))
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
if len(check_first_name) == 0:
|
|
124
|
+
graph_insert.add(
|
|
125
|
+
(individual_uri, ABI.first_name, Literal(parameters.first_name))
|
|
126
|
+
)
|
|
127
|
+
if parameters.last_name:
|
|
128
|
+
check_last_name = list(
|
|
129
|
+
graph.triples(
|
|
130
|
+
(individual_uri, ABI.last_name, Literal(parameters.last_name))
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
if len(check_last_name) == 0:
|
|
134
|
+
graph_insert.add(
|
|
135
|
+
(individual_uri, ABI.last_name, Literal(parameters.last_name))
|
|
136
|
+
)
|
|
137
|
+
if parameters.date_of_birth:
|
|
138
|
+
check_date_of_birth = list(
|
|
139
|
+
graph.triples(
|
|
140
|
+
(
|
|
141
|
+
individual_uri,
|
|
142
|
+
ABI.date_of_birth,
|
|
143
|
+
Literal(parameters.date_of_birth, datatype=XSD.date),
|
|
144
|
+
)
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
if len(check_date_of_birth) == 0:
|
|
148
|
+
graph_insert.add(
|
|
149
|
+
(
|
|
150
|
+
individual_uri,
|
|
151
|
+
ABI.date_of_birth,
|
|
152
|
+
Literal(parameters.date_of_birth, datatype=XSD.date),
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Save the graph
|
|
157
|
+
self.__configuration.triple_store.insert(graph_insert)
|
|
158
|
+
graph += graph_insert
|
|
159
|
+
return graph
|
|
160
|
+
|
|
161
|
+
def as_tools(self) -> list[BaseTool]:
|
|
162
|
+
return [
|
|
163
|
+
StructuredTool(
|
|
164
|
+
name="update_person",
|
|
165
|
+
description="Update a person in the ontology.",
|
|
166
|
+
func=lambda **kwargs: self.run(
|
|
167
|
+
UpdatePersonPipelineParameters(**kwargs)
|
|
168
|
+
),
|
|
169
|
+
args_schema=UpdatePersonPipelineParameters,
|
|
170
|
+
)
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
def as_api(
|
|
174
|
+
self,
|
|
175
|
+
router: APIRouter,
|
|
176
|
+
route_name: str = "",
|
|
177
|
+
name: str = "",
|
|
178
|
+
description: str = "",
|
|
179
|
+
description_stream: str = "",
|
|
180
|
+
tags: list[str | Enum] | None = None,
|
|
181
|
+
) -> None:
|
|
182
|
+
if tags is None:
|
|
183
|
+
tags = []
|
|
184
|
+
return None
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter
|
|
6
|
+
from langchain_core.tools import BaseTool, StructuredTool
|
|
7
|
+
from naas_abi_core.pipeline import Pipeline, PipelineConfiguration, PipelineParameters
|
|
8
|
+
from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStoreService
|
|
9
|
+
from naas_abi_core.utils.Graph import ABI, URI_REGEX
|
|
10
|
+
from pydantic import Field
|
|
11
|
+
from rdflib import Graph, Literal, URIRef
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class UpdateSkillPipelineConfiguration(PipelineConfiguration):
|
|
16
|
+
"""Configuration for UpdateSkillPipeline.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
triple_store (ITripleStoreService): The triple store service to use
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
triple_store: ITripleStoreService
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UpdateSkillPipelineParameters(PipelineParameters):
|
|
26
|
+
individual_uri: Annotated[
|
|
27
|
+
str, Field(description="URI of the skill.", pattern=URI_REGEX)
|
|
28
|
+
]
|
|
29
|
+
description: Annotated[
|
|
30
|
+
Optional[str], Field(None, description="Description of the skill")
|
|
31
|
+
] = None
|
|
32
|
+
person_uri: Annotated[
|
|
33
|
+
Optional[str],
|
|
34
|
+
Field(
|
|
35
|
+
None,
|
|
36
|
+
description="Person URI from class: https://www.commoncoreontologies.org/ont00001262.",
|
|
37
|
+
pattern=URI_REGEX,
|
|
38
|
+
),
|
|
39
|
+
] = None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class UpdateSkillPipeline(Pipeline):
|
|
43
|
+
"""Pipeline for updating a skill in the ontology."""
|
|
44
|
+
|
|
45
|
+
__configuration: UpdateSkillPipelineConfiguration
|
|
46
|
+
|
|
47
|
+
def __init__(self, configuration: UpdateSkillPipelineConfiguration):
|
|
48
|
+
super().__init__(configuration)
|
|
49
|
+
self.__configuration = configuration
|
|
50
|
+
|
|
51
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
52
|
+
if not isinstance(parameters, UpdateSkillPipelineParameters):
|
|
53
|
+
raise ValueError("Parameters must be of type UpdateSkillPipelineParameters")
|
|
54
|
+
|
|
55
|
+
# Initialize a new graph
|
|
56
|
+
graph_insert = Graph()
|
|
57
|
+
|
|
58
|
+
# Get subject URI & graph
|
|
59
|
+
individual_uri = URIRef(parameters.individual_uri)
|
|
60
|
+
graph = self.__configuration.triple_store.get_subject_graph(individual_uri)
|
|
61
|
+
|
|
62
|
+
# Update properties
|
|
63
|
+
if parameters.description:
|
|
64
|
+
check_description = list(
|
|
65
|
+
graph.triples(
|
|
66
|
+
(
|
|
67
|
+
individual_uri,
|
|
68
|
+
ABI.hasDescription,
|
|
69
|
+
Literal(parameters.description),
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
if len(check_description) == 0:
|
|
74
|
+
graph_insert.add(
|
|
75
|
+
(
|
|
76
|
+
individual_uri,
|
|
77
|
+
ABI.hasDescription,
|
|
78
|
+
Literal(parameters.description),
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
if parameters.person_uri:
|
|
82
|
+
check_person_uri = list(
|
|
83
|
+
graph.triples(
|
|
84
|
+
(individual_uri, ABI.isSkillOf, URIRef(parameters.person_uri))
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
if len(check_person_uri) == 0:
|
|
88
|
+
graph_insert.add(
|
|
89
|
+
(individual_uri, ABI.isSkillOf, URIRef(parameters.person_uri))
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# Save the graph
|
|
93
|
+
self.__configuration.triple_store.insert(graph_insert)
|
|
94
|
+
graph += graph_insert
|
|
95
|
+
return graph
|
|
96
|
+
|
|
97
|
+
def as_tools(self) -> list[BaseTool]:
|
|
98
|
+
return [
|
|
99
|
+
StructuredTool(
|
|
100
|
+
name="update_skill",
|
|
101
|
+
description="Update a skill with a description in the ontology.",
|
|
102
|
+
func=lambda **kwargs: self.run(UpdateSkillPipelineParameters(**kwargs)),
|
|
103
|
+
args_schema=UpdateSkillPipelineParameters,
|
|
104
|
+
)
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
def as_api(
|
|
108
|
+
self,
|
|
109
|
+
router: APIRouter,
|
|
110
|
+
route_name: str = "",
|
|
111
|
+
name: str = "",
|
|
112
|
+
description: str = "",
|
|
113
|
+
description_stream: str = "",
|
|
114
|
+
tags: list[str | Enum] | None = None,
|
|
115
|
+
) -> None:
|
|
116
|
+
if tags is None:
|
|
117
|
+
tags = []
|
|
118
|
+
return None
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter
|
|
6
|
+
from langchain_core.tools import BaseTool, StructuredTool
|
|
7
|
+
from naas_abi_core.pipeline import Pipeline, PipelineConfiguration, PipelineParameters
|
|
8
|
+
from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStoreService
|
|
9
|
+
from naas_abi_core.utils.Graph import ABI, URI_REGEX
|
|
10
|
+
from pydantic import Field
|
|
11
|
+
from rdflib import Graph, URIRef
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class UpdateTickerPipelineConfiguration(PipelineConfiguration):
|
|
16
|
+
triple_store: ITripleStoreService
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class UpdateTickerPipelineParameters(PipelineParameters):
|
|
20
|
+
individual_uri: Annotated[
|
|
21
|
+
str,
|
|
22
|
+
Field(
|
|
23
|
+
description="URI of the ticker. It must start with 'http://ontology.naas.ai/abi/'.",
|
|
24
|
+
pattern=URI_REGEX,
|
|
25
|
+
),
|
|
26
|
+
]
|
|
27
|
+
organization_uri: Annotated[
|
|
28
|
+
Optional[str],
|
|
29
|
+
Field(
|
|
30
|
+
None,
|
|
31
|
+
description="Organization URI from class: https://www.commoncoreontologies.org/ont00000443. It must start with 'http://ontology.naas.ai/abi/'.",
|
|
32
|
+
pattern=URI_REGEX,
|
|
33
|
+
),
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class UpdateTickerPipeline(Pipeline):
|
|
38
|
+
__configuration: UpdateTickerPipelineConfiguration
|
|
39
|
+
|
|
40
|
+
def __init__(self, configuration: UpdateTickerPipelineConfiguration):
|
|
41
|
+
super().__init__(configuration)
|
|
42
|
+
self.__configuration = configuration
|
|
43
|
+
|
|
44
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
45
|
+
if not isinstance(parameters, UpdateTickerPipelineParameters):
|
|
46
|
+
raise ValueError(
|
|
47
|
+
"Parameters must be of type UpdateTickerPipelineParameters"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Initialize graphs
|
|
51
|
+
graph_insert = Graph()
|
|
52
|
+
|
|
53
|
+
# Get subject URI & graph
|
|
54
|
+
individual_uri = URIRef(parameters.individual_uri)
|
|
55
|
+
graph = self.__configuration.triple_store.get_subject_graph(individual_uri)
|
|
56
|
+
|
|
57
|
+
# Update properties
|
|
58
|
+
if parameters.organization_uri:
|
|
59
|
+
check_organization_uri = list(
|
|
60
|
+
graph.triples(
|
|
61
|
+
(
|
|
62
|
+
individual_uri,
|
|
63
|
+
ABI.isTickerSymbolOf,
|
|
64
|
+
URIRef(parameters.organization_uri),
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
if len(check_organization_uri) == 0:
|
|
69
|
+
graph_insert.add(
|
|
70
|
+
(
|
|
71
|
+
individual_uri,
|
|
72
|
+
ABI.isTickerSymbolOf,
|
|
73
|
+
URIRef(parameters.organization_uri),
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
self.__configuration.triple_store.insert(graph_insert)
|
|
78
|
+
graph += graph_insert
|
|
79
|
+
return graph
|
|
80
|
+
|
|
81
|
+
def as_tools(self) -> list[BaseTool]:
|
|
82
|
+
return [
|
|
83
|
+
StructuredTool(
|
|
84
|
+
name="update_ticker",
|
|
85
|
+
description="Update a ticker symbol in the ontology.",
|
|
86
|
+
func=lambda **kwargs: self.run(
|
|
87
|
+
UpdateTickerPipelineParameters(**kwargs)
|
|
88
|
+
),
|
|
89
|
+
args_schema=UpdateTickerPipelineParameters,
|
|
90
|
+
)
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
def as_api(
|
|
94
|
+
self,
|
|
95
|
+
router: APIRouter,
|
|
96
|
+
route_name: str = "",
|
|
97
|
+
name: str = "",
|
|
98
|
+
description: str = "",
|
|
99
|
+
description_stream: str = "",
|
|
100
|
+
tags: list[str | Enum] | None = None,
|
|
101
|
+
) -> None:
|
|
102
|
+
if tags is None:
|
|
103
|
+
tags = []
|
|
104
|
+
return None
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter
|
|
6
|
+
from langchain_core.tools import BaseTool, StructuredTool
|
|
7
|
+
from naas_abi_core.pipeline import Pipeline, PipelineConfiguration, PipelineParameters
|
|
8
|
+
from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStoreService
|
|
9
|
+
from naas_abi_core.utils.Graph import ABI, URI_REGEX
|
|
10
|
+
from pydantic import Field
|
|
11
|
+
from rdflib import Graph, URIRef
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class UpdateWebsitePipelineConfiguration(PipelineConfiguration):
|
|
16
|
+
"""Configuration for UpdateWebsitePipeline.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
triple_store (ITripleStoreService): The triple store service to use
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
triple_store: ITripleStoreService
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UpdateWebsitePipelineParameters(PipelineParameters):
|
|
26
|
+
individual_uri: Annotated[
|
|
27
|
+
str,
|
|
28
|
+
Field(
|
|
29
|
+
description="URI of the website. It must start with 'http://ontology.naas.ai/abi/'.",
|
|
30
|
+
pattern=URI_REGEX,
|
|
31
|
+
),
|
|
32
|
+
]
|
|
33
|
+
owner_uri: Annotated[
|
|
34
|
+
Optional[str],
|
|
35
|
+
Field(
|
|
36
|
+
None,
|
|
37
|
+
description="Owner URI from class: https://www.commoncoreontologies.org/ont00001262 or https://www.commoncoreontologies.org/ont00000443.",
|
|
38
|
+
pattern=URI_REGEX,
|
|
39
|
+
),
|
|
40
|
+
] = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class UpdateWebsitePipeline(Pipeline):
|
|
44
|
+
"""Pipeline for updating a Website in the ontology."""
|
|
45
|
+
|
|
46
|
+
__configuration: UpdateWebsitePipelineConfiguration
|
|
47
|
+
|
|
48
|
+
def __init__(self, configuration: UpdateWebsitePipelineConfiguration):
|
|
49
|
+
super().__init__(configuration)
|
|
50
|
+
self.__configuration = configuration
|
|
51
|
+
|
|
52
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
53
|
+
if not isinstance(parameters, UpdateWebsitePipelineParameters):
|
|
54
|
+
raise ValueError(
|
|
55
|
+
"Parameters must be of type UpdateWebsitePipelineParameters"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Initialize a new graph
|
|
59
|
+
graph = Graph()
|
|
60
|
+
|
|
61
|
+
# Get website URI
|
|
62
|
+
website_uri = URIRef(parameters.individual_uri)
|
|
63
|
+
if not parameters.individual_uri.startswith("http://ontology.naas.ai/abi/"):
|
|
64
|
+
raise ValueError(
|
|
65
|
+
f"Invalid Website URI: {parameters.individual_uri}. It must start with 'http://ontology.naas.ai/abi/'."
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Add owners URI if provided
|
|
69
|
+
if parameters.owner_uri:
|
|
70
|
+
check_owner_uri = list(
|
|
71
|
+
graph.triples(
|
|
72
|
+
(website_uri, ABI.isWebsiteOf, URIRef(parameters.owner_uri))
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
if len(check_owner_uri) == 0:
|
|
76
|
+
graph.add((website_uri, ABI.isWebsiteOf, URIRef(parameters.owner_uri)))
|
|
77
|
+
graph.add((URIRef(parameters.owner_uri), ABI.hasWebsite, website_uri))
|
|
78
|
+
|
|
79
|
+
# Save the graph
|
|
80
|
+
self.__configuration.triple_store.insert(graph)
|
|
81
|
+
return graph
|
|
82
|
+
|
|
83
|
+
def as_tools(self) -> list[BaseTool]:
|
|
84
|
+
return [
|
|
85
|
+
StructuredTool(
|
|
86
|
+
name="update_website",
|
|
87
|
+
description="Update a website in the ontology.",
|
|
88
|
+
func=lambda **kwargs: self.run(
|
|
89
|
+
UpdateWebsitePipelineParameters(**kwargs)
|
|
90
|
+
),
|
|
91
|
+
args_schema=UpdateWebsitePipelineParameters,
|
|
92
|
+
)
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
def as_api(
|
|
96
|
+
self,
|
|
97
|
+
router: APIRouter,
|
|
98
|
+
route_name: str = "",
|
|
99
|
+
name: str = "",
|
|
100
|
+
description: str = "",
|
|
101
|
+
description_stream: str = "",
|
|
102
|
+
tags: list[str | Enum] | None = None,
|
|
103
|
+
) -> None:
|
|
104
|
+
if tags is None:
|
|
105
|
+
tags = []
|
|
106
|
+
return None
|
naas_abi/triggers.py
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# This file defines triggers for the opendata module
|
|
2
|
+
# Triggers allow the module to react automatically to changes in the ontology store
|
|
3
|
+
# Each trigger consists of:
|
|
4
|
+
# 1. A triple pattern (subject, predicate, object) where None acts as a wildcard
|
|
5
|
+
# 2. An event type (OntologyEvent.INSERT or OntologyEvent.DELETE)
|
|
6
|
+
# 3. A callback function to execute when the event occurs
|
|
7
|
+
#
|
|
8
|
+
# Example:
|
|
9
|
+
# from naas_abi_core.services.triple_store.TripleStorePorts import OntologyEvent
|
|
10
|
+
# from rdflib import URIRef, Namespace
|
|
11
|
+
#
|
|
12
|
+
# ex = Namespace("http://example.org/")
|
|
13
|
+
#
|
|
14
|
+
# def handle_new_dataset(event_type, ontology_name, triple):
|
|
15
|
+
# subject, predicate, obj = triple
|
|
16
|
+
# # Process the new dataset here
|
|
17
|
+
#
|
|
18
|
+
# triggers = [
|
|
19
|
+
# ((None, URIRef(ex + "hasOpenData"), None), OntologyEvent.INSERT, handle_new_dataset),
|
|
20
|
+
# ]
|
|
21
|
+
|
|
22
|
+
import os
|
|
23
|
+
|
|
24
|
+
from naas_abi_core import logger, secret, services
|
|
25
|
+
from naas_abi_core.services.triple_store.TripleStorePorts import OntologyEvent
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def is_production_mode():
|
|
29
|
+
"""Check if the application is running in production mode"""
|
|
30
|
+
return os.environ.get("ENV") != "dev"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def create_class_ontology_yaml():
|
|
34
|
+
"""Create class ontology YAML trigger - only active in production"""
|
|
35
|
+
if not is_production_mode():
|
|
36
|
+
logger.debug("Skipping class ontology YAML trigger - not in production mode")
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
from naas_abi_marketplace.applications.naas.integrations.NaasIntegration import (
|
|
40
|
+
NaasIntegrationConfiguration,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
from naas_abi.workflows.ConvertOntologyGraphToYamlWorkflow import (
|
|
44
|
+
ConvertOntologyGraphToYamlWorkflowConfiguration,
|
|
45
|
+
)
|
|
46
|
+
from naas_abi.workflows.CreateClassOntologyYamlWorkflow import (
|
|
47
|
+
CreateClassOntologyYamlWorkflow,
|
|
48
|
+
CreateClassOntologyYamlWorkflowConfiguration,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Get secrets
|
|
52
|
+
naas_api_key = secret.get("NAAS_API_KEY")
|
|
53
|
+
if naas_api_key is None:
|
|
54
|
+
logger.error("NAAS_API_KEY is not set")
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
# Configure Naas integration
|
|
58
|
+
naas_integration_config = NaasIntegrationConfiguration(api_key=naas_api_key)
|
|
59
|
+
|
|
60
|
+
# Configure ConvertOntologyGraphToYaml workflow
|
|
61
|
+
convert_ontology_graph_config = ConvertOntologyGraphToYamlWorkflowConfiguration(
|
|
62
|
+
naas_integration_config
|
|
63
|
+
)
|
|
64
|
+
workflow = CreateClassOntologyYamlWorkflow(
|
|
65
|
+
CreateClassOntologyYamlWorkflowConfiguration(
|
|
66
|
+
services.triple_store_service, convert_ontology_graph_config
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Subscribe to the trigger
|
|
71
|
+
logger.info("Activating class ontology YAML trigger in production mode")
|
|
72
|
+
return ((None, None, None), OntologyEvent.INSERT, workflow.trigger, True)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def create_individual_ontology_yaml():
|
|
76
|
+
"""Create individual ontology YAML trigger - only active in production"""
|
|
77
|
+
if not is_production_mode():
|
|
78
|
+
logger.debug(
|
|
79
|
+
"Skipping individual ontology YAML trigger - not in production mode"
|
|
80
|
+
)
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
from naas_abi_marketplace.applications.naas.integrations.NaasIntegration import (
|
|
84
|
+
NaasIntegrationConfiguration,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
from naas_abi.workflows.ConvertOntologyGraphToYamlWorkflow import (
|
|
88
|
+
ConvertOntologyGraphToYamlWorkflowConfiguration,
|
|
89
|
+
)
|
|
90
|
+
from naas_abi.workflows.CreateIndividualOntologyYamlWorkflow import (
|
|
91
|
+
CreateIndividualOntologyYamlWorkflow,
|
|
92
|
+
CreateIndividualOntologyYamlWorkflowConfiguration,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Get secrets
|
|
96
|
+
naas_api_key = secret.get("NAAS_API_KEY")
|
|
97
|
+
if naas_api_key is None:
|
|
98
|
+
logger.error("NAAS_API_KEY is not set")
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
# Configure Naas integration
|
|
102
|
+
naas_integration_config = NaasIntegrationConfiguration(api_key=naas_api_key)
|
|
103
|
+
|
|
104
|
+
# Configure ConvertOntologyGraphToYaml workflow
|
|
105
|
+
convert_ontology_graph_config = ConvertOntologyGraphToYamlWorkflowConfiguration(
|
|
106
|
+
naas_integration_config
|
|
107
|
+
)
|
|
108
|
+
workflow = CreateIndividualOntologyYamlWorkflow(
|
|
109
|
+
CreateIndividualOntologyYamlWorkflowConfiguration(
|
|
110
|
+
services.triple_store_service, convert_ontology_graph_config
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Subscribe to the trigger
|
|
115
|
+
logger.info("Activating individual ontology YAML trigger in production mode")
|
|
116
|
+
return ((None, None, None), OntologyEvent.INSERT, workflow.trigger, True)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# Filter out None values from triggers (when not in production mode)
|
|
120
|
+
# Skip triggers in test environment to avoid SSH tunnel initialization
|
|
121
|
+
if os.getenv("PYTEST_CURRENT_TEST") is not None or os.getenv("TESTING") == "true":
|
|
122
|
+
triggers = [] # Skip all triggers during testing
|
|
123
|
+
else:
|
|
124
|
+
triggers = [
|
|
125
|
+
trigger
|
|
126
|
+
for trigger in [
|
|
127
|
+
create_class_ontology_yaml(),
|
|
128
|
+
create_individual_ontology_yaml(),
|
|
129
|
+
]
|
|
130
|
+
if trigger is not None
|
|
131
|
+
]
|