mentedb-langchain 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.
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""LangChain chat history backed by MenteDB."""
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
|
|
4
|
+
from mentedb import MenteDB
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MenteDBChatHistory:
|
|
8
|
+
"""Stores chat message history in MenteDB with persistent recall.
|
|
9
|
+
|
|
10
|
+
Each message is stored as an episodic memory, enabling semantic
|
|
11
|
+
search across conversation history and cross-session continuity.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
from mentedb_langchain import MenteDBChatHistory
|
|
15
|
+
|
|
16
|
+
history = MenteDBChatHistory(
|
|
17
|
+
session_id="session-123",
|
|
18
|
+
data_dir="./agent-memory",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
history.add_user_message("What database should I use?")
|
|
22
|
+
history.add_ai_message("I recommend PostgreSQL.")
|
|
23
|
+
|
|
24
|
+
messages = history.messages
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, session_id: str, data_dir: str = "./mentedb-data",
|
|
28
|
+
agent_id: Optional[str] = None):
|
|
29
|
+
self.session_id = session_id
|
|
30
|
+
self.data_dir = data_dir
|
|
31
|
+
self.agent_id = agent_id
|
|
32
|
+
self._db = MenteDB(data_dir)
|
|
33
|
+
self._messages: list = []
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def messages(self) -> list:
|
|
37
|
+
return self._messages
|
|
38
|
+
|
|
39
|
+
def add_user_message(self, message: str) -> None:
|
|
40
|
+
self._messages.append({"role": "user", "content": message})
|
|
41
|
+
self._db.store(
|
|
42
|
+
f"[{self.session_id}] User: {message}",
|
|
43
|
+
memory_type="episodic",
|
|
44
|
+
agent_id=self.agent_id,
|
|
45
|
+
tags=["chat_history", self.session_id],
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def add_ai_message(self, message: str) -> None:
|
|
49
|
+
self._messages.append({"role": "assistant", "content": message})
|
|
50
|
+
self._db.store(
|
|
51
|
+
f"[{self.session_id}] Assistant: {message}",
|
|
52
|
+
memory_type="episodic",
|
|
53
|
+
agent_id=self.agent_id,
|
|
54
|
+
tags=["chat_history", self.session_id],
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def clear(self) -> None:
|
|
58
|
+
self._messages.clear()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""LangChain memory backed by MenteDB."""
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
from mentedb import MenteDB
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MenteDBMemory:
|
|
8
|
+
"""LangChain compatible memory that stores conversation context in MenteDB.
|
|
9
|
+
|
|
10
|
+
Usage with LangChain:
|
|
11
|
+
from mentedb_langchain import MenteDBMemory
|
|
12
|
+
|
|
13
|
+
memory = MenteDBMemory(data_dir="./agent-memory", agent_id="my-agent")
|
|
14
|
+
|
|
15
|
+
memory.save_context(
|
|
16
|
+
inputs={"input": "What database should I use?"},
|
|
17
|
+
outputs={"output": "I recommend PostgreSQL for your use case."}
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
context = memory.load_memory_variables({"input": "Tell me more about that database"})
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
memory_key: str = "history"
|
|
24
|
+
|
|
25
|
+
def __init__(self, data_dir: str = "./mentedb-data", agent_id: Optional[str] = None,
|
|
26
|
+
token_budget: int = 4096, return_messages: bool = False):
|
|
27
|
+
self.data_dir = data_dir
|
|
28
|
+
self.agent_id = agent_id
|
|
29
|
+
self.token_budget = token_budget
|
|
30
|
+
self.return_messages = return_messages
|
|
31
|
+
self._db = MenteDB(data_dir)
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def memory_variables(self) -> List[str]:
|
|
35
|
+
return [self.memory_key]
|
|
36
|
+
|
|
37
|
+
def load_memory_variables(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
|
|
38
|
+
"""Load relevant memories based on the current input."""
|
|
39
|
+
query = inputs.get("input", "")
|
|
40
|
+
if not query:
|
|
41
|
+
return {self.memory_key: ""}
|
|
42
|
+
results = self._db.search_text(query, k=10)
|
|
43
|
+
if not results:
|
|
44
|
+
return {self.memory_key: ""}
|
|
45
|
+
texts = []
|
|
46
|
+
for r in results:
|
|
47
|
+
mem = self._db.get_memory(r.id)
|
|
48
|
+
if mem:
|
|
49
|
+
texts.append(mem["content"])
|
|
50
|
+
return {self.memory_key: "\n".join(texts)}
|
|
51
|
+
|
|
52
|
+
def save_context(self, inputs: Dict[str, Any], outputs: Dict[str, str]) -> None:
|
|
53
|
+
"""Save a conversation turn as episodic memory."""
|
|
54
|
+
input_text = inputs.get("input", "")
|
|
55
|
+
output_text = outputs.get("output", "")
|
|
56
|
+
content = f"User: {input_text}\nAssistant: {output_text}"
|
|
57
|
+
self._db.store(content, memory_type="episodic", agent_id=self.agent_id)
|
|
58
|
+
|
|
59
|
+
def clear(self) -> None:
|
|
60
|
+
"""Clear all memories by closing and reopening."""
|
|
61
|
+
self._db.close()
|
|
62
|
+
self._db = MenteDB(self.data_dir)
|
|
63
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""LangChain retriever backed by MenteDB vector search."""
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
|
|
4
|
+
from mentedb import MenteDB
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MenteDBRetriever:
|
|
8
|
+
"""LangChain compatible retriever using MenteDB hybrid search.
|
|
9
|
+
|
|
10
|
+
Combines vector similarity, tag filtering, and temporal relevance
|
|
11
|
+
in a single retrieval call.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
from mentedb_langchain import MenteDBRetriever
|
|
15
|
+
|
|
16
|
+
retriever = MenteDBRetriever(
|
|
17
|
+
data_dir="./agent-memory",
|
|
18
|
+
k=10,
|
|
19
|
+
tags=["backend", "architecture"],
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
docs = retriever.get_relevant_documents("database migration strategy")
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, data_dir: str = "./mentedb-data", k: int = 10,
|
|
26
|
+
tags: Optional[List[str]] = None, agent_id: Optional[str] = None):
|
|
27
|
+
self.data_dir = data_dir
|
|
28
|
+
self.k = k
|
|
29
|
+
self.tags = tags
|
|
30
|
+
self.agent_id = agent_id
|
|
31
|
+
self._db = MenteDB(data_dir)
|
|
32
|
+
|
|
33
|
+
def get_relevant_documents(self, query: str) -> list:
|
|
34
|
+
"""Retrieve relevant memories as dicts with id, content, and score."""
|
|
35
|
+
results = self._db.search_text(query, k=self.k, tags=self.tags)
|
|
36
|
+
docs = []
|
|
37
|
+
for r in results:
|
|
38
|
+
mem = self._db.get_memory(r.id)
|
|
39
|
+
if mem:
|
|
40
|
+
docs.append({
|
|
41
|
+
"page_content": mem["content"],
|
|
42
|
+
"metadata": {
|
|
43
|
+
"id": r.id,
|
|
44
|
+
"score": r.score,
|
|
45
|
+
"memory_type": mem.get("memory_type", ""),
|
|
46
|
+
"tags": mem.get("tags", []),
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
return docs
|
|
50
|
+
|
|
51
|
+
async def aget_relevant_documents(self, query: str) -> list:
|
|
52
|
+
"""Async version of get_relevant_documents."""
|
|
53
|
+
return self.get_relevant_documents(query)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
mentedb_langchain/__init__.py,sha256=1sdnbAnHFPGsjgEAcb0zATsWEb07w8uzr22XyiUSTmk,241
|
|
2
|
+
mentedb_langchain/chat_history.py,sha256=uy6d5Cx_Vmv4j6vADbRqvEHl1bXwBPu98SPCmMZC8Kw,1821
|
|
3
|
+
mentedb_langchain/memory.py,sha256=MmOcr85AxzEaYMIFNmVKjgp2NkEtRxru0ocjQYFXPQA,2251
|
|
4
|
+
mentedb_langchain/retriever.py,sha256=NbIsZQwUs4VsFPAKD4NUe_Zhmi08qI3L2mmJ9sCsx2o,1792
|
|
5
|
+
mentedb_langchain-0.1.0.dist-info/METADATA,sha256=dANlfeZj4C6qszEO3sERpSrZBmeIq_i-lBt1bqq0z2c,237
|
|
6
|
+
mentedb_langchain-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
7
|
+
mentedb_langchain-0.1.0.dist-info/RECORD,,
|