Skip to content
Merged
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
59 changes: 40 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ An older version of this project may be found here https://github.com/GilesStron

- High-level backend/frontend architecture and flows: [`docs/developer-architecture-guide.md`](docs/developer-architecture-guide.md)
- Dedicated deck-building flow guide: [`docs/deck-building.md`](docs/deck-building.md)
- AI memory system architecture, maintenance, and operations: [`docs/memory-system.md`](docs/memory-system.md)
Comment thread
GilesStrong marked this conversation as resolved.
Resolved

## Fresh Clone Setup (Docker)

Expand Down Expand Up @@ -131,26 +132,27 @@ If you run Ollama in a separate compose project, attach it to `llm_net` using a

```yaml
services:
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
volumes:
- ~/infra/ollama:/root/.ollama
networks:
- llm_net
- 127.0.0.1:11434:11434
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
ollama:
image: ollama/ollama:latest
container_name: ollama
restart: unless-stopped
volumes:
- ~/infra/ollama:/root/.ollama
ports:
- "127.0.0.1:11434:11434"
networks:
- llm_net
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]

networks:
llm_net:
name: llm_net
llm_net:
name: llm_net
```

After starting Ollama, pull the models referenced by your `.env` (`EMBEDDING_MODEL`), for example:
Expand Down Expand Up @@ -210,6 +212,25 @@ Run frontend tests:
docker compose exec frontend bun run test --run
```

## Memory System Operations

The AI memory system is integrated into deck generation and automatically maintained by Celery beat.

- Full guide: [`docs/memory-system.md`](docs/memory-system.md)
- Scheduled maintenance task: `appai.tasks.memory_maintenance.run_memory_maintenance_task`

Run maintenance manually (direct graph execution):

```bash
docker compose exec web python app/manage.py shell -c "import asyncio; from appai.services.graphs.memory_maintenance import run_memory_maintenance; asyncio.run(run_memory_maintenance())"
```

Queue maintenance via Celery (requires `celery_llm_worker` running):

```bash
docker compose exec web python app/manage.py shell -c "from appai.tasks.memory_maintenance import run_memory_maintenance_task; run_memory_maintenance_task.delay()"
```

## Production Server Commands

```bash
Expand Down Expand Up @@ -318,7 +339,7 @@ docker compose \
--project-name deepmtg_2_prod \
--env-file .env.prod \
-f docker-compose.prod.yml \
run --rm web python manage.py migrate
run --rm web python app/manage.py migrate

docker compose \
--project-name deepmtg_2_prod \
Expand Down
4 changes: 4 additions & 0 deletions app/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@
"task": "appai.tasks.daily_theme.make_daily_theme",
"schedule": crontab(minute="*/30"), # every 30 minutes, but only completes once a day due to early exit
},
"daily-memory-maintenance-job": {
"task": "appai.tasks.memory_maintenance.run_memory_maintenance_task",
"schedule": crontab(minute="*/30"), # every 30 minutes, but only completes once a day due to early exit
},
"cleanup-old-deck-build-tasks": {
"task": "appai.tasks.cleanup.cleanup_old_deck_build_tasks",
"schedule": crontab(minute="*/30"), # every 30 minutes
Expand Down
Empty file.
37 changes: 37 additions & 0 deletions app/appai/dataclasses/memory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2026 Giles Strong
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from uuid import UUID

from pydantic import BaseModel, Field


class Memory(BaseModel):
name: str = Field(
max_length=64, description="The name of the memory, which can be used to reference it in future queries."
)
text: str = Field(description="The content of the memory, which can be any text that the agent wants to remember.")
related_card_uuids: set[UUID] = Field(
default_factory=set,
max_length=10,
description="A list of UUIDs of cards that are related to this memory, which can be used to link the memory to specific cards and retrieve it later based on those cards. Up to 10 related card UUIDs can be included.",
)


class ExistingMemory(Memory):
id: UUID = Field(
description="The unique identifier of the memory in the database, used for referencing and updating the memory."
)
created_at: str = Field(
description="The timestamp of when the memory was created in the database, used for tracking the age of the memory and determining if it may be obsolete or in need of consolidation with newer memories."
)
Loading
Loading