personal_knowledge_library 3.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.

Potentially problematic release.


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

Files changed (42) hide show
  1. knowledge/__init__.py +91 -0
  2. knowledge/base/__init__.py +22 -0
  3. knowledge/base/access.py +167 -0
  4. knowledge/base/entity.py +267 -0
  5. knowledge/base/language.py +27 -0
  6. knowledge/base/ontology.py +2734 -0
  7. knowledge/base/search.py +473 -0
  8. knowledge/base/tenant.py +192 -0
  9. knowledge/nel/__init__.py +11 -0
  10. knowledge/nel/base.py +495 -0
  11. knowledge/nel/engine.py +123 -0
  12. knowledge/ontomapping/__init__.py +667 -0
  13. knowledge/ontomapping/manager.py +320 -0
  14. knowledge/public/__init__.py +27 -0
  15. knowledge/public/cache.py +115 -0
  16. knowledge/public/helper.py +373 -0
  17. knowledge/public/relations.py +128 -0
  18. knowledge/public/wikidata.py +1324 -0
  19. knowledge/services/__init__.py +128 -0
  20. knowledge/services/asyncio/__init__.py +7 -0
  21. knowledge/services/asyncio/base.py +458 -0
  22. knowledge/services/asyncio/graph.py +1420 -0
  23. knowledge/services/asyncio/group.py +450 -0
  24. knowledge/services/asyncio/search.py +439 -0
  25. knowledge/services/asyncio/users.py +270 -0
  26. knowledge/services/base.py +533 -0
  27. knowledge/services/graph.py +1897 -0
  28. knowledge/services/group.py +819 -0
  29. knowledge/services/helper.py +142 -0
  30. knowledge/services/ontology.py +1234 -0
  31. knowledge/services/search.py +488 -0
  32. knowledge/services/session.py +444 -0
  33. knowledge/services/tenant.py +281 -0
  34. knowledge/services/users.py +445 -0
  35. knowledge/utils/__init__.py +10 -0
  36. knowledge/utils/graph.py +417 -0
  37. knowledge/utils/wikidata.py +197 -0
  38. knowledge/utils/wikipedia.py +175 -0
  39. personal_knowledge_library-3.0.0.dist-info/LICENSE +201 -0
  40. personal_knowledge_library-3.0.0.dist-info/METADATA +1163 -0
  41. personal_knowledge_library-3.0.0.dist-info/RECORD +42 -0
  42. personal_knowledge_library-3.0.0.dist-info/WHEEL +4 -0
