Bạn gửi một yêu cầu, và chỉ một giây sau, câu trả lời bắt đầu hiện ra trong terminal. Không phải hiện ra cả khối, mà được gõ dần: từng mẩu một, như thể có ai đó đang gõ nó ngay lúc này. Đôi khi trước đó trên màn hình hiện chữ Thinking, câu trả lời đến chậm hơn hẳn, nhưng bù lại thấu đáo hơn.

Tất cả những điều này đều là hệ quả của một cơ chế duy nhất. Hãy cùng xem mô hình ngôn ngữ lớn hoạt động ra sao: nó làm gì với văn bản của bạn, đo độ dài văn bản bằng gì, kiến thức của nó đến từ đâu và điều gì diễn ra trong những giây nó suy nghĩ. Để nhấn Enter thì không cần biết điều nào trong số này. Nhưng gộp lại, chúng thay đổi đáng kể điều bạn chờ đợi ở câu trả lời.

Truyện tranh: một người đang sơn hàng rào và chỉ cho một robot cách làm, nhưng robot lại bắt chước hình các vệt cọ thay vì sơn từng tấm ván
Mọi thứ ở đây được đơn giản hóa đến mức nào

Bài viết được cố ý đơn giản hóa. Nhờ vậy nó đọc nhanh và trả lời được câu hỏi điều gì đang diễn ra trên màn hình của bạn. Ở đây không có và cũng không thể có một phân tích chính xác - riêng một khối transformer thôi đã đủ cho cả một công trình riêng.

Mô hình ngôn ngữ ước lượng phần tiếp theo

Trước hết, hãy nói rõ ta đang bàn về cái gì. Mô hình ngôn ngữ lớn, hay LLM, viết tắt của large language model, không phải chương trình có cửa sổ và nút bấm, cũng không phải một ứng dụng chat. Đó là một cơ chế được gọi tới: người ta đưa cho nó văn bản của cuộc trò chuyện, nó trả về phần tiếp theo. Claude Code, web chat, gợi ý trong trình soạn thảo - tất cả đều là lớp vỏ bao quanh những lần gọi như vậy, và lớp vỏ ở mỗi nơi một khác.

Còn bản thân mô hình chỉ biết làm một việc: từ phần đầu của văn bản, ước lượng xem phần tiếp theo nào có khả năng cao hơn. Không phải tìm ra câu trả lời đúng, mà là ước lượng xác suất - và không chỉ cho một phương án, mà cho từng phương án có trong từ điển của nó.

Dễ thấy điều này nhất là qua một câu ngắn. Hãy nói tiếp thành tiếng: "Tôi uống cà phê không..." Từ bật ra đầu tiên là "đường", sau đó là "sữa", còn "internet" thì chẳng khớp chút nào, dù về ngữ pháp vẫn ổn. Bạn ước lượng điều đó trong tích tắc, không cần nghĩ. Mô hình cũng làm y như vậy, chỉ có điều làm một cách hình thức và đến cùng: đi qua toàn bộ từ điển và gán cho mỗi ứng viên một con số.

Mô hình ước lượng các phương án nối tiếp câu: sau "Tôi uống cà phê không", phương án "đường" rất có khả năng, "sữa" cũng hay gặp, "internet" gần như không bao giờPhần đầu câuTôi uống cà phê khôngđườngrất có khả năngsữacũng hay gặpinternetgần như không bao giờ
Mỗi phương án có điểm ước lượng riêng. Không phương án nào mang nhãn "đúng"

Hãy để ý xem sơ đồ thiếu điều gì. Không phương án nào được đánh dấu là đúng: chỉ có những phần tiếp theo khả năng cao hơn và thấp hơn. Và những con số này không đến từ việc đếm xem tổ hợp từ đó đã gặp bao nhiêu lần trong các văn bản - đó là cách làm của một công nghệ hoàn toàn khác, đơn giản hơn nhiều, đã bị bỏ từ lâu trước các mô hình ngày nay. Xác suất được tính theo những quy luật đã được ghi lại bên trong mô hình trong quá trình huấn luyện. Chính vì thế mà nó tính được cả cho những câu chưa ai từng viết trước bạn.

LLM khác với chat và agent như thế nào

