oc_chat
Loading...
Searching...
No Matches
memory.py
Go to the documentation of this file.
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
# oc_chat/tools/memory.py
4
5
"""
6
Persistent memory via ChromaDB vector store.
7
8
Purpose
9
-------
10
Provides :func:`remember` and :func:`recall` for long-term semantic
11
memory across REPL sessions. Backed by a local ChromaDB persistent
12
client at ``./memory_store/`` with cosine-similarity search.
13
14
Falls back to the structured ``missing_dependency`` shape that the
15
dependency healer can intercept when ``chromadb`` is not installed.
16
17
Responsibilities
18
----------------
19
- :func:`_get_collection` — lazily build (or reload) the persistent
20
collection on first access.
21
- :func:`remember` — embed and store a text chunk with optional
22
metadata; returns the assigned id.
23
- :func:`recall` — semantic-similarity query returning the top-k
24
matches with their metadata and distances.
25
26
Requires: ``pip install chromadb``
27
28
Diagnostics
29
-----------
30
Domain: OC_CHAT.TOOLS
31
Levels:
32
L2 — lifecycle events
33
L3 — semantic details
34
L4 — deep tracing
35
36
Contracts
37
---------
38
- The collection is process-singleton — repeat calls reuse the same
39
client/collection handles.
40
- Missing ``chromadb`` returns ``{"missing_dependency": "chromadb",
41
...}`` rather than raising, so the healer can offer to install.
42
- The on-disk store at ``memory_store/`` is opaque to callers; only
43
the public ``remember`` / ``recall`` API is supported.
44
45
Dependencies
46
------------
47
- oc_diagnostics (structured debug logging via _dbg)
48
- oc_chat.tools.filesystem (lazy; _sandbox_root - places the memory store under the effective sandbox root)
49
- chromadb (lazy; the persistent vector store client and its cosine-similarity collection, optional)
50
51
See Also
52
--------
53
oc_chat/docs/conventions/CONTRACTS.md §3 Tool registry contract; §4 Tool return-
54
value conventions.
55
"""
56
from
pathlib
import
Path
57
58
from
oc_diagnostics
import
_dbg
59
60
def
_store_dir
() -> str:
61
"""Resolve the memory store dir under the effective sandbox root.
62
63
Resolved at first use (not import time) so a session sandbox override set
64
after import is honoured — keeping the long-term memory store aligned with
65
the read/write sandbox (M8 F77; M8.0 WU-1) instead of the import-time
66
process cwd.
67
"""
68
from
oc_chat.tools.filesystem
import
_sandbox_root
69
70
return
str(_sandbox_root() /
"memory_store"
)
71
_COLLECTION_NAME =
"oc_chat_memory"
72
_client =
None
73
_collection =
None
74
75
76
def
_get_collection
():
77
"""Return (or lazily create) the ChromaDB collection."""
78
func =
"_get_collection"
79
global
_client, _collection
80
if
_collection
is
not
None
:
81
return
_collection
82
try
:
83
import
chromadb
84
except
ImportError:
85
raise
ImportError(
"chromadb not installed. Run: pip install chromadb"
)
86
87
store_dir =
_store_dir
()
88
_dbg(
"OC_CHAT.TOOLS"
, func, f
"first-time init at {store_dir}"
, 2)
89
_client = chromadb.PersistentClient(path=store_dir)
90
_collection = _client.get_or_create_collection(
91
name=_COLLECTION_NAME,
92
metadata={
"hnsw:space"
:
"cosine"
},
93
)
94
return
_collection
95
96
97
def
remember
(text: str, metadata: dict |
None
=
None
) -> dict:
98
"""Store a piece of information in long-term persistent memory."""
99
try
:
100
col =
_get_collection
()
101
except
ImportError
as
e:
102
return
{
"error"
: str(e)}
103
104
import
uuid
105
doc_id = str(uuid.uuid4())
106
col.add(documents=[text], ids=[doc_id], metadatas=[metadata
or
{}])
107
return
{
"stored"
:
True
,
"id"
: doc_id}
108
109
110
def
recall
(query: str, n_results: int = 5) -> dict:
111
"""Retrieve relevant memories using semantic similarity search."""
112
try
:
113
col =
_get_collection
()
114
except
ImportError
as
e:
115
return
{
"error"
: str(e)}
116
117
count = col.count()
118
if
count == 0:
119
return
{
"memories"
: [],
"note"
:
"Memory store is empty."
}
120
121
results = col.query(
122
query_texts=[query],
123
n_results=min(n_results, count),
124
)
125
memories = []
126
for
doc, meta
in
zip(
127
results.get(
"documents"
, [[]])[0],
128
results.get(
"metadatas"
, [[]])[0],
129
):
130
memories.append({
"text"
: doc,
"metadata"
: meta})
131
132
return
{
"memories"
: memories}
133
134
135
TOOLS = {
136
"remember"
: remember,
137
"recall"
: recall,
138
}
139
140
SCHEMAS = [
141
{
142
"type"
:
"function"
,
143
"function"
: {
144
"name"
:
"remember"
,
145
"description"
:
"Store a piece of information in long-term persistent memory."
,
146
"parameters"
: {
147
"type"
:
"object"
,
148
"properties"
: {
149
"text"
: {
"type"
:
"string"
,
"description"
:
"Information to remember"
},
150
"metadata"
: {
"type"
:
"object"
,
"description"
:
"Optional key-value metadata"
},
151
},
152
"required"
: [
"text"
],
153
},
154
},
155
},
156
{
157
"type"
:
"function"
,
158
"function"
: {
159
"name"
:
"recall"
,
160
"description"
:
"Retrieve relevant memories using semantic similarity search."
,
161
"parameters"
: {
162
"type"
:
"object"
,
163
"properties"
: {
164
"query"
: {
"type"
:
"string"
,
"description"
:
"Search query"
},
165
"n_results"
: {
"type"
:
"integer"
,
"description"
:
"Number of memories to return (default 5)"
},
166
},
167
"required"
: [
"query"
],
168
},
169
},
170
},
171
]
oc_chat.tools.filesystem
Definition
filesystem.py:1
oc_chat.tools.memory._get_collection
_get_collection()
Definition
memory.py:76
oc_chat.tools.memory.recall
dict recall(str query, int n_results=5)
Definition
memory.py:110
oc_chat.tools.memory._store_dir
str _store_dir()
Definition
memory.py:60
oc_chat.tools.memory.remember
dict remember(str text, dict|None metadata=None)
Definition
memory.py:97
oc_chat
tools
memory.py
Generated by
1.15.0