agAdvisor / tests /conftest.py
tirtho149's picture
Deploy AgAdvisor
b30f068 verified
Raw
History Blame Contribute Delete
4.26 kB
"""Shared pytest fixtures.
Generalizes the in-memory-Qdrant + local-hashing-embedder trick (previously
hand-wired in the root offline scripts) into reusable fixtures, and provides
temp-SQLite account fixtures plus HF-sync mocks — so the whole default suite
runs with NO credentials, network, or Docker.
"""
from __future__ import annotations
import hashlib
import os
import re
import sqlite3
import sys
from pathlib import Path
import pytest
# Repo root on sys.path + as CWD-independent anchor.
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
CDMS_DB = ROOT / "data" / "cdms_metadata.db"
_DIM = 1536
_TOKEN = re.compile(r"[a-z0-9]+")
# --------------------------------------------------------------------------- #
# Deterministic local embedder (stand-in for OpenAIEmbeddingService)
# --------------------------------------------------------------------------- #
def _embed(text: str):
import numpy as np
v = np.zeros(_DIM, dtype=np.float32)
for tok in _TOKEN.findall((text or "").lower()):
idx = int(hashlib.md5(tok.encode()).hexdigest(), 16) % _DIM
v[idx] += 1.0
n = np.linalg.norm(v)
if n > 0:
v /= n
return v.tolist()
class LocalEmbedder:
"""Drop-in replacement for the OpenAI embedding service (offline, deterministic)."""
def generate_embedding(self, text: str):
return _embed(text)
@pytest.fixture(scope="session")
def local_embedder():
return LocalEmbedder()
# --------------------------------------------------------------------------- #
# Accounts: temp SQLite store + service with HF sync disabled
# --------------------------------------------------------------------------- #
@pytest.fixture()
def account_store(tmp_path):
from src.accounts.store import AccountStore
return AccountStore(tmp_path / "accounts.db")
@pytest.fixture()
def accounts_service(tmp_path, monkeypatch):
"""Real AccountsService on a temp DB with sync OFF (no HF token) and a
known SESSION_SECRET so token tests are deterministic."""
monkeypatch.setenv("SESSION_SECRET", "unit-test-secret")
monkeypatch.delenv("HF_DATA_REPO", raising=False)
monkeypatch.delenv("HF_DATA_TOKEN", raising=False)
from src.accounts.service import AccountsService
svc = AccountsService(db_path=str(tmp_path / "accounts.db"), daily_quota=5)
assert svc.sync.enabled is False # local-dev guard: no sync without a token
return svc
# --------------------------------------------------------------------------- #
# Integration: real CDMS pipeline over the committed index (in-memory Qdrant)
# --------------------------------------------------------------------------- #
@pytest.fixture(scope="session")
def in_memory_rag():
"""Build an in-memory Qdrant from the committed chunk DB and wire the REAL
CDMSRAGSearch to it with the local embedder. Skips if the index or
qdrant-client is unavailable."""
if not CDMS_DB.exists():
pytest.skip(f"CDMS index not present ({CDMS_DB}); skipping integration test")
try:
from src.rag.vector_store import QdrantVectorStore
from src.cdms.rag_search import CDMSRAGSearch
except Exception as e: # missing qdrant-client etc.
pytest.skip(f"RAG deps unavailable: {e}")
conn = sqlite3.connect(str(CDMS_DB))
try:
rows = conn.execute(
"SELECT dc.id, dc.content, dc.page_number, dc.document_id, d.filename "
"FROM document_chunks dc JOIN documents d ON dc.document_id = d.id"
).fetchall()
finally:
conn.close()
if not rows:
pytest.skip("CDMS index has no chunks")
store = QdrantVectorStore() # Docker unavailable -> in-memory mode
for cid, content, page, docid, filename in rows:
if not content:
continue
store.add_document_chunk(
str(cid),
_embed(content),
{
"content": content,
"source_file": filename,
"page_number": page or 0,
"document_id": docid,
},
)
searcher = CDMSRAGSearch()
searcher.vector_store = store
searcher.embedding_service = LocalEmbedder()
return searcher