pycontextdb 0.1.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.
- contextdb/__init__.py +72 -0
- contextdb/agents/__init__.py +8 -0
- contextdb/agents/memory_bus.py +80 -0
- contextdb/agents/rl_manager.py +89 -0
- contextdb/cli.py +107 -0
- contextdb/client.py +516 -0
- contextdb/core/__init__.py +41 -0
- contextdb/core/config.py +89 -0
- contextdb/core/exceptions.py +29 -0
- contextdb/core/models.py +151 -0
- contextdb/dynamics/__init__.py +25 -0
- contextdb/dynamics/evolution.py +168 -0
- contextdb/dynamics/formation.py +193 -0
- contextdb/dynamics/retrieval.py +130 -0
- contextdb/graphs/__init__.py +17 -0
- contextdb/graphs/base.py +46 -0
- contextdb/graphs/causal.py +224 -0
- contextdb/graphs/entity.py +251 -0
- contextdb/graphs/semantic.py +156 -0
- contextdb/graphs/temporal.py +173 -0
- contextdb/integrations/__init__.py +10 -0
- contextdb/integrations/autogen.py +39 -0
- contextdb/integrations/crewai.py +41 -0
- contextdb/integrations/langchain.py +132 -0
- contextdb/integrations/openai_tools.py +124 -0
- contextdb/memory/__init__.py +9 -0
- contextdb/memory/experiential.py +102 -0
- contextdb/memory/factual.py +58 -0
- contextdb/memory/working.py +90 -0
- contextdb/privacy/__init__.py +9 -0
- contextdb/privacy/audit.py +199 -0
- contextdb/privacy/pii_detector.py +173 -0
- contextdb/privacy/retention.py +99 -0
- contextdb/py.typed +0 -0
- contextdb/store/__init__.py +15 -0
- contextdb/store/base.py +67 -0
- contextdb/store/sqlite_store.py +517 -0
- contextdb/store/vector_index.py +241 -0
- contextdb/utils/__init__.py +22 -0
- contextdb/utils/embeddings.py +159 -0
- contextdb/utils/llm.py +139 -0
- contextdb/utils/migrations.py +159 -0
- pycontextdb-0.1.0.dist-info/METADATA +589 -0
- pycontextdb-0.1.0.dist-info/RECORD +47 -0
- pycontextdb-0.1.0.dist-info/WHEEL +4 -0
- pycontextdb-0.1.0.dist-info/entry_points.txt +2 -0
- pycontextdb-0.1.0.dist-info/licenses/LICENSE +190 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Migration tools — import from competitors, export to JSON.
|
|
2
|
+
|
|
3
|
+
Each importer accepts an iterable of dicts in the source system's shape and
|
|
4
|
+
translates them into :class:`~contextdb.core.models.MemoryItem` writes. We
|
|
5
|
+
keep the mapping forgiving: missing fields fall back to sensible defaults
|
|
6
|
+
so a partial dump still loads cleanly.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
from collections.abc import Iterable
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import TYPE_CHECKING, Any
|
|
16
|
+
|
|
17
|
+
from contextdb.core.models import MemoryItem, MemoryType
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from contextdb.client import ContextDB
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _parse_datetime(value: Any) -> datetime | None:
|
|
24
|
+
if value is None:
|
|
25
|
+
return None
|
|
26
|
+
if isinstance(value, datetime):
|
|
27
|
+
return value
|
|
28
|
+
try:
|
|
29
|
+
return datetime.fromisoformat(str(value))
|
|
30
|
+
except (TypeError, ValueError):
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Mem0Importer:
|
|
35
|
+
"""Import from a Mem0 JSON export.
|
|
36
|
+
|
|
37
|
+
Mem0 records typically carry ``memory`` (text), ``user_id``, ``metadata``,
|
|
38
|
+
and ISO ``created_at``. Anything beyond that lands in ``metadata``.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, client: ContextDB) -> None:
|
|
42
|
+
self.client = client
|
|
43
|
+
|
|
44
|
+
async def import_records(self, records: Iterable[dict[str, Any]]) -> int:
|
|
45
|
+
count = 0
|
|
46
|
+
for record in records:
|
|
47
|
+
content = record.get("memory") or record.get("content") or ""
|
|
48
|
+
if not content:
|
|
49
|
+
continue
|
|
50
|
+
await self.client.add(
|
|
51
|
+
content=str(content),
|
|
52
|
+
metadata=dict(record.get("metadata", {})),
|
|
53
|
+
event_time=_parse_datetime(record.get("created_at")),
|
|
54
|
+
)
|
|
55
|
+
count += 1
|
|
56
|
+
return count
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ZepImporter:
|
|
60
|
+
"""Import from a Zep session dump."""
|
|
61
|
+
|
|
62
|
+
def __init__(self, client: ContextDB) -> None:
|
|
63
|
+
self.client = client
|
|
64
|
+
|
|
65
|
+
async def import_records(self, records: Iterable[dict[str, Any]]) -> int:
|
|
66
|
+
count = 0
|
|
67
|
+
for record in records:
|
|
68
|
+
content = record.get("content") or record.get("message") or ""
|
|
69
|
+
if not content:
|
|
70
|
+
continue
|
|
71
|
+
meta = dict(record.get("metadata", {}))
|
|
72
|
+
if "role" in record:
|
|
73
|
+
meta.setdefault("role", record["role"])
|
|
74
|
+
await self.client.add(
|
|
75
|
+
content=str(content),
|
|
76
|
+
metadata=meta,
|
|
77
|
+
event_time=_parse_datetime(record.get("created_at")),
|
|
78
|
+
)
|
|
79
|
+
count += 1
|
|
80
|
+
return count
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class LangChainImporter:
|
|
84
|
+
"""Import from LangChain ``ChatMessageHistory`` dumps."""
|
|
85
|
+
|
|
86
|
+
def __init__(self, client: ContextDB) -> None:
|
|
87
|
+
self.client = client
|
|
88
|
+
|
|
89
|
+
async def import_records(self, messages: Iterable[dict[str, Any]]) -> int:
|
|
90
|
+
count = 0
|
|
91
|
+
for message in messages:
|
|
92
|
+
text = message.get("content") or message.get("text") or ""
|
|
93
|
+
if not text:
|
|
94
|
+
continue
|
|
95
|
+
role = message.get("type") or message.get("role") or "human"
|
|
96
|
+
await self.client.add(
|
|
97
|
+
content=f"{role}: {text}",
|
|
98
|
+
metadata={"role": role},
|
|
99
|
+
)
|
|
100
|
+
count += 1
|
|
101
|
+
return count
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class JSONExporter:
|
|
105
|
+
"""Dump the entire store as a JSON array of memory records."""
|
|
106
|
+
|
|
107
|
+
def __init__(self, client: ContextDB) -> None:
|
|
108
|
+
self.client = client
|
|
109
|
+
|
|
110
|
+
async def export(self, path: str | Path) -> int:
|
|
111
|
+
await self.client._ensure_init()
|
|
112
|
+
store = self.client._require_store()
|
|
113
|
+
memories = await store.list_memories(limit=100000)
|
|
114
|
+
records = [self._to_record(m) for m in memories]
|
|
115
|
+
Path(path).write_text(json.dumps(records, indent=2, default=str))
|
|
116
|
+
return len(records)
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def _to_record(item: MemoryItem) -> dict[str, Any]:
|
|
120
|
+
return {
|
|
121
|
+
"id": item.id,
|
|
122
|
+
"content": item.content,
|
|
123
|
+
"memory_type": item.memory_type.value,
|
|
124
|
+
"source": item.source,
|
|
125
|
+
"metadata": item.metadata,
|
|
126
|
+
"event_time": item.event_time.isoformat() if item.event_time else None,
|
|
127
|
+
"created_at": item.created_at.isoformat(),
|
|
128
|
+
"updated_at": item.updated_at.isoformat(),
|
|
129
|
+
"entity_mentions": item.entity_mentions,
|
|
130
|
+
"tags": item.tags,
|
|
131
|
+
"confidence": item.confidence,
|
|
132
|
+
"status": item.status.value,
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class JSONImporter:
|
|
137
|
+
"""Re-import a :class:`JSONExporter` dump."""
|
|
138
|
+
|
|
139
|
+
def __init__(self, client: ContextDB) -> None:
|
|
140
|
+
self.client = client
|
|
141
|
+
|
|
142
|
+
async def import_path(self, path: str | Path) -> int:
|
|
143
|
+
records = json.loads(Path(path).read_text())
|
|
144
|
+
assert isinstance(records, list)
|
|
145
|
+
count = 0
|
|
146
|
+
for record in records:
|
|
147
|
+
content = record.get("content")
|
|
148
|
+
if not content:
|
|
149
|
+
continue
|
|
150
|
+
mt = MemoryType(record.get("memory_type", "FACTUAL"))
|
|
151
|
+
await self.client.add(
|
|
152
|
+
content=content,
|
|
153
|
+
memory_type=mt,
|
|
154
|
+
metadata=dict(record.get("metadata", {})),
|
|
155
|
+
event_time=_parse_datetime(record.get("event_time")),
|
|
156
|
+
entity_mentions=list(record.get("entity_mentions", [])),
|
|
157
|
+
)
|
|
158
|
+
count += 1
|
|
159
|
+
return count
|