maximem-synap-semantic-kernel 0.1.1__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.
- maximem_synap_semantic_kernel-0.1.1/PKG-INFO +12 -0
- maximem_synap_semantic_kernel-0.1.1/maximem_synap_semantic_kernel.egg-info/PKG-INFO +12 -0
- maximem_synap_semantic_kernel-0.1.1/maximem_synap_semantic_kernel.egg-info/SOURCES.txt +9 -0
- maximem_synap_semantic_kernel-0.1.1/maximem_synap_semantic_kernel.egg-info/dependency_links.txt +1 -0
- maximem_synap_semantic_kernel-0.1.1/maximem_synap_semantic_kernel.egg-info/requires.txt +7 -0
- maximem_synap_semantic_kernel-0.1.1/maximem_synap_semantic_kernel.egg-info/top_level.txt +1 -0
- maximem_synap_semantic_kernel-0.1.1/pyproject.toml +22 -0
- maximem_synap_semantic_kernel-0.1.1/setup.cfg +4 -0
- maximem_synap_semantic_kernel-0.1.1/synap_semantic_kernel/__init__.py +5 -0
- maximem_synap_semantic_kernel-0.1.1/synap_semantic_kernel/plugin.py +93 -0
- maximem_synap_semantic_kernel-0.1.1/tests/test_plugin.py +53 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: maximem-synap-semantic-kernel
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Synap memory integration for Microsoft Semantic Kernel
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: maximem-synap>=0.2.0
|
|
8
|
+
Requires-Dist: synap-integrations-common>=0.1.0
|
|
9
|
+
Requires-Dist: semantic-kernel>=1.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
12
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: maximem-synap-semantic-kernel
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Synap memory integration for Microsoft Semantic Kernel
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: maximem-synap>=0.2.0
|
|
8
|
+
Requires-Dist: synap-integrations-common>=0.1.0
|
|
9
|
+
Requires-Dist: semantic-kernel>=1.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
12
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
maximem_synap_semantic_kernel.egg-info/PKG-INFO
|
|
3
|
+
maximem_synap_semantic_kernel.egg-info/SOURCES.txt
|
|
4
|
+
maximem_synap_semantic_kernel.egg-info/dependency_links.txt
|
|
5
|
+
maximem_synap_semantic_kernel.egg-info/requires.txt
|
|
6
|
+
maximem_synap_semantic_kernel.egg-info/top_level.txt
|
|
7
|
+
synap_semantic_kernel/__init__.py
|
|
8
|
+
synap_semantic_kernel/plugin.py
|
|
9
|
+
tests/test_plugin.py
|
maximem_synap_semantic_kernel-0.1.1/maximem_synap_semantic_kernel.egg-info/dependency_links.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
synap_semantic_kernel
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "maximem-synap-semantic-kernel"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Synap memory integration for Microsoft Semantic Kernel"
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
license = "Apache-2.0"
|
|
11
|
+
dependencies = ["maximem-synap>=0.2.0", "synap-integrations-common>=0.1.0", "semantic-kernel>=1.0"]
|
|
12
|
+
|
|
13
|
+
[project.optional-dependencies]
|
|
14
|
+
dev = ["pytest>=7.0", "pytest-asyncio>=0.21"]
|
|
15
|
+
|
|
16
|
+
[tool.setuptools.packages.find]
|
|
17
|
+
where = ["."]
|
|
18
|
+
include = ["synap_semantic_kernel*"]
|
|
19
|
+
|
|
20
|
+
[tool.pytest.ini_options]
|
|
21
|
+
testpaths = ["tests"]
|
|
22
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Synap plugin for Microsoft Semantic Kernel.
|
|
2
|
+
|
|
3
|
+
Exposes Synap memory as kernel functions (search_memory, store_memory)
|
|
4
|
+
that can be registered with a Semantic Kernel instance.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Annotated, Optional
|
|
9
|
+
|
|
10
|
+
from semantic_kernel.functions import kernel_function
|
|
11
|
+
|
|
12
|
+
from maximem_synap import MaximemSynapSDK
|
|
13
|
+
from synap_integrations_common import wrap_sdk_errors_async
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SynapPlugin:
|
|
19
|
+
"""Semantic Kernel plugin for Synap memory operations.
|
|
20
|
+
|
|
21
|
+
Example::
|
|
22
|
+
|
|
23
|
+
from semantic_kernel import Kernel
|
|
24
|
+
from synap_semantic_kernel import SynapPlugin
|
|
25
|
+
|
|
26
|
+
kernel = Kernel()
|
|
27
|
+
kernel.add_plugin(
|
|
28
|
+
SynapPlugin(sdk=sdk, user_id="u1"),
|
|
29
|
+
plugin_name="synap",
|
|
30
|
+
)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
sdk: MaximemSynapSDK,
|
|
36
|
+
user_id: str,
|
|
37
|
+
customer_id: str = "",
|
|
38
|
+
conversation_id: Optional[str] = None,
|
|
39
|
+
):
|
|
40
|
+
if sdk is None:
|
|
41
|
+
raise ValueError("SynapPlugin requires a non-None sdk")
|
|
42
|
+
if not user_id:
|
|
43
|
+
raise ValueError("SynapPlugin requires a non-empty user_id")
|
|
44
|
+
|
|
45
|
+
self._sdk = sdk
|
|
46
|
+
self._user_id = user_id
|
|
47
|
+
self._customer_id = customer_id
|
|
48
|
+
self._conversation_id = conversation_id
|
|
49
|
+
|
|
50
|
+
@kernel_function(
|
|
51
|
+
name="search_memory",
|
|
52
|
+
description=(
|
|
53
|
+
"Search the user's memory for relevant context. Use when you need "
|
|
54
|
+
"to recall past conversations, preferences, or facts about the user."
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
async def search_memory(
|
|
58
|
+
self,
|
|
59
|
+
query: Annotated[str, "Natural language search query"],
|
|
60
|
+
) -> str:
|
|
61
|
+
async with wrap_sdk_errors_async(
|
|
62
|
+
"semantic_kernel.search_memory", logger, user_id=self._user_id,
|
|
63
|
+
):
|
|
64
|
+
response = await self._sdk.fetch(
|
|
65
|
+
conversation_id=self._conversation_id,
|
|
66
|
+
user_id=self._user_id,
|
|
67
|
+
customer_id=self._customer_id or None,
|
|
68
|
+
search_query=[query],
|
|
69
|
+
mode="accurate",
|
|
70
|
+
include_conversation_context=False,
|
|
71
|
+
)
|
|
72
|
+
return response.formatted_context or "No relevant memories found."
|
|
73
|
+
|
|
74
|
+
@kernel_function(
|
|
75
|
+
name="store_memory",
|
|
76
|
+
description=(
|
|
77
|
+
"Store an important fact, preference, or event about the user "
|
|
78
|
+
"for future reference."
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
async def store_memory(
|
|
82
|
+
self,
|
|
83
|
+
content: Annotated[str, "Information to remember about the user"],
|
|
84
|
+
) -> str:
|
|
85
|
+
async with wrap_sdk_errors_async(
|
|
86
|
+
"semantic_kernel.store_memory", logger, user_id=self._user_id,
|
|
87
|
+
):
|
|
88
|
+
result = await self._sdk.memories.create(
|
|
89
|
+
document=content,
|
|
90
|
+
user_id=self._user_id,
|
|
91
|
+
customer_id=self._customer_id,
|
|
92
|
+
)
|
|
93
|
+
return f"Memory stored (ingestion_id: {result.ingestion_id})"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Tests for SynapPlugin."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from unittest.mock import AsyncMock, MagicMock
|
|
5
|
+
|
|
6
|
+
from synap_semantic_kernel.plugin import SynapPlugin
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture
|
|
10
|
+
def mock_sdk():
|
|
11
|
+
sdk = MagicMock()
|
|
12
|
+
sdk.fetch = AsyncMock()
|
|
13
|
+
sdk.memories.create = AsyncMock()
|
|
14
|
+
return sdk
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
def plugin(mock_sdk):
|
|
19
|
+
return SynapPlugin(sdk=mock_sdk, user_id="u1")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_import():
|
|
23
|
+
from synap_semantic_kernel import SynapPlugin
|
|
24
|
+
assert SynapPlugin is not None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.asyncio
|
|
28
|
+
async def test_search_memory(plugin, mock_sdk):
|
|
29
|
+
mock_sdk.fetch.return_value = MagicMock(formatted_context="likes coffee")
|
|
30
|
+
|
|
31
|
+
result = await plugin.search_memory(query="coffee")
|
|
32
|
+
|
|
33
|
+
assert result == "likes coffee"
|
|
34
|
+
mock_sdk.fetch.assert_awaited_once()
|
|
35
|
+
assert mock_sdk.fetch.call_args.kwargs["search_query"] == ["coffee"]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.asyncio
|
|
39
|
+
async def test_search_memory_no_results(plugin, mock_sdk):
|
|
40
|
+
mock_sdk.fetch.return_value = MagicMock(formatted_context=None)
|
|
41
|
+
|
|
42
|
+
result = await plugin.search_memory(query="nothing")
|
|
43
|
+
assert result == "No relevant memories found."
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.asyncio
|
|
47
|
+
async def test_store_memory(plugin, mock_sdk):
|
|
48
|
+
mock_sdk.memories.create.return_value = MagicMock(ingestion_id="ing-1")
|
|
49
|
+
|
|
50
|
+
result = await plugin.store_memory(content="prefers dark mode")
|
|
51
|
+
|
|
52
|
+
assert "ing-1" in result
|
|
53
|
+
mock_sdk.memories.create.assert_awaited_once()
|