personal_knowledge_library 3.1.1__tar.gz → 3.2.0__tar.gz

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.

Potentially problematic release.


This version of personal_knowledge_library might be problematic. Click here for more details.

Files changed (46) hide show
  1. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/PKG-INFO +1 -1
  2. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/__init__.py +1 -1
  3. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/base/__init__.py +5 -1
  4. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/base/language.py +2 -2
  5. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/base/ontology.py +4 -2
  6. personal_knowledge_library-3.2.0/knowledge/base/response.py +361 -0
  7. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/ontomapping/__init__.py +2 -0
  8. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/public/client.py +3 -2
  9. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/__init__.py +3 -1
  10. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/asyncio/graph.py +116 -1
  11. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/graph.py +226 -6
  12. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/search.py +4 -4
  13. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/tenant.py +2 -1
  14. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/users.py +2 -0
  15. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/utils/__init__.py +3 -3
  16. personal_knowledge_library-3.2.0/knowledge/utils/diff.py +598 -0
  17. personal_knowledge_library-3.2.0/knowledge/utils/import_format.py +168 -0
  18. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/pyproject.toml +1 -1
  19. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/LICENSE +0 -0
  20. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/README.md +0 -0
  21. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/base/access.py +0 -0
  22. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/base/entity.py +0 -0
  23. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/base/search.py +0 -0
  24. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/base/tenant.py +0 -0
  25. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/nel/__init__.py +0 -0
  26. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/nel/base.py +0 -0
  27. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/nel/engine.py +0 -0
  28. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/ontomapping/manager.py +0 -0
  29. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/public/__init__.py +0 -0
  30. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/public/cache.py +0 -0
  31. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/public/helper.py +0 -0
  32. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/public/relations.py +0 -0
  33. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/public/wikidata.py +0 -0
  34. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/asyncio/__init__.py +0 -0
  35. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/asyncio/base.py +0 -0
  36. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/asyncio/group.py +0 -0
  37. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/asyncio/search.py +0 -0
  38. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/asyncio/users.py +0 -0
  39. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/base.py +0 -0
  40. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/group.py +0 -0
  41. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/helper.py +0 -0
  42. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/ontology.py +0 -0
  43. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/services/session.py +0 -0
  44. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/utils/graph.py +0 -0
  45. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/utils/wikidata.py +0 -0
  46. {personal_knowledge_library-3.1.1 → personal_knowledge_library-3.2.0}/knowledge/utils/wikipedia.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: personal_knowledge_library
3
- Version: 3.1.1
3
+ Version: 3.2.0
4
4
  Summary: Library to access Wacom's Personal Knowledge graph.
5
5
  License: Apache-2.0
6
6
  Keywords: semantic-knowledge,knowledge-graph
@@ -17,7 +17,7 @@ __license__ = "Wacom"
17
17
  __maintainer__ = ["Markus Weber"]
18
18
  __email__ = "markus.weber@wacom.com"
19
19
  __status__ = "beta"
20
- __version__ = "3.1.1"
20
+ __version__ = "3.2.0"
21
21
 
22
22
  import loguru
23
23
 
@@ -15,8 +15,12 @@ The access is used to access the knowledge graph, there are different types of a
15
15
  - Public access: the user can access all the entities.
16
16
  - Group access: the user can access the entities that are in the same group.