knowledge/__init__.py ADDED
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2021-present Wacom. All rights reserved.
3
+ """
4
+ Personal knowledge Library
5
+ --------------------------
6
+ This library provides a set of tools to manage Wacom private knowledge graph API.
7
+ All services are wrapped in a pythonic way to make it easy to use.
8
+ Additionally, the library provides a set of tools to utilise Wikidata.
9
+ """
10
+ import sys
11
+ from datetime import datetime
12
+
13
+ __author__ = "Markus Weber"
14
+ __copyright__ = "Copyright 2021-present Wacom. All rights reserved."
15
+ __credits__ = ["Markus Weber"]
16
+ __license__ = "Wacom"
17
+ __maintainer__ = ["Markus Weber"]
18
+ __email__ = "markus.weber@wacom.com"
19
+ __status__ = "beta"
20
+ __version__ = "3.0.0"
21
+
22
+ import loguru
23
+
24
+ # Create the Logger
25
+ logger = None
26
+
27
+ if logger is None:
28
+ import logging
29
+ import inspect
30
+ from typing import Union
31
+
32
+ class InterceptHandler(logging.Handler):
33
+ """
34
+ Custom logging handler to redirect logs from the standard logging module to Loguru.
35
+ This handler intercepts log messages and forwards them to the Loguru logger.
36
+ """
37
+
38
+ def emit(self, record: logging.LogRecord) -> None:
39
+ # Get corresponding Loguru level if it exists.
40
+ try:
41
+ level: Union[str, int] = logger.level(record.levelname).name
42
+ except ValueError:
43
+ level = record.levelno
44
+
45
+ # Find caller from where originated the logged message.
46
+ frame, depth = inspect.currentframe(), 0
47
+ while frame:
48
+ filename = frame.f_code.co_filename
49
+ is_logging = filename == logging.__file__
50
+ is_frozen = "importlib" in filename and "_bootstrap" in filename
51
+ if depth > 0 and not (is_logging or is_frozen):
52
+ break
53
+ frame = frame.f_back
54
+ depth += 1
55
+
56
+ logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
57
+
58
+ logger = loguru.logger
59
+ logger.remove()
60
+ logger.info("Logger initialized in for pks tools.")
61
+ today = datetime.now()
62
+ logger.add(
63
+ sys.stderr,
64
+ colorize=True,
65
+ format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}",
66
+ level="INFO",
67
+ enqueue=True,
68
+ )
69
+ logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
70
+
71
+ __all__ = [
72
+ "__copyright__",
73
+ "__credits__",
74
+ "__license__",
75
+ "__maintainer__",
76
+ "__email__",
77
+ "__status__",
78
+ "__version__",
79
+ "logger",
80
+ "base",
81
+ "nel",
82
+ "public",
83
+ "services",
84
+ "utils",
85
+ ]
86
+
87
+ from knowledge import base
88
+ from knowledge import nel
89
+ from knowledge import public
90
+ from knowledge import services
91
+ from knowledge import utils
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2021-present Wacom. All rights reserved.
3
+ """
4
+ Base structures.
5
+ ----------------
6
+ This module provides the base structures for the knowledge graph.
7
+ Such as the ontology, entities and access.
8
+
9
+ The classes in this module are used by the knowledge graph service.
10
+ For instance, the ontology structure is used to create the structure knowledge graph.
11
+ The entities are used to store the knowledge graph.
12
+
13
+ The access is used to access the knowledge graph, there are different types of access:
14
+ - Private access: the user can access only the entities that he/she created.
15
+ - Public access: the user can access all the entities.
16
+ - Group access: the user can access the entities that are in the same group.
17
+ """
18
+ __all__ = ["access", "entity", "ontology"]
19
+
20
+ from knowledge.base import access
21
+ from knowledge.base import entity
22
+ from knowledge.base import ontology
@@ -0,0 +1,167 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2021-present Wacom. All rights reserved.
3
+ from typing import List
4
+
5
+
6
+ class AccessRight:
7
+ """
8
+ Access rights for entities within a tenant.
9
+
10
+ Parameters
11
+ ----------
12
+ read: bool (default := False)
13
+ Read access for entity within tenant.
14
+ write: bool (default := False)
15
+ Write access for entity within tenant.
16
+ delete: bool (default := False)
17
+ Delete access for entity within tenant.
18
+ """
19
+
20
+ READ: str = "Read"
21
+ WRITE: str = "Write"
22
+ DELETE: str = "Delete"
23
+
24
+ def __init__(self, read: bool, write: bool, delete: bool):
25
+ self.__read: bool = read
26
+ self.__write: bool = write
27
+ self.__delete: bool = delete
28
+
29
+ @property
30
+ def read(self) -> bool:
31
+ """Read access for tenant."""
32
+ return self.__read
33
+
34
+ @read.setter
35
+ def read(self, value: bool):
36
+ self.__read = value
37
+
38
+ @property
39
+ def write(self) -> bool:
40
+ """Write access for tenant."""
41
+ return self.__write
42
+
43
+ @write.setter
44
+ def write(self, value: bool):
45
+ self.__write = value
46
+
47
+ @property
48
+ def delete(self) -> bool:
49
+ """Delete access for tenant."""
50
+ return self.__delete
51
+
52
+ @delete.setter
53
+ def delete(self, value: bool):
54
+ self.__delete = value
55
+
56
+ def __repr__(self):
57
+ result: str = "["
58
+ prefix: str = ""
59
+ if self.read:
60
+ result += AccessRight.READ
61
+ prefix = ", "
62
+ if self.write:
63
+ result += prefix + AccessRight.WRITE
64
+ if self.delete:
65
+ result += AccessRight.DELETE
66
+ result += "]"
67
+ return result
68
+
69
+ def to_list(self) -> List[str]:
70
+ """
71
+ Converts the access to list of properties.
72
+
73
+ Returns
74
+ -------
75
+ access_list: List[str]
76
+ List of rights
77
+ """
78
+ rights: List[str] = []
79
+ if self.read:
80
+ rights.append(TenantAccessRight.READ)
81
+ if self.write:
82
+ rights.append(TenantAccessRight.WRITE)
83
+ if self.delete:
84
+ rights.append(TenantAccessRight.DELETE)
85
+ return rights
86
+
87
+
88
+ class TenantAccessRight(AccessRight):
89
+ """
90
+ TenantAccessRight
91
+ -----------------
92
+ Access rights for entities within a tenant.
93
+
94
+ Parameters
95
+ ----------
96
+ read: bool (default := False)
97
+ Read access for entity within tenant.
98
+ write: bool (default := False)
99
+ Write access for entity within tenant.
100
+ delete: bool (default := False)
101
+ Delete access for entity within tenant.
102
+ """
103
+
104
+ def __init__(self, read: bool = False, write: bool = False, delete: bool = False):
105
+ super().__init__(read, write, delete)
106
+
107
+ @classmethod
108
+ def parse(cls, param: List[str]) -> "TenantAccessRight":
109
+ """
110
+ Converts the access to list of properties.
111
+
112
+ Parameters
113
+ ----------
114
+ param: List[str]
115
+ List of rights
116
+
117
+ Returns
118
+ -------
119
+ tenant_rights: TenantAccessRight
120
+ Instantiated rights.
121
+ """
122
+ rights: TenantAccessRight = TenantAccessRight()
123
+ rights.read = TenantAccessRight.READ in param
124
+ rights.write = TenantAccessRight.WRITE in param
125
+ rights.delete = TenantAccessRight.DELETE in param
126
+ return rights
127
+
128
+
129
+ class GroupAccessRight(AccessRight):
130
+ """
131
+ GroupAccessRight
132
+ -----------------
133
+ Group rights for entities within a group.
134
+
135
+ Parameters
136
+ ----------
137
+ read: bool (default := False)
138
+ Read access for entity within group.
139
+ write: bool (default := False)
140
+ Write access for entity within group.
141
+ delete: bool (default := False)
142
+ Delete access for entity within group.
143
+ """
144
+
145
+ def __init__(self, read: bool = False, write: bool = False, delete: bool = False):
146
+ super().__init__(read, write, delete)
147
+
148
+ @classmethod
149
+ def parse(cls, param: List[str]) -> "GroupAccessRight":
150
+ """
151
+ Converts the access to list of properties.
152
+
153
+ Parameters
154
+ ----------
155
+ param: List[str]
156
+ List of rights
157
+
158
+ Returns
159
+ -------
160
+ group_rights: GroupAccessRight
161
+ Instantiated rights.
162
+ """
163
+ rights: GroupAccessRight = GroupAccessRight()
164
+ rights.read = GroupAccessRight.READ in param
165
+ rights.write = GroupAccessRight.WRITE in param
166
+ rights.delete = GroupAccessRight.DELETE in param
167
+ return rights
@@ -0,0 +1,267 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2021-present Wacom. All rights reserved.
3
+ import abc
4
+ import enum
5
+ from typing import Any, List, Dict, Union
6
+
7
+ from knowledge.base.language import LocaleCode, LanguageCode, EN_US
8
+
9
+
10
+ # ---------------------------------------- Exceptions -----------------------------------------------------------------
11
+ class ServiceException(Exception):
12
+ """Service exception."""
13
+
14
+
15
+ class KnowledgeException(Exception):
16
+ """Knowledge exception."""
17
+
18
+
19
+ # ---------------------------------------- Constants ------------------------------------------------------------------
20
+ RDF_SYNTAX_NS_TYPE: str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
21
+ RDF_SCHEMA_COMMENT: str = "http://www.w3.org/2000/01/rdf-schema#comment"
22
+ RDF_SCHEMA_LABEL: str = "http://www.w3.org/2000/01/rdf-schema#label"
23
+ ALIAS_TAG: str = "alias"
24
+ DATA_PROPERTY_TAG: str = "literal"
25
+ VALUE_TAG: str = "value"
26
+ LANGUAGE_TAG: str = "lang"
27
+ LOCALE_TAG: str = "locale"
28
+ DATA_PROPERTIES_TAG: str = "literals"
29
+ SEND_TO_NEL_TAG: str = "sendToNEL"
30
+ SEND_VECTOR_INDEX_TAG: str = "sendToVectorIndex"
31
+ SOURCE_REFERENCE_ID_TAG: str = "source_reference_id"
32
+ EXTERNAL_USER_ID_TAG: str = "external_user_id"
33
+ SOURCE_SYSTEM_TAG: str = "source_system"
34
+ OBJECT_PROPERTIES_TAG: str = "relations"
35
+ OWNER_TAG: str = "owner"
36
+ OWNER_ID_TAG: str = "ownerId"
37
+ GROUP_IDS: str = "groupIds"
38
+ LOCALIZED_CONTENT_TAG: str = "LocalizedContent"
39
+ STATUS_FLAG_TAG: str = "status"
40
+ CONTENT_TAG: str = "value"
41
+ URI_TAG: str = "uri"
42
+ URIS_TAG: str = "uris"
43
+ FORCE_TAG: str = "force"
44
+ ERRORS_TAG: str = "errors"
45
+ TEXT_TAG: str = "text"
46
+ TYPE_TAG: str = "type"
47
+ IMAGE_TAG: str = "image"
48
+ DESCRIPTION_TAG: str = "description"
49
+ COMMENT_TAG: str = "text"
50
+ COMMENTS_TAG: str = "comments"
51
+ DESCRIPTIONS_TAG: str = "descriptions"
52
+ REPOSITORY_TAG: str = "repository"
53
+ DISPLAY_TAG: str = "display"
54
+ USE_NEL_TAG: str = "use_for_nel"
55
+ USE_VECTOR_INDEX_TAG: str = "use_for_vector_index"
56
+ USE_VECTOR_DOCUMENT_INDEX_TAG: str = "use_for_vector_document_index"
57
+ USE_FULLTEXT_TAG: str = "user_full_text"
58
+ TARGETS_TAG: str = "targets"
59
+ VISIBILITY_TAG: str = "visibility"
60
+ RELATIONS_TAG: str = "relations"
61
+ LABELS_TAG: str = "labels"
62
+ IS_MAIN_TAG: str = "isMain"
63
+ DATA_TYPE_TAG: str = "dataType"
64
+ RELATION_TAG: str = "relation"
65
+ OUTGOING_TAG: str = "out"
66
+ INCOMING_TAG: str = "in"
67
+ TENANT_RIGHTS_TAG: str = "tenantRights"
68
+ INFLECTION_CONCEPT_CLASS: str = "concept"
69
+ INFLECTION_SETTING: str = "inflection"
70
+ INFLECTION_CASE_SENSITIVE: str = "caseSensitive"
71
+ # ------------------------------------------ Indexing targets ----------------------------------------------------------
72
+ INDEXING_NEL_TARGET: str = "NEL"
73
+ INDEXING_VECTOR_SEARCH_TARGET: str = "VectorSearchWord"
74
+ INDEXING_VECTOR_SEARCH_DOCUMENT_TARGET: str = "VectorSearchDocument"
75
+ INDEXING_FULLTEXT_TARGET: str = "ElasticSearch"
76
+
77
+
78
+ class EntityStatus(enum.Enum):
79
+ """
80
+ Entity Status
81
+ -------------
82
+ Status of the entity synchronization (client and knowledge graph).
83
+ """
84
+
85
+ UNKNOWN = 0
86
+ """Unknown status."""
87
+ CREATED = 1
88
+ """Entity has been created and not yet update."""
89
+ UPDATED = 2
90
+ """Entity has been updated by the client and must be synced."""
91
+ SYNCED = 3
92
+ """State of entity is in sync with knowledge graph."""
93
+
94
+
95
+ class LocalizedContent(abc.ABC):
96
+ """
97
+ Localized content
98
+ -----------------
99
+ Content that is multilingual.
100
+
101
+ Parameters
102
+ ----------
103
+ content: str
104
+ Content value
105
+ language_code: LanguageCode (default:= 'en_US')
106
+ ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
107
+ """
108
+
109
+ def __init__(self, content: str, language_code: Union[LocaleCode, LanguageCode]):
110
+ self.__content: str = content
111
+ self.__language_code: Union[LocaleCode, LanguageCode] = language_code
112
+
113
+ @property
114
+ def content(self) -> str:
115
+ """String representation of the content."""
116
+ return self.__content
117
+
118
+ @content.setter
119
+ def content(self, value: str):
120
+ self.__content = value
121
+
122
+ @property
123
+ def language_code(self) -> Union[LocaleCode, LanguageCode]:
124
+ """Locale"""
125
+ return self.__language_code
126
+
127
+ def __repr__(self):
128
+ return f"{self.content}@{self.language_code}"
129
+
130
+
131
+ class Label(LocalizedContent):
132
+ """
133
+ Label
134
+ -----
135
+ Label that is multilingual.
136
+
137
+ Parameters
138
+ ----------
139
+ content: str
140
+ Content value
141
+ language_code: LocaleCode (default:= 'en_US')
142
+ ISO-3166 Country Codes and ISO-639 Language Codes in the format <language_code>_<country>, e.g., en_US.
143
+ main: bool (default:=False)
144
+ Main content
145
+ """
146
+
147
+ def __init__(self, content: str, language_code: LocaleCode = EN_US, main: bool = False):
148
+ self.__main: bool = main
149
+ super().__init__(content, language_code)
150
+
151
+ @property
152
+ def main(self) -> bool:
153
+ """Flag if the content is the main content or an alias."""
154
+ return self.__main
155
+
156
+ @staticmethod
157
+ def create_from_dict(
158
+ dict_label: Dict[str, Any], tag_name: str = CONTENT_TAG, locale_name: str = LOCALE_TAG
159
+ ) -> "Label":
160
+ """
161
+ Create a label from a dictionary.
162
+ Parameters
163
+ ----------
164
+ dict_label: Dict[str, Any]
165
+ Dictionary containing the label information.
166
+ tag_name: str
167
+ Tag name of the content.
168
+ locale_name: str
169
+ Tag name of the language code.
170
+
171
+ Returns
172
+ -------
173
+ instance: Label
174
+ The Label instance.
175
+ """
176
+ if tag_name not in dict_label:
177
+ raise ValueError("Dict is does not contain a localized label.")
178
+ if locale_name not in dict_label:
179
+ raise ValueError("Dict is does not contain a language code")
180
+ if IS_MAIN_TAG in dict_label:
181
+ return Label(dict_label[tag_name], LocaleCode(dict_label[locale_name]), dict_label[IS_MAIN_TAG])
182
+ return Label(dict_label[tag_name], LocaleCode(dict_label[locale_name]))
183
+
184
+ @staticmethod
185
+ def create_from_list(param: List[dict]) -> List[LOCALIZED_CONTENT_TAG]:
186
+ """
187
+ Create a list of labels from a list of dictionaries.
188
+
189
+ Parameters
190
+ ----------
191
+ param: List[dict]
192
+ List of dictionaries containing the label information.
193
+
194
+ Returns
195
+ -------
196
+ instance: List[Label]
197
+ List of label instances.
198
+ """
199
+ return [Label.create_from_dict(p) for p in param]
200
+
201
+ def __dict__(self):
202
+ return {CONTENT_TAG: self.content, LOCALE_TAG: self.language_code, IS_MAIN_TAG: self.main}
203
+
204
+
205
+ class Description(LocalizedContent):
206
+ """
207
+ Description
208
+ -----------
209
+ Description that is multilingual.
210
+
211
+ Parameters
212
+ ----------
213
+ description: str
214
+ Description value
215
+ language_code: LanguageCode (default:= 'en_US')
216
+ Language code of content
217
+ """
218
+
219
+ def __init__(self, description: str, language_code: LocaleCode = EN_US):
220
+ super().__init__(description, language_code)
221
+
222
+ @staticmethod
223
+ def create_from_dict(
224
+ dict_description: Dict[str, Any], tag_name: str = DESCRIPTION_TAG, locale_name: str = LOCALE_TAG
225
+ ) -> "Description":
226
+ """
227
+ Create a description from a dictionary.
228
+
229
+ Parameters
230
+ ----------
231
+ dict_description: Dict[str, Any]
232
+ Dictionary containing the description information.
233
+ tag_name: str
234
+ Tag name of the content.
235
+ locale_name:
236
+ Tag name of the language code.
237
+
238
+ Returns
239
+ -------
240
+ instance: Description
241
+ The description instance.
242
+ """
243
+ if tag_name not in dict_description or locale_name not in dict_description:
244
+ raise ValueError("Dict is does not contain a localized label.")
245
+ return Description(dict_description[tag_name], LocaleCode(dict_description[locale_name]))
246
+
247
+ @staticmethod
248
+ def create_from_list(param: List[Dict[str, Any]]) -> List["Description"]:
249
+ """Create a list of descriptions from a list of dictionaries.
250
+
251
+ Parameters
252
+ ----------
253
+ param: List[Dict[str, Any]]
254
+ List of dictionaries containing the description information.
255
+
256
+ Returns
257
+ -------
258
+ instance: List[Description]
259
+ List of description instances.
260
+ """
261
+ return [Description.create_from_dict(p) for p in param]
262
+
263
+ def __dict__(self):
264
+ return {
265
+ DESCRIPTION_TAG: self.content,
266
+ LOCALE_TAG: self.language_code,
267
+ }
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2024-present Wacom. All rights reserved.
3
+ from typing import NewType, List, Dict
4
+
5
+ # ---------------------------------------- Type definitions -----------------------------------------------------------
6
+ LanguageCode = NewType("LanguageCode", str)
7
+ LocaleCode = NewType("LocaleCode", str)
8
+ # ------------------------------------------------ Language codes ------------------------------------------------------
9
+ EN_US: LocaleCode = LocaleCode("en_US")
10
+ JA_JP: LocaleCode = LocaleCode("ja_JP")
11
+ DE_DE: LocaleCode = LocaleCode("de_DE")
12
+ BG_BG: LocaleCode = LocaleCode("bg_BG")
13
+ FR_FR: LocaleCode = LocaleCode("fr_FR")
14
+ IT_IT: LocaleCode = LocaleCode("it_IT")
15
+ ES_ES: LocaleCode = LocaleCode("es_ES")
16
+ EN: LanguageCode = LanguageCode("en")
17
+ DE: LanguageCode = LanguageCode("de")
18
+ BG: LanguageCode = LanguageCode("bg")
19
+ JA: LanguageCode = LanguageCode("ja")
20
+ FR: LanguageCode = LanguageCode("fr")
21
+ IT: LanguageCode = LanguageCode("it")
22
+ ES: LanguageCode = LanguageCode("es")
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]
26
+ LANGUAGE_LOCALE_MAPPING: Dict[LanguageCode, LocaleCode] = dict(list(zip(SUPPORTED_LANGUAGES, SUPPORTED_LOCALES)))
27
+ LOCALE_LANGUAGE_MAPPING: Dict[LocaleCode, LanguageCode] = dict(list(zip(SUPPORTED_LOCALES, SUPPORTED_LANGUAGES)))