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,198 @@
|
|
|
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 UpdateCommercialOrganizationPipelineConfiguration(PipelineConfiguration):
|
|
16
|
+
"""Configuration for UpdateCommercialOrganizationPipeline.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
triple_store (ITripleStoreService): The triple store service to use
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
triple_store: ITripleStoreService
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UpdateCommercialOrganizationPipelineParameters(PipelineParameters):
|
|
26
|
+
individual_uri: Annotated[
|
|
27
|
+
str,
|
|
28
|
+
Field(
|
|
29
|
+
description="URI of the commercial organization extracted from class: https://www.commercoreontologies.org/ont00000443",
|
|
30
|
+
pattern=URI_REGEX,
|
|
31
|
+
),
|
|
32
|
+
]
|
|
33
|
+
legal_uri: Annotated[
|
|
34
|
+
Optional[str],
|
|
35
|
+
Field(
|
|
36
|
+
description="Individual URI from class: https://www.commoncoreontologies.org/ont00001331",
|
|
37
|
+
pattern=URI_REGEX,
|
|
38
|
+
),
|
|
39
|
+
] = None
|
|
40
|
+
ticker_uri: Annotated[
|
|
41
|
+
Optional[str],
|
|
42
|
+
Field(
|
|
43
|
+
description="Individual URI from class: http://ontology.naas.ai/abi/Ticker",
|
|
44
|
+
pattern=URI_REGEX,
|
|
45
|
+
),
|
|
46
|
+
] = None
|
|
47
|
+
website_uri: Annotated[
|
|
48
|
+
Optional[str],
|
|
49
|
+
Field(
|
|
50
|
+
description="Individual URI from class: http://ontology.naas.ai/abi/Website",
|
|
51
|
+
pattern=URI_REGEX,
|
|
52
|
+
),
|
|
53
|
+
] = None
|
|
54
|
+
linkedin_page_uri: Annotated[
|
|
55
|
+
Optional[str],
|
|
56
|
+
Field(
|
|
57
|
+
description="Individual URI from class: http://ontology.naas.ai/abi/LinkedInOrganizationPage",
|
|
58
|
+
pattern=URI_REGEX,
|
|
59
|
+
),
|
|
60
|
+
] = None
|
|
61
|
+
logo_url: Annotated[
|
|
62
|
+
Optional[str],
|
|
63
|
+
Field(
|
|
64
|
+
description="Logo URL of the commercial organization.",
|
|
65
|
+
pattern=r"https?://.*",
|
|
66
|
+
),
|
|
67
|
+
] = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class UpdateCommercialOrganizationPipeline(Pipeline):
|
|
71
|
+
"""Pipeline for updating a commercial organization in the ontology."""
|
|
72
|
+
|
|
73
|
+
__configuration: UpdateCommercialOrganizationPipelineConfiguration
|
|
74
|
+
|
|
75
|
+
def __init__(
|
|
76
|
+
self, configuration: UpdateCommercialOrganizationPipelineConfiguration
|
|
77
|
+
):
|
|
78
|
+
super().__init__(configuration)
|
|
79
|
+
self.__configuration = configuration
|
|
80
|
+
|
|
81
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
82
|
+
if not isinstance(parameters, UpdateCommercialOrganizationPipelineParameters):
|
|
83
|
+
raise ValueError(
|
|
84
|
+
"Parameters must be of type UpdateCommercialOrganizationPipelineParameters"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Initialize graphs
|
|
88
|
+
graph_insert = Graph()
|
|
89
|
+
|
|
90
|
+
# Get subject URI & graph
|
|
91
|
+
individual_uri = URIRef(parameters.individual_uri)
|
|
92
|
+
graph = self.__configuration.triple_store.get_subject_graph(individual_uri)
|
|
93
|
+
|
|
94
|
+
# Update properties
|
|
95
|
+
if parameters.legal_uri:
|
|
96
|
+
check_legal = list(
|
|
97
|
+
graph.triples(
|
|
98
|
+
(
|
|
99
|
+
individual_uri,
|
|
100
|
+
URIRef("http://ontology.naas.ai/abi/hasLegalName"),
|
|
101
|
+
URIRef(parameters.legal_uri),
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
if len(check_legal) == 0:
|
|
106
|
+
graph_insert.add(
|
|
107
|
+
(individual_uri, ABI.hasLegalName, URIRef(parameters.legal_uri))
|
|
108
|
+
)
|
|
109
|
+
if parameters.ticker_uri:
|
|
110
|
+
check_ticker = list(
|
|
111
|
+
graph.triples(
|
|
112
|
+
(
|
|
113
|
+
individual_uri,
|
|
114
|
+
URIRef("http://ontology.naas.ai/abi/hasTickerSymbol"),
|
|
115
|
+
URIRef(parameters.ticker_uri),
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
if len(check_ticker) == 0:
|
|
120
|
+
graph_insert.add(
|
|
121
|
+
(individual_uri, ABI.hasTickerSymbol, URIRef(parameters.ticker_uri))
|
|
122
|
+
)
|
|
123
|
+
if parameters.website_uri:
|
|
124
|
+
check_website = list(
|
|
125
|
+
graph.triples(
|
|
126
|
+
(
|
|
127
|
+
individual_uri,
|
|
128
|
+
URIRef("http://ontology.naas.ai/abi/hasWebsite"),
|
|
129
|
+
URIRef(parameters.website_uri),
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
if len(check_website) == 0:
|
|
134
|
+
graph_insert.add(
|
|
135
|
+
(individual_uri, ABI.hasWebsite, URIRef(parameters.website_uri))
|
|
136
|
+
)
|
|
137
|
+
if parameters.linkedin_page_uri:
|
|
138
|
+
check_linkedin_page = list(
|
|
139
|
+
graph.triples(
|
|
140
|
+
(
|
|
141
|
+
individual_uri,
|
|
142
|
+
URIRef("http://ontology.naas.ai/abi/hasLinkedInPage"),
|
|
143
|
+
URIRef(parameters.linkedin_page_uri),
|
|
144
|
+
)
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
if len(check_linkedin_page) == 0:
|
|
148
|
+
graph_insert.add(
|
|
149
|
+
(
|
|
150
|
+
individual_uri,
|
|
151
|
+
ABI.hasLinkedInPage,
|
|
152
|
+
URIRef(parameters.linkedin_page_uri),
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
if parameters.logo_url:
|
|
156
|
+
check_logo = list(
|
|
157
|
+
graph.triples(
|
|
158
|
+
(
|
|
159
|
+
individual_uri,
|
|
160
|
+
URIRef("http://ontology.naas.ai/abi/logo"),
|
|
161
|
+
Literal(parameters.logo_url),
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
)
|
|
165
|
+
if len(check_logo) == 0:
|
|
166
|
+
graph_insert.add(
|
|
167
|
+
(individual_uri, ABI.logo, Literal(parameters.logo_url))
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Save graphs to triple store
|
|
171
|
+
self.__configuration.triple_store.insert(graph_insert)
|
|
172
|
+
graph += graph_insert
|
|
173
|
+
return graph
|
|
174
|
+
|
|
175
|
+
def as_tools(self) -> list[BaseTool]:
|
|
176
|
+
return [
|
|
177
|
+
StructuredTool(
|
|
178
|
+
name="update_commercial_organization",
|
|
179
|
+
description="Update a commercial organization properties",
|
|
180
|
+
func=lambda **kwargs: self.run(
|
|
181
|
+
UpdateCommercialOrganizationPipelineParameters(**kwargs)
|
|
182
|
+
),
|
|
183
|
+
args_schema=UpdateCommercialOrganizationPipelineParameters,
|
|
184
|
+
)
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
def as_api(
|
|
188
|
+
self,
|
|
189
|
+
router: APIRouter,
|
|
190
|
+
route_name: str = "",
|
|
191
|
+
name: str = "",
|
|
192
|
+
description: str = "",
|
|
193
|
+
description_stream: str = "",
|
|
194
|
+
tags: list[str | Enum] | None = None,
|
|
195
|
+
) -> None:
|
|
196
|
+
if tags is None:
|
|
197
|
+
tags = []
|
|
198
|
+
return None
|
|
@@ -0,0 +1,175 @@
|
|
|
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 import ABIModule
|
|
8
|
+
from naas_abi_core import logger
|
|
9
|
+
from naas_abi_core.pipeline import Pipeline, PipelineConfiguration, PipelineParameters
|
|
10
|
+
from naas_abi_core.services.triple_store.TripleStorePorts import ITripleStoreService
|
|
11
|
+
from naas_abi_core.utils.Graph import URI_REGEX
|
|
12
|
+
from naas_abi_core.utils.SPARQL import SPARQLUtils
|
|
13
|
+
from pydantic import Field
|
|
14
|
+
from rdflib import RDFS, SKOS, XSD, Graph, Literal, URIRef
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class UpdateDataPropertyPipelineConfiguration(PipelineConfiguration):
|
|
19
|
+
"""Configuration for UpdateDataPropertyPipeline.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
triple_store (ITripleStoreService): The triple store service to use
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
triple_store: ITripleStoreService
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class UpdateDataPropertyPipelineParameters(PipelineParameters):
|
|
29
|
+
subject_uri: Annotated[str, Field(description="Subject URI", pattern=URI_REGEX)]
|
|
30
|
+
predicate_uri: Annotated[
|
|
31
|
+
str, Field(description="Predicate URI", pattern=r"^http.+$")
|
|
32
|
+
]
|
|
33
|
+
object_new_value: Annotated[
|
|
34
|
+
str,
|
|
35
|
+
Field(
|
|
36
|
+
description="New value for the object",
|
|
37
|
+
),
|
|
38
|
+
]
|
|
39
|
+
language: Optional[
|
|
40
|
+
Annotated[
|
|
41
|
+
Optional[str],
|
|
42
|
+
Field(
|
|
43
|
+
description="Language of the object",
|
|
44
|
+
),
|
|
45
|
+
]
|
|
46
|
+
] = None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class UpdateDataPropertyPipeline(Pipeline):
|
|
50
|
+
"""Pipeline for updating a data property in the ontology."""
|
|
51
|
+
|
|
52
|
+
__configuration: UpdateDataPropertyPipelineConfiguration
|
|
53
|
+
|
|
54
|
+
def __init__(self, configuration: UpdateDataPropertyPipelineConfiguration):
|
|
55
|
+
super().__init__(configuration)
|
|
56
|
+
self.__configuration = configuration
|
|
57
|
+
self.__sparql_utils = SPARQLUtils(
|
|
58
|
+
ABIModule.get_instance().engine.services.triple_store
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
62
|
+
if not isinstance(parameters, UpdateDataPropertyPipelineParameters):
|
|
63
|
+
raise ValueError(
|
|
64
|
+
"Parameters must be of type UpdateDataPropertyPipelineParameters"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
graph_insert = Graph()
|
|
68
|
+
graph_remove = Graph()
|
|
69
|
+
subject_uri = URIRef(parameters.subject_uri)
|
|
70
|
+
predicate_uri = URIRef(parameters.predicate_uri)
|
|
71
|
+
logger.info(
|
|
72
|
+
f"Updating subject '{subject_uri}' with predicate '{predicate_uri}' and value '{parameters.object_new_value}'"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
if isinstance(parameters.object_new_value, str):
|
|
76
|
+
if parameters.language is not None:
|
|
77
|
+
object_new_value = Literal(
|
|
78
|
+
parameters.object_new_value, lang=parameters.language
|
|
79
|
+
)
|
|
80
|
+
else:
|
|
81
|
+
object_new_value = Literal(parameters.object_new_value)
|
|
82
|
+
elif isinstance(parameters.object_new_value, float):
|
|
83
|
+
object_new_value = Literal(parameters.object_new_value, datatype=XSD.float)
|
|
84
|
+
elif isinstance(parameters.object_new_value, int):
|
|
85
|
+
object_new_value = Literal(
|
|
86
|
+
parameters.object_new_value, datatype=XSD.integer
|
|
87
|
+
)
|
|
88
|
+
else:
|
|
89
|
+
logger.error(f"Invalid object new value: {parameters.object_new_value}")
|
|
90
|
+
return Graph()
|
|
91
|
+
|
|
92
|
+
graph = self.__sparql_utils.get_subject_graph(parameters.subject_uri)
|
|
93
|
+
check_object_property = list(graph.triples((subject_uri, predicate_uri, None)))
|
|
94
|
+
logger.info(f"Check object property: {len(check_object_property)}")
|
|
95
|
+
if len(check_object_property) == 0:
|
|
96
|
+
logger.error(
|
|
97
|
+
f"Property {parameters.predicate_uri} not found for subject {parameters.subject_uri}"
|
|
98
|
+
)
|
|
99
|
+
return Graph()
|
|
100
|
+
elif len(check_object_property) == 1 and predicate_uri != RDFS.label:
|
|
101
|
+
property_value = graph.value(subject_uri, predicate_uri)
|
|
102
|
+
if property_value:
|
|
103
|
+
graph_remove.add((subject_uri, predicate_uri, property_value))
|
|
104
|
+
graph_insert.add((subject_uri, predicate_uri, object_new_value))
|
|
105
|
+
elif len(check_object_property) == 1 and predicate_uri == RDFS.label:
|
|
106
|
+
property_value = graph.value(subject_uri, predicate_uri)
|
|
107
|
+
if property_value:
|
|
108
|
+
graph_remove.add((subject_uri, predicate_uri, property_value))
|
|
109
|
+
graph_insert.add((subject_uri, predicate_uri, object_new_value))
|
|
110
|
+
graph_insert.add((subject_uri, SKOS.altLabel, object_new_value))
|
|
111
|
+
else:
|
|
112
|
+
logger.error(
|
|
113
|
+
f"Multiple values found for property {parameters.predicate_uri} for subject {parameters.subject_uri}"
|
|
114
|
+
)
|
|
115
|
+
return Graph()
|
|
116
|
+
|
|
117
|
+
# Save to triplestore
|
|
118
|
+
if len(graph_insert) > 0:
|
|
119
|
+
logger.info("✅ Inserting data to triplestore:")
|
|
120
|
+
logger.info(graph_insert.serialize(format="turtle"))
|
|
121
|
+
self.__configuration.triple_store.insert(graph_insert)
|
|
122
|
+
if len(graph_remove) > 0:
|
|
123
|
+
logger.info("✅ Removing data from triplestore:")
|
|
124
|
+
logger.info(graph_remove.serialize(format="turtle"))
|
|
125
|
+
self.__configuration.triple_store.remove(graph_remove)
|
|
126
|
+
return self.__sparql_utils.get_subject_graph(parameters.subject_uri)
|
|
127
|
+
|
|
128
|
+
def as_tools(self) -> list[BaseTool]:
|
|
129
|
+
return [
|
|
130
|
+
StructuredTool(
|
|
131
|
+
name="update_data_property",
|
|
132
|
+
description="Update a data property in the ontology",
|
|
133
|
+
func=lambda **kwargs: self.run(
|
|
134
|
+
UpdateDataPropertyPipelineParameters(**kwargs)
|
|
135
|
+
),
|
|
136
|
+
args_schema=UpdateDataPropertyPipelineParameters,
|
|
137
|
+
)
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
def as_api(
|
|
141
|
+
self,
|
|
142
|
+
router: APIRouter,
|
|
143
|
+
route_name: str = "",
|
|
144
|
+
name: str = "",
|
|
145
|
+
description: str = "",
|
|
146
|
+
description_stream: str = "",
|
|
147
|
+
tags: list[str | Enum] | None = None,
|
|
148
|
+
) -> None:
|
|
149
|
+
if tags is None:
|
|
150
|
+
tags = []
|
|
151
|
+
return None
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
from naas_abi import services
|
|
156
|
+
|
|
157
|
+
subject_uri = "http://ontology.naas.ai/abi/1b765700-9fa1-4e1d-9496-108445aafb34"
|
|
158
|
+
predicate_uri = str(RDFS.label)
|
|
159
|
+
object_new_value = "Ford Motor Company"
|
|
160
|
+
language = "en"
|
|
161
|
+
|
|
162
|
+
configuration = UpdateDataPropertyPipelineConfiguration(
|
|
163
|
+
triple_store=services.triple_store_service
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
pipeline = UpdateDataPropertyPipeline(configuration)
|
|
167
|
+
graph = pipeline.run(
|
|
168
|
+
UpdateDataPropertyPipelineParameters(
|
|
169
|
+
subject_uri=subject_uri,
|
|
170
|
+
predicate_uri=predicate_uri,
|
|
171
|
+
object_new_value=object_new_value,
|
|
172
|
+
language=language,
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
logger.info(graph.serialize(format="turtle"))
|
|
@@ -0,0 +1,107 @@
|
|
|
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 UpdateLegalNamePipelineConfiguration(PipelineConfiguration):
|
|
16
|
+
"""Configuration for UpdateLegalNamePipeline.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
triple_store (ITripleStoreService): The triple store service to use
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
triple_store: ITripleStoreService
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UpdateLegalNamePipelineParameters(PipelineParameters):
|
|
26
|
+
individual_uri: Annotated[
|
|
27
|
+
str, Field(description="URI of the legal name.", pattern=URI_REGEX)
|
|
28
|
+
]
|
|
29
|
+
organization_uri: Annotated[
|
|
30
|
+
Optional[str],
|
|
31
|
+
Field(
|
|
32
|
+
None,
|
|
33
|
+
description="Organization URI from class: https://www.commoncoreontologies.org/ont00000443.",
|
|
34
|
+
pattern=URI_REGEX,
|
|
35
|
+
),
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class UpdateLegalNamePipeline(Pipeline):
|
|
40
|
+
__configuration: UpdateLegalNamePipelineConfiguration
|
|
41
|
+
|
|
42
|
+
def __init__(self, configuration: UpdateLegalNamePipelineConfiguration):
|
|
43
|
+
super().__init__(configuration)
|
|
44
|
+
self.__configuration = configuration
|
|
45
|
+
|
|
46
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
47
|
+
if not isinstance(parameters, UpdateLegalNamePipelineParameters):
|
|
48
|
+
raise ValueError(
|
|
49
|
+
"Parameters must be of type UpdateLegalNamePipelineParameters"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Init graph
|
|
53
|
+
graph_insert = Graph()
|
|
54
|
+
|
|
55
|
+
# Get subject URI & graph
|
|
56
|
+
individual_uri = URIRef(parameters.individual_uri)
|
|
57
|
+
graph = self.__configuration.triple_store.get_subject_graph(individual_uri)
|
|
58
|
+
|
|
59
|
+
# Update properties
|
|
60
|
+
if parameters.organization_uri:
|
|
61
|
+
check_organization = list(
|
|
62
|
+
graph.triples(
|
|
63
|
+
(
|
|
64
|
+
individual_uri,
|
|
65
|
+
ABI.isLegalNameOf,
|
|
66
|
+
URIRef(parameters.organization_uri),
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
if len(check_organization) == 0:
|
|
71
|
+
graph_insert.add(
|
|
72
|
+
(
|
|
73
|
+
individual_uri,
|
|
74
|
+
ABI.isLegalNameOf,
|
|
75
|
+
URIRef(parameters.organization_uri),
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Save graph to triple store
|
|
80
|
+
self.__configuration.triple_store.insert(graph_insert)
|
|
81
|
+
graph += graph_insert
|
|
82
|
+
return graph
|
|
83
|
+
|
|
84
|
+
def as_tools(self) -> list[BaseTool]:
|
|
85
|
+
return [
|
|
86
|
+
StructuredTool(
|
|
87
|
+
name="update_legal_name",
|
|
88
|
+
description="Update a legal name in the ontology.",
|
|
89
|
+
func=lambda **kwargs: self.run(
|
|
90
|
+
UpdateLegalNamePipelineParameters(**kwargs)
|
|
91
|
+
),
|
|
92
|
+
args_schema=UpdateLegalNamePipelineParameters,
|
|
93
|
+
)
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
def as_api(
|
|
97
|
+
self,
|
|
98
|
+
router: APIRouter,
|
|
99
|
+
route_name: str = "",
|
|
100
|
+
name: str = "",
|
|
101
|
+
description: str = "",
|
|
102
|
+
description_stream: str = "",
|
|
103
|
+
tags: list[str | Enum] | None = None,
|
|
104
|
+
) -> None:
|
|
105
|
+
if tags is None:
|
|
106
|
+
tags = []
|
|
107
|
+
return None
|
|
@@ -0,0 +1,179 @@
|
|
|
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 UpdateLinkedInPagePipelineConfiguration(PipelineConfiguration):
|
|
16
|
+
"""Configuration for UpdateLinkedInPagePipeline.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
triple_store (ITripleStoreService): The triple store service to use
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
triple_store: ITripleStoreService
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class UpdateLinkedInPagePipelineParameters(PipelineParameters):
|
|
26
|
+
individual_uri: Annotated[
|
|
27
|
+
str, Field(description="URI of the LinkedIn page.", pattern=URI_REGEX)
|
|
28
|
+
]
|
|
29
|
+
linkedin_id: Annotated[
|
|
30
|
+
Optional[str], Field(None, description="LinkedIn unique ID of the individual.")
|
|
31
|
+
]
|
|
32
|
+
linkedin_url: Annotated[
|
|
33
|
+
Optional[str],
|
|
34
|
+
Field(None, description="LinkedIn URL with the LinkedIn ID as identifier."),
|
|
35
|
+
]
|
|
36
|
+
linkedin_public_id: Annotated[
|
|
37
|
+
Optional[str], Field(None, description="LinkedIn Public ID of the individual.")
|
|
38
|
+
]
|
|
39
|
+
linkedin_public_url: Annotated[
|
|
40
|
+
Optional[str],
|
|
41
|
+
Field(
|
|
42
|
+
None,
|
|
43
|
+
description="LinkedIn Public URL of the individual with the LinkedIn Public ID as identifier.",
|
|
44
|
+
pattern=r"https?://.+\.linkedin\.com/(in|company|school|showcase)/[^?]+",
|
|
45
|
+
),
|
|
46
|
+
]
|
|
47
|
+
owner_uri: Annotated[
|
|
48
|
+
Optional[str],
|
|
49
|
+
Field(
|
|
50
|
+
None,
|
|
51
|
+
description="URI of the owner from class: https://www.commoncoreontologies.org/ont00001262 or https://www.commoncoreontologies.org/ont00000443",
|
|
52
|
+
pattern=URI_REGEX,
|
|
53
|
+
),
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class UpdateLinkedInPagePipeline(Pipeline):
|
|
58
|
+
"""Pipeline for updating a LinkedIn page in the ontology."""
|
|
59
|
+
|
|
60
|
+
__configuration: UpdateLinkedInPagePipelineConfiguration
|
|
61
|
+
|
|
62
|
+
def __init__(self, configuration: UpdateLinkedInPagePipelineConfiguration):
|
|
63
|
+
super().__init__(configuration)
|
|
64
|
+
self.__configuration = configuration
|
|
65
|
+
|
|
66
|
+
def run(self, parameters: PipelineParameters) -> Graph:
|
|
67
|
+
if not isinstance(parameters, UpdateLinkedInPagePipelineParameters):
|
|
68
|
+
raise ValueError(
|
|
69
|
+
"Parameters must be of type UpdateLinkedInPagePipelineParameters"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Initialize graphs
|
|
73
|
+
graph_insert = Graph()
|
|
74
|
+
|
|
75
|
+
# Get existing graph
|
|
76
|
+
graph = self.__configuration.triple_store.get_subject_graph(
|
|
77
|
+
parameters.individual_uri
|
|
78
|
+
)
|
|
79
|
+
individual_uri = URIRef(parameters.individual_uri)
|
|
80
|
+
|
|
81
|
+
# Update properties
|
|
82
|
+
if parameters.linkedin_id:
|
|
83
|
+
check_id = list(
|
|
84
|
+
graph.triples(
|
|
85
|
+
(individual_uri, ABI.linkedin_id, Literal(parameters.linkedin_id))
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
if len(check_id) == 0:
|
|
89
|
+
graph_insert.add(
|
|
90
|
+
(individual_uri, ABI.linkedin_id, Literal(parameters.linkedin_id))
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if parameters.linkedin_url:
|
|
94
|
+
check_url = list(
|
|
95
|
+
graph.triples(
|
|
96
|
+
(individual_uri, ABI.linkedin_url, Literal(parameters.linkedin_url))
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
if len(check_url) == 0:
|
|
100
|
+
graph_insert.add(
|
|
101
|
+
(individual_uri, ABI.linkedin_url, Literal(parameters.linkedin_url))
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
if parameters.linkedin_public_id:
|
|
105
|
+
check_public_id = list(
|
|
106
|
+
graph.triples(
|
|
107
|
+
(
|
|
108
|
+
individual_uri,
|
|
109
|
+
ABI.linkedin_public_id,
|
|
110
|
+
Literal(parameters.linkedin_public_id),
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
if len(check_public_id) == 0:
|
|
115
|
+
graph_insert.add(
|
|
116
|
+
(
|
|
117
|
+
individual_uri,
|
|
118
|
+
ABI.linkedin_public_id,
|
|
119
|
+
Literal(parameters.linkedin_public_id),
|
|
120
|
+
)
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
if parameters.linkedin_public_url:
|
|
124
|
+
check_public_url = list(
|
|
125
|
+
graph.triples(
|
|
126
|
+
(
|
|
127
|
+
individual_uri,
|
|
128
|
+
ABI.linkedin_public_url,
|
|
129
|
+
Literal(parameters.linkedin_public_url),
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
if len(check_public_url) == 0:
|
|
134
|
+
graph_insert.add(
|
|
135
|
+
(
|
|
136
|
+
individual_uri,
|
|
137
|
+
ABI.linkedin_public_url,
|
|
138
|
+
Literal(parameters.linkedin_public_url),
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if parameters.owner_uri:
|
|
143
|
+
owner_uri = URIRef(parameters.owner_uri)
|
|
144
|
+
check_owner = list(
|
|
145
|
+
graph.triples((individual_uri, ABI.isLinkedInPageOf, owner_uri))
|
|
146
|
+
)
|
|
147
|
+
if len(check_owner) == 0:
|
|
148
|
+
graph_insert.add((individual_uri, ABI.isLinkedInPageOf, owner_uri))
|
|
149
|
+
graph_insert.add((owner_uri, ABI.hasLinkedInPage, individual_uri))
|
|
150
|
+
|
|
151
|
+
# Save the graph
|
|
152
|
+
self.__configuration.triple_store.insert(graph_insert)
|
|
153
|
+
graph += graph_insert
|
|
154
|
+
return graph
|
|
155
|
+
|
|
156
|
+
def as_tools(self) -> list[BaseTool]:
|
|
157
|
+
return [
|
|
158
|
+
StructuredTool(
|
|
159
|
+
name="update_linkedin_page",
|
|
160
|
+
description="Update a LinkedIn page in the ontology.",
|
|
161
|
+
func=lambda **kwargs: self.run(
|
|
162
|
+
UpdateLinkedInPagePipelineParameters(**kwargs)
|
|
163
|
+
),
|
|
164
|
+
args_schema=UpdateLinkedInPagePipelineParameters,
|
|
165
|
+
)
|
|
166
|
+
]
|
|
167
|
+
|
|
168
|
+
def as_api(
|
|
169
|
+
self,
|
|
170
|
+
router: APIRouter,
|
|
171
|
+
route_name: str = "",
|
|
172
|
+
name: str = "",
|
|
173
|
+
description: str = "",
|
|
174
|
+
description_stream: str = "",
|
|
175
|
+
tags: list[str | Enum] | None = None,
|
|
176
|
+
) -> None:
|
|
177
|
+
if tags is None:
|
|
178
|
+
tags = []
|
|
179
|
+
return None
|