Ba từ này hay được dùng như từ đồng nghĩa, dù chúng mô tả những lớp khác nhau của hệ thống.

  • LLM - chính mô hình ngôn ngữ. Nhận ngữ cảnh và sinh ra tin nhắn tiếp theo.
  • Chat - giao diện và chương trình bao quanh LLM. Nó lưu lịch sử, tạo yêu cầu, gửi cho mô hình và hiển thị câu trả lời.
  • Agent - LLM có mục tiêu, vòng lặp làm việc và công cụ. Nó có thể nhờ ứng dụng đọc file, tìm kiếm hoặc chạy test, xem kết quả rồi chọn bước tiếp theo.
Sơ đồ đơn giản của ba lớp lồng nhau: bên trong agent là chat, và bên trong chat là mô hình ngôn ngữ. LLM sinh ra tin nhắn, chat thêm lịch sử và giao diện, agent thêm mục tiêu, vòng lặp làm việc, công cụ và quyền hạnAgentmục tiêu · vòng lặp làm việc · công cụ · quyền hạnChatgiao diện · lịch sử · tạo ngữ cảnhLLMngữ cảnh → tin nhắn tiếp theoMỗi lớp bên ngoài bổ sung khả năng quanh mô hình
LLM là lõi; chat và agent bổ sung khả năng riêng của chúng quanh mô hình

Nói ngắn gọn: LLM đưa ra quyết định, chat tổ chức cuộc trò chuyện, agent nối các quyết định của mô hình với hành động ở thế giới bên ngoài.

Token, không phải từ

Sơ đồ ở trên cần một chỗ đính chính: các từ nằm nguyên vẹn trên đó chỉ để dễ hình dung. Thực tế, mô hình tách văn bản thành các token - những mẩu lấy từ từ điển riêng của nó. Một token có thể là cả một từ, một phần của từ hoặc một dấu câu, còn khoảng trắng thường bị gộp vào token đứng sau và không được tính là một đơn vị riêng.

Từ điển được xây dựng từ trước, trên một tập văn bản lớn, và xây dựng dần dần: thuật toán tìm những chuỗi ký tự hay gặp và ghép chúng thành các mẩu lớn hơn. Cái gì gặp nhiều thì được một token riêng. Vì vậy trong từ điển hoàn chỉnh có lẫn lộn cả từ nguyên vẹn lẫn mảnh của từ.

Mỗi token trong từ điển có một số hiệu riêng, và văn bản đi vào mô hình dưới dạng các con số: trước tiên chuỗi được cắt thành từng mẩu, sau đó mỗi mẩu được thay bằng số hiệu của nó. Theo chiều ngược lại, câu trả lời được chuyển về văn bản đọc được bằng chính từ điển đó.

Cùng một ý tưởng trên hai ngôn ngữ: cụm từ tiếng Anh "coffee every morning" chia thành ba token, tiếng Việt "cà phê mỗi sáng" cũng ba từ nhưng thành năm. Khoảng trắng được vẽ bằng hình chữ nhật xám bên trong token mà nó đứng trướcTiếng Anh3 từ, 3 tokenTiếng Việt3 từ, mà đã thành 5 tokencoffeeeverymorningcàphêmỗisáng
Hình chữ nhật xám là khoảng trắng: nó không mất đi đâu cả, mà nằm vào trong token đứng sau. Cách tách chỉ mang tính minh họa, mỗi mô hình có từ điển riêng

Từ đây có hai điều nên ghi nhớ. Thứ nhất: mỗi họ mô hình có từ điển riêng, nên cùng một chuỗi sẽ bị cắt theo những cách khác nhau, còn những ước lượng kiểu "một token xấp xỉ ba phần tư một từ" chỉ là mốc thô cho tiếng Anh, không hơn. Thứ hai: ngôn ngữ nào ít xuất hiện trong văn bản huấn luyện thì bị cắt vụn hơn. Một từ tiếng Việt thường vỡ thành hai, ba token ở chỗ mà từ tiếng Anh gói gọn trong một.

Chuyện này nhìn tận mắt một lần thì dễ hiểu hơn đọc. Hãy mở The Tokenizer Playground, dán vào vài yêu cầu quen thuộc của bạn, rồi dán tiếp chính nội dung đó bằng tiếng Anh - bạn sẽ thấy ngay chuỗi bị vỡ thành những mẩu nào và bao nhiêu mẩu. Chỉ có một lưu ý: tokenizer ở đó thuộc về một mô hình cụ thể, còn mô hình bạn đang dùng sẽ tách theo cách riêng của nó. Nên vào đó để thấy hiện tượng, chứ không phải để lấy con số chính xác.

Hệ quả thực tế của điều này khá bất ngờ. Mô hình không thấy chữ cái mà thấy các mẩu, nên câu hỏi về chữ cái khó với nó hơn hẳn câu hỏi về ý nghĩa. Nhờ nó đếm xem trong một từ dài có bao nhiêu chữ "o", và rất có thể câu trả lời sẽ sai. Không phải vì bài toán khó, mà vì từ đó đến với mô hình thành hai mẩu, và với nó không có những chữ cái riêng lẻ bên trong.

Câu trả lời được ghép từ token như thế nào

Giờ hãy ghép cả cơ chế lại, và nó hóa ra đơn giản hơn bạn nghĩ. Mô hình ước lượng các phương án, một phương án được chọn và nối vào cuối văn bản. Sau đó mọi thứ bắt đầu lại từ đầu - với chính văn bản ấy, chỉ dài hơn một token.

Ba bước sinh liên tiếp: vào câu "Tôi uống cà phê không" được nối thêm token "đường", vào câu vừa có - token "đã", rồi token "mười"Phần đã viếtToken tiếp theoMỗi token vừa chọn lại trở thành đầu vào của bước kế tiếpTôi uống cà phê khôngTôi uống cà phê không đườngTôi uống cà phê không đường đãđườngđãmười
Câu trả lời không có sẵn: nó lớn dần từng token một, và mỗi token mới ảnh hưởng đến token sau

Câu trả lời hoàn chỉnh không nằm sẵn ở đâu và cũng không được lấy ra từ đâu - nó được ghép qua đúng số bước bằng số token trong nó. Việc dừng lại cũng không theo đồng hồ: đến một lúc nào đó, phần tiếp theo có khả năng nhất lại là một token đặc biệt mang nghĩa "hết ở đây", và quá trình sinh dừng lại.

Cũng từ hình trên còn rút ra một chi tiết nữa. Mô hình không thể xóa những gì đã viết: token nào đã vào văn bản thì ở lại đó và trở thành đầu vào của mọi bước sau. Nó chỉ có thể tự sửa đúng như con người khi nói chuyện - bằng câu tiếp theo.

Còn đây là hệ quả khiến nhiều người ngạc nhiên: cùng một câu hỏi, hỏi hai lần, có thể nhận hai câu trả lời khác nhau. Ở mỗi bước, lựa chọn không nhất thiết rơi vào phương án có khả năng nhất, và chỉ một token rẽ khác là kéo theo mọi thứ phía sau. Thường thì chỉ cách diễn đạt thay đổi, nhưng đôi khi cả giải pháp được đề xuất cũng khác.

Điều gì xảy ra trong terminal

Việc câu trả lời hiện dần trong cửa sổ Claude Code không phải là hiệu ứng đang tải, mà chính là các bước sinh: mô hình trả token ra ngay khi chọn xong, còn chương trình lập tức in chúng lên màn hình. Vì thế câu trả lời dài mới hiện ra dần dần, chứ không bật ra nguyên khối sau một khoảng chờ.

Vì sao mô hình được gọi là lớn

Chữ "lớn" không nói về dung lượng của một file nằm đâu đó. Đằng sau nó là hai thang đo hoàn toàn khác, và cả hai đều nên hình dung cho đúng.

Thang đo thứ nhất là lượng văn bản mô hình đã đi qua khi huấn luyện: sách, bài báo, tài liệu, diễn đàn, code, và tất cả với khối lượng mà một người đọc mấy đời cũng không hết. Thang đo thứ hai là số tham số. Tham số là một con số bên trong mô hình, một trong những thiết lập được tinh chỉnh dần trong lúc huấn luyện. Có hàng tỷ tham số như vậy. Các mô hình mở ghi thẳng con số này vào tên: 7B, 14B, 70B, trong đó B là billion, tức một tỷ.

Đến đây là chỗ dễ nhầm. Số tham số không phải là bảng xếp hạng chất lượng. Kết quả phụ thuộc cả vào dữ liệu mô hình được học, vào cấu trúc của nó, vào loại việc nó được tối ưu cho, lẫn vào cách nó bị nén lại để vừa chạy ở đâu đó. Một mô hình nhỏ hơn hoàn toàn có thể vượt mô hình lớn hơn ở một việc cụ thể. Con số lớn trong tên, tự nó, chẳng hứa hẹn điều gì.

Và còn một điều nữa, ở quy mô như vậy dường như tự nó mà thành. Để nói tiếp trôi chảy một câu về test bị fail, biết những từ nào hay đứng cạnh nhau là chưa đủ. Còn phải nắm được test được tổ chức ra sao. Mô hình học đoán từ, và trên đường đi, những gì được mô tả bằng các từ đó cũng được ghi lại trong tham số của nó. Cảm giác "nó hiểu biết" đến từ đây, dù cơ chế không đổi lấy một bước.

Kiến thức của mô hình đến từ đâu

Nguồn chỉ có đúng hai, và nhầm lẫn giữa chúng thì cái giá khá đắt.

Nguồn thứ nhất là tham số. Trong đó ghi lại những quy luật học được khi huấn luyện. Đây không phải một tủ phiếu mà mỗi phiếu đều ghi rõ nguồn: kiến thức bị trải ra trên vô số con số, và không thể rút ra từ đó một trích dẫn chính xác. Vì vậy mô hình có thể đưa ra thứ gần đúng: hình thức chuẩn, cái tên quen, nhưng chi tiết cụ thể lại sai.

Nguồn thứ hai là những gì đang nằm trong cuộc trò chuyện ngay lúc này: yêu cầu của bạn, mọi thứ đã nói trước đó, nội dung các file đã mở, đầu ra của các lệnh đã chạy. Nguồn này chính xác nhưng ngắn hạn. Nó không chuyển vào tham số, và cuộc trò chuyện sau sẽ không biết gì về nó.

Mọi thứ khác mà bạn muốn gọi là một nguồn riêng - file bộ nhớ, tài liệu tìm được, câu trả lời của một dịch vụ bên ngoài - đều đi qua đúng con đường này: trước tiên vào cuộc trò chuyện, rồi mới ảnh hưởng đến câu trả lời. Mô hình không có cánh cửa riêng nào dẫn vào dự án hay internet.

Nguồn thứ nhất có một mốc thời gian, và mốc đó có tên - knowledge cutoff. Đây là mốc cho biết kiến thức sẵn có của mô hình thường còn cập nhật đến thời điểm nào. Về một thư viện ra mắt sau mốc này, mô hình chỉ biết đúng những gì đã được đưa vào cuộc trò chuyện hiện tại.

Ở đây lời lưu ý còn quan trọng hơn chính mốc thời gian. Cutoff không có nghĩa là trước ngày đó mô hình biết tất cả, còn sau đó thì không biết gì. Ngay trong khoảng thời gian ấy vẫn có lỗ hổng: về chủ đề này thì ít văn bản, chủ đề kia thì các văn bản mâu thuẫn nhau, có thứ đơn giản là không lọt vào dữ liệu huấn luyện. Mốc này đặt ra giới hạn trên, chứ không hứa hẹn sự đầy đủ bên dưới nó.

Và một điều nhỏ nhưng có ích. Hỏi chính mô hình về cutoff của nó là ý không hay: nó sẽ trả lời bằng cách sinh văn bản, tức là chọn ra điều nghe có vẻ hợp lý. Mốc chính xác nằm trong tài liệu của từng phiên bản cụ thể, và các mô hình cạnh nhau trong cùng một họ hoàn toàn có thể có mốc khác nhau.

Thinking có nghĩa là gì

