Skip to content

examples: add persistent memory cookbook with Dakera integration (31 tests)#2405

Open
ferhimedamine wants to merge 1 commit into
567-labs:mainfrom
ferhimedamine:feat/dakera-persistent-memory
Open

examples: add persistent memory cookbook with Dakera integration (31 tests)#2405
ferhimedamine wants to merge 1 commit into
567-labs:mainfrom
ferhimedamine:feat/dakera-persistent-memory

Conversation

@ferhimedamine

Copy link
Copy Markdown

Closes #2404

Summary

Adds a complete cookbook recipe for persistent, cross-session memory using Dakera — a self-hosted, decay-weighted vector memory server.

Instructor currently has no memory example. This PR adds one using Instructor's native hook system, matching the pattern already established by examples/tracing_with_langfuse.md.

Files added

examples/persistent_memory_dakera/
├── dakera_memory.py         # DakeraMemory, AsyncDakeraMemory, DakeraMemoryHook, build_context_messages
├── run.py                   # 4 runnable scenarios
└── test_dakera_memory.py    # 31 tests, all passing (mocked)

docs/examples/persistent_memory_dakera.md  # Cookbook page
mkdocs.yml                                 # 1 line added under Cookbook:

How DakeraMemoryHook works

Uses Instructor's client.on() hook system — same mechanism as the Langfuse tracing integration:

import instructor
from examples.persistent_memory_dakera.dakera_memory import DakeraMemory, DakeraMemoryHook

client = instructor.from_provider("openai/gpt-4o-mini")
mem = DakeraMemory(base_url="http://localhost:3300", api_key="demo", agent_id="user-123")
hook = DakeraMemoryHook(mem)
hook.attach(client)   # 3 lines — that's the integration
  • completion:kwargs — searches Dakera for the top-K relevant memories for the current prompt and prepends them as a system message block
  • completion:response — stores the user prompt + model reply in Dakera after the call

Errors from Dakera are swallowed (non-fatal) — the hook never crashes an LLM call.

Four runnable examples

1. Manual store + recall

mem = DakeraMemory(base_url="http://localhost:3300", agent_id="user-123")
mem.store("I prefer concise technical answers.")

messages = [{"role": "user", "content": "How should you respond to me?"}]
messages = build_context_messages(messages, mem.search("answer style preference"))
reply = client.create(messages=messages, response_model=Reply)

2. Zero-boilerplate hook (auto-recall + auto-store)

hook.attach(client)
# All subsequent client.create() calls automatically recall and store

3. Structured extraction pipeline

class UserProfile(BaseModel):
    name: str
    preferences: list[str]

profile = client.create(
    messages=[{"role": "user", "content": "I'm Alex, I love Python and Rust."}],
    response_model=UserProfile,
)
# profile.name, profile.preferences are structured — and the exchange is persisted

4. Multi-turn CLI chat loop (persists across restarts)

python examples/persistent_memory_dakera/run.py

Tests

31 tests using unittest.mock — no live server or LLM credentials required:

test_dakera_memory.py
  test_store_success ✓
  test_store_sends_auth_header ✓
  test_store_http_error_raises ✓
  test_search_returns_hits ✓
  test_search_empty_result ✓
  test_search_http_error_raises ✓
  test_forget_by_ids ✓
  test_forget_all ✓
  test_forget_http_error_raises ✓
  test_build_context_messages_no_hits ✓
  test_build_context_messages_with_hits ✓
  test_hook_attach_registers_handlers ✓
  test_hook_completion_kwargs_injects_memories ✓
  test_hook_completion_kwargs_no_recall_when_top_k_zero ✓
  test_hook_completion_response_stores_exchange ✓
  test_hook_errors_are_swallowed ✓
  ... (31 total)

Prerequisites

# Start Dakera (Docker)
docker run -p 3300:3300 -e DAKERA_API_KEY=demo ghcr.io/dakera-ai/dakera:latest

# Install
pip install instructor openai httpx

No new dependencies added to pyproject.tomlhttpx is already a transitive dependency of instructor.

Adds a new cookbook entry showing how to give any Instructor application
persistent, decay-weighted long-term memory using Dakera
(https://dakera.ai) — a self-hosted vector memory server.

## What's added

### `examples/persistent_memory_dakera/`

- `dakera_memory.py` — integration helper:
  - `DakeraMemory`: sync httpx client for `/v1/memory/store`, `/v1/memory/search`,
    `/v1/memory/forget`
  - `AsyncDakeraMemory`: async variant using `httpx.AsyncClient`
  - `DakeraMemoryHook`: attaches to any instructor client via `client.on()`; auto-recalls
    before each call (`completion:kwargs`), auto-stores after (`completion:response`);
    Dakera errors are silently swallowed so they never crash an LLM call
  - `build_context_messages(messages, hits)`: inject recalled memories as a leading
    system message

- `run.py` — four runnable examples:
  1. Manual store + recall with `build_context_messages`
  2. Zero-boilerplate hook-based approach (`hook.attach(client)`)
  3. Structured extraction pipeline: `UserProfile` Pydantic model
  4. Multi-turn CLI chat loop that persists across restarts

- `test_dakera_memory.py` — 31 tests, all passing (fully mocked, no live server needed)

### `docs/examples/persistent_memory_dakera.md`

Cookbook page with usage examples, API reference, and Quick Start.

### `mkdocs.yml`

Entry added under `Cookbook:` alongside `Tracing with Langfuse`.

## Quick start

```bash
docker run -p 3300:3300 -e DAKERA_API_KEY=demo ghcr.io/dakera-ai/dakera:latest
pip install instructor openai httpx

python examples/persistent_memory_dakera/run.py
```

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Add persistent memory cookbook with Dakera integration

1 participant