Anthropic Engineering

Xây dựng trình biên dịch C với một nhóm các Claude song song

🕐 20/07/2026 12:08 📰 Anthropic Engineering ✅ Đã dịch sang tiếng Việt

Tác giả: Nicholas Carlini, nhà nghiên cứu trong nhóm Safeguards của chúng tôi.

Tôi đã thử nghiệm một phương pháp mới để giám sát các mô hình ngôn ngữ mà chúng tôi gọi là "nhóm tác tử" (agent teams).

Với nhóm tác tử, nhiều phiên bản Claude hoạt động song song trên một mã nguồn chung mà không cần can thiệp thủ công từ con người. Cách tiếp cận này mở rộng đáng kể phạm vi những gì có thể đạt được với các tác tử LLM.

Để kiểm tra sức chịu đựng, tôi đã giao nhiệm vụ cho 16 tác tử viết một trình biên dịch C dựa trên Rust, từ đầu, có khả năng biên dịch nhân Linux. Qua gần 2.000 phiên Claude Code và 20.000 đô la chi phí API, nhóm tác tử đã tạo ra một trình biên dịch 100.000 dòng có thể xây dựng Linux 6.9 trên x86, ARM và RISC-V.

Bản thân trình biên dịch là một sản phẩm thú vị, nhưng tôi tập trung ở đây vào những gì tôi học được về thiết kế khung (harness) cho các nhóm tác tử tự động chạy dài: cách viết bài kiểm tra giúp các tác tử đi đúng hướng mà không cần giám sát con người, cách cấu trúc công việc để nhiều tác tử có thể tiến triển song song, và nơi phương pháp này chạm đến giới hạn của nó.

Các khung tác tử hiện có như Claude Code yêu cầu người vận hành phải trực tuyến và sẵn sàng làm việc cùng nhau. Nếu bạn yêu cầu giải pháp cho một vấn đề dài và phức tạp, mô hình có thể giải quyết một phần, nhưng cuối cùng nó sẽ dừng lại và chờ đầu vào tiếp theo—một câu hỏi, cập nhật trạng thái, hoặc yêu cầu làm rõ.

Để đạt được tiến triển tự động bền vững, tôi đã xây dựng một khung (harness) đặt Claude vào một vòng lặp đơn giản (nếu bạn đã thấy Ralph-loop, điều này sẽ quen thuộc). Khi nó hoàn thành một nhiệm vụ, nó ngay lập tức nhận nhiệm vụ tiếp theo. (Chạy cái này trong một container, không phải máy thật của bạn).

Trong lời nhắc tác tử, tôi bảo Claude vấn đề cần giải quyết và yêu cầu nó tiếp cận vấn đề bằng cách chia nhỏ thành các phần, theo dõi những gì nó đang làm, xác định việc cần làm tiếp theo, và tiếp tục cho đến khi hoàn hảo. (Về điểm cuối này, Claude không có lựa chọn. Vòng lặp chạy mãi mãi—mặc dù trong một trường hợp, tôi thấy Claude vô tình chạy `pkill -9 bash`, tự giết chính nó và kết thúc vòng lặp. Rất tiếc!).

Chạy nhiều phiên bản song song có thể giải quyết hai điểm yếu của khung tác tử đơn lẻ:

Triển khai Claude song song của tôi rất cơ bản. Một kho git trống mới được tạo, và cho mỗi tác tử, một container Docker được khởi tạo với kho được gắn vào `/upstream`. Mỗi tác tử sao chép một bản sao cục bộ vào `/workspace`, và khi hoàn thành, đẩy từ container cục bộ của nó lên upstream.

Để ngăn hai tác tử cố gắng giải cùng một vấn đề cùng lúc, khung sử dụng một thuật toán đồng bộ hóa đơn giản:

