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.
Files changed (62) hide show
  1. naas_abi/__init__.py +35 -0
  2. naas_abi/agents/AbiAgent.py +442 -0
  3. naas_abi/agents/AbiAgent_test.py +157 -0
  4. naas_abi/agents/EntitytoSPARQLAgent.py +952 -0
  5. naas_abi/agents/EntitytoSPARQLAgent_test.py +66 -0
  6. naas_abi/agents/KnowledgeGraphBuilderAgent.py +321 -0
  7. naas_abi/agents/KnowledgeGraphBuilderAgent_test.py +86 -0
  8. naas_abi/agents/OntologyEngineerAgent.py +115 -0
  9. naas_abi/agents/OntologyEngineerAgent_test.py +42 -0
  10. naas_abi/apps/oxigraph_admin/main.py +392 -0
  11. naas_abi/apps/oxigraph_admin/terminal_style.py +151 -0
  12. naas_abi/apps/sparql_terminal/main.py +68 -0
  13. naas_abi/apps/sparql_terminal/terminal_style.py +236 -0
  14. naas_abi/apps/terminal_agent/main.py +553 -0
  15. naas_abi/apps/terminal_agent/terminal_style.py +175 -0
  16. naas_abi/cli.py +714 -0
  17. naas_abi/mappings.py +83 -0
  18. naas_abi/models/airgap_gemma.py +220 -0
  19. naas_abi/models/airgap_qwen.py +24 -0
  20. naas_abi/models/default.py +23 -0
  21. naas_abi/models/gpt_4_1.py +25 -0
  22. naas_abi/pipelines/AIAgentOntologyGenerationPipeline.py +635 -0
  23. naas_abi/pipelines/AIAgentOntologyGenerationPipeline_test.py +133 -0
  24. naas_abi/pipelines/AddIndividualPipeline.py +215 -0
  25. naas_abi/pipelines/AddIndividualPipeline_test.py +66 -0
  26. naas_abi/pipelines/InsertDataSPARQLPipeline.py +197 -0
  27. naas_abi/pipelines/InsertDataSPARQLPipeline_test.py +96 -0
  28. naas_abi/pipelines/MergeIndividualsPipeline.py +245 -0
  29. naas_abi/pipelines/MergeIndividualsPipeline_test.py +98 -0
  30. naas_abi/pipelines/RemoveIndividualPipeline.py +166 -0
  31. naas_abi/pipelines/RemoveIndividualPipeline_test.py +58 -0
  32. naas_abi/pipelines/UpdateCommercialOrganizationPipeline.py +198 -0
  33. naas_abi/pipelines/UpdateDataPropertyPipeline.py +175 -0
  34. naas_abi/pipelines/UpdateLegalNamePipeline.py +107 -0
  35. naas_abi/pipelines/UpdateLinkedInPagePipeline.py +179 -0
  36. naas_abi/pipelines/UpdatePersonPipeline.py +184 -0
  37. naas_abi/pipelines/UpdateSkillPipeline.py +118 -0
  38. naas_abi/pipelines/UpdateTickerPipeline.py +104 -0
  39. naas_abi/pipelines/UpdateWebsitePipeline.py +106 -0
  40. naas_abi/triggers.py +131 -0
  41. naas_abi/workflows/AgentRecommendationWorkflow.py +321 -0
  42. naas_abi/workflows/AgentRecommendationWorkflow_test.py +160 -0
  43. naas_abi/workflows/ArtificialAnalysisWorkflow.py +337 -0
  44. naas_abi/workflows/ArtificialAnalysisWorkflow_test.py +57 -0
  45. naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow.py +210 -0
  46. naas_abi/workflows/ConvertOntologyGraphToYamlWorkflow_test.py +78 -0
  47. naas_abi/workflows/CreateClassOntologyYamlWorkflow.py +208 -0
  48. naas_abi/workflows/CreateClassOntologyYamlWorkflow_test.py +65 -0
  49. naas_abi/workflows/CreateIndividualOntologyYamlWorkflow.py +183 -0
  50. naas_abi/workflows/CreateIndividualOntologyYamlWorkflow_test.py +86 -0
  51. naas_abi/workflows/ExportGraphInstancesToExcelWorkflow.py +450 -0
  52. naas_abi/workflows/ExportGraphInstancesToExcelWorkflow_test.py +33 -0
  53. naas_abi/workflows/GetObjectPropertiesFromClassWorkflow.py +385 -0
  54. naas_abi/workflows/GetObjectPropertiesFromClassWorkflow_test.py +57 -0
  55. naas_abi/workflows/GetSubjectGraphWorkflow.py +84 -0
  56. naas_abi/workflows/GetSubjectGraphWorkflow_test.py +71 -0
  57. naas_abi/workflows/SearchIndividualWorkflow.py +190 -0
  58. naas_abi/workflows/SearchIndividualWorkflow_test.py +98 -0
  59. naas_abi-1.0.0.dist-info/METADATA +9 -0
  60. naas_abi-1.0.0.dist-info/RECORD +62 -0
  61. naas_abi-1.0.0.dist-info/WHEEL +5 -0
  62. 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