nylonme-integrations 0.1.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.
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: nylonme-integrations
3
+ Version: 0.1.0
4
+ Summary: LangChain and LlamaIndex adapters for the NylonME memory engine
5
+ Author: NylonME contributors
6
+ License: Apache-2.0
7
+ Keywords: memory,rag,langchain,llamaindex,nylonme
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: nylon-sdk>=0.2
16
+ Provides-Extra: langchain
17
+ Requires-Dist: langchain-core>=0.3; extra == "langchain"
18
+ Provides-Extra: llamaindex
19
+ Requires-Dist: llama-index-core>=0.11; extra == "llamaindex"
20
+ Provides-Extra: all
21
+ Requires-Dist: langchain-core>=0.3; extra == "all"
22
+ Requires-Dist: llama-index-core>=0.11; extra == "all"
23
+ Provides-Extra: test
24
+ Requires-Dist: pytest; extra == "test"
25
+
26
+ # NylonME Integrations
27
+
28
+ LangChain 和 LlamaIndex 的 NylonME 适配器。核心共振逻辑只依赖
29
+ `nylon-sdk`,框架类在真正使用时才导入,避免强制安装框架。
30
+
31
+ ## 安装
32
+
33
+ ```bash
34
+ # LangChain
35
+ pip install nylonme-integrations[langchain]
36
+
37
+ # LlamaIndex
38
+ pip install nylonme-integrations[llamaindex]
39
+
40
+ # 两者都要
41
+ pip install nylonme-integrations[all]
42
+ ```
43
+
44
+ ## LangChain
45
+
46
+ ```python
47
+ from nylonme_integrations.langchain import NylonMeRetriever, NylonMeMemory
48
+
49
+ retriever = NylonMeRetriever(target="127.0.0.1:50051", owner="alice", budget=5)
50
+ docs = retriever.invoke("上次出差住在哪里?")
51
+ for d in docs:
52
+ print(d.page_content, d.metadata["resonance"])
53
+ ```
54
+
55
+ 对话记忆(在 prompt 里放一个 `{memory}` 占位符):
56
+
57
+ ```python
58
+ memory = NylonMeMemory(target="127.0.0.1:50051", owner="alice")
59
+ memory.save_context({"input": "我喜欢靠窗座位"}, {"output": "已记住"})
60
+ print(memory.load_memory_variables({"input": "出差选座"}))
61
+ # {'memory': '- 出差偏好:靠窗座位'}
62
+ ```
63
+
64
+ ## LlamaIndex
65
+
66
+ ```python
67
+ from nylonme_integrations.llamaindex import NylonMeRetriever
68
+
69
+ retriever = NylonMeRetriever(target="127.0.0.1:50051", owner="alice", budget=5)
70
+ nodes = retriever.retrieve("上次出差住在哪里?")
71
+ for n in nodes:
72
+ print(n.node.text, n.score)
73
+ ```
74
+
75
+ ## 配置
76
+
77
+ 两个适配器都暴露同样的字段:
78
+
79
+ | 字段 | 默认值 | 说明 |
80
+ |---|---|---|
81
+ | `target` | `127.0.0.1:50051` | NylonME gRPC 地址(也读 `NYLON_SERVER`) |
82
+ | `owner` | `default` | 记忆归属(也读 `NYLON_OWNER`) |
83
+ | `tenant` | `default` | 租户(也读 `NYLON_TENANT`) |
84
+ | `budget` | `5` | 共振召回预算 |
85
+ | `task` | `None` | 可选任务上下文 |
86
+
87
+ 引擎默认监听 `127.0.0.1:50051`(gRPC)和 `50052`(REST/UI)。用 Docker 一键起:
88
+ `docker compose up -d`。
@@ -0,0 +1,63 @@
1
+ # NylonME Integrations
2
+
3
+ LangChain 和 LlamaIndex 的 NylonME 适配器。核心共振逻辑只依赖
4
+ `nylon-sdk`,框架类在真正使用时才导入,避免强制安装框架。
5
+
6
+ ## 安装
7
+
8
+ ```bash
9
+ # LangChain
10
+ pip install nylonme-integrations[langchain]
11
+
12
+ # LlamaIndex
13
+ pip install nylonme-integrations[llamaindex]
14
+
15
+ # 两者都要
16
+ pip install nylonme-integrations[all]
17
+ ```
18
+
19
+ ## LangChain
20
+
21
+ ```python
22
+ from nylonme_integrations.langchain import NylonMeRetriever, NylonMeMemory
23
+
24
+ retriever = NylonMeRetriever(target="127.0.0.1:50051", owner="alice", budget=5)
25
+ docs = retriever.invoke("上次出差住在哪里?")
26
+ for d in docs:
27
+ print(d.page_content, d.metadata["resonance"])
28
+ ```
29
+
30
+ 对话记忆(在 prompt 里放一个 `{memory}` 占位符):
31
+
32
+ ```python
33
+ memory = NylonMeMemory(target="127.0.0.1:50051", owner="alice")
34
+ memory.save_context({"input": "我喜欢靠窗座位"}, {"output": "已记住"})
35
+ print(memory.load_memory_variables({"input": "出差选座"}))
36
+ # {'memory': '- 出差偏好:靠窗座位'}
37
+ ```
38
+
39
+ ## LlamaIndex
40
+
41
+ ```python
42
+ from nylonme_integrations.llamaindex import NylonMeRetriever
43
+
44
+ retriever = NylonMeRetriever(target="127.0.0.1:50051", owner="alice", budget=5)
45
+ nodes = retriever.retrieve("上次出差住在哪里?")
46
+ for n in nodes:
47
+ print(n.node.text, n.score)
48
+ ```
49
+
50
+ ## 配置
51
+
52
+ 两个适配器都暴露同样的字段:
53
+
54
+ | 字段 | 默认值 | 说明 |
55
+ |---|---|---|
56
+ | `target` | `127.0.0.1:50051` | NylonME gRPC 地址(也读 `NYLON_SERVER`) |
57
+ | `owner` | `default` | 记忆归属(也读 `NYLON_OWNER`) |
58
+ | `tenant` | `default` | 租户(也读 `NYLON_TENANT`) |
59
+ | `budget` | `5` | 共振召回预算 |
60
+ | `task` | `None` | 可选任务上下文 |
61
+
62
+ 引擎默认监听 `127.0.0.1:50051`(gRPC)和 `50052`(REST/UI)。用 Docker 一键起:
63
+ `docker compose up -d`。
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "nylonme-integrations"
7
+ version = "0.1.0"
8
+ description = "LangChain and LlamaIndex adapters for the NylonME memory engine"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "Apache-2.0" }
12
+ authors = [{ name = "NylonME contributors" }]
13
+ keywords = ["memory", "rag", "langchain", "llamaindex", "nylonme"]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: Apache Software License",
18
+ "Programming Language :: Python :: 3",
19
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
20
+ ]
21
+ dependencies = ["nylon-sdk>=0.2"]
22
+
23
+ [project.optional-dependencies]
24
+ langchain = ["langchain-core>=0.3"]
25
+ llamaindex = ["llama-index-core>=0.11"]
26
+ all = ["langchain-core>=0.3", "llama-index-core>=0.11"]
27
+ test = ["pytest"]
28
+
29
+ [tool.setuptools.packages.find]
30
+ where = ["src"]
31
+
32
+ [tool.setuptools.package-data]
33
+ nylonme_integrations = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,18 @@
1
+ """NylonME framework adapters.
2
+
3
+ A thin bridge from NylonME to the two most common Python agent/RAG
4
+ frameworks. The core resonance logic lives in ``_core.py`` and only depends
5
+ on ``nylon-sdk``; the framework modules import their framework lazily.
6
+
7
+ # LangChain
8
+ from nylonme_integrations.langchain import NylonMeRetriever, NylonMeMemory
9
+
10
+ # LlamaIndex
11
+ from nylonme_integrations.llamaindex import NylonMeRetriever
12
+ """
13
+
14
+ from ._core import build_client, node_metadata, resonate_records
15
+
16
+ __version__ = "0.1.0"
17
+
18
+ __all__ = ["build_client", "node_metadata", "resonate_records", "__version__"]
@@ -0,0 +1,63 @@
1
+ """Framework-agnostic bridge between NylonME and RAG/agent frameworks.
2
+
3
+ This module only depends on ``nylon-sdk``. The LangChain and LlamaIndex
4
+ adapters import it, so the same resonate/weave semantics are shared and can
5
+ be tested without pulling in either framework.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Optional
11
+
12
+ from nylon_sdk import NylonClient
13
+
14
+
15
+ def build_client(
16
+ target: str,
17
+ owner: str,
18
+ tenant: str,
19
+ *,
20
+ timeout: float = 30.0,
21
+ ) -> NylonClient:
22
+ """Create a NylonME client from the values the adapters expose as fields."""
23
+ return NylonClient(target, owner=owner, tenant=tenant, timeout=timeout)
24
+
25
+
26
+ def node_metadata(record: dict[str, Any]) -> dict[str, Any]:
27
+ """Flatten one ActivatedNode into stable, JSON-friendly metadata."""
28
+ f = record["filaments"]
29
+ return {
30
+ "node_id": record["node_id"],
31
+ "resonance": record["resonance"],
32
+ "relations": f["relations"],
33
+ "confidence": f["confidence"],
34
+ "emotion_valence": f["emotion_valence"],
35
+ "emotion_intensity": f["emotion_intensity"],
36
+ "mentions_7d": f["mentions_7d"],
37
+ }
38
+
39
+
40
+ def resonate_records(
41
+ client: NylonClient,
42
+ query: str,
43
+ *,
44
+ budget: int = 5,
45
+ task: Optional[str] = None,
46
+ ) -> list[dict[str, Any]]:
47
+ """Return resonated memories as plain dictionaries."""
48
+ result = client.resonate(query, budget=budget, task=task)
49
+ return [
50
+ {
51
+ "node_id": a.node_id,
52
+ "resonance": a.resonance,
53
+ "filaments": {
54
+ "fact": a.filaments.fact,
55
+ "relations": list(a.filaments.relations),
56
+ "confidence": a.filaments.confidence,
57
+ "emotion_valence": a.filaments.emotion_valence,
58
+ "emotion_intensity": a.filaments.emotion_intensity,
59
+ "mentions_7d": a.filaments.mentions_7d,
60
+ },
61
+ }
62
+ for a in result.activated
63
+ ]
@@ -0,0 +1,114 @@
1
+ """LangChain adapter for NylonME.
2
+
3
+ Exposes:
4
+
5
+ * :class:`NylonMeRetriever` - RAG retrieval over resonated memories.
6
+ * :class:`NylonMeMemory` - conversational memory that weaves turns and
7
+ injects the most relevant memories into the prompt.
8
+
9
+ ``langchain-core`` is a required dependency of this module; install it with
10
+ ``pip install nylonme-integrations[langchain]``.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Any, Optional
16
+
17
+ try:
18
+ from langchain_core.callbacks.manager import CallbackManagerForRetrieverRun
19
+ from langchain_core.documents import Document
20
+ from langchain_core.memory import BaseMemory
21
+ from langchain_core.retrievers import BaseRetriever
22
+ except ImportError as exc: # pragma: no cover
23
+ raise ImportError(
24
+ "This adapter requires langchain-core. "
25
+ "Install it with: pip install nylonme-integrations[langchain]"
26
+ ) from exc
27
+
28
+ from ._core import build_client, node_metadata, resonate_records
29
+
30
+
31
+ class NylonMeRetriever(BaseRetriever):
32
+ """Retriever that maps a query to resonated NylonME memories as Documents."""
33
+
34
+ target: str = "127.0.0.1:50051"
35
+ owner: str = "default"
36
+ tenant: str = "default"
37
+ budget: int = 5
38
+ task: Optional[str] = None
39
+
40
+ def _get_relevant_documents(
41
+ self,
42
+ query: str,
43
+ *,
44
+ run_manager: CallbackManagerForRetrieverRun,
45
+ ) -> list[Document]:
46
+ del run_manager
47
+ with build_client(self.target, self.owner, self.tenant) as client:
48
+ records = resonate_records(client, query, budget=self.budget, task=self.task)
49
+ return [
50
+ Document(page_content=r["filaments"]["fact"], metadata=node_metadata(r))
51
+ for r in records
52
+ ]
53
+
54
+ async def _aget_relevant_documents(
55
+ self,
56
+ query: str,
57
+ *,
58
+ run_manager=None,
59
+ ) -> list[Document]:
60
+ del run_manager
61
+ # The sync SDK call is the simplest correct path; async callers can
62
+ # use AsyncNylonClient directly if they need a truly async channel.
63
+ return self._get_relevant_documents(query, run_manager=run_manager)
64
+
65
+
66
+ class NylonMeMemory(BaseMemory):
67
+ """Conversational memory: weaves each turn, injects recall into prompts.
68
+
69
+ Wire it into a prompt that contains a ``{memory}`` placeholder (or the
70
+ ``memory_key`` you configure). On ``save_context`` the latest user input
71
+ and model output are woven into the engine; on ``load_memory_variables``
72
+ the engine resonates on the current input and returns the matched facts.
73
+ """
74
+
75
+ target: str = "127.0.0.1:50051"
76
+ owner: str = "default"
77
+ tenant: str = "default"
78
+ budget: int = 4
79
+ memory_key: str = "memory"
80
+ input_key: str = "input"
81
+
82
+ @property
83
+ def memory_variables(self) -> list[str]:
84
+ return [self.memory_key]
85
+
86
+ def load_memory_variables(self, inputs: dict[str, Any]) -> dict[str, str]:
87
+ query = self._query_from(inputs)
88
+ if not query:
89
+ return {self.memory_key: ""}
90
+ with build_client(self.target, self.owner, self.tenant) as client:
91
+ records = resonate_records(client, query, budget=self.budget)
92
+ facts = [r["filaments"]["fact"] for r in records]
93
+ return {self.memory_key: "\n".join(f"- {f}" for f in facts)}
94
+
95
+ def save_context(self, inputs: dict[str, Any], outputs: dict[str, str]) -> None:
96
+ text = " ".join(
97
+ str(v) for v in list(inputs.values()) + list(outputs.values()) if v
98
+ ).strip()
99
+ if text:
100
+ with build_client(self.target, self.owner, self.tenant) as client:
101
+ client.weave(text)
102
+
103
+ def clear(self) -> None:
104
+ # The community engine has no destructive clear; memories decay via
105
+ # the tension model rather than being force-deleted.
106
+ return None
107
+
108
+ def _query_from(self, inputs: dict[str, Any]) -> str:
109
+ if self.input_key in inputs:
110
+ return str(inputs[self.input_key])
111
+ return " ".join(str(v) for v in inputs.values() if v).strip()
112
+
113
+
114
+ __all__ = ["NylonMeRetriever", "NylonMeMemory"]
@@ -0,0 +1,69 @@
1
+ """LlamaIndex adapter for NylonME.
2
+
3
+ Exposes :class:`NylonMeRetriever`, which wraps NylonME resonance recall as a
4
+ LlamaIndex retriever returning ``NodeWithScore`` objects.
5
+
6
+ ``llama-index-core`` is a required dependency of this module; install it with
7
+ ``pip install nylonme-integrations[llamaindex]``.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any, Optional
13
+
14
+ try:
15
+ from llama_index.core.retrievers import BaseRetriever
16
+ from llama_index.core.schema import NodeWithScore, QueryBundle, TextNode
17
+ except ImportError as exc: # pragma: no cover
18
+ raise ImportError(
19
+ "This adapter requires llama-index-core. "
20
+ "Install it with: pip install nylonme-integrations[llamaindex]"
21
+ ) from exc
22
+
23
+ from ._core import build_client, node_metadata, resonate_records
24
+
25
+
26
+ class NylonMeRetriever(BaseRetriever):
27
+ """LlamaIndex retriever backed by NylonME resonance recall."""
28
+
29
+ def __init__(
30
+ self,
31
+ target: str = "127.0.0.1:50051",
32
+ owner: str = "default",
33
+ tenant: str = "default",
34
+ budget: int = 5,
35
+ task: Optional[str] = None,
36
+ **kwargs: Any,
37
+ ) -> None:
38
+ # llama-index-core >= 0.11 BaseRetriever is a plain class with an
39
+ # explicit __init__ (no pydantic fields), so config must be stored
40
+ # as instance attributes after super().__init__.
41
+ super().__init__(**kwargs)
42
+ self.target = target
43
+ self.owner = owner
44
+ self.tenant = tenant
45
+ self.budget = budget
46
+ self.task = task
47
+
48
+ def _retrieve(self, query_bundle: QueryBundle) -> list[NodeWithScore]:
49
+ query = query_bundle.query_str
50
+ with build_client(self.target, self.owner, self.tenant) as client:
51
+ records = resonate_records(client, query, budget=self.budget, task=self.task)
52
+ return [
53
+ NodeWithScore(
54
+ node=TextNode(
55
+ text=r["filaments"]["fact"],
56
+ id_=str(r["node_id"]),
57
+ metadata=node_metadata(r),
58
+ ),
59
+ score=float(r["resonance"]),
60
+ )
61
+ for r in records
62
+ ]
63
+
64
+ async def _aretrieve(self, query_bundle: QueryBundle) -> list[NodeWithScore]:
65
+ # Sync SDK call on the event loop for a simple, correct default.
66
+ return self._retrieve(query_bundle)
67
+
68
+
69
+ __all__ = ["NylonMeRetriever"]
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: nylonme-integrations
3
+ Version: 0.1.0
4
+ Summary: LangChain and LlamaIndex adapters for the NylonME memory engine
5
+ Author: NylonME contributors
6
+ License: Apache-2.0
7
+ Keywords: memory,rag,langchain,llamaindex,nylonme
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: nylon-sdk>=0.2
16
+ Provides-Extra: langchain
17
+ Requires-Dist: langchain-core>=0.3; extra == "langchain"
18
+ Provides-Extra: llamaindex
19
+ Requires-Dist: llama-index-core>=0.11; extra == "llamaindex"
20
+ Provides-Extra: all
21
+ Requires-Dist: langchain-core>=0.3; extra == "all"
22
+ Requires-Dist: llama-index-core>=0.11; extra == "all"
23
+ Provides-Extra: test
24
+ Requires-Dist: pytest; extra == "test"
25
+
26
+ # NylonME Integrations
27
+
28
+ LangChain 和 LlamaIndex 的 NylonME 适配器。核心共振逻辑只依赖
29
+ `nylon-sdk`,框架类在真正使用时才导入,避免强制安装框架。
30
+
31
+ ## 安装
32
+
33
+ ```bash
34
+ # LangChain
35
+ pip install nylonme-integrations[langchain]
36
+
37
+ # LlamaIndex
38
+ pip install nylonme-integrations[llamaindex]
39
+
40
+ # 两者都要
41
+ pip install nylonme-integrations[all]
42
+ ```
43
+
44
+ ## LangChain
45
+
46
+ ```python
47
+ from nylonme_integrations.langchain import NylonMeRetriever, NylonMeMemory
48
+
49
+ retriever = NylonMeRetriever(target="127.0.0.1:50051", owner="alice", budget=5)
50
+ docs = retriever.invoke("上次出差住在哪里?")
51
+ for d in docs:
52
+ print(d.page_content, d.metadata["resonance"])
53
+ ```
54
+
55
+ 对话记忆(在 prompt 里放一个 `{memory}` 占位符):
56
+
57
+ ```python
58
+ memory = NylonMeMemory(target="127.0.0.1:50051", owner="alice")
59
+ memory.save_context({"input": "我喜欢靠窗座位"}, {"output": "已记住"})
60
+ print(memory.load_memory_variables({"input": "出差选座"}))
61
+ # {'memory': '- 出差偏好:靠窗座位'}
62
+ ```
63
+
64
+ ## LlamaIndex
65
+
66
+ ```python
67
+ from nylonme_integrations.llamaindex import NylonMeRetriever
68
+
69
+ retriever = NylonMeRetriever(target="127.0.0.1:50051", owner="alice", budget=5)
70
+ nodes = retriever.retrieve("上次出差住在哪里?")
71
+ for n in nodes:
72
+ print(n.node.text, n.score)
73
+ ```
74
+
75
+ ## 配置
76
+
77
+ 两个适配器都暴露同样的字段:
78
+
79
+ | 字段 | 默认值 | 说明 |
80
+ |---|---|---|
81
+ | `target` | `127.0.0.1:50051` | NylonME gRPC 地址(也读 `NYLON_SERVER`) |
82
+ | `owner` | `default` | 记忆归属(也读 `NYLON_OWNER`) |
83
+ | `tenant` | `default` | 租户(也读 `NYLON_TENANT`) |
84
+ | `budget` | `5` | 共振召回预算 |
85
+ | `task` | `None` | 可选任务上下文 |
86
+
87
+ 引擎默认监听 `127.0.0.1:50051`(gRPC)和 `50052`(REST/UI)。用 Docker 一键起:
88
+ `docker compose up -d`。
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/nylonme_integrations/__init__.py
4
+ src/nylonme_integrations/_core.py
5
+ src/nylonme_integrations/langchain.py
6
+ src/nylonme_integrations/llamaindex.py
7
+ src/nylonme_integrations/py.typed
8
+ src/nylonme_integrations.egg-info/PKG-INFO
9
+ src/nylonme_integrations.egg-info/SOURCES.txt
10
+ src/nylonme_integrations.egg-info/dependency_links.txt
11
+ src/nylonme_integrations.egg-info/requires.txt
12
+ src/nylonme_integrations.egg-info/top_level.txt
@@ -0,0 +1,14 @@
1
+ nylon-sdk>=0.2
2
+
3
+ [all]
4
+ langchain-core>=0.3
5
+ llama-index-core>=0.11
6
+
7
+ [langchain]
8
+ langchain-core>=0.3
9
+
10
+ [llamaindex]
11
+ llama-index-core>=0.11
12
+
13
+ [test]
14
+ pytest