17
17
  """
18
- __all__ = ["access", "entity", "ontology"]
18
+ __all__ = ["access", "entity", "language", "ontology", "response", "search", "tenant"]
19
19
 
20
20
  from knowledge.base import access
21
21
  from knowledge.base import entity
22
+ from knowledge.base import language
22
23
  from knowledge.base import ontology
24
+ from knowledge.base import response
25
+ from knowledge.base import search
26
+ from knowledge.base import tenant
@@ -21,7 +21,7 @@ FR: LanguageCode = LanguageCode("fr")
21
21
  IT: LanguageCode = LanguageCode("it")
22
22
  ES: LanguageCode = LanguageCode("es")
23
23
  # ----------------------------------------------------------------------------------------------------------------------
24
- SUPPORTED_LOCALES: List[LocaleCode] = [JA_JP, EN_US, DE_DE, BG_BG, FR_FR, IT_IT, ES_ES]
25
- SUPPORTED_LANGUAGES: List[LanguageCode] = [JA, EN, DE, BG, FR, IT, ES]
24
+ SUPPORTED_LOCALES: List[LocaleCode] = [JA_JP, EN_US, DE_DE, BG_BG, IT_IT]
25
+ SUPPORTED_LANGUAGES: List[LanguageCode] = [JA, EN, DE, BG, IT]
26
26
  LANGUAGE_LOCALE_MAPPING: Dict[LanguageCode, LocaleCode] = dict(list(zip(SUPPORTED_LANGUAGES, SUPPORTED_LOCALES)))
27
27
  LOCALE_LANGUAGE_MAPPING: Dict[LocaleCode, LanguageCode] = dict(list(zip(SUPPORTED_LOCALES, SUPPORTED_LANGUAGES)))
@@ -1833,7 +1833,7 @@ class ThingObject(abc.ABC):
1833
1833
  @property
1834
1834
  def source_system(self) -> Optional[str]:
1835
1835
  """Default reference system for the entity."""
1836
- if SYSTEM_SOURCE_REFERENCE_ID in self.__data_properties:
1836
+ if SYSTEM_SOURCE_SYSTEM in self.__data_properties:
1837
1837
  # The en_US is the default language for the source reference system
1838
1838
  for sr in self.data_properties[SYSTEM_SOURCE_SYSTEM]:
1839
1839
  if sr.language_code == EN_US:
@@ -2179,7 +2179,9 @@ class ThingObject(abc.ABC):
2179
2179
  labels.extend([la.__dict__() for la in self.label])
2180
2180
  labels.extend([la.__dict__() for la in self.alias])
2181
2181
  dict_object: Dict[str, Any] = {
2182
- SOURCE_REFERENCE_ID_TAG: self.source_reference_id if self.source_reference_id is None else reference_id,
2182
+ SOURCE_REFERENCE_ID_TAG: (
2183
+ self.default_source_reference_id() if self.source_reference_id is not None else reference_id
2184
+ ),
2183
2185
  SOURCE_SYSTEM_TAG: self.source_system,
2184
2186
  IMAGE_TAG: self.image,
2185
2187
  LABELS_TAG: labels,
@@ -0,0 +1,361 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2025-present Wacom. All rights reserved.
3
+ from datetime import datetime
4
+ from typing import List, Optional, Dict, Any
5
+ from typing import Literal
6
+
7
+
8
+ class JobStatus:
9
+ """
10
+ JobStatus
11
+ ---------
12
+ Represents the status of a job.
13
+
14
+ Parameters
15
+ ----------
16
+ user_id: str
17
+ Identifies the user who started the job.
18
+ tenant_id: str
19
+ Identifies the tenant where the entities are imported.
20
+ internal_job_id: str
21
+ Identifies the internal job ID.
22
+ job_id: str
23
+ Identifies the job ID.
24
+ status: Literal["Pending", "InProgress", "Completed", "Failed", "Retrying"]
25
+ The status of the job. Possible values are:
26
+ - Pending - The job is pending.
27
+ - InProgress - The job is in progress.
28
+ - Completed - The job is completed.
29
+ - Failed - The job has failed.
30
+ - Retrying - The job is being retried.
31
+ processed_entities: int
32
+ The number of processed entities.
33
+ processed_relations: int
34
+ The number of processed relations.
35
+ processed_images: int
36
+ The number of processed images.
37
+ started_at: Optional[datetime]
38
+ The timestamp when the job started.
39
+ finished_at: Optional[datetime]
40
+ The timestamp when the job finished.
41
+ """
42
+
43
+ PENDING: str = "Pending"
44
+ """The job is pending. It has not started yet, as another job is in progress."""
45
+ IN_PROGRESS: str = "InProgress"
46
+ """The job is in progress. It has started but not yet completed."""
47
+ COMPLETED: str = "Completed"
48
+ """The job is completed."""
49
+ FAILED: str = "Failed"
50
+ """The job has failed."""
51
+ RETRYING: str = "Retrying"
52
+ """The job is being retried."""
53
+
54
+ def __init__(
55
+ self,
56
+ user_id: str,
57
+ tenant_id: str,
58
+ internal_job_id: str,
59
+ job_id: str,
60
+ status: Literal["Pending", "InProgress", "Completed", "Failed", "Retrying"],
61
+ processed_entities: int = 0,
62
+ processed_relations: int = 0,
63
+ processed_images: int = 0,
64
+ started_at: Optional[datetime] = None,
65
+ finished_at: Optional[datetime] = None,
66
+ failures: int = 0,
67
+ ):
68
+ self._userId: str = user_id
69
+ self._tenantId: str = tenant_id
70
+ self._internalJobId: str = internal_job_id
71
+ self._jobId: str = job_id
72
+ self._status: Literal["Pending", "InProgress", "Completed", "Failed", "Retrying"] = status
73
+ self._processed_entities: int = processed_entities
74
+ self._processed_relations: int = processed_relations
75
+ self._processed_images: int = processed_images
76
+ self._started_at: Optional[datetime] = started_at
77
+ self._finished_at: Optional[datetime] = finished_at
78
+ self._failures: int = failures
79
+
80
+ @property
81
+ def user_id(self) -> str:
82
+ """
83
+ Identifies the user who started the job.
84
+ """
85
+ return self._userId
86
+
87
+ @property
88
+ def tenant_id(self) -> str:
89
+ """
90
+ Identifies the tenant where the entities are imported.
91
+ """
92
+ return self._tenantId
93
+
94
+ @property
95
+ def internal_job_id(self) -> str:
96
+ """
97
+ Identifies the internal job ID.
98
+ """
99
+ return self._internalJobId
100
+
101
+ @property
102
+ def job_id(self) -> str:
103
+ """
104
+ Identifies the job ID.
105
+ """
106
+ return self._jobId
107
+
108
+ @property
109
+ def status(self) -> Literal["Pending", "InProgress", "Completed", "Failed", "Retrying"]:
110
+ """
111
+ The status of the job. Possible values are:
112
+ - Pending - The job is pending.
113
+ - InProgress - The job is in progress.
114
+ - Completed - The job is completed.
115
+ - Failed - The job has failed.
116
+ - Retrying - The job is being retried.
117
+ """
118
+ return self._status
119
+
120
+ @property
121
+ def processed_entities(self) -> int:
122
+ """
123
+ The number of processed entities.
124
+ """
125
+ return self._processed_entities
126
+
127
+ @property
128
+ def processed_relations(self) -> int:
129
+ """
130
+ The number of processed relations.
131
+ """
132
+ return self._processed_relations
133
+
134
+ @property
135
+ def processed_images(self) -> int:
136
+ """
137
+ The number of processed images.
138
+ """
139
+ return self._processed_images
140
+
141
+ @property
142
+ def started_at(self) -> Optional[datetime]:
143
+ """
144
+ The timestamp when the job started.
145
+ """
146
+ return self._started_at
147
+
148
+ @property
149
+ def finished_at(self) -> Optional[datetime]:
150
+ """
151
+ The timestamp when the job finished.
152
+ """
153
+ return self._finished_at
154
+
155
+ @property
156
+ def failures(self) -> int:
157
+ """
158
+ The number of failures encountered during the job.
159
+ """
160
+ return self._failures
161
+
162
+ @classmethod
163
+ def from_dict(cls, data: Dict[str, Any]) -> "JobStatus":
164
+ """
165
+ Create a JobStatus instance from a dictionary.
166
+ Parameters
167
+ ----------
168
+ data: Dict[str, Any]
169
+ Response data from the API.
170
+
171
+ Returns
172
+ -------
173
+ instance: JobStatus
174
+ Instance of JobStatus.
175
+ """
176
+ return cls(
177
+ user_id=data.get("userId"),
178
+ tenant_id=data.get("tenantId"),
179
+ internal_job_id=data.get("internalJobId"),
180
+ job_id=data.get("jobId"),
181
+ status=data.get("status"),
182
+ processed_entities=data.get("processed", {}).get("entities", 0),
183
+ processed_relations=data.get("processed", {}).get("relations", 0),
184
+ processed_images=data.get("processed", {}).get("images", 0),
185
+ started_at=datetime.fromisoformat(data.get("startedAt", datetime.now().isoformat())),
186
+ finished_at=datetime.fromisoformat(data.get("finishedAt", datetime.now().isoformat())),
187
+ failures=data.get("failures", 0),
188
+ )
189
+
190
+ def __repr__(self):
191
+ return (
192
+ f"JobStatus(userId={self.user_id}, tenantId={self.tenant_id}, internalJobId={self.internal_job_id}, "
193
+ f"jobId={self.job_id}, status={self.status}, failures={self.failures}, "
194
+ f"processed_entities={self.processed_entities}, "
195
+ f"processed_relations={self.processed_relations}, processed_images={self.processed_images}, "
196
+ f"started_at={self.started_at}, finished_at={self.finished_at})"
197
+ )
198
+
199
+
200
+ class ErrorDetail:
201
+ """
202
+ ErrorDetail
203
+ ----------
204
+ Represents an error detail.
205
+
206
+ Parameters
207
+ ----------
208
+ severity: str
209
+ The severity of the error.
210
+ reason: str
211
+ The reason for the error.
212
+ position_offset: int
213
+ The position offset of the error in the file.
214
+ timestamp: str
215
+ The timestamp of the error in ISO 8601 format.
216
+ """
217
+
218
+ def __init__(self, severity: str, reason: str, position_offset: int, timestamp: str):
219
+ self._severity = severity
220
+ self._reason = reason
221
+ self._position_offset = position_offset
222
+ self._timestamp = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
223
+
224
+ @property
225
+ def severity(self) -> str:
226
+ """The severity of the error."""
227
+ return self._severity
228
+
229
+ @property
230
+ def reason(self) -> str:
231
+ """The reason for the error."""
232
+ return self._reason
233
+
234
+ @property
235
+ def position_offset(self) -> int:
236
+ """The position offset of the error in the file."""
237
+ return self._position_offset
238
+
239
+ @property
240
+ def timestamp(self) -> datetime:
241
+ """The timestamp of the error in ISO 8601 format."""
242
+ return self._timestamp
243
+
244
+
245
+ class ErrorLogEntry:
246
+ """
247
+ ErrorLogEntry
248
+ -------------
249
+ Represents an entry in the error log.
250
+
251
+ """
252
+
253
+ def __init__(self, source_reference_id: Optional[str], errors: List[ErrorDetail]):
254
+ self._source_reference_id = source_reference_id
255
+ self._errors = errors
256
+
257
+ @property
258
+ def source_reference_id(self) -> Optional[str]:
259
+ """The source reference ID."""
260
+ return self._source_reference_id
261
+
262
+ @property
263
+ def errors(self) -> List[ErrorDetail]:
264
+ """The list of errors."""
265
+ return self._errors
266
+
267
+
268
+ class ErrorLogResponse:
269
+ """
270
+ ErrorLogResponse
271
+ ----------------
272
+ Represents the response for error log.
273
+ """
274
+
275
+ def __init__(self, next_page_id: str, error_log: List[ErrorLogEntry]):
276
+ self._next_page_id = next_page_id
277
+ self._error_log = error_log
278
+
279
+ @property
280
+ def next_page_id(self) -> str:
281
+ """The ID of the next page."""
282
+ return self._next_page_id
283
+
284
+ @property
285
+ def error_log(self) -> List[ErrorLogEntry]:
286
+ """The list of error log entries."""
287
+ return self._error_log
288
+
289
+ @classmethod
290
+ def from_dict(cls, param: Dict[str, Any]) -> "ErrorLogResponse":
291
+ """
292
+ Create an ErrorLogResponse instance from a dictionary.
293
+ Parameters
294
+ ----------
295
+ param: Dict[str, Any]
296
+ Response data from the API.
297
+
298
+ Returns
299
+ -------
300
+ instance: ErrorLogResponse
301
+ Instance of ErrorLogResponse.
302
+ """
303
+ error_log_entries = []
304
+ for entry in param.get("errorLog", []):
305
+ errors = [
306
+ ErrorDetail(
307
+ severity=e["severity"],
308
+ reason=e["reason"],
309
+ position_offset=e["positionOffset"],
310
+ timestamp=e["timestamp"],
311
+ )
312
+ for e in entry.get("errors", [])
313
+ ]
314
+ error_log_entries.append(ErrorLogEntry(source_reference_id=entry.get("sourceReferenceId"), errors=errors))
315
+
316
+ return ErrorLogResponse(next_page_id=param["nextPageId"], error_log=error_log_entries)
317
+
318
+
319
+ class NewEntityUrisResponse:
320
+ """
321
+ NewEntityUrisResponse
322
+ -------------------
323
+ Represents the response for new entities.
324
+
325
+ Parameters
326
+ ----------
327
+ new_entities_uris: List[str]
328
+ The list of URIs of new entities.
329
+ next_page_id: Optional[str]
330
+ Next page ID for pagination.
331
+ """
332
+
333
+ def __init__(self, new_entities_uris: List[str], next_page_id: Optional[str]):
334
+ self._new_entities_uris: List[str] = new_entities_uris
335
+ self._next_page_id: Optional[str] = next_page_id
336
+
337
+ @property
338
+ def new_entities_uris(self) -> List[str]:
339
+ """The list the uris of new entities."""
340
+ return self._new_entities_uris
341
+
342
+ @property
343
+ def next_page_id(self) -> Optional[str]:
344
+ """The ID of the next page."""
345
+ return self._next_page_id
346
+
347
+ @classmethod
348
+ def from_dict(cls, param: Dict[str, Any]) -> "NewEntityUrisResponse":
349
+ """
350
+ Create a NewEntityUrisResponse instance from a dictionary.
351
+ Parameters
352
+ ----------
353
+ param: Dict[str, Any]
354
+ Response data from the API.
355
+
356
+ Returns
357
+ -------
358
+ instance: NewEntityUrisResponse
359
+ Instance of NewEntityUrisResponse.
360
+ """
361
+ return cls(new_entities_uris=param["uris"], next_page_id=param.get("nextPage"))
@@ -543,6 +543,7 @@ def build_configuration(mapping: Dict[str, Any]) -> MappingConfiguration:
543
543
  conf.add_property(property_config)
544
544
  return conf
545
545
 
546
+
546
547
  def register_ontology(rdf_str: str):
547
548
  """
