Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions mempalace/backends/chroma.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
import sqlite3

import chromadb
from chromadb.config import Settings

from .base import BaseCollection

#: Shared ChromaDB settings that silence the posthog telemetry spam
#: (see https://github.com/MemPalace/mempalace/issues/458).
CHROMA_SETTINGS = Settings(anonymized_telemetry=False)

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -86,7 +91,7 @@ def _client(self, palace_path: str):
"""Return a cached PersistentClient for *palace_path*, creating one if needed."""
if palace_path not in self._clients:
_fix_blob_seq_ids(palace_path)
self._clients[palace_path] = chromadb.PersistentClient(path=palace_path)
self._clients[palace_path] = chromadb.PersistentClient(path=palace_path, settings=CHROMA_SETTINGS)
return self._clients[palace_path]

# ------------------------------------------------------------------
Expand All @@ -101,7 +106,7 @@ def make_client(palace_path: str):
inode/mtime-based client cache.
"""
_fix_blob_seq_ids(palace_path)
return chromadb.PersistentClient(path=palace_path)
return chromadb.PersistentClient(path=palace_path, settings=CHROMA_SETTINGS)

@staticmethod
def backend_version() -> str:
Expand Down
1 change: 1 addition & 0 deletions mempalace/dedup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

from .backends.chroma import ChromaBackend

from .backends.chroma import CHROMA_SETTINGS

COLLECTION_NAME = "mempalace_drawers"
# Cosine DISTANCE threshold (not similarity). Lower = stricter.
Expand Down
1 change: 1 addition & 0 deletions mempalace/repair.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

from .backends.chroma import ChromaBackend

from .backends.chroma import CHROMA_SETTINGS

COLLECTION_NAME = "mempalace_drawers"

Expand Down
3 changes: 2 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import chromadb # noqa: E402
import pytest # noqa: E402

from mempalace.backends.chroma import CHROMA_SETTINGS # noqa: E402
from mempalace.config import MempalaceConfig # noqa: E402
from mempalace.knowledge_graph import KnowledgeGraph # noqa: E402

Expand Down Expand Up @@ -100,7 +101,7 @@ def config(tmp_dir, palace_path):
@pytest.fixture
def collection(palace_path):
"""A ChromaDB collection pre-seeded in the temp palace."""
client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(path=palace_path, settings=CHROMA_SETTINGS)
col = client.get_or_create_collection("mempalace_drawers", metadata={"hnsw:space": "cosine"})
yield col
client.delete_collection("mempalace_drawers")
Expand Down
11 changes: 8 additions & 3 deletions tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
import chromadb
import pytest

from mempalace.backends.chroma import ChromaBackend, ChromaCollection, _fix_blob_seq_ids
from mempalace.backends.chroma import (
CHROMA_SETTINGS,
ChromaBackend,
ChromaCollection,
_fix_blob_seq_ids,
)


class _FakeCollection:
Expand Down Expand Up @@ -78,7 +83,7 @@ def test_chroma_backend_create_true_creates_directory_and_collection(tmp_path):
assert palace_path.is_dir()
assert isinstance(collection, ChromaCollection)

client = chromadb.PersistentClient(path=str(palace_path))
client = chromadb.PersistentClient(path=str(palace_path), settings=CHROMA_SETTINGS)
client.get_collection("mempalace_drawers")


Expand All @@ -91,7 +96,7 @@ def test_chroma_backend_creates_collection_with_cosine_distance(tmp_path):
create=True,
)

client = chromadb.PersistentClient(path=str(palace_path))
client = chromadb.PersistentClient(path=str(palace_path), settings=CHROMA_SETTINGS)
col = client.get_collection("mempalace_drawers")
assert col.metadata.get("hnsw:space") == "cosine"

Expand Down
9 changes: 5 additions & 4 deletions tests/test_convo_miner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import chromadb

from mempalace.backends.chroma import CHROMA_SETTINGS
from mempalace.convo_miner import mine_convos
from mempalace.palace import file_already_mined

Expand All @@ -19,7 +20,7 @@ def test_convo_mining():
palace_path = os.path.join(tmpdir, "palace")
mine_convos(tmpdir, palace_path, wing="test_convos")

client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=palace_path)
col = client.get_collection("mempalace_drawers")
assert col.count() >= 2

Expand All @@ -46,7 +47,7 @@ def test_mine_convos_does_not_reprocess_short_files(capsys):

# Verify sentinel was written (resolve path -- macOS /var -> /private/var)
resolved_file = str(Path(tmpdir).resolve() / "tiny.txt")
client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=palace_path)
col = client.get_collection("mempalace_drawers")
assert file_already_mined(col, resolved_file)

Expand Down Expand Up @@ -100,7 +101,7 @@ def test_mine_convos_rebuilds_stale_drawers_after_schema_bump(capsys):
mine_convos(tmpdir, palace_path, wing="test")
capsys.readouterr()

client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=palace_path)
col = client.get_collection("mempalace_drawers")
resolved = str(Path(tmpdir).resolve() / "chat.txt")
first_pass = col.get(where={"source_file": resolved})
Expand Down Expand Up @@ -144,7 +145,7 @@ def test_mine_convos_rebuilds_stale_drawers_after_schema_bump(capsys):
"Files skipped (already filed): 0" in out
), "stale drawers should force a rebuild, not a skip"

client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=palace_path)
col = client.get_collection("mempalace_drawers")
rebuilt = col.get(where={"source_file": resolved})
# Orphan is gone
Expand Down
12 changes: 7 additions & 5 deletions tests/test_mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ def _get_collection(palace_path, create=False):
when they are done.
"""
import chromadb
from mempalace.backends.chroma import CHROMA_SETTINGS

client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(path=palace_path, settings=CHROMA_SETTINGS)
if create:
return (
client,
Expand Down Expand Up @@ -220,10 +221,11 @@ def test_status_cold_start_no_collection(self, monkeypatch, config, palace_path,
should return total_drawers: 0, not 'No palace found'.
"""
import chromadb
from mempalace.backends.chroma import CHROMA_SETTINGS

_patch_mcp_server(monkeypatch, config, kg)
# Create the DB file (init does this) but NOT the collection
client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(path=palace_path, settings=CHROMA_SETTINGS)
del client
from mempalace.mcp_server import tool_status

Expand Down Expand Up @@ -444,9 +446,9 @@ def test_add_drawer_shared_header_no_collision(self, monkeypatch, config, palace

assert result1["success"] is True
assert result2["success"] is True
assert (
result1["drawer_id"] != result2["drawer_id"]
), "Documents with shared header but different content must have distinct drawer IDs"
assert result1["drawer_id"] != result2["drawer_id"], (
"Documents with shared header but different content must have distinct drawer IDs"
)

def test_delete_drawer(self, monkeypatch, config, palace_path, seeded_collection, kg):
_patch_mcp_server(monkeypatch, config, kg)
Expand Down
10 changes: 6 additions & 4 deletions tests/test_miner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import chromadb
import yaml

from mempalace.backends.chroma import CHROMA_SETTINGS

from mempalace.miner import load_config, mine, scan_project, status
from mempalace.palace import NORMALIZE_VERSION, file_already_mined

Expand Down Expand Up @@ -45,7 +47,7 @@ def test_project_mining():
palace_path = project_root / "palace"
mine(str(project_root), str(palace_path))

client = chromadb.PersistentClient(path=str(palace_path))
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=str(palace_path))
col = client.get_collection("mempalace_drawers")
assert col.count() > 0
finally:
Expand Down Expand Up @@ -229,7 +231,7 @@ def test_file_already_mined_check_mtime():
try:
palace_path = os.path.join(tmpdir, "palace")
os.makedirs(palace_path)
client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=palace_path)
col = client.get_or_create_collection(
"mempalace_drawers", metadata={"hnsw:space": "cosine"}
)
Expand Down Expand Up @@ -339,7 +341,7 @@ def test_file_already_mined_returns_false_for_stale_normalize_version():
try:
palace_path = os.path.join(tmpdir, "palace")
os.makedirs(palace_path)
client = chromadb.PersistentClient(path=palace_path)
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=palace_path)
col = client.get_or_create_collection("mempalace_drawers")

# Pre-v2 drawer: no normalize_version field at all
Expand Down Expand Up @@ -381,7 +383,7 @@ def test_add_drawer_stamps_normalize_version(tmp_path):

palace_path = tmp_path / "palace"
palace_path.mkdir()
client = chromadb.PersistentClient(path=str(palace_path))
client = chromadb.PersistentClient(settings=CHROMA_SETTINGS, path=str(palace_path))
col = client.get_or_create_collection("mempalace_drawers")
try:
added = add_drawer(
Expand Down