Khi trên màn hình hiện Thinking, mô hình không chuyển sang một trạng thái ý thức nào khác. Nó chỉ được cho thêm chỗ để suy nghĩ trước khi bắt đầu trả lời. Về kỹ thuật, đó vẫn chính là quá trình sinh văn bản: trước tiên mô hình viết một bản nháp cho riêng mình - phân tích bài toán, cân nhắc các phương án, tự tranh luận với bản thân - rồi mới đưa ra văn bản cuối cùng. Suy nghĩ bao nhiêu thì phần lớn do các mô hình hiện đại tự quyết: với câu hỏi đơn giản, bản nháp ngắn hoặc không có, với câu hỏi rối rắm thì dài hơn.

Một yêu cầu có thể đi thẳng tới câu trả lời nhanh hoặc đi qua bước phân tích bài toán và kiểm tra trước khi có câu trả lời cuối cùngMột yêu cầu - ngân sách khác nhau trước câu trả lờiNhanhYêu cầuCâu trả lời nhanhThinkingYêu cầuPhân tíchKiểm traTrả lờiCon đường thứ hai tốn nhiều thời gian và token hơn trước câu trả lời cuối cùng
Cùng một yêu cầu có thể nhận câu trả lời nhanh hoặc được thêm thời gian để phân tích và kiểm tra

Cái này để làm gì thì xem qua một ví dụ sẽ rõ. Agent đang tìm nguyên nhân khiến một test bị fail. Lời giải thích hợp lý đầu tiên chỉ vào client gọi tới một dịch vụ bên ngoài, nhưng test bên cạnh và nội dung lỗi lại nói điều khác: vấn đề nằm ở khâu parse dữ liệu. Có dư chỗ để suy nghĩ, mô hình kịp nhận ra mâu thuẫn và đổi hướng trước khi đề xuất bản sửa. Cái lợi ở đây không nằm ở độ dài của lập luận, mà ở chỗ bước kiểm tra đã thay đổi bước tiếp theo.

Nói chung, lời giải thích đầu tiên khá thường xuyên hóa ra không đúng. Nó nghe hợp lý, nhưng nghe hợp lý chính là tiêu chí mà cơ chế dùng để chọn ra nó.

Giờ đến chuyện khi nào suy luận thêm là đáng. Nó tốn thời gian, và bật nó cho mọi việc vặt thì chẳng để làm gì.

Thường chỉ cần câu trả lời nhanhNên cho mô hình chỗ để suy luận
giải thích đoạn code trên màn hình làm gìtìm nguyên nhân test bị fail khi liên quan đến nhiều file
sửa lỗi chính tả hoặc định dạngso sánh hai giải pháp cùng với những giới hạn của chúng
tóm tắt lại đoạn văn bạn vừa đưalên kế hoạch refactor mà các bước phụ thuộc lẫn nhau

Mốc để dựa vào rất đơn giản: bài toán càng nhiều ngã rẽ và phụ thuộc thì càng nên để mô hình suy nghĩ rộng ra. Còn với việc đổi tên một biến, xem ngay kết quả sẽ nhanh hơn là đọc cả bài suy luận về nó.

Và một giới hạn cần nói thẳng. Phần suy luận được hiển thị không phải bản ghi chính xác những gì diễn ra bên trong; thường nó là bản tóm lược được soạn cho người đọc. Một chuỗi suy luận dài và mạch lạc hoàn toàn có thể xuất phát từ một tiền đề sai, và chính vì thế trông đáng tin hơn thực tế. Cũng có chiều ngược lại: đáp án đã tìm ra, nhưng mô hình vẫn tiếp tục nghi ngờ, đi vòng vòng và tự làm rối mình. Hiện tượng này thậm chí có tên riêng - overthinking.

Điều gì hiệu quả hơn câu "hãy nghĩ cho kỹ"

Nhờ mô hình nghĩ lâu hơn là một đòn bẩy yếu: bản thân độ dài của bản nháp không cải thiện được gì. Hiệu quả hơn nhiều là một mục tiêu rõ ràng, các ràng buộc được nêu cụ thể và một dấu hiệu dễ hiểu cho biết bài toán đã được giải xong. Khi đó mô hình mới có cái để đối chiếu trong chính suy luận của mình.

Mô hình không thể làm gì

