semantic-kernel 0.2.4.dev0__py3-none-any.whl → 0.2.5.dev0__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.
- semantic_kernel/{ai → connectors/ai}/chat_completion_client_base.py +1 -1
- semantic_kernel/connectors/ai/hugging_face/__init__.py +10 -0
- semantic_kernel/connectors/ai/hugging_face/services/hf_text_completion.py +95 -0
- semantic_kernel/connectors/ai/hugging_face/services/hf_text_embedding.py +63 -0
- semantic_kernel/connectors/ai/open_ai/__init__.py +29 -0
- semantic_kernel/{ai → connectors/ai}/open_ai/services/azure_chat_completion.py +2 -2
- semantic_kernel/{ai → connectors/ai}/open_ai/services/azure_text_completion.py +2 -2
- semantic_kernel/{ai → connectors/ai}/open_ai/services/azure_text_embedding.py +2 -2
- semantic_kernel/{ai → connectors/ai}/open_ai/services/open_ai_chat_completion.py +36 -4
- semantic_kernel/{ai → connectors/ai}/open_ai/services/open_ai_text_completion.py +10 -6
- semantic_kernel/{ai → connectors/ai}/open_ai/services/open_ai_text_embedding.py +2 -2
- semantic_kernel/{ai → connectors/ai}/text_completion_client_base.py +4 -2
- semantic_kernel/core_skills/time_skill.py +11 -1
- semantic_kernel/kernel.py +23 -17
- semantic_kernel/kernel_config.py +118 -109
- semantic_kernel/kernel_exception.py +4 -4
- semantic_kernel/kernel_extensions/import_skills.py +21 -21
- semantic_kernel/kernel_extensions/memory_configuration.py +10 -12
- semantic_kernel/memory/memory_query_result.py +36 -6
- semantic_kernel/memory/memory_record.py +52 -11
- semantic_kernel/memory/memory_store_base.py +74 -5
- semantic_kernel/memory/semantic_text_memory.py +92 -10
- semantic_kernel/memory/semantic_text_memory_base.py +1 -2
- semantic_kernel/memory/volatile_memory_store.py +251 -25
- semantic_kernel/orchestration/sk_function.py +32 -30
- semantic_kernel/orchestration/sk_function_base.py +11 -9
- semantic_kernel/semantic_functions/prompt_template_config.py +2 -2
- semantic_kernel/text/__init__.py +17 -0
- semantic_kernel/text/function_extension.py +23 -0
- semantic_kernel/text/text_chunker.py +250 -0
- {semantic_kernel-0.2.4.dev0.dist-info → semantic_kernel-0.2.5.dev0.dist-info}/METADATA +9 -6
- {semantic_kernel-0.2.4.dev0.dist-info → semantic_kernel-0.2.5.dev0.dist-info}/RECORD +37 -35
- semantic_kernel/ai/embeddings/embedding_index_base.py +0 -20
- semantic_kernel/ai/open_ai/__init__.py +0 -27
- semantic_kernel/memory/storage/data_entry.py +0 -36
- semantic_kernel/memory/storage/data_store_base.py +0 -36
- semantic_kernel/memory/storage/volatile_data_store.py +0 -62
- /semantic_kernel/{ai → connectors/ai}/ai_exception.py +0 -0
- /semantic_kernel/{ai → connectors/ai}/chat_request_settings.py +0 -0
- /semantic_kernel/{ai → connectors/ai}/complete_request_settings.py +0 -0
- /semantic_kernel/{ai → connectors/ai}/embeddings/embedding_generator_base.py +0 -0
- {semantic_kernel-0.2.4.dev0.dist-info → semantic_kernel-0.2.5.dev0.dist-info}/WHEEL +0 -0
|
@@ -6,10 +6,16 @@ from enum import Enum
|
|
|
6
6
|
from logging import Logger
|
|
7
7
|
from typing import Any, Callable, List, Optional, cast
|
|
8
8
|
|
|
9
|
-
from semantic_kernel.ai.chat_completion_client_base import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from semantic_kernel.ai.
|
|
9
|
+
from semantic_kernel.connectors.ai.chat_completion_client_base import (
|
|
10
|
+
ChatCompletionClientBase,
|
|
11
|
+
)
|
|
12
|
+
from semantic_kernel.connectors.ai.chat_request_settings import ChatRequestSettings
|
|
13
|
+
from semantic_kernel.connectors.ai.complete_request_settings import (
|
|
14
|
+
CompleteRequestSettings,
|
|
15
|
+
)
|
|
16
|
+
from semantic_kernel.connectors.ai.text_completion_client_base import (
|
|
17
|
+
TextCompletionClientBase,
|
|
18
|
+
)
|
|
13
19
|
from semantic_kernel.kernel_exception import KernelException
|
|
14
20
|
from semantic_kernel.memory.null_memory import NullMemory
|
|
15
21
|
from semantic_kernel.memory.semantic_text_memory_base import SemanticTextMemoryBase
|
|
@@ -41,9 +47,9 @@ class SKFunction(SKFunctionBase):
|
|
|
41
47
|
_function: Callable[..., Any]
|
|
42
48
|
_skill_collection: Optional[ReadOnlySkillCollectionBase]
|
|
43
49
|
_log: Logger
|
|
44
|
-
|
|
50
|
+
_ai_service: Optional[TextCompletionClientBase]
|
|
45
51
|
_ai_request_settings: CompleteRequestSettings
|
|
46
|
-
|
|
52
|
+
_chat_service: Optional[ChatCompletionClientBase]
|
|
47
53
|
_chat_request_settings: ChatRequestSettings
|
|
48
54
|
|
|
49
55
|
@staticmethod
|
|
@@ -99,7 +105,7 @@ class SKFunction(SKFunctionBase):
|
|
|
99
105
|
|
|
100
106
|
async def _local_func(client, request_settings, context):
|
|
101
107
|
if client is None:
|
|
102
|
-
raise ValueError("AI LLM
|
|
108
|
+
raise ValueError("AI LLM service cannot be `None`")
|
|
103
109
|
|
|
104
110
|
try:
|
|
105
111
|
if function_config.has_chat_prompt:
|
|
@@ -125,9 +131,7 @@ class SKFunction(SKFunctionBase):
|
|
|
125
131
|
context.variables.update(completion)
|
|
126
132
|
else:
|
|
127
133
|
prompt = await function_config.prompt_template.render_async(context)
|
|
128
|
-
completion = await client.
|
|
129
|
-
prompt, request_settings
|
|
130
|
-
)
|
|
134
|
+
completion = await client.complete_async(prompt, request_settings)
|
|
131
135
|
context.variables.update(completion)
|
|
132
136
|
except Exception as e:
|
|
133
137
|
# TODO: "critical exceptions"
|
|
@@ -194,9 +198,9 @@ class SKFunction(SKFunctionBase):
|
|
|
194
198
|
self._is_semantic = is_semantic
|
|
195
199
|
self._log = log if log is not None else NullLogger()
|
|
196
200
|
self._skill_collection = None
|
|
197
|
-
self.
|
|
201
|
+
self._ai_service = None
|
|
198
202
|
self._ai_request_settings = CompleteRequestSettings()
|
|
199
|
-
self.
|
|
203
|
+
self._chat_service = None
|
|
200
204
|
self._chat_request_settings = ChatRequestSettings()
|
|
201
205
|
|
|
202
206
|
def set_default_skill_collection(
|
|
@@ -205,22 +209,22 @@ class SKFunction(SKFunctionBase):
|
|
|
205
209
|
self._skill_collection = skills
|
|
206
210
|
return self
|
|
207
211
|
|
|
208
|
-
def
|
|
209
|
-
self,
|
|
212
|
+
def set_ai_service(
|
|
213
|
+
self, ai_service: Callable[[], TextCompletionClientBase]
|
|
210
214
|
) -> "SKFunction":
|
|
211
|
-
if
|
|
212
|
-
raise ValueError("AI LLM
|
|
215
|
+
if ai_service is None:
|
|
216
|
+
raise ValueError("AI LLM service factory cannot be `None`")
|
|
213
217
|
self._verify_is_semantic()
|
|
214
|
-
self.
|
|
218
|
+
self._ai_service = ai_service()
|
|
215
219
|
return self
|
|
216
220
|
|
|
217
|
-
def
|
|
218
|
-
self,
|
|
221
|
+
def set_chat_service(
|
|
222
|
+
self, chat_service: Callable[[], ChatCompletionClientBase]
|
|
219
223
|
) -> "SKFunction":
|
|
220
|
-
if
|
|
221
|
-
raise ValueError("Chat LLM
|
|
224
|
+
if chat_service is None:
|
|
225
|
+
raise ValueError("Chat LLM service factory cannot be `None`")
|
|
222
226
|
self._verify_is_semantic()
|
|
223
|
-
self.
|
|
227
|
+
self._chat_service = chat_service()
|
|
224
228
|
return self
|
|
225
229
|
|
|
226
230
|
def set_ai_configuration(self, settings: CompleteRequestSettings) -> "SKFunction":
|
|
@@ -279,7 +283,6 @@ class SKFunction(SKFunctionBase):
|
|
|
279
283
|
skill_collection=self._skill_collection,
|
|
280
284
|
memory=memory if memory is not None else NullMemory.instance,
|
|
281
285
|
logger=log if log is not None else self._log,
|
|
282
|
-
# TODO: ctoken?
|
|
283
286
|
)
|
|
284
287
|
else:
|
|
285
288
|
# If context is passed, we need to merge the variables
|
|
@@ -326,7 +329,6 @@ class SKFunction(SKFunctionBase):
|
|
|
326
329
|
skill_collection=self._skill_collection,
|
|
327
330
|
memory=memory if memory is not None else NullMemory.instance,
|
|
328
331
|
logger=log if log is not None else self._log,
|
|
329
|
-
# TODO: ctoken?
|
|
330
332
|
)
|
|
331
333
|
else:
|
|
332
334
|
# If context is passed, we need to merge the variables
|
|
@@ -355,20 +357,20 @@ class SKFunction(SKFunctionBase):
|
|
|
355
357
|
self._ensure_context_has_skills(context)
|
|
356
358
|
|
|
357
359
|
if settings is None:
|
|
358
|
-
if self.
|
|
360
|
+
if self._ai_service is not None:
|
|
359
361
|
settings = self._ai_request_settings
|
|
360
|
-
elif self.
|
|
362
|
+
elif self._chat_service is not None:
|
|
361
363
|
settings = self._chat_request_settings
|
|
362
364
|
else:
|
|
363
365
|
raise KernelException(
|
|
364
366
|
KernelException.ErrorCodes.UnknownError,
|
|
365
|
-
"Semantic functions must have either an AI
|
|
367
|
+
"Semantic functions must have either an AI service or Chat service",
|
|
366
368
|
)
|
|
367
369
|
|
|
368
|
-
|
|
369
|
-
self.
|
|
370
|
+
service = (
|
|
371
|
+
self._ai_service if self._ai_service is not None else self._chat_service
|
|
370
372
|
)
|
|
371
|
-
new_context = await self._function(
|
|
373
|
+
new_context = await self._function(service, settings, context)
|
|
372
374
|
context.variables.merge_or_overwrite(new_context.variables)
|
|
373
375
|
return context
|
|
374
376
|
|
|
@@ -4,8 +4,12 @@ from abc import ABC, abstractmethod
|
|
|
4
4
|
from logging import Logger
|
|
5
5
|
from typing import TYPE_CHECKING, Callable, Optional
|
|
6
6
|
|
|
7
|
-
from semantic_kernel.ai.complete_request_settings import
|
|
8
|
-
|
|
7
|
+
from semantic_kernel.connectors.ai.complete_request_settings import (
|
|
8
|
+
CompleteRequestSettings,
|
|
9
|
+
)
|
|
10
|
+
from semantic_kernel.connectors.ai.text_completion_client_base import (
|
|
11
|
+
TextCompletionClientBase,
|
|
12
|
+
)
|
|
9
13
|
from semantic_kernel.memory.semantic_text_memory_base import SemanticTextMemoryBase
|
|
10
14
|
from semantic_kernel.orchestration.context_variables import ContextVariables
|
|
11
15
|
from semantic_kernel.orchestration.sk_context import SKContext
|
|
@@ -80,7 +84,7 @@ class SKFunctionBase(ABC):
|
|
|
80
84
|
@property
|
|
81
85
|
@abstractmethod
|
|
82
86
|
def request_settings(self) -> CompleteRequestSettings:
|
|
83
|
-
"""AI
|
|
87
|
+
"""AI service settings"""
|
|
84
88
|
pass
|
|
85
89
|
|
|
86
90
|
@abstractmethod
|
|
@@ -103,7 +107,6 @@ class SKFunctionBase(ABC):
|
|
|
103
107
|
memory: Optional[SemanticTextMemoryBase] = None,
|
|
104
108
|
settings: Optional[CompleteRequestSettings] = None,
|
|
105
109
|
log: Optional[Logger] = None,
|
|
106
|
-
# TODO: ctoken
|
|
107
110
|
) -> SKContext:
|
|
108
111
|
"""
|
|
109
112
|
Invokes the function with an explicit string input
|
|
@@ -129,7 +132,6 @@ class SKFunctionBase(ABC):
|
|
|
129
132
|
memory: Optional[SemanticTextMemoryBase] = None,
|
|
130
133
|
settings: Optional[CompleteRequestSettings] = None,
|
|
131
134
|
log: Optional[Logger] = None,
|
|
132
|
-
# TODO: ctoken
|
|
133
135
|
) -> SKContext:
|
|
134
136
|
"""
|
|
135
137
|
Invokes the function with an explicit string input
|
|
@@ -165,16 +167,16 @@ class SKFunctionBase(ABC):
|
|
|
165
167
|
pass
|
|
166
168
|
|
|
167
169
|
@abstractmethod
|
|
168
|
-
def
|
|
169
|
-
self,
|
|
170
|
+
def set_ai_service(
|
|
171
|
+
self, service_factory: Callable[[], TextCompletionClientBase]
|
|
170
172
|
) -> "SKFunctionBase":
|
|
171
173
|
"""
|
|
172
|
-
Sets the AI
|
|
174
|
+
Sets the AI service used by the semantic function, passing in a factory
|
|
173
175
|
method. The factory allows us to lazily instantiate the client and to
|
|
174
176
|
properly handle its disposal
|
|
175
177
|
|
|
176
178
|
Arguments:
|
|
177
|
-
|
|
179
|
+
service_factory -- AI service factory
|
|
178
180
|
|
|
179
181
|
Returns:
|
|
180
182
|
SKFunctionBase -- The function instance
|
|
@@ -33,7 +33,7 @@ class PromptTemplateConfig:
|
|
|
33
33
|
completion: "PromptTemplateConfig.CompletionConfig" = field(
|
|
34
34
|
default_factory=CompletionConfig
|
|
35
35
|
)
|
|
36
|
-
|
|
36
|
+
default_services: List[str] = field(default_factory=list)
|
|
37
37
|
input: "PromptTemplateConfig.InputConfig" = field(default_factory=InputConfig)
|
|
38
38
|
|
|
39
39
|
@staticmethod
|
|
@@ -52,7 +52,7 @@ class PromptTemplateConfig:
|
|
|
52
52
|
config.completion.frequency_penalty = completion_dict.get("frequency_penalty")
|
|
53
53
|
config.completion.max_tokens = completion_dict.get("max_tokens")
|
|
54
54
|
config.completion.stop_sequences = completion_dict.get("stop_sequences", [])
|
|
55
|
-
config.
|
|
55
|
+
config.default_services = data.get("default_services", [])
|
|
56
56
|
|
|
57
57
|
# Some skills may not have input parameters defined
|
|
58
58
|
config.input = PromptTemplateConfig.InputConfig()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
from semantic_kernel.text.function_extension import aggregate_chunked_results_async
|
|
4
|
+
from semantic_kernel.text.text_chunker import (
|
|
5
|
+
split_markdown_lines,
|
|
6
|
+
split_markdown_paragraph,
|
|
7
|
+
split_plaintext_lines,
|
|
8
|
+
split_plaintext_paragraph,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"split_plaintext_lines",
|
|
13
|
+
"split_markdown_paragraph",
|
|
14
|
+
"split_plaintext_paragraph",
|
|
15
|
+
"split_markdown_lines",
|
|
16
|
+
"aggregate_chunked_results_async",
|
|
17
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
from semantic_kernel.orchestration.sk_context import SKContext
|
|
6
|
+
from semantic_kernel.orchestration.sk_function import SKFunction
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def aggregate_chunked_results_async(
|
|
10
|
+
func: SKFunction, chunked_results: List[str], context: SKContext
|
|
11
|
+
) -> SKContext:
|
|
12
|
+
"""
|
|
13
|
+
Aggregate the results from the chunked results.
|
|
14
|
+
"""
|
|
15
|
+
results = []
|
|
16
|
+
for chunk in chunked_results:
|
|
17
|
+
context.variables.update(chunk)
|
|
18
|
+
context = await func.invoke_async(context=context)
|
|
19
|
+
|
|
20
|
+
results.append(str(context.variables))
|
|
21
|
+
|
|
22
|
+
context.variables.update("\n".join(results))
|
|
23
|
+
return context
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
"""
|
|
3
|
+
Split text in chunks, attempting to leave meaning intact.
|
|
4
|
+
For plain text, split looking at new lines first, then periods, and so on.
|
|
5
|
+
For markdown, split looking at punctuation first, and so on.
|
|
6
|
+
"""
|
|
7
|
+
import os
|
|
8
|
+
from typing import List
|
|
9
|
+
|
|
10
|
+
NEWLINE = os.linesep
|
|
11
|
+
|
|
12
|
+
TEXT_SPLIT_OPTIONS = [
|
|
13
|
+
["\n", "\r"],
|
|
14
|
+
["."],
|
|
15
|
+
["?", "!"],
|
|
16
|
+
[";"],
|
|
17
|
+
[":"],
|
|
18
|
+
[","],
|
|
19
|
+
[")", "]", "}"],
|
|
20
|
+
[" "],
|
|
21
|
+
["-"],
|
|
22
|
+
None,
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
MD_SPLIT_OPTIONS = [
|
|
26
|
+
["."],
|
|
27
|
+
["?", "!"],
|
|
28
|
+
[";"],
|
|
29
|
+
[":"],
|
|
30
|
+
[","],
|
|
31
|
+
[")", "]", "}"],
|
|
32
|
+
[" "],
|
|
33
|
+
["-"],
|
|
34
|
+
["\n", "\r"],
|
|
35
|
+
None,
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def split_plaintext_lines(text: str, max_token_per_line: int) -> List[str]:
|
|
40
|
+
"""
|
|
41
|
+
Split plain text into lines.
|
|
42
|
+
it will split on new lines first, and then on punctuation.
|
|
43
|
+
"""
|
|
44
|
+
return _split_text_lines(text, max_token_per_line, True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def split_markdown_lines(text: str, max_token_per_line: int) -> List[str]:
|
|
48
|
+
"""
|
|
49
|
+
Split markdown into lines.
|
|
50
|
+
It will split on punctuation first, and then on space and new lines.
|
|
51
|
+
"""
|
|
52
|
+
return _split_markdown_lines(text, max_token_per_line, True)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def split_plaintext_paragraph(text: List[str], max_tokens: int) -> List[str]:
|
|
56
|
+
"""
|
|
57
|
+
Split plain text into paragraphs.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
split_lines = []
|
|
61
|
+
for line in text:
|
|
62
|
+
split_lines.extend(_split_text_lines(line, max_tokens, True))
|
|
63
|
+
|
|
64
|
+
return _split_text_paragraph(split_lines, max_tokens)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def split_markdown_paragraph(text: List[str], max_tokens: int) -> List[str]:
|
|
68
|
+
"""
|
|
69
|
+
Split markdown into paragraphs.
|
|
70
|
+
"""
|
|
71
|
+
split_lines = []
|
|
72
|
+
for line in text:
|
|
73
|
+
split_lines.extend(_split_markdown_lines(line, max_tokens, False))
|
|
74
|
+
|
|
75
|
+
return _split_text_paragraph(split_lines, max_tokens)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _split_text_paragraph(text: List[str], max_tokens: int) -> List[str]:
|
|
79
|
+
"""
|
|
80
|
+
Split text into paragraphs.
|
|
81
|
+
"""
|
|
82
|
+
if not text:
|
|
83
|
+
return []
|
|
84
|
+
|
|
85
|
+
paragraphs = []
|
|
86
|
+
current_paragraph = []
|
|
87
|
+
|
|
88
|
+
for line in text:
|
|
89
|
+
num_tokens_line = _token_count(line)
|
|
90
|
+
num_tokens_paragraph = _token_count("".join(current_paragraph))
|
|
91
|
+
|
|
92
|
+
if (
|
|
93
|
+
num_tokens_paragraph + num_tokens_line + 1 >= max_tokens
|
|
94
|
+
and len(current_paragraph) > 0
|
|
95
|
+
):
|
|
96
|
+
paragraphs.append("".join(current_paragraph).strip())
|
|
97
|
+
current_paragraph = []
|
|
98
|
+
|
|
99
|
+
current_paragraph.append(f"{line}{NEWLINE}")
|
|
100
|
+
|
|
101
|
+
if len(current_paragraph) > 0:
|
|
102
|
+
paragraphs.append("".join(current_paragraph).strip())
|
|
103
|
+
current_paragraph = []
|
|
104
|
+
|
|
105
|
+
# Distribute text more evenly in the last paragraphs
|
|
106
|
+
# when the last paragraph is too short.
|
|
107
|
+
|
|
108
|
+
if len(paragraphs) > 1:
|
|
109
|
+
last_para = paragraphs[-1]
|
|
110
|
+
sec_last_para = paragraphs[-2]
|
|
111
|
+
|
|
112
|
+
if _token_count(last_para) < max_tokens / 4:
|
|
113
|
+
last_para_tokens = last_para.split(" ")
|
|
114
|
+
sec_last_para_tokens = sec_last_para.split(" ")
|
|
115
|
+
last_para_token_count = len(last_para_tokens)
|
|
116
|
+
sec_last_para_token_count = len(sec_last_para_tokens)
|
|
117
|
+
|
|
118
|
+
if last_para_token_count + sec_last_para_token_count <= max_tokens:
|
|
119
|
+
sec_last_para = " ".join(sec_last_para_tokens) + NEWLINE
|
|
120
|
+
last_para = " ".join(last_para_tokens)
|
|
121
|
+
new_sec_last_para = sec_last_para + last_para
|
|
122
|
+
paragraphs[-2] = new_sec_last_para.strip()
|
|
123
|
+
paragraphs.pop()
|
|
124
|
+
|
|
125
|
+
return paragraphs
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _split_markdown_lines(text: str, max_token_per_line: int, trim: bool) -> List[str]:
|
|
129
|
+
"""
|
|
130
|
+
Split markdown into lines.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
lines = _split_str_lines(text, max_token_per_line, MD_SPLIT_OPTIONS, trim)
|
|
134
|
+
return lines
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _split_text_lines(text: str, max_token_per_line: int, trim: bool) -> List[str]:
|
|
138
|
+
"""
|
|
139
|
+
Split text into lines.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
lines = _split_str_lines(text, max_token_per_line, TEXT_SPLIT_OPTIONS, trim)
|
|
143
|
+
|
|
144
|
+
return lines
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _split_str_lines(
|
|
148
|
+
text: str, max_tokens: int, separators: List[List[str]], trim: bool
|
|
149
|
+
) -> List[str]:
|
|
150
|
+
if not text:
|
|
151
|
+
return []
|
|
152
|
+
|
|
153
|
+
text = text.replace("\r\n", "\n")
|
|
154
|
+
lines = []
|
|
155
|
+
was_split = False
|
|
156
|
+
for split_option in separators:
|
|
157
|
+
if not lines:
|
|
158
|
+
lines, was_split = _split_str(text, max_tokens, split_option, trim)
|
|
159
|
+
else:
|
|
160
|
+
lines, was_split = _split_list(lines, max_tokens, split_option, trim)
|
|
161
|
+
if not was_split:
|
|
162
|
+
break
|
|
163
|
+
|
|
164
|
+
return lines
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _split_str(
|
|
168
|
+
text: str, max_tokens: int, separators: List[str], trim: bool
|
|
169
|
+
) -> List[str]:
|
|
170
|
+
"""
|
|
171
|
+
Split text into lines.
|
|
172
|
+
"""
|
|
173
|
+
if not text:
|
|
174
|
+
return []
|
|
175
|
+
|
|
176
|
+
input_was_split = False
|
|
177
|
+
text = text.strip() if trim else text
|
|
178
|
+
|
|
179
|
+
text_as_is = [text]
|
|
180
|
+
|
|
181
|
+
if _token_count(text) <= max_tokens:
|
|
182
|
+
return text_as_is, input_was_split
|
|
183
|
+
|
|
184
|
+
input_was_split = True
|
|
185
|
+
|
|
186
|
+
half = int(len(text) / 2)
|
|
187
|
+
|
|
188
|
+
cutpoint = -1
|
|
189
|
+
|
|
190
|
+
if not separators:
|
|
191
|
+
cutpoint = half
|
|
192
|
+
|
|
193
|
+
elif set(separators) & set(text) and len(text) > 2:
|
|
194
|
+
for index, text_char in enumerate(text):
|
|
195
|
+
if text_char not in separators:
|
|
196
|
+
continue
|
|
197
|
+
|
|
198
|
+
if abs(half - index) < abs(half - cutpoint):
|
|
199
|
+
cutpoint = index + 1
|
|
200
|
+
|
|
201
|
+
else:
|
|
202
|
+
return text_as_is, input_was_split
|
|
203
|
+
|
|
204
|
+
if 0 < cutpoint < len(text):
|
|
205
|
+
lines = []
|
|
206
|
+
first_split, has_split1 = _split_str(
|
|
207
|
+
text[:cutpoint], max_tokens, separators, trim
|
|
208
|
+
)
|
|
209
|
+
second_split, has_split2 = _split_str(
|
|
210
|
+
text[cutpoint:], max_tokens, separators, trim
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
lines.extend(first_split)
|
|
214
|
+
lines.extend(second_split)
|
|
215
|
+
|
|
216
|
+
input_was_split = has_split1 or has_split2
|
|
217
|
+
else:
|
|
218
|
+
return text_as_is, input_was_split
|
|
219
|
+
|
|
220
|
+
return lines, input_was_split
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _split_list(
|
|
224
|
+
text: List[str], max_tokens: int, separators: List[str], trim: bool
|
|
225
|
+
) -> List[str]:
|
|
226
|
+
"""
|
|
227
|
+
Split list of sring into lines.
|
|
228
|
+
"""
|
|
229
|
+
if not text:
|
|
230
|
+
return []
|
|
231
|
+
|
|
232
|
+
lines = []
|
|
233
|
+
input_was_split = False
|
|
234
|
+
for line in text:
|
|
235
|
+
split_str, was_split = _split_str(line, max_tokens, separators, trim)
|
|
236
|
+
lines.extend(split_str)
|
|
237
|
+
input_was_split = input_was_split or was_split
|
|
238
|
+
|
|
239
|
+
return lines, input_was_split
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def _token_count(text: str) -> int:
|
|
243
|
+
"""
|
|
244
|
+
Count the number of tokens in a string.
|
|
245
|
+
|
|
246
|
+
TODO: chunking methods should be configurable to allow for different
|
|
247
|
+
tokenization strategies depending on the model to be called.
|
|
248
|
+
For now, we use an extremely rough estimate.
|
|
249
|
+
"""
|
|
250
|
+
return int(len(text) / 4)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: semantic-kernel
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5.dev0
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Microsoft
|
|
6
6
|
Author-email: SK-Support@microsoft.com
|
|
@@ -13,6 +13,9 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
13
13
|
Requires-Dist: aiofiles (>=23.1.0,<24.0.0)
|
|
14
14
|
Requires-Dist: numpy (>=1.24.2,<2.0.0)
|
|
15
15
|
Requires-Dist: openai (>=0.27.0,<0.28.0)
|
|
16
|
+
Requires-Dist: sentence-transformers (>=2.2.2,<3.0.0)
|
|
17
|
+
Requires-Dist: torch (>=2.0.0,<3.0.0)
|
|
18
|
+
Requires-Dist: transformers (>=4.28.1,<5.0.0)
|
|
16
19
|
Description-Content-Type: text/markdown
|
|
17
20
|
|
|
18
21
|
# Get Started with Semantic Kernel ⚡
|
|
@@ -22,7 +25,7 @@ Install the latest package:
|
|
|
22
25
|
python -m pip install --upgrade semantic-kernel
|
|
23
26
|
|
|
24
27
|
|
|
25
|
-
# AI
|
|
28
|
+
# AI Services
|
|
26
29
|
|
|
27
30
|
## OpenAI / Azure OpenAI API keys
|
|
28
31
|
|
|
@@ -44,17 +47,17 @@ AZURE_OPENAI_API_KEY=""
|
|
|
44
47
|
|
|
45
48
|
```python
|
|
46
49
|
import semantic_kernel as sk
|
|
47
|
-
from semantic_kernel.ai.open_ai import OpenAITextCompletion, AzureTextCompletion
|
|
50
|
+
from semantic_kernel.connectors.ai.open_ai import OpenAITextCompletion, AzureTextCompletion
|
|
48
51
|
|
|
49
52
|
kernel = sk.Kernel()
|
|
50
53
|
|
|
51
|
-
# Prepare OpenAI
|
|
54
|
+
# Prepare OpenAI service using credentials stored in the `.env` file
|
|
52
55
|
api_key, org_id = sk.openai_settings_from_dot_env()
|
|
53
|
-
kernel.config.
|
|
56
|
+
kernel.config.add_text_service("dv", OpenAITextCompletion("text-davinci-003", api_key, org_id))
|
|
54
57
|
|
|
55
58
|
# Alternative using Azure:
|
|
56
59
|
# deployment, api_key, endpoint = sk.azure_openai_settings_from_dot_env()
|
|
57
|
-
# kernel.config.
|
|
60
|
+
# kernel.config.add_text_service("dv", AzureTextCompletion(deployment, endpoint, api_key))
|
|
58
61
|
|
|
59
62
|
# Wrap your prompt in a function
|
|
60
63
|
prompt = kernel.create_semantic_function("""
|
|
@@ -1,57 +1,56 @@
|
|
|
1
1
|
semantic_kernel/__init__.py,sha256=Adohtrqn3wRrsYGz3peEca8ZuR6jeWPFtpC-zLfLkbI,1302
|
|
2
|
-
semantic_kernel/ai/ai_exception.py,sha256=L_Cc_YTIbveXSOXQ8BbSjnjgLCxBz9297akNfX6EsGo,1647
|
|
3
|
-
semantic_kernel/ai/chat_completion_client_base.py,sha256=
|
|
4
|
-
semantic_kernel/ai/chat_request_settings.py,sha256=EusH7xhpVXxO7lcIcG7_ErfcyYdm5-eu1fSiEIurt6s,1129
|
|
5
|
-
semantic_kernel/ai/complete_request_settings.py,sha256=s6BYw-jES7JEyXvuh6pz2jrOOPlx_xC4j7CJY0ptlp4,1332
|
|
6
|
-
semantic_kernel/ai/embeddings/embedding_generator_base.py,sha256=TjWr4gf-SUBLBVCgF3ekFEs8dPHLAKzUWZ5WVTucdfk,282
|
|
7
|
-
semantic_kernel/ai/
|
|
8
|
-
semantic_kernel/ai/
|
|
9
|
-
semantic_kernel/ai/
|
|
10
|
-
semantic_kernel/ai/open_ai/
|
|
11
|
-
semantic_kernel/ai/open_ai/services/
|
|
12
|
-
semantic_kernel/ai/open_ai/services/
|
|
13
|
-
semantic_kernel/ai/open_ai/services/
|
|
14
|
-
semantic_kernel/ai/open_ai/services/
|
|
15
|
-
semantic_kernel/ai/
|
|
2
|
+
semantic_kernel/connectors/ai/ai_exception.py,sha256=L_Cc_YTIbveXSOXQ8BbSjnjgLCxBz9297akNfX6EsGo,1647
|
|
3
|
+
semantic_kernel/connectors/ai/chat_completion_client_base.py,sha256=FUSw5GFUPTLIcea1MGz2rEve7o6qO1n3J22xWEshOL0,506
|
|
4
|
+
semantic_kernel/connectors/ai/chat_request_settings.py,sha256=EusH7xhpVXxO7lcIcG7_ErfcyYdm5-eu1fSiEIurt6s,1129
|
|
5
|
+
semantic_kernel/connectors/ai/complete_request_settings.py,sha256=s6BYw-jES7JEyXvuh6pz2jrOOPlx_xC4j7CJY0ptlp4,1332
|
|
6
|
+
semantic_kernel/connectors/ai/embeddings/embedding_generator_base.py,sha256=TjWr4gf-SUBLBVCgF3ekFEs8dPHLAKzUWZ5WVTucdfk,282
|
|
7
|
+
semantic_kernel/connectors/ai/hugging_face/__init__.py,sha256=-QjM630BtqkYKXYnuuCj0rHAtvi2y1PxfShIwpEfbIk,352
|
|
8
|
+
semantic_kernel/connectors/ai/hugging_face/services/hf_text_completion.py,sha256=rOBfXi2qU6ntdJg0Wp6y1-unaPR0-Xv9B3_7lvYMvg4,3463
|
|
9
|
+
semantic_kernel/connectors/ai/hugging_face/services/hf_text_embedding.py,sha256=EHzm9BgWFEVDww0Xd1YesYpWwdflEMdHLnHv4WnV7S4,2093
|
|
10
|
+
semantic_kernel/connectors/ai/open_ai/__init__.py,sha256=R2DKk3sI0QoVHReuJbuAKbeBBAcLeTcyD_ZNrYT5irk,892
|
|
11
|
+
semantic_kernel/connectors/ai/open_ai/services/azure_chat_completion.py,sha256=LNT9Fz2qJNbKuJY_gm_nW31kxG62QfQNawr21UtUsoc,2782
|
|
12
|
+
semantic_kernel/connectors/ai/open_ai/services/azure_text_completion.py,sha256=uYv4e9APYRDVmYgR470Uh9VbwGXcEqkJMY7DS8CKuRI,2774
|
|
13
|
+
semantic_kernel/connectors/ai/open_ai/services/azure_text_embedding.py,sha256=I8ePGCK4BnnglS86VepZ0Jf24n-FgK7hB_TACTn4Xnw,2769
|
|
14
|
+
semantic_kernel/connectors/ai/open_ai/services/open_ai_chat_completion.py,sha256=-NfP5PPg5pb7cofxiBDm5S9AGycpxpI67w8me3fErUk,5227
|
|
15
|
+
semantic_kernel/connectors/ai/open_ai/services/open_ai_text_completion.py,sha256=IYrt-XTTaMtb32p7iaP6ItCeOdLrQsPiMGSOdAy-SIo,4471
|
|
16
|
+
semantic_kernel/connectors/ai/open_ai/services/open_ai_text_embedding.py,sha256=AVGeSTLr5UC_eqnSFRByB1LIbDxvJDxMFxsELzr08j8,2449
|
|
17
|
+
semantic_kernel/connectors/ai/text_completion_client_base.py,sha256=PxLOwDatOlddLObfF33OaCUq2qQCfab8llLc_a0cVV8,497
|
|
16
18
|
semantic_kernel/core_skills/__init__.py,sha256=CyLz2bgmsaKu3FSTzU7KmoAZPlWl4YQpIQ7inVmSZJs,457
|
|
17
19
|
semantic_kernel/core_skills/file_io_skill.py,sha256=b9m7Ll3A7exhb49eCOYQBO1H8AEJbwCIdnGdDXuj2Ts,2072
|
|
18
20
|
semantic_kernel/core_skills/http_skill.py,sha256=ferr2_4x5mMfUj-FHjLRCdtHLOlMBsTx4H03g4o1V4I,3754
|
|
19
21
|
semantic_kernel/core_skills/text_memory_skill.py,sha256=LSv6G2rE-Zhhym_ry9oyUQJxeiYAI3okBU_kEpz4VoM,4641
|
|
20
22
|
semantic_kernel/core_skills/text_skill.py,sha256=GdB8tAs8lFYBSGXNX9R6ppGzLt1-tlR2oz5-ecrXiH8,2403
|
|
21
|
-
semantic_kernel/core_skills/time_skill.py,sha256=
|
|
22
|
-
semantic_kernel/kernel.py,sha256=
|
|
23
|
+
semantic_kernel/core_skills/time_skill.py,sha256=fu7vrXL4yFPdYNCZGu7Jp-d51EU1GsBOFkGCZGuz2Yo,5849
|
|
24
|
+
semantic_kernel/kernel.py,sha256=P3CJ3qTSUW-Dq7wX9hwRRiu-j-zQEozC5hlMmMVPghM,12503
|
|
23
25
|
semantic_kernel/kernel_base.py,sha256=0MZCdswabNiRuo60RUrxakoRmW65-5qK5ZVmn7PhwQY,2240
|
|
24
|
-
semantic_kernel/kernel_config.py,sha256=
|
|
25
|
-
semantic_kernel/kernel_exception.py,sha256=
|
|
26
|
+
semantic_kernel/kernel_config.py,sha256=mGqNucb5nON4-qg54mRihs4eIr4X3vuV6S1SPP-TEpA,9401
|
|
27
|
+
semantic_kernel/kernel_exception.py,sha256=HpUGXGHndLzV1d1QxED3UEQQAHuc46r6XyBNDjT92es,1626
|
|
26
28
|
semantic_kernel/kernel_extensions/__init__.py,sha256=84fkiRzxl3He5DrBuj5zGbHOqPGfa-pTbcYCneZdi7k,710
|
|
27
29
|
semantic_kernel/kernel_extensions/extends_kernel.py,sha256=lStaPx4YT1f61-y9-fYw4-z18DTrsOW9WlhsM2JDAKY,210
|
|
28
|
-
semantic_kernel/kernel_extensions/import_skills.py,sha256=
|
|
30
|
+
semantic_kernel/kernel_extensions/import_skills.py,sha256=l-97gUpNgILOhfyUAF09xyp-Tebi0bTqSH9krGS11So,3822
|
|
29
31
|
semantic_kernel/kernel_extensions/inline_definition.py,sha256=caPbJ99BdZdYa6GsegLQ4SurP0hDY9nK1lLUF887Quw,2323
|
|
30
|
-
semantic_kernel/kernel_extensions/memory_configuration.py,sha256=
|
|
32
|
+
semantic_kernel/kernel_extensions/memory_configuration.py,sha256=URcNYZiCiEp28T4XvePmmEgpxdzNGueGz4sUpBKbyu8,1481
|
|
31
33
|
semantic_kernel/memory/__init__.py,sha256=S67WhFdqzVoXcIHWDZ1_zKtEn50_iBqpX6W2Y1LCB34,160
|
|
32
|
-
semantic_kernel/memory/memory_query_result.py,sha256=
|
|
33
|
-
semantic_kernel/memory/memory_record.py,sha256=
|
|
34
|
-
semantic_kernel/memory/memory_store_base.py,sha256=
|
|
34
|
+
semantic_kernel/memory/memory_query_result.py,sha256=2gJxIhGPFrxd_nDncYGqBB1n7FlQuHAGf8l9o-jHyGg,2345
|
|
35
|
+
semantic_kernel/memory/memory_record.py,sha256=yb4DE9SNGrhbMJsZd1tMifvZp5uQeOcHz50Onf9hW0w,3089
|
|
36
|
+
semantic_kernel/memory/memory_store_base.py,sha256=ZW7xs_lPH3yDgQv4p77pOu1DLowJ_UU0GPCxyMP0Hpo,2012
|
|
35
37
|
semantic_kernel/memory/null_memory.py,sha256=Ucoj269Qexr8jHHZmLzgfwAW1yIqne65Tm8e6TTpJek,1137
|
|
36
|
-
semantic_kernel/memory/semantic_text_memory.py,sha256=
|
|
37
|
-
semantic_kernel/memory/semantic_text_memory_base.py,sha256
|
|
38
|
-
semantic_kernel/memory/
|
|
39
|
-
semantic_kernel/memory/storage/data_store_base.py,sha256=E9-Dv-YztU_H1fqa4ExPx1c2LllXcKAP-qMD3GVTP-w,953
|
|
40
|
-
semantic_kernel/memory/storage/volatile_data_store.py,sha256=NdmZ7hUpR1-3tN7TQ5AYutZfWZ3Pl44X-D5b3rOJW5k,1989
|
|
41
|
-
semantic_kernel/memory/volatile_memory_store.py,sha256=kxN4YAR32WT2h0o1qSiqCYze0zKwqQ1vfv8xDsYBo3U,4050
|
|
38
|
+
semantic_kernel/memory/semantic_text_memory.py,sha256=gYrlq1-bOn-qMtFxBS3FHaTMZuQjjGz8ASWLvr73YZw,6036
|
|
39
|
+
semantic_kernel/memory/semantic_text_memory_base.py,sha256=-IF6cmtrqM2aNQyjL6ikm1ZIGNULmvBAtehHDS6SHRI,1196
|
|
40
|
+
semantic_kernel/memory/volatile_memory_store.py,sha256=SxmvMt2snwDCKazsgozcCcrtxaQ4t2Ov6Kc5GNIBHmg,12032
|
|
42
41
|
semantic_kernel/orchestration/context_variables.py,sha256=sNGrZPxZQXE3pGVoahjYqb5BZ49WFvyBDpMwI-VWT0Q,2361
|
|
43
42
|
semantic_kernel/orchestration/delegate_handlers.py,sha256=uyZsiPr5v-UphQXwsH1ftqbJxPCigXoqMsrY2m9VVjQ,5079
|
|
44
43
|
semantic_kernel/orchestration/delegate_inference.py,sha256=c3ullA55Mf8kX6jcdiIuBv6eGsSSRsFphF_vHL-viA8,8966
|
|
45
44
|
semantic_kernel/orchestration/delegate_types.py,sha256=ZcnZCMtyrZMj7r8y6cPom3IuD0sHa4KQPucdZHpQsKE,638
|
|
46
45
|
semantic_kernel/orchestration/sk_context.py,sha256=DZl_ucEtGjKqbOZYWgSRn9-FMLzhDJbli5Cqv3PMlIg,7514
|
|
47
|
-
semantic_kernel/orchestration/sk_function.py,sha256=
|
|
48
|
-
semantic_kernel/orchestration/sk_function_base.py,sha256=
|
|
46
|
+
semantic_kernel/orchestration/sk_function.py,sha256=VOsEEQQQMJviofHc906P4dC1KYo48bS4K97Xx_t6UwU,15917
|
|
47
|
+
semantic_kernel/orchestration/sk_function_base.py,sha256=oSADu3xi7foDHGSbo156Lvm0iJnSAv0VTLNhYZkbuFA,6158
|
|
49
48
|
semantic_kernel/reliability/pass_through_without_retry.py,sha256=ULbry84vLGbh58naaBgwVCrPQr0Y_sxQFO9FRlpA5yg,919
|
|
50
49
|
semantic_kernel/reliability/retry_mechanism.py,sha256=kXQp4M1MKeGob84L4F02lVM1d0fDEwzS1kI1MI0ezHg,673
|
|
51
50
|
semantic_kernel/semantic_functions/chat_prompt_template.py,sha256=lZF02xYXuZNtRVAZ4h2DYN_le-kNow2RhXWQnLD1UU4,2101
|
|
52
51
|
semantic_kernel/semantic_functions/prompt_template.py,sha256=7qzsY_3Yyf3sqUM7XuMw35PlX-N7Feqqw24b5-3Ek0A,2332
|
|
53
52
|
semantic_kernel/semantic_functions/prompt_template_base.py,sha256=y_pG7LtwbSsdWTikxUQNApAscIJtB0S_E53-WMk-JVQ,506
|
|
54
|
-
semantic_kernel/semantic_functions/prompt_template_config.py,sha256=
|
|
53
|
+
semantic_kernel/semantic_functions/prompt_template_config.py,sha256=6Zq1bkIao_D8eE0dYagUEUKVRrX1SXnCh8PQV4KeniM,4269
|
|
55
54
|
semantic_kernel/semantic_functions/semantic_function_config.py,sha256=buON4ZVTHBQQSVOJ1AVEIZtONqgVJFH1tXeiVkFip1Q,671
|
|
56
55
|
semantic_kernel/skill_definition/__init__.py,sha256=rEhtQBLH1L-OMTailF4yORbOKzSUudA5F1fZSSjPYgw,322
|
|
57
56
|
semantic_kernel/skill_definition/function_view.py,sha256=YFj7mhTI2OMv2QcxMEABMW7C6RrgKv-iadmZQLkZQqo,2053
|
|
@@ -78,10 +77,13 @@ semantic_kernel/template_engine/protocols/code_renderer.py,sha256=edZ4gseJdB9xw6
|
|
|
78
77
|
semantic_kernel/template_engine/protocols/prompt_templating_engine.py,sha256=e7THxsNhLKZ5l55FOkGch_N2nTnXLU-iTX2gupamd5o,3043
|
|
79
78
|
semantic_kernel/template_engine/protocols/text_renderer.py,sha256=9tr0wF6TilL5ZmZzrlDIUBTVzNT_JHbjQxVgfjTAovM,596
|
|
80
79
|
semantic_kernel/template_engine/template_tokenizer.py,sha256=IfnnsN6u43ks0RuM6eyNmlzGPU8r9VsCWsmY0eTOva4,7637
|
|
80
|
+
semantic_kernel/text/__init__.py,sha256=lOLUtteokw8bUV4ZckhI3VHa4Z0YxDa4baPzAb4ZpFk,473
|
|
81
|
+
semantic_kernel/text/function_extension.py,sha256=Qv9fHLSjOswJY1bve52hJ42G-ZfsmZiZ6Yyz1fcMUI4,667
|
|
82
|
+
semantic_kernel/text/text_chunker.py,sha256=uSGYBkJ3F6a5mrawWtbrs3m__bDQCXHqYUIyCgKsJj8,6466
|
|
81
83
|
semantic_kernel/utils/null_logger.py,sha256=DSEc9sUhmhPq2PHw8ClA8p_cyETMVmghhaKbzMcRe1w,403
|
|
82
84
|
semantic_kernel/utils/settings.py,sha256=nH4uQvS4v22w2CiImJxSDa-yQ9hQW9uttlCN4krgotM,2436
|
|
83
85
|
semantic_kernel/utils/static_property.py,sha256=Yx0skR7C6-7tPG47rB_T5dteYmKxGVLksKcGinwBRFI,221
|
|
84
86
|
semantic_kernel/utils/validation.py,sha256=vo3Xuvj0P9FlGZeQZYbcSwcQI19w7b8KyJ2QgWbAchY,2198
|
|
85
|
-
semantic_kernel-0.2.
|
|
86
|
-
semantic_kernel-0.2.
|
|
87
|
-
semantic_kernel-0.2.
|
|
87
|
+
semantic_kernel-0.2.5.dev0.dist-info/METADATA,sha256=WtOH8wy7lzp9U8a04qEb2WY2OHHp2VeAJkZiOxvFU6w,5285
|
|
88
|
+
semantic_kernel-0.2.5.dev0.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
|
|
89
|
+
semantic_kernel-0.2.5.dev0.dist-info/RECORD,,
|