Context engineering (kỹ thuật ngữ cảnh) là việc quyết định mọi thứ mà mô hình ngôn ngữ nhìn thấy khi trả lời: không chỉ câu hỏi bạn gõ, mà cả các chỉ dẫn xung quanh nó, các tài liệu và kết quả công cụ được chèn vào, bộ nhớ đã lưu về người dùng, và cuộc trò chuyện từ đầu đến giờ. Tất cả cùng chia sẻ một cửa sổ ngữ cảnh, và mô hình trả lời dựa trên văn bản đó chứ không gì khác. Thuật ngữ này phổ biến từ năm 2025, khi ngày càng nhiều sản phẩm AI trở thành agent tự động lắp ráp phần lớn ngữ cảnh của mình.
Prompt engineering chủ yếu là cách diễn đạt một yêu cầu. Context engineering là việc mô hình nên có những gì trước mặt trong mỗi lần gọi, và theo thứ tự nào.
Từ một prompt đến một ngữ cảnh
Trong một ứng dụng chat, bạn tự viết phần lớn ngữ cảnh: ứng dụng thêm system prompt và lịch sử, còn bạn thêm phần còn lại. Trong một ứng dụng tự xây, cán cân đảo ngược. Người dùng gõ một câu, và code xung quanh mô hình thêm chỉ dẫn, hồ sơ người dùng, ba bài trợ giúp tìm được qua tìm kiếm, danh sách công cụ có sẵn và đầu ra của lần gọi công cụ gần nhất. Câu của người dùng có thể chỉ là một phần nhỏ trong những gì mô hình đọc.
Khi một hệ thống như vậy trả lời kém, cách sửa hiếm khi nằm ở câu chữ. Nguyên nhân thường gặp là mô hình có sai tài liệu: thiếu một sự thật, một kết quả công cụ đã lỗi thời, một tài liệu không liên quan nhưng trông có vẻ liên quan với bộ tìm kiếm.
Những gì đi vào cửa sổ ngữ cảnh
Một lần gọi điển hình trong ứng dụng AI chứa một vài hoặc tất cả những thứ sau, theo thứ tự gần như thế này:
- Chỉ dẫn hệ thống: vai trò, quy tắc và định dạng đầu ra, thường cố định cho toàn bộ ứng dụng. Xem system prompt.
- Định nghĩa công cụ: tên, mô tả và tham số của các công cụ mà mô hình có thể gọi.
- Ví dụ: vài cặp đầu vào và đầu ra mẫu cho thấy hành vi mong đợi.
- Bộ nhớ: những sự thật được lưu từ các phiên trước, như gói của người dùng, ngôn ngữ hoặc sở thích.
- Tài liệu được truy xuất: các đoạn văn tìm được khi tìm kiếm trong cơ sở tri thức cho câu hỏi này (retrieval-augmented generation, hay RAG).
- Lịch sử trò chuyện: các lượt trước đó, giữ nguyên văn hoặc được tóm tắt.
- Kết quả công cụ: đầu ra từ các lần tìm kiếm, chạy code hoặc gọi API trong tác vụ này, như trong một vòng lặp ReAct.
- Tin nhắn hiện tại: điều người dùng vừa hỏi.
Khối bên dưới là một ngữ cảnh đã được lắp ráp cho một trợ lý hỗ trợ khách hàng. Hãy lần lượt tắt từng phần. Không có phần ngữ cảnh, mô hình không thể biết gói của khách hàng; không có phần đầu vào, nó không có thông tin sản phẩm nào, và phần ràng buộc yêu cầu nó nói rõ điều đó thay vì đoán.
Chào Dana, chế độ ngoại tuyến thuộc gói Pro, mà tài khoản của bạn hiện đang dùng gói Free, nên tạm thời bạn chưa dùng được tính năng này. Với Pro, các ghi chú bạn tạo trong chuyến bay sẽ tự động đồng bộ khi điện thoại kết nối lại. Có một giới hạn bạn nên biết: tệp đính kèm lớn hơn 20 MB không dùng được khi ngoại tuyến.
Để ý rằng câu trả lời đúng phụ thuộc vào việc kết hợp hai nguồn: bộ nhớ (gói Free) và một tài liệu (chế độ ngoại tuyến chỉ có ở Pro). Không nguồn nào tự nó là đủ, và điều này rất thường gặp. Phần lớn context engineering là đảm bảo những mảnh cần nhau đến cùng nhau.
Bốn cách một ngữ cảnh đi sai
- Thiếu thông tin. Mô hình lấp chỗ trống bằng phỏng đoán nghe hợp lý, và đó là nguồn gốc của nhiều ảo giác. Hãy thêm sự thật còn thiếu, hoặc cho mô hình biết phải làm gì khi thiếu một sự thật.
- Quá nhiều tài liệu. Mỗi đoạn văn không liên quan đều tốn token và tranh giành sự chú ý. Liu và cộng sự năm 2023, trong "Lost in the Middle: How Language Models Use Long Contexts", phát hiện các mô hình họ thử nghiệm dùng thông tin ở đầu hoặc cuối một đầu vào dài đáng tin cậy hơn thông tin ở giữa. Các mô hình mới hơn xử lý đầu vào dài tốt hơn, nhưng gửi vài đoạn trả lời đúng câu hỏi vẫn rẻ hơn, và dễ cho mô hình dùng hơn, so với dán cả cuốn hướng dẫn.
- Thông tin lỗi thời. Một kết quả công cụ từ mười bước trước có thể mô tả một tệp hay một số dư đã thay đổi từ lâu. Nếu mô hình thấy cả hai phiên bản, nó có thể dùng bản cũ.
- Mâu thuẫn. Hai tài liệu nói khác nhau, hoặc bộ nhớ nói một đằng còn người dùng nói một nẻo. Hãy cho mô hình biết nguồn nào được ưu tiên, ví dụ "tin nhắn mới nhất của người dùng được ưu tiên hơn bộ nhớ đã lưu".
Sắp xếp ngữ cảnh
Thứ tự ảnh hưởng đến cả kết quả lẫn chi phí.
- Phần ổn định đặt trước. Chỉ dẫn hệ thống, định nghĩa công cụ và tài liệu tham khảo cố định hiếm khi thay đổi giữa các lần gọi. Một số nhà cung cấp API có prompt caching, tính năng dùng lại phần xử lý cho phần đầu giống hệt nhau của đầu vào, nên một tiền tố không đổi giúp các lần gọi lặp lại rẻ hơn và nhanh hơn.
- Tài liệu dài đặt trước câu hỏi. Với một tài liệu dài hoặc một tập lớn các đoạn văn, hãy đặt tài liệu lên trước, câu hỏi và chỉ dẫn cuối cùng đặt sau. Chẳng hạn, hướng dẫn viết prompt của Anthropic khuyên dùng thứ tự này cho đầu vào dài, với câu hỏi nằm ngay trước chỗ mô hình bắt đầu viết.
- Gắn nhãn cho từng phần. Bọc mỗi nguồn trong các thẻ như
<document>,<memory>hoặc<tool_result>, kèm tên nguồn. Nhãn giúp mô hình phân biệt dữ liệu với chỉ dẫn, và cho phép bạn yêu cầu nó trích dẫn câu trả lời đến từ đâu. Bài dấu phân cách và thẻ XML trình bày các định dạng này.
Cắt gọn một ngữ cảnh dài
Mỗi lượt chat đều gửi lại toàn bộ lịch sử, nên các phiên dài cứ lớn dần cho đến khi phải bỏ bớt thứ gì đó. Tùy ứng dụng, nó có thể tóm tắt hoặc bỏ các tin nhắn cũ, hoặc yêu cầu bạn bắt đầu cuộc trò chuyện mới. Bạn sẽ có kết quả tốt hơn nếu chủ động cắt gọn.
- Giữ nguyên văn vài lượt gần nhất và thay các lượt cũ hơn bằng một bản tóm tắt.
- Khi một kết quả công cụ đã được dùng xong, thay nó bằng một ghi chú một dòng về những gì nó cho thấy.
- Giữ nguyên các định danh chính xác trong mọi bản tóm tắt: tên tệp, tên hàm, ID, thông báo lỗi và con số. Một bản tóm tắt ghi "tệp cấu hình" trong khi lịch sử ghi
settings.prod.yamlsẽ đánh mất đúng chi tiết quan trọng nhất. - Trong ứng dụng chat, khi cuộc trò chuyện đi lạc hướng, hãy bắt đầu cuộc trò chuyện mới với một ghi chú bàn giao. Prompt bên dưới sẽ viết ghi chú đó.
Mục tiêu: thay các bước kiểm tra viết tay của biểu mẫu đăng ký bằng một schema xác thực dùng chung cho cả trình duyệt và máy chủ.
Quyết định
- Một tệp schema duy nhất,
signupSchema.ts, được import bởiSignupForm.tsxvàapi/signup.ts, để hai bộ quy tắc không thể lệch nhau. - Thông báo lỗi giữ nguyên từng chữ, vì trung tâm trợ giúp có trích dẫn chúng.
Trạng thái hiện tại
- Phần xác thực trên trình duyệt đã dùng schema và
SignupForm.test.tsxchạy thành công. - Máy chủ vẫn gọi hàm cũ
validateSignup()trongapi/signup.ts.
Chi tiết chính xác: mật khẩu cần ít nhất 8 ký tự và một chữ số. Nội dung lỗi email: "Vui lòng nhập địa chỉ email hợp lệ."
Bước tiếp theo: thay validateSignup() bằng schema và chạy các test API.
Câu hỏi bỏ ngỏ: email đã đăng ký nên trả về 409 hay 400?
Bộ nhớ qua các phiên
Bộ nhớ là ngữ cảnh tồn tại lâu hơn một cuộc trò chuyện: những sự thật được ghi vào kho lưu trữ khi một phiên kết thúc và được nạp vào phiên tiếp theo. Các ứng dụng chat có những phiên bản của tính năng này, như bộ nhớ đã lưu hoặc chỉ dẫn dự án được thêm vào mọi cuộc chat trong một dự án. Trong ứng dụng của riêng bạn, bộ nhớ là một bảng hoặc một tệp ghi chú mà code của bạn đọc và chèn vào. Hai quy tắc giúp bộ nhớ hữu ích: lưu những sự thật luôn đúng (gói, ngôn ngữ, công nghệ yêu thích), không lưu nguyên văn các cuộc trò chuyện; và chỉ nạp những gì liên quan đến tác vụ hiện tại, vì bộ nhớ tranh giành cùng một không gian với mọi thứ khác.
Lắp ráp ngữ cảnh bằng code
Trong một ứng dụng, context engineering là code bình thường. Bản phác thảo dùng Anthropic Python SDK này đặt các quy tắc cố định và bộ nhớ vào system prompt, chỉ giữ lịch sử gần đây, và đặt các tài liệu có gắn nhãn trước câu hỏi.
import anthropic
client = anthropic.Anthropic()
MODEL = "your-model-id" # e.g. from your provider's model list
def build_context(question, docs, history, memory, max_messages=6):
documents = "\n".join(
f'<document source="{d["source"]}">\n{d["text"]}\n</document>' for d in docs
)
system = (
"You are the support assistant for Acme Notes. Answer only from the documents. "
"If they do not cover the question, say so.\n"
f"<memory>\n{memory}\n</memory>"
)
# history holds complete user/assistant pairs, so an even slice starts with a user turn
recent = history[-max_messages:]
user = f"<documents>\n{documents}\n</documents>\n\n{question}"
return system, recent + [{"role": "user", "content": user}]
# question, docs, history and memory come from your application
system, messages = build_context(question, docs, history, memory)
response = client.messages.create(model=MODEL, max_tokens=1024, system=system, messages=messages)
print(response.content[0].text)
Mỗi quyết định trong hàm đó (tài liệu nào, bao nhiêu tin nhắn, bộ nhớ đặt ở đâu) là một lựa chọn context engineering, và mỗi lựa chọn đều đáng được thử nghiệm trên các câu hỏi thật, giống như cách bạn thử nghiệm một thay đổi về câu chữ.
Câu hỏi thường gặp
Context engineering là gì?
Context engineering là công việc chọn lọc, sắp xếp và cắt gọn mọi thứ mà mô hình ngôn ngữ nhận được trong một lần gọi: chỉ dẫn hệ thống, ví dụ, tài liệu được truy xuất, định nghĩa và kết quả của công cụ, bộ nhớ đã lưu, lịch sử trò chuyện và tin nhắn của người dùng. Mô hình chỉ trả lời dựa trên văn bản đó, nên những gì có trong đó, và những gì bị bỏ ra, quyết định chất lượng câu trả lời.
Context engineering và prompt engineering khác nhau thế nào?
Prompt engineering chủ yếu là cách diễn đạt chỉ dẫn. Context engineering bao quát toàn bộ đầu vào, phần lớn trong đó được code lắp ráp chứ không phải do người gõ: truy xuất tài liệu nào, giữ kết quả công cụ nào, đưa vào bao nhiêu lịch sử và theo thứ tự nào. Trong một cuộc chat, bạn tự viết phần lớn ngữ cảnh; trong một ứng dụng hay một agent, phần lớn ngữ cảnh do hệ thống xung quanh mô hình chọn.
Có phải càng nhiều ngữ cảnh càng tốt?
Không. Tài liệu không liên quan hoặc đã lỗi thời cạnh tranh với những phần quan trọng, tốn token, và có thể mâu thuẫn với trạng thái hiện tại. Các nghiên cứu về đầu vào dài đã phát hiện mô hình có thể bỏ sót thông tin nằm ở giữa một ngữ cảnh dài. Hãy đưa vào những gì tác vụ cần, gắn nhãn cho chúng, và bỏ đi những gì không còn cần nữa.
Vì sao một cuộc trò chuyện dài lại kém dần theo thời gian?
Toàn bộ cuộc trò chuyện được gửi lại ở mỗi lượt, nên những lỗi cũ, ý tưởng đã bỏ và code đã bị thay thế vẫn nằm trong ngữ cảnh và tiếp tục ảnh hưởng đến câu trả lời. Khi cuộc trò chuyện vượt quá cửa sổ ngữ cảnh, ứng dụng phải bỏ bớt hoặc tóm tắt các tin nhắn cũ. Bắt đầu một cuộc trò chuyện mới với bản tóm tắt ngắn về các quyết định và trạng thái hiện tại thường hiệu quả hơn là tiếp tục.
RAG trong context engineering là gì?
RAG (retrieval-augmented generation, sinh văn bản có tăng cường truy xuất) là việc tìm trong tài liệu của chính bạn những đoạn liên quan đến câu hỏi và chèn chúng vào ngữ cảnh trước khi mô hình trả lời. Đây là một trong những công cụ chính của context engineering: mô hình nhận được những sự thật cụ thể, cập nhật mà nó không thể biết từ dữ liệu huấn luyện, và bạn có thể yêu cầu nó chỉ trả lời dựa trên các đoạn đó.