548
549
  Registers the ontology.
@@ -553,6 +554,7 @@ def register_ontology(rdf_str: str):
553
554
  """
554
555
  ontology_graph.parse(data=rdf_str, format="xml")
555
556
 
557
+
556
558
  def load_configuration(configuration: Path):
557
559
  """
558
560
  Loads the configuration.
@@ -348,8 +348,9 @@ class WikiDataAPIClient:
348
348
  return WikiDataAPIClient.__wikidata_task__(qid)
349
349
 
350
350
  @staticmethod
351
- def retrieve_entities(qids: Union[List[str], Set[str]], progress: Optional[Callable[[int, int], None]] = None) \
352
- -> List[WikidataThing]:
351
+ def retrieve_entities(
352
+ qids: Union[List[str], Set[str]], progress: Optional[Callable[[int, int], None]] = None
353
+ ) -> List[WikidataThing]:
353
354
  """
354
355
  Retrieve multiple Wikidata things.
355
356
  Parameters
@@ -3,7 +3,7 @@
3
3
  """
4
4
  This package contains the services for the knowledge graph functionality.
5
5
  """
6
- from typing import List
6
+ from typing import List, Literal
7
7
 
8
8
  # ------------------------------------------------- Constants ----------------------------------------------------------
9
9
  USER_AGENT_HEADER_FLAG: str = "User-Agent"
@@ -52,6 +52,7 @@ PRUNE_PARAM: str = "prune"
52
52
  NEL_PARAM: str = "nelType"
53
53
 
54
54
  APPLICATION_JSON_HEADER: str = "application/json"
55
+ IndexType = Literal["NEL", "ElasticSearch", "VectorSearchWord", "VectorSearchDocument"]
55
56
 
56
57
  DEFAULT_TIMEOUT: int = 60
57
58
  DEFAULT_TOKEN_REFRESH_TIME: int = 360
@@ -119,6 +120,7 @@ __all__ = [
119
120
  "STATUS_FORCE_LIST",
120
121
  "DEFAULT_BACKOFF_FACTOR",
121
122
  "DEFAULT_MAX_RETRIES",
123
+ "IndexType",
122
124
  ]
123
125
 
124
126
  from knowledge.services import base
@@ -36,7 +36,7 @@ from knowledge.base.ontology import (
36
36
  ObjectProperty,
37
37
  )
38
38
  from knowledge.nel.base import KnowledgeGraphEntity, EntityType, KnowledgeSource, EntitySource
39
- from knowledge.services import AUTHORIZATION_HEADER_FLAG, IS_OWNER_PARAM
39
+ from knowledge.services import AUTHORIZATION_HEADER_FLAG, IS_OWNER_PARAM, IndexType
40
40
  from knowledge.services import (
41
41
  SUBJECT_URI,
42
42
  RELATION_URI,
@@ -570,6 +570,121 @@ class AsyncWacomKnowledgeService(AsyncServiceAPIClient):
570
570
  )
571
571
  await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
572
572
 
573
+ async def add_entity_indexes(
574
+ self,
575
+ entity_uri: str,
576
+ targets: List[IndexType],
577
+ auth_key: Optional[str] = None,
578
+ timeout: int = DEFAULT_TIMEOUT,
579
+ ) -> Dict[IndexType, Any]:
580
+ """
581
+ Updates index targets of an entity. The index targets can be set to "NEL", "ElasticSearch", "VectorSearchWord",
582
+ or "VectorSearchDocument".
583
+ If the target is already set for the entity, there will be no changes.
584
+
585
+ Parameters
586
+ ----------
587
+ entity_uri: str
588
+ URI of entity
589
+ targets: List[Literal["NEL", "ElasticSearch", "VectorSearchWord", "VectorSearchDocument"]]
590
+ List of indexing targets
591
+ auth_key: Optional[str]
592
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
593
+ timeout: int
594
+ Timeout for the request (default: 60 seconds)
595
+
596
+ Returns
597
+ -------
598
+ update_status: Dict[str, Any]
599
+ Status per target (depending on the targets of entity and the ones set in the request). If the entity
600
+ already has the target set, the status will be "Target already exists" for that target,
601
+ otherwise it will be "UPSERT".
602
+
603
+ Raises
604
+ ------
605
+ WacomServiceException
606
+ If the graph service returns an error code
607
+ """
608
+ if auth_key is None:
609
+ auth_key, _ = await self.handle_token()
610
+ url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{entity_uri}/indexes"
611
+ # Header info
612
+ headers: dict = {
613
+ USER_AGENT_HEADER_FLAG: self.user_agent,
614
+ CONTENT_TYPE_HEADER_FLAG: APPLICATION_JSON_HEADER,
615
+ AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
616
+ }
617
+ async with AsyncServiceAPIClient.__async_session__() as session:
618
+ async with session.patch(
619
+ url, json=targets, headers=headers, timeout=timeout, verify_ssl=self.verify_calls
620
+ ) as response:
621
+ if not response.ok:
622
+ raise await handle_error(
623
+ f"Update of entity indexes failed. URI:={entity_uri}.",
624
+ response,
625
+ payload={"targets": targets},
626
+ headers=headers,
627
+ )
628
+ response_dict: Dict[str, Any] = await response.json(loads=orjson.loads)
629
+ await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
630
+ return response_dict
631
+
632
+ async def remove_entity_indexes(
633
+ self,
634
+ entity_uri: str,
635
+ targets: List[IndexType],
636
+ auth_key: Optional[str] = None,
637
+ timeout: int = DEFAULT_TIMEOUT,
638
+ ) -> Dict[IndexType, Any]:
639
+ """
640
+ Deletes the search index for a given entity.
641
+
642
+ Parameters
643
+ ----------
644
+ entity_uri: str
645
+ URI of entity
646
+ targets: List[Literal["NEL", "ElasticSearch", "VectorSearchWord", "VectorSearchDocument"]]
647
+ List of indexing targets
648
+ auth_key: Optional[str]
649
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
650
+ timeout: int
651
+ Timeout for the request (default: 60 seconds)
652
+
653
+ Returns
654
+ -------
655
+ update_status: Dict[str, Any]
656
+ Status per target (depending on the targets of entity and the ones set in the request), e.g.,
657
+ response will only contain {"NEL: "DELETE"}, if NEL is the only target in the request.
658
+
659
+ Raises
660
+ ------
661
+ WacomServiceException
662
+ If the graph service returns an error code
663
+ """
664
+ if auth_key is None:
665
+ auth_key, _ = await self.handle_token()
666
+ url: str = f"{self.service_base_url}{AsyncWacomKnowledgeService.ENTITY_ENDPOINT}/{entity_uri}/indexes"
667
+ # Header info
668
+ headers: dict = {
669
+ USER_AGENT_HEADER_FLAG: self.user_agent,
670
+ CONTENT_TYPE_HEADER_FLAG: APPLICATION_JSON_HEADER,
671
+ AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}",
672
+ }
673
+ async with AsyncServiceAPIClient.__async_session__() as session:
674
+ async with session.delete(
675
+ url, json=targets, headers=headers, timeout=timeout, verify_ssl=self.verify_calls
676
+ ) as response:
677
+ if not response.ok:
678
+ raise await handle_error(
679
+ f"Deletion of entity indexes failed. URI:={entity_uri}.",
680
+ response,
681
+ payload={"targets": targets},
682
+ headers=headers,
683
+ )
684
+ response_dict: Dict[str, Any] = await response.json(loads=orjson.loads)
685
+ await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
686
+ return response_dict
687
+
573
688
  async def relations(
574
689
  self, uri: str, auth_key: Optional[str] = None
575
690
  ) -> Dict[OntologyPropertyReference, ObjectProperty]: