| """Dummy memory adapter for end-to-end pipeline testing. |
| |
| Stores all ingested turns as raw text and retrieves by simple substring match. |
| No external dependencies required. |
| """ |
|
|
| from __future__ import annotations |
|
|
| from typing import Any |
|
|
| from eval_framework.datasets.schemas import ( |
| MemoryDeltaRecord, |
| MemorySnapshotRecord, |
| NormalizedTurn, |
| RetrievalItem, |
| RetrievalRecord, |
| ) |
| from eval_framework.memory_adapters.base import MemoryAdapter |
|
|
|
|
| class DummyAdapter(MemoryAdapter): |
| """Minimal adapter that stores turns verbatim — for pipeline testing.""" |
|
|
| def __init__(self) -> None: |
| self._memories: list[dict[str, str]] = [] |
| self._session_id = "" |
| self._prev_ids: set[str] = set() |
|
|
| def reset(self) -> None: |
| self._memories = [] |
| self._session_id = "" |
| self._prev_ids = set() |
|
|
| def ingest_turn(self, turn: NormalizedTurn) -> None: |
| self._session_id = turn.session_id |
| text = f"{turn.role}: {turn.text}" |
| for att in turn.attachments: |
| text += f"\n[{att.type}] {att.caption}" |
| mid = str(len(self._memories)) |
| self._memories.append({ |
| "id": mid, |
| "text": text, |
| "session_id": turn.session_id, |
| }) |
|
|
| def end_session(self, session_id: str) -> None: |
| self._session_id = session_id |
|
|
| def snapshot_memories(self) -> list[MemorySnapshotRecord]: |
| return [ |
| MemorySnapshotRecord( |
| memory_id=m["id"], |
| text=m["text"], |
| session_id=m["session_id"], |
| status="active", |
| source="Dummy", |
| raw_backend_id=m["id"], |
| raw_backend_type="dummy", |
| metadata={}, |
| ) |
| for m in self._memories |
| ] |
|
|
| def export_memory_delta(self, session_id: str) -> list[MemoryDeltaRecord]: |
| current_ids = {m["id"] for m in self._memories} |
| new_ids = current_ids - self._prev_ids |
| deltas = [ |
| MemoryDeltaRecord( |
| session_id=session_id, |
| op="add", |
| text=m["text"], |
| linked_previous=(), |
| raw_backend_id=m["id"], |
| metadata={"baseline": "Dummy"}, |
| ) |
| for m in self._memories |
| if m["id"] in new_ids |
| ] |
| self._prev_ids = current_ids |
| return deltas |
|
|
| def retrieve(self, query: str, top_k: int) -> RetrievalRecord: |
| query_lower = query.lower() |
| scored = [] |
| for m in self._memories: |
| text_lower = m["text"].lower() |
| |
| query_words = set(query_lower.split()) |
| text_words = set(text_lower.split()) |
| overlap = len(query_words & text_words) |
| scored.append((overlap, m)) |
| scored.sort(key=lambda x: x[0], reverse=True) |
|
|
| items = [ |
| RetrievalItem( |
| rank=i, |
| memory_id=m["id"], |
| text=m["text"], |
| score=float(overlap) / max(len(query.split()), 1), |
| raw_backend_id=m["id"], |
| ) |
| for i, (overlap, m) in enumerate(scored[:top_k]) |
| ] |
| return RetrievalRecord( |
| query=query, |
| top_k=top_k, |
| items=items, |
| raw_trace={"baseline": "Dummy"}, |
| ) |
|
|
| def get_capabilities(self) -> dict[str, Any]: |
| return { |
| "backend": "Dummy", |
| "baseline": "Dummy", |
| "available": True, |
| "delta_granularity": "per_turn", |
| "snapshot_mode": "full", |
| } |
|
|