Đây là một nguyên mẫu nghiên cứu rất sớm. Tôi chưa triển khai bất kỳ phương pháp giao tiếp nào khác giữa các tác tử, cũng như không áp đặt bất kỳ quy trình nào để quản lý các mục tiêu cấp cao. Tôi không sử dụng tác tử điều phối.

Thay vào đó, tôi để mỗi tác tử Claude tự quyết định cách hành động. Trong hầu hết các trường hợp, Claude chọn vấn đề "hiển nhiên tiếp theo". Khi gặp lỗi, Claude thường duy trì một tài liệu chạy về các cách tiếp cận đã thất bại và các nhiệm vụ còn lại. Trong kho git của

Trong dự án này, bạn có thể đọc lại lịch sử và thấy nó dần dần gỡ bỏ các khóa trên nhiều tác vụ khác nhau.

Khung nền tảng chạy Claude trong một vòng lặp, nhưng vòng lặp đó chỉ hữu ích nếu Claude có thể biết cách tạo ra tiến triển. Phần lớn công sức của tôi dồn vào việc thiết kế môi trường xung quanh Claude—các bài kiểm tra, môi trường, phản hồi—để nó có thể tự định hướng mà không cần tôi. Đây là những cách tiếp cận tôi thấy hữu ích nhất khi điều phối nhiều phiên bản Claude.

Claude sẽ làm việc tự động để giải quyết bất kỳ vấn đề nào tôi đưa ra. Vì vậy, điều quan trọng là bộ xác minh tác vụ phải gần như hoàn hảo, nếu không Claude sẽ giải quyết sai vấn đề. Cải thiện khung kiểm thử đòi hỏi phải tìm ra các bộ kiểm thử trình biên dịch chất lượng cao, viết bộ xác minh và script xây dựng cho các gói phần mềm mã nguồn mở, đồng thời theo dõi các lỗi Claude mắc phải, sau đó thiết kế các bài kiểm tra mới khi tôi xác định được các chế độ thất bại đó.

Ví dụ, gần cuối dự án, Claude bắt đầu thường xuyên phá vỡ chức năng hiện có mỗi khi triển khai một tính năng mới. Để giải quyết vấn đề này, tôi đã xây dựng một pipeline tích hợp liên tục và thực thi các biện pháp chặt chẽ hơn, cho phép Claude kiểm tra tốt hơn công việc của mình để các commit mới không thể phá vỡ mã hiện có.

Tôi phải liên tục nhắc nhở bản thân rằng tôi đang viết khung kiểm thử này cho Claude chứ không phải cho chính mình, điều này có nghĩa là phải suy nghĩ lại nhiều giả định về cách các bài kiểm tra nên truyền đạt kết quả.

Ví dụ, mỗi agent được thả vào một container mới không có ngữ cảnh và sẽ dành thời gian đáng kể để tự định hướng, đặc biệt là trong các dự án lớn. Trước khi chúng ta chạm đến các bài kiểm tra, để giúp Claude tự hỗ trợ, tôi đã bao gồm các hướng dẫn để duy trì các tệp README và tiến độ chi tiết, cần được cập nhật thường xuyên với trạng thái hiện tại.

Tôi cũng ghi nhớ thực tế rằng các mô hình ngôn ngữ có những hạn chế cố hữu, và trong trường hợp này, cần được thiết kế để khắc phục. Những hạn chế này bao gồm:

Khi có nhiều bài kiểm tra thất bại riêng biệt, việc song song hóa là đơn giản: mỗi agent chọn một bài kiểm tra thất bại khác nhau để làm việc. Sau khi bộ kiểm thử đạt tỷ lệ thành công 99%, mỗi agent làm việc để biên dịch một dự án mã nguồn mở nhỏ khác nhau (ví dụ: SQLite, Redis, libjpeg, MQuickJS, Lua).

Nhưng khi các agent bắt đầu biên dịch nhân Linux, chúng bị kẹt. Không giống như một bộ kiểm thử với hàng trăm bài kiểm tra độc lập, biên dịch nhân Linux là một tác vụ khổng lồ duy nhất. Mọi agent đều gặp cùng một lỗi, sửa lỗi đó, và sau đó ghi đè lên các thay đổi của nhau. Việc có 16 agent chạy không giúp ích gì vì mỗi agent đều bị kẹt giải quyết cùng một tác vụ.

Giải pháp là sử dụng GCC như một oracle trình biên dịch trực tuyến đã biết là tốt để so sánh. Tôi đã viết một khung kiểm thử mới biên dịch ngẫu nhiên hầu hết nhân bằng GCC, và chỉ các tệp còn lại bằng Trình biên dịch C của Claude. Nếu nhân hoạt động, thì vấn đề không nằm trong tập con tệp của Claude. Nếu nó bị hỏng, thì nó có thể tinh chỉnh thêm bằng cách biên dịch lại một số tệp này với GCC. Điều này cho phép mỗi agent làm việc song song, sửa các lỗi khác nhau trong các tệp khác nhau.

cho đến khi trình biên dịch của Claude cuối cùng có thể biên dịch tất cả các tệp. (Sau khi việc này thành công, vẫn cần áp dụng kỹ thuật gỡ lỗi delta để tìm ra các cặp tệp bị lỗi khi chạy cùng nhau nhưng hoạt động độc lập.)

Song song hóa cũng cho phép chuyên môn hóa. Mã do LLM viết thường xuyên triển khai lại các chức năng hiện có, vì vậy tôi giao cho một agent nhiệm vụ hợp nhất bất kỳ mã trùng lặp nào mà nó tìm thấy. Tôi giao cho một agent khác phụ trách cải thiện hiệu suất của chính trình biên dịch, và một agent thứ ba chịu trách nhiệm xuất mã đã biên dịch hiệu quả. Tôi yêu cầu một agent khác phê bình thiết kế của dự án từ góc nhìn của một nhà phát triển Rust, và thực hiện các thay đổi về cấu trúc đối với dự án để cải thiện chất lượng mã tổng thể, và một agent khác làm việc về tài liệu.

Dự án này được thiết kế như một điểm chuẩn năng lực. Tôi quan tâm đến việc kiểm tra sức chịu đựng các giới hạn của những gì LLM có thể *vừa đủ* đạt được ngày nay để giúp chúng ta chuẩn bị cho những gì các mô hình sẽ đạt được một cách đáng tin cậy trong tương lai.

Tôi đã sử dụng dự án Trình biên dịch C như một điểm chuẩn trên toàn bộ dòng mô hình Claude 4. Như tôi đã làm với các dự án trước đây, tôi bắt đầu bằng cách phác thảo những gì tôi muốn: một trình biên dịch tối ưu hóa viết từ đầu, không phụ thuộc, tương thích với GCC, có khả năng biên dịch nhân Linux, và được thiết kế để hỗ trợ nhiều backend. Mặc dù tôi đã chỉ định một số khía cạnh của thiết kế (ví dụ: nó nên có SSA IR để cho phép nhiều lượt tối ưu hóa), tôi không đi vào chi tiết về cách thực hiện.

Các mô hình Opus 4 trước đây hầu như không có khả năng tạo ra một trình biên dịch chức năng. Opus 4.5 là mô hình đầu tiên vượt qua ngưỡng cho phép nó tạo ra một trình biên dịch chức năng có thể vượt qua các bộ kiểm thử lớn, nhưng nó vẫn không thể biên dịch bất kỳ dự án lớn thực tế nào. Mục tiêu của tôi với Opus 4.6 là một lần nữa kiểm tra các giới hạn.

Qua gần 2.000 phiên Claude Code trong hai tuần, Opus 4.6 đã tiêu thụ 2 tỷ token đầu vào và tạo ra 140 triệu token đầu ra, với tổng chi phí chỉ dưới 20.000 đô la. So với ngay cả Claude M đắt nhất

📎 Nguồn gốc: Anthropic Engineering Xem bài gốc →