Neural Mastery
← Practice
Long-Term Memory Recallmedium

Long-Term Memory Recall

medium Build an Agent 15–20 min

Standard library only · runs in your browser

Trimming (stage 7) throws old turns away. Long-term memory keeps the important facts outside the context window and brings back only the ones relevant to the current question, newest first when facts conflict.

Task

Implement recall(memories, query, k=3). Each memory is {"id": str, "turn": int, "text": str}.

  • Terms of a text: lowercase it, take re.findall(r"[a-z0-9]+", ...), and drop single-character words (the "s" in "user's") and words in the provided STOPWORDS set. Use a set, so repeats count once.
  • Score of a memory: the number of query terms that also appear in the memory's terms.
  • Leave out memories that score 0.
  • Sort by score (high first), then turn (newer first), then id (alphabetical).
  • Return the ids of the top k.

Function Signature

recall(memories: list[dict], query: str, k: int = 3) -> list[str]

Examples

Example 1: Newer fact outranks the older one
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'Which city is Priya in now: Lima or Paris?'
Output: ['m4', 'm1', 'm5']
Example 2: One clear match
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'When does the Tokyo flight leave?'
Output: ['m3']
Example 3: No overlap recalls nothing
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'What\'s the GDP of Chile?'
Output: []
Example 4: k limits the result
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'Priya Paris' k = 1
Output: ['m4']

Constraints

  • `STOPWORDS` is provided in the starter. Use it as-is.
  • Return a list of ids, not the memory dicts.
  • A query made only of stopwords recalls nothing.
Python3Saved ✓
import json
import math
import re


STOPWORDS = {"a", "an", "and", "are", "did", "do", "does", "for", "i", "in", "is",
"it", "me", "my", "of", "on", "the", "to", "was", "what", "when",
"where", "which", "who", "with", "you", "your"}


def recall(memories, query, k=3):
"""Return the ids of the k most relevant memories (score, then recency, then id)."""
# Your code here
pass

Case 1: Newer fact outranks the older one
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'Which city is Priya in now: Lima or Paris?'
Expected: ['m4', 'm1', 'm5']
Case 2: One clear match
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'When does the Tokyo flight leave?'
Expected: ['m3']
Case 3: No overlap recalls nothing
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'What\'s the GDP of Chile?'
Expected: []
Case 4: k limits the result
Input: memories = [{'id': 'm1', 'turn': 1, 'text': 'User\'s name is Priya and she lives in Lima.'}, {'id': 'm2', 'turn': 3, 'text': 'Priya prefers vegetarian restaurants.'}, {'id': 'm3', 'turn': 4, 'text': 'The user\'s flight to Tokyo departs on March 3.'}, {'id': 'm4', 'turn': 6, 'text': 'Priya moved from Lima to Paris last month.'}, {'id': 'm5', 'turn': 7, 'text': 'Weather in Paris was rainy during the last trip.'}] query = 'Priya Paris' k = 1
Expected: ['m4']