Code Generation — Từ Codex đến Cursor, cách LLM viết code
Giải mã cách AI viết code: từ autocomplete dựa trên probability đến agentic workflows với execution feedback. Tại sao code generation lại là 'low entropy canyon'?
Năm 2021, GitHub Copilot biến phím Tab từ một tính năng IDE vô thưởng vô phạt thành "cặp lập trình viên AI" có khả năng viết cả function chỉ từ comment tiếng Anh. Ba năm sau, Cursor và các công cụ agentic đi tiếp một bước: không chỉ gợi ý từng dòng, mà lập kế hoạch, thực thi, debug và refactor code trong kho lưu trữ hàng triệu dòng. Bước nhảy vọt này không đến từ model lớn hơn, mà từ sự chuyển đổi kiến trúc từ "predict next token" sang hệ thống multi-agent với tool use và execution feedback.
Vấn đề
Trước Codex, autocomplete trong IDE như VS Code hoặc IntelliJ dựa trên static analysis: regex, Abstract Syntax Tree (AST) parsing, và templates cứng nhắc. Chúng hiểu cú pháp nhưng không hiểu ngữ nghĩa (semantic)—chúng không biết ý định của bạn khi viết def calculate_fibonacci(n): là gì, chỉ biết rằng sau def cần một tên hàm. Điều này tạo ra "syntax lookup time"—những phút giây lãng phí để tra cứu tên hàm, tham số API, hoặc viết boilerplate code mà lẽ ra nên được tự động hóa.
Vấn đề sâu hơn nằm ở "context horizon". Code, không giống văn xuôi, mang tính modular với dependencies dài hạn—một class định nghĩa ở file A có thể quyết định behavior ở file B cách đó 300 dòng. Con người có thể nhảy qua lại giữa các file, nhưng model chỉ nhìn được 50-100 token (khoảng 2-3 dòng) thì bị "mù" với kiến trúc tổng thể. Để viết code đúng, AI cần nhìn thấy cả imports, type definitions, và business logic từ các file khác—đòi hỏi một "working memory" lớn hơn nhiều so với chế độ autocomplete truyền thống.
Ý tưởng cốt lõi
Cái hay của code generation nằm ở chỗ: code là "low entropy canyon".
Trong ngôn ngữ tự nhiên, câu "Hôm nay thời tiết..." có thể kết thúc bằng vô số cách (nắng, mưa, đẹp, tệ, ấm áp...). Entropy cao. Nhưng trong code, sau import pandas as pd; df = pd.read_csv(, xác suất cao nhất gần như chắc chắn là một chuỗi string chỉ đường dẫn file. Không có sáng tạo ở đây—chỉ có đúng hoặc sai theo grammar của Python. LLM khai thác điều này: thay vì "sáng tạo", nó "điền vào chỗ trống" (infilling) trong một không gian bị ràng buộc chặt chẽ bởi syntax và semantics của ngôn ngữ lập trình.
Nhưng đó chỉ là lớp vỏ. Bước nhảy từ Codex (2021) đến Cursor (2024) không phải từ việc model "thông minh hơn", mà từ việc context window trở thành "working memory".
Hãy tưởng tượng bạn đang viết code trong một codebase khổng lồ. Để quyết định "nên dùng list hay tuple?", bạn cần biết dữ liệu có immutable hay không—thông tin nằm trong định nghĩa class ở file khác. Cursor sử dụng RAG (Retrieval Augmented Generation) để embed toàn bộ repository, biến việc viết code từ "closed-book test" thành "open-book test"—model tra cứu định nghĩa hàm và type hint trong chính codebase của bạn trước khi generate, thay vì đoán mò từ training data.
Và rồi, tầng cao nhất là agentic workflows. CodeT và các hệ thống như Devin không chỉ generate rồi dừng lại; chúng đưa code vào vòng lặp: generate → execute (chạy compiler/test) → debug → regenerate. Đây là sự chuyển đổi từ "stochastic parrot" sang "trial-and-error reasoner"—biến code generation thành một search problem với verifiable reward (pass/fail của unit test). Điều này đặc biệt quan trọng trong cụm multi-agent, nơi code generation chỉ là một "agent" trong pipeline lớn hơn bao gồm planning, execution, và verification.
Khoảnh khắc "à ha": Code generation không phải là nghệ thuật sáng tạo như viết tiểu thuyết; nó là giải câu đố Sudoku với execution feedback. Model không cần "hiểu" thuật toán theo nghĩa triết học; nó chỉ cần tìm chuỗi token sao cho khi chạy qua Python interpreter, kết quả đúng. Sự "xác định tại chỗ" (local determinism) của code làm cho next-token prediction trở nên đáng tin cậy hơn nhiều so với văn xuôi.
Hiểu lầm phổ biến: Nhiều người nghĩ rằng AI "học thuộc lòng" code từ GitHub. Thực tế, nó học distribution của syntax và patterns—giống như học cách "lắc hông" để đi qua "canyon" của grammar rules, chứ không phải nhớ từng dòng code cụ thể. Khi bạn thấy AI viết đúng một hàm phức tạp, nó không nhớ hàm đó từ training data; nó đang "suy luận" từ context hiện tại dựa trên statistical patterns đã học.
Tại sao nó hoạt động
Toán học đằng sau là xác suất có điều kiện cực kỳ "nhọn" (sharply peaked). Với cùng một context, distribution P(next_token) trong code có entropy thấp hơn nhiều so với văn xuôi. Khi bạn viết def calculate_fibonacci(n):, chỉ có 2-3 cách viết canonical (recursive, iterative, matrix exponentiation). Model gán xác suất cao cho đúng pattern này và gần như loại bỏ các lựa chọn ngữ pháp sai.
Về kiến trúc, code generation hiện đại hoạt động qua ba lớp:
1. Pretraining trên The Stack (6TB code)
Model học syntax, idioms (list comprehension, decorator patterns), và API usage thông qua next-token prediction thuần túy. Đây là nơi nó nắm được "local determinism"—biết rằng sau ( thường là string, sau class là tên viết hoa.
2. RAG cho Codebase (Context Augmentation)
Embedding toàn bộ repository cho phép cross-file reference. Khi bạn viết self.user_manager., model tra cứu vector database của codebase để biết user_manager có method gì. Điều này giải quyết vấn đề "long-range dependencies" mà context window cố định không thể chứa. Chi tiết kỹ thuật retrieval được đề cập trong RAG.
3. Execution Feedback (Agentic Loop)
Trong agentic workflows (như Agentic AI & Tool Use), LLM gọi function execute_code() và nhận về lỗi compiler hoặc output. Điều này tạo vòng lặp perceive-reason-act, cho phép self-correction dựa trên ground truth thay vì chỉ dựa trán probability.
Pseudo-code cho agentic loop:
state = initial_prompt + codebase_context
for step in max_steps:
code = llm.generate(state)
result = execute(code) # Tool use
if result.success:
return code
else:
state += f"Error: {result.stderr}" # Feedback loopÝ nghĩa thực tế
So sánh với cách tiếp cận cũ:
| Feature | Static Analysis (IDE truyền thống) | LLM Code Generation |
|---|---|---|
| Context | File hiện tại | Toàn bộ repository + external docs |
| Understanding | Syntax tree | Semantic intent (natural language) |
| Feedback | Lint errors | Execution + Test results |
| Creativity | None (template-based) | Idiomatic code patterns |
| Long-range deps | Không | Có, thông qua RAG |
Số liệu benchmark:
- HumanEval: Đo khả năng viết function đơn lẻ. GPT-4 đạt ~67% pass@1, Claude 3.5 Sonnet ~92%, o1 ~97%+. Đây là bài kiểm tra "viết code từ docstring".
- SWE-bench: Đo khả năng sửa bug thực tế trên GitHub (multi-file, test suite phức tạp). Agent tốt nhất chỉ đạt ~50%—chứng tỏ khoảng cách giữa viết code snippet và làm việc với codebase production vẫn lớn, và tại sao chúng ta cần Multi-Agent Frameworks để phân chia planning và execution.
Hạn chế thành thật:
- Hallucination API: Model có thể gọi hàm đã deprecated hoặc tưởng tượng ra thư viện không tồn tại (ví dụ: inventing methods from
numpy). - Security: Nghiên cứu cho thấy Copilot có thể reproduce CVE ~40% thời gian—sinh code bảo mật kém nếu prompt liên quan đến lỗ hổng.
- Novel algorithms: Thất bại trên thuật toán chưa từng thấy trong training data (distribution shift)—AI giỏi "ghép patterns" nhưng kém "phát minh mới". Đây là lý do chúng ta cần Reasoning RL để tìm kiếm giải pháp ngoài distribution.
Đào sâu hơn
- Paper gốc: "Evaluating Large Language Models Trained on Code" (Codex, 2021) — arXiv:2107.03374 mở đầu cho kỷ nguyên này.
- Survey: "A Survey on Large Language Models for Code Generation" (2024) — arXiv:2406.00515.
- MCP for Code: MCP Protocol — Chuẩn hóa giao tiếp giữa AI và công cụ lập trình như compiler, debugger, và version control.
Cùng cụm (Multi-Agent):
- Mixture of Agents — Dùng ensemble LLM để review và tổng hợp code từ nhiều "chuyên gia" ảo, nâng cao chất lượng trước khi commit.
- Agentic AI & Tool Use — Chi tiết về cách LLM gọi function, thực thi code và lập kế hoạch multi-step trong vòng lặp ReAct.
- Multi-Agent Frameworks — AutoGen, CrewAI và kiến trúc society of mind cho dự án phần mềm phức tạp.
- LLM-as-Judge — Dùng LLM để đánh giá chất lượng code review và đảm bảo tiêu chuẩn trước khi merge.
Đọc tiếp:
- RAG — Retrieval Augmented Generation — Hiểu cách codebase được index và truy xuất để cung cấp context cho code generation.
- Benchmarks MMLU, HumanEval — Các bộ đo lường capability của model, bao gồm code generation và đánh giá an toàn.
- GRPO — RL for Reasoning — Tại sao reinforcement learning với verifiable reward (như pass/fail test) là chìa khóa cho agentic coding hiệu quả.
MCP — Model Context Protocol, chuẩn hoá tool use cho LLM
MCP là chuẩn kết nối 'USB-C' cho AI agents, giải quyết bài toán N×M integration hell khi mỗi LLM cần kết nối với hàng trăm tools.
ViT — Chia ảnh thành patch, self-attention cho vision
Vision Transformer (ViT) biến ảnh thành chuỗi patch 16×16, áp dụng self-attention toàn cục từ lớp đầu — giải phóng mô hình khỏi giới hạn của CNN, mở đường cho CLIP và Multimodal LLM.