Memory Augmentation › A Worked Example: Document QA with Memory

Michael BrenndoerferUpdated July 8, 20254 min read
Language AI HandbookAll chapters
Part 18 of 67Long Context
Chapter 131Memory Augmentation › A Worked Example: Document QA with Memory
Reading section 7 of 12 · A Worked Example: Document QA with Memory · 4 minSection 7 of 12 · 4 min

Book contents

Section 7 of 12 · 4 min read

Memory Augmentation › A Worked Example: Document QA with MemoryOne section · Sections in this chapter7 / 12 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Let's build a complete example of using memory augmentation for question answering over a long document. We'll process the document in chunks, store key information to memory, and then query that memory to answer questions.

In[32]:
Code
class DocumentMemoryQA:
    """
    Memory-augmented document QA system.

    Processes documents in chunks, storing important information
    to memory, then retrieves relevant context for questions.
    """

    def __init__(
        self, chunk_size=100, memory_size=1000, key_dim=64, value_dim=128
    ):
        self.chunk_size = chunk_size
        self.key_dim = key_dim
        self.value_dim = value_dim

        # Memory storage
        self.memory_keys = []
        self.memory_values = []
        self.memory_texts = []  # Store original text for interpretability
        self.memory_size = memory_size

        # Simple encoder (in practice, would be a trained model)
        self.key_encoder = nn.Linear(100, key_dim)  # Simplified
        self.value_encoder = nn.Linear(100, value_dim)

    def encode_text(self, text):
        """Simple bag-of-chars encoding for demonstration."""
        # Create fixed-size representation
        chars = [ord(c) % 100 for c in text[:100]]
        chars = chars + [0] * (100 - len(chars))
        return torch.tensor(chars, dtype=torch.float32)

    def process_document(self, document):
        """Process document into memory chunks."""
        words = document.split()

        for i in range(0, len(words), self.chunk_size):
            chunk = " ".join(words[i : i + self.chunk_size])
            if len(chunk.strip()) == 0:
                continue

            # Encode chunk
            encoded = self.encode_text(chunk)
            key = self.key_encoder(encoded)
            value = self.value_encoder(encoded)

            # Store
            self.memory_keys.append(key)
            self.memory_values.append(value)
            self.memory_texts.append(chunk)

        # Truncate if needed
        if len(self.memory_keys) > self.memory_size:
            self.memory_keys = self.memory_keys[-self.memory_size :]
            self.memory_values = self.memory_values[-self.memory_size :]
            self.memory_texts = self.memory_texts[-self.memory_size :]

    def query(self, question, top_k=3):
        """Query memory for relevant context."""
        if not self.memory_keys:
            return []

        # Encode question
        q_encoded = self.encode_text(question)
        q_key = self.key_encoder(q_encoded)

        # Compute similarities
        keys_tensor = torch.stack(self.memory_keys)
        scores = torch.matmul(q_key, keys_tensor.T)

        # Get top-k
        k = min(top_k, len(self.memory_keys))
        topk_scores, topk_indices = torch.topk(scores, k)

        # Return relevant chunks
        results = []
        for idx, score in zip(topk_indices.tolist(), topk_scores.tolist()):
            results.append(
                {"chunk": self.memory_texts[idx], "score": score, "index": idx}
            )

        return results


# Create a sample document
sample_document = """
The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France. 
It is named after the engineer Gustave Eiffel, whose company designed and built the tower. 
Locally nicknamed "La dame de fer" (French for "Iron Lady"), it was constructed from 1887 to 1889 
as the entrance arch for the 1889 World's Fair. The tower is 330 metres tall, about the same 
height as an 81-storey building, and the tallest structure in Paris. Its base is square, 
measuring 125 metres on each side. During its construction, the Eiffel Tower surpassed the 
Washington Monument to become the tallest human-made structure in the world, a title it held 
for 41 years until the Chrysler Building in New York City was finished in 1930.

The tower has three levels for visitors, with restaurants on the first and second levels. 
The top level's upper platform is 276 metres above the ground, the highest observation deck 
accessible to the public in the European Union. Tickets can be purchased to ascend by stairs 
or lift to the first and second levels. The climb from ground level to the first level is 
over 300 steps, as is the climb from the first level to the second. Although there is a 
staircase to the top level, it is usually accessible only by lift.
"""

# Process document and query
qa_system = DocumentMemoryQA(chunk_size=50)
qa_system.process_document(sample_document)
In[33]:
Code
# Ask questions
questions = [
    "How tall is the Eiffel Tower?",
    "Who designed the tower?",
    "How many steps to climb?",
]

query_results = []
for q in questions:
    results = qa_system.query(q, top_k=2)
    query_results.append({"question": q, "results": results})
Out[34]:
Console
Document Memory QA Demonstration

Document processed into 5 memory chunks
============================================================

Question: How tall is the Eiffel Tower?
----------------------------------------
  Retrieved #1 (score: 6120.13):
    "The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, ..."
  Retrieved #2 (score: 3925.87):
    "tallest human-made structure in the world, a title it held for 41 years until th..."

Question: Who designed the tower?
----------------------------------------
  Retrieved #1 (score: 3707.34):
    "The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, ..."
  Retrieved #2 (score: 377.85):
    "entrance arch for the 1889 World's Fair. The tower is 330 metres tall, about the..."

Question: How many steps to climb?
----------------------------------------
  Retrieved #1 (score: 8241.50):
    "The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, ..."
  Retrieved #2 (score: 5158.49):
    "tallest human-made structure in the world, a title it held for 41 years until th..."

The retrieval scores indicate how well each memory chunk matches the question. Higher scores suggest stronger relevance. For the question about height, the system successfully retrieves chunks containing the phrase "330 metres tall." The simple bag-of-characters encoding used here provides only basic matching. A production system would use learned embeddings that capture semantic similarity rather than surface-level character overlap.

The QA system demonstrates the core memory augmentation workflow: process a document into memory chunks, then query memory to find relevant context for answering questions. In a real system, the encoder would be a trained transformer, and the question answering would combine retrieved context with a generative model.