Danh sách không dài, và tốt nhất là biết nó từ trước, thay vì phát hiện ra giữa một task thật.

  • Đảm bảo một thông tin là đúng. Cơ chế chọn phần tiếp theo có khả năng cao, chứ không đối chiếu khẳng định với nguồn. Những chi tiết bịa ra nhưng nghe hợp lý được gọi là ảo giác.
  • Không phụ thuộc vào cách diễn đạt. Đảo vài chữ hay thêm một chi tiết làm rõ là câu trả lời đã khác, vì mọi thứ được quyết định bởi phần văn bản đứng trước chỗ đó.
  • Tự mình cập nhật kiến thức mới. Không có nguồn bên ngoài thì kiến thức sẵn có không được làm mới: về bản phát hành hôm qua của một thư viện, mô hình chỉ biết những gì người ta cho nó xem.
  • Lặp lại y nguyên từng chữ. Cùng một yêu cầu có thể cho ra kết quả khác nhau, và đó là đặc tính của cơ chế, chứ không phải trục trặc.
  • Thoát khỏi những thiên lệch của văn bản gốc. Điều gì ở đó được mô tả phiến diện hoặc hoàn toàn không được mô tả thì cũng sẽ vọng lại trong câu trả lời.

Gần như mọi thứ mọc lên quanh các mô hình đều là lời đáp cho một điểm nào đó trong danh sách này. Tìm kiếm và làm việc với tài liệu xuất hiện vì kiến thức sẵn có bị lỗi thời. Công cụ và agent - vì tự bản thân mô hình chỉ biết nói.

Cơ chế này giải thích gì về hành vi của agent

Đây là những gì của cơ chế này bạn thấy được ngay trên màn hình Claude Code:

  • câu trả lời hiện ra từng mẩu, vì nó được tạo ra đúng như thế. Đó là quá trình, không phải hiệu ứng trình bày;
  • hai yêu cầu giống hệt nhau cho ra hai câu trả lời khác nhau - vậy là bình thường, quá trình sinh không lặp lại chính nó từng chữ. Cần kết quả cũ thì quay lại cái đã nhận được sẽ chắc hơn là hỏi lại;
  • Thinking cho chỗ để viết nháp, chứ không bảo đảm sự đúng đắn. Với bài toán nhiều bước nó đáng giá, còn với việc đổi tên biến thì thường chỉ vướng víu;
  • chừng nào agent chưa đọc file, câu trả lời về file đó chỉ dựa vào những quy luật chung. Mọi thứ đã vào cuộc trò chuyện đều nặng ký hơn những gì được ghi lại trong tham số;
  • về các phiên bản thư viện mới, mặc định mô hình biết rất ít, và cách sửa đơn giản nhất là đưa tài liệu vào cuộc trò chuyện;
  • nếu câu trả lời đi chệch hướng, bổ sung phần còn thiếu có ích hơn là lặp lại yêu cầu bằng đúng những từ cũ. Cơ chế dựa vào văn bản đứng trước câu trả lời, chứ không dựa vào sự kiên trì.

Hiểu cơ chế không làm mô hình kém đi so với thực tế của nó. Nó chỉ cho biết nên chờ đợi gì: không phải một cuốn cẩm nang có bảo hành, mà là một cỗ máy viết tiếp văn bản rất giỏi, còn phần mở đầu thì do bạn đưa.

Video: cùng cơ chế đó qua hình ảnh

Kênh 3Blue1Brown có một video ngắn gom những ý chính vào một đoạn hoạt hình trực quan: token, xác suất của từ tiếp theo, attention và việc các tham số của mô hình từ đâu mà có. Video có tên Large Language Models explained briefly.

Bản gốc bằng tiếng Anh, nhưng video có vài bản lồng tiếng, có thể chuyển trong phần cài đặt của trình phát. Nếu không có bản cho ngôn ngữ bạn cần, hãy mở video ngay trên YouTube: trình phát trên web có nhiều lựa chọn hơn.

Kênh này không chỉ có mỗi video đó. Ở đó còn cả một loạt video về mạng nơ-ron, transformer và attention - vẫn những ý tưởng ấy, nhưng chi tiết hơn và có cả toán. Nếu đọc xong bài này bạn muốn hiểu không phải "chuyện gì đang diễn ra" mà "vì sao nó lại hoạt động được", thì nên bắt đầu từ đó.