Series 3 - Bài 3: Context Architecture

Thứ tự các phần trong context window không ngẫu nhiên. LLM attend khác nhau theo vị trí. Bài này thiết kế context stack tối ưu cho coding agent.

Nghe bài viết này dưới dạng podcast

Bạn có thể có system prompt hoàn hảo, tool definitions tốt, và conversation history đầy đủ — nhưng nếu chúng nằm sai thứ tự trong context, agent sẽ hoạt động dưới mức tối ưu.

Context architecture là quyết định về thứ tự và tỷ lệ của từng phần — và nó không phải là detail nhỏ.

Tại sao thứ tự quan trọng

LLM không đọc context như human đọc một document rồi "nhớ" toàn bộ. Nó process theo attention mechanism — và attention không đồng đều theo vị trí:

 Position-based attention:

 TOP of context:
  ████████████████████ Strong attention
  → LLM dễ "nhớ" và follow

 MIDDLE of context (long docs):
  ████████░░░░░░░░░░░░ Weaker attention
  → "Lost in the middle" phenomenon
  → LLM có thể miss information ở đây

 BOTTOM of context:
  ████████████████████ Strong attention
  → LLM vừa đọc xong → fresh in "mind"
  → User message ở đây → thường được prioritize

Implication: Đặt critical instructions ở đầu và cuối. Đặt supportive context (file tree, history) ở giữa.

Context Stack chuẩn cho Coding Agent

┌─────────────────────────────────────────────────────────┐
│ 1. SYSTEM IDENTITY & CONSTRAINTS      [TOP — strong]    │
│    Role, behavior rules, hard constraints               │
│    Token budget: 1,000–3,000                            │
├─────────────────────────────────────────────────────────┤
│ 2. PROJECT CONTEXT                    [UPPER MIDDLE]    │
│    File tree, tech stack, conventions                   │
│    Token budget: 2,000–5,000                            │
├─────────────────────────────────────────────────────────┤
│ 3. LONG-TERM MEMORY / EPISODIC        [MIDDLE]          │
│    Relevant past sessions, key decisions                │
│    Token budget: 0–3,000 (optional)                     │
├─────────────────────────────────────────────────────────┤
│ 4. CONVERSATION HISTORY               [MIDDLE]          │
│    Previous turns, tool calls, results                  │
│    Token budget: 10,000–50,000 (variable)               │
├─────────────────────────────────────────────────────────┤
│ 5. CURRENT FILE CONTEXT               [LOWER MIDDLE]    │
│    Files relevant to current task                       │
│    Token budget: 5,000–30,000                           │
├─────────────────────────────────────────────────────────┤
│ 6. CURRENT USER MESSAGE               [BOTTOM — strong] │
│    What user just asked                                 │
│    Token budget: 100–2,000                              │
└─────────────────────────────────────────────────────────┘

Phân tích từng layer

Layer 1: System Identity & Constraints

Đây là nền tảng của mọi response. Đặt ở TOP vì:

  • LLM cần biết mình là ai trước khi xử lý bất cứ gì
  • Hard constraints cần được attention mạnh nhất
  • Nếu agent quên constraint ở giữa session, đây là lý do
[SYSTEM]
You are a senior TypeScript engineer on MSB lending system.
Never modify T24 integration files.
Always run tests before reporting completion.
If task is ambiguous, ask once before proceeding.

Layer 2: Project Context

File tree và conventions giúp LLM hiểu landscape mà không cần đọc từng file:

[PROJECT]
Stack: NestJS 10, TypeORM 0.3, Oracle 19c
Working dir: /project/msb-lending

structure:
src/
  loan/
    loan.service.ts
    loan.controller.ts
    loan.entity.ts
  payment/
    payment.service.ts

File tree compact giúp LLM biết đọc file nào mà không cần list_directory trước — tiết kiệm 1 round trip.

Layer 3: Long-term Memory (Optional)

Chỉ inject khi có relevance. Nếu user đang làm task liên quan đến payment, inject episodic memory về payment sessions:

[MEMORY]
Session 2025-05-20: Refactored payment.service.ts
  Decision: Dùng Strategy pattern cho payment methods
  Key files: payment.service.ts, payment-strategy.interface.ts

Không inject memory không liên quan — đó là noise.

Layer 4: Conversation History

History là phần lớn nhất và cũng cần được managed chủ động nhất. Đây là layer cần trim khi budget thấp.

Thứ tự history: chronological (cũ nhất trước, mới nhất sau) — để LLM có sense of progression.

Layer 5: Current File Context

Đặt ngay trước user message để tận dụng "bottom attention":

[FILES]
--- src/loan/loan.service.ts ---
[full file content]

--- src/loan/loan.entity.ts ---
[full file content]

Chỉ inject files thực sự cần cho task. Không inject toàn bộ codebase.

Layer 6: Current User Message

Bottom of context = strong attention. User message ở đây là đúng. LLM vừa đọc xong context đầy đủ và bắt gặp câu hỏi ngay sau — context tươi nhất trong tâm trí.

Anti-patterns

File context ở đầu, system prompt ở cuối

Sai:
  [File content 30,000 tokens]
  [History]
  [System prompt]  ← quá muộn, LLM có thể không follow tốt
  [User message]

History dài không có trimming

Sai:
  [System]
  [History: 100 turns, 80,000 tokens]
                ↑ LLM sẽ ignore phần giữa
  [User message]

Inject files không liên quan

Sai:
  [Files: toàn bộ src/ — 50 files, 200,000 tokens]
                ↑ Hầu hết là noise cho task hiện tại

Dynamic Context vs Static Context

Static (không thay đổi trong session):
  System prompt
  Project conventions
  → Inject một lần ở đầu

Dynamic (thay đổi theo task):
  File context
  Episodic memory
  → Rebuild mỗi turn dựa trên task hiện tại

Accumulative (grow theo thời gian):
  Conversation history
  Tool results
  → Trim khi cần

Trade-off: Rigid Structure vs Flexible

Rigid context structure:
  + Predictable behavior
  + Dễ debug (biết thứ tự cố định)
  + Consistent attention distribution
  - Không flexible với edge cases
  - Một số tasks có thể cần khác cấu trúc

Flexible context structure:
  + Adapt theo task
  - Harder to reason about behavior
  - Inconsistent across sessions

Bắt đầu với rigid structure. Chỉ introduce flexibility khi có specific use case đòi hỏi.

Kết luận

  • LLM attend mạnh hơn ở top và bottom của context — thiết kế dựa vào điều này.
  • Context stack chuẩn: System → Project → Memory → History → Files → User message.
  • System prompt ở top để enforce constraints sớm nhất.
  • Files ở ngay trước user message để tận dụng bottom attention.
  • History là layer lớn nhất và cần active trimming.
  • Dynamic injection (files, memory) theo task — không inject mọi thứ mọi lúc.
  • Bắt đầu rigid, introduce flexibility chỉ khi có specific need.

Chưa có bình luận

Để lại bình luận

Bình luận sẽ được phê duyệt trước khi hiển thị.

Nhận bài viết mới

Mình sẽ gửi email khi có bài mới. Không spam.