1 điểm bởi GN⁺ 3 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Tác nhân LLM mạnh trong việc sinh mã từ đặc tả lỏng, nhưng vẫn còn yếu khi phải tuân thủ các ràng buộc mà backend cấp độ production yêu cầu như hợp đồng API, kiến trúc, DB và ORM
  • Cố định yêu cầu chức năng bằng cùng một đặc tả OpenAPI, và áp dụng cùng một bộ kiểm thử hành vi cho 80 bài toán greenfield và 20 bài toán triển khai tính năng trên 8 framework web
  • Các ràng buộc phi chức năng được chia thành 4 chiều: lựa chọn framework, mẫu kiến trúc, backend cơ sở dữ liệu và tích hợp ORM, để tách riêng ảnh hưởng của độ phức tạp cấu trúc
  • Constraint decay là hiện tượng hiệu năng giảm mạnh khi các yêu cầu cấu trúc tích lũy; trong các bài toán được đặc tả đầy đủ với cấu hình cao, assertion pass rate giảm trung bình 30 điểm
  • Cốt lõi của thất bại là lỗi ở tầng dữ liệu; việc xây dựng truy vấn sai và vi phạm ORM lúc runtime chiếm khoảng 45% số lần thất bại logic của tác nhân

Vấn đề cốt lõi và thiết lập đánh giá

  • Tác nhân LLM mạnh trong sinh mã tự động với đặc tả lỏng, nhưng năng lực tuân thủ nghiêm ngặt các ràng buộc cấu trúc cần thiết cho phần mềm backend cấp độ production vẫn chưa được đánh giá đầy đủ
  • Backend cấp production không chỉ cần các endpoint tuân theo hợp đồng API mà còn phải đáp ứng các yêu cầu ngoài chức năng như mẫu kiến trúc, tích hợp cơ sở dữ liệu và tầng ORM được chỉ định
  • Nhiều benchmark trước đây vẫn thưởng cho các lời giải đúng về mặt chức năng nhưng tùy ý về mặt cấu trúc, nên chưa phản ánh đầy đủ độ khó của phát triển backend nhiều file có ràng buộc
  • Các nghiên cứu trước chủ yếu tập trung vào việc xử lý các issue cụ thể trong codebase có sẵn, sinh mã không ràng buộc từ prompt ngôn ngữ tự nhiên, lời giải một file hoặc hoàn thiện skeleton code, và chưa xem xét tác động của việc thay đổi có hệ thống mức độ ràng buộc cấu trúc
  • Tác động của độ phức tạp cấu trúc được tách riêng bằng cách cố định yêu cầu chức năng bằng cùng một đặc tả OpenAPI và áp dụng cùng một bộ kiểm thử hành vi end-to-end cho mọi điều kiện
  • Thí nghiệm gồm 80 bài toán sinh mới greenfield20 bài toán triển khai tính năng trên 8 framework web
  • Các ràng buộc phi chức năng được chia thành 4 chiều: lựa chọn framework, mẫu kiến trúc, backend cơ sở dữ liệu và tích hợp ORM
  • Ở điều kiện cơ sở, chỉ cung cấp cùng một đặc tả API; còn ở điều kiện có ràng buộc, các yêu cầu như clean architecture, PostgreSQL và SQLAlchemy được thêm vào
  • Đánh giá kết hợp kiểm thử hành vi end-to-end với trình kiểm tra tĩnh để tách biệt độ chính xác chức năng và mức độ tuân thủ cấu trúc

Kết quả chính và ý nghĩa

  • Constraint decay được xác nhận là hiện tượng hiệu năng của tác nhân giảm đáng kể khi các yêu cầu cấu trúc được tích lũy
  • Ngay cả những cấu hình có hiệu năng cao cũng giảm trung bình 30 điểm assertion pass rate khi đi từ điều kiện cơ sở sang bài toán được đặc tả đầy đủ; một số cấu hình yếu gần như về 0
  • Ngay cả với cùng một hợp đồng API, tỷ lệ thành công khác biệt lớn theo framework; tác nhân hoạt động tốt hơn trên các framework nhẹ và tường minh như Flask
  • Trong các môi trường nhiều quy ước như FastAPI và Django, hiệu năng trung bình thấp hơn đáng kể
  • Phân tích lỗi cho thấy lỗi ở tầng dữ liệu là nguyên nhân chính, tiêu biểu là việc xây dựng truy vấn sai và vi phạm ORM lúc runtime
  • Lỗi tầng dữ liệu được phân loại là nguyên nhân cốt lõi gây ra khoảng 45% số lần thất bại logic của tác nhân
  • Việc đồng thời đáp ứng yêu cầu chức năng và yêu cầu cấu trúc vẫn là một bài toán quan trọng chưa được giải quyết đối với các tác nhân lập trình
  • Pipeline đánh giá, bộ bài toán, quỹ đạo thực thi của tác nhân và các script phân tích được công bố tại constraint-decay

1 bình luận

 
Ý kiến trên Hacker News
  • Trước đây tôi hoàn toàn hoài nghi về việc tạo mã bằng LLM, nhưng giờ thì hơn 80% lượng mã tôi dùng trong công việc là mã được tạo ra
    Tuy vậy, các giới hạn cũng đã trở nên khá rõ ràng, bắt đầu lộ ra ở một số dự án, và bài viết này dường như xác nhận nghi ngờ của tôi
    Công việc càng phức tạp thì lại càng phải liên tục thêm ràng buộc vào đặc tả Markdown, quy tắc, kỹ năng, style guide, điều kiện biên, xử lý lỗi và hướng dẫn tối ưu hóa
    Đến một lúc nào đó, nó trông như đang chuyển độ phức tạp từ thế giới hình thức và mang tính quyết định của ngôn ngữ lập trình sang thế giới phi hình thức và phi quyết định của ngôn ngữ tự nhiên
    Tốc độ viết tăng lên cực lớn, và doanh nghiệp dĩ nhiên xem đó là tăng năng suất, nhưng cái giá phải trả thì rất rõ, chỉ là nhiều người có vẻ phớt lờ

    • Đây chính là vấn đề mà mọi người không nói ra. Codebase đang phình ra bằng các tệp Markdown chứa chỉ dẫn, guideline và yêu cầu do LLM tạo ra, và chúng cứ tiếp tục tích tụ
      Không ai rà soát 100%, mà ngay cả khi có rà soát thì cũng rất chủ quan
      Khó mà phân biệt rõ giữa “hãy theo cách tiếp cận RESTful”, “chúng tôi dùng REST chứ không dùng GraphQL”, và “90% endpoint là định hướng tài nguyên nhưng một số cái trông giống RPC nên cứ bỏ qua”
      Tất cả trông khá ngớ ngẩn
    • Nó giống như dùng một compiler mà mỗi lần chạy lại sinh ra đoạn mã mang ý nghĩa khác nhau
      Về thực chất là compile các chương trình đầy hành vi không xác định, nhưng phần lớn lại “trông như hoạt động”
      Việc doanh nghiệp xem đây là tăng năng suất khiến tôi có cảm giác chúng ta đang quay lại thời kỳ đo “năng suất” bằng số dòng mã mỗi giây
    • Tôi không gặp quá nhiều khó khăn ngay cả với các codebase rất lớn và phức tạp. Có vẻ tôi được hưởng lợi nhiều từ static typing mạnh, kể cả ở quy mô trên 50MB tính theo mã nguồn thô, nhưng tôi không nghĩ chỉ có thế
      Khi codebase vượt ra ngoài mức có thể nằm trong 20% đầu của cửa sổ ngữ cảnh để được xử lý hoàn toàn bằng một lần suy luận có thể lặp lại, thì execution harness và kỹ thuật vá mã trở nên quan trọng hơn nhiều
      Cách làm apply_patch mà OAI đã tinh chỉnh cho model có vẻ là phương án tốt nhất cho codebase siêu lớn
      Những cách dựa trên phạm vi dòng hoặc tìm-thay đơn giản sẽ sụp đổ ở rìa, và để xử lý các ca khó như file cshtml thì cần nhiều neo không gian
      Cơ chế prepare/commit là lý tưởng để lặp lại ngữ cảnh mơ hồ trên nhiều tệp lớn và tinh chỉnh các neo
    • Nếu 80% mã được tạo ra đến từ LLM thì đó gần như chỉ là tái tổ hợp những gì đã có sẵn, và rốt cuộc chỉ là slop
      LLM không thể tạo ra điều gì thực sự mới
  • “Nghiên cứu có hệ thống cho thấy hiện tượng suy giảm ràng buộc trong các tác nhân lập trình dựa trên LLM. Các model hiện tại rất giỏi ở việc sinh ra nội dung không có ràng buộc, nhưng hiệu năng giảm khi phải tuân theo các quy tắc kiến trúc tường minh. Với người dùng cuối, sự phân đôi này có nghĩa là các tác nhân đáng tin cho tạo mẫu nhanh, nhưng vẫn khó tin cậy cho phát triển backend cấp độ production.”
    Điểm yếu lớn của nghiên cứu này là do vấn đề chi phí nên họ chưa thử nghiệm đủ với các model tuyến đầu, vì vậy cần thận trọng khi nhìn vào các con số hiệu năng cụ thể
    Dù vậy, kết luận rằng hiệu năng model giảm khi vừa phải đúng về hành vi vừa phải đúng về kiến trúc vẫn rất đáng chú ý và đáng tiếp tục theo dõi

    • Có vẻ đây là hiện tượng hạ nguồn của bài toán “không thể tối ưu đồng thời hai mục tiêu khác nhau”
      Nếu chỉ có yêu cầu chức năng thì về bản chất là đang làm tổng hợp chương trình, và học tăng cường có thể tối ưu việc này rất mạnh
      Khi trộn yêu cầu chức năng với yêu cầu phi chức năng, về thực chất là đang đưa cho model một đặc tả không đầy đủ, và model sẽ phải phần nào đoán ý người dùng để lấp chỗ trống
      Đây cũng là lý do việc đưa ví dụ về style mã mong muốn vào prompt lại mạnh đến vậy
    • Tôi cũng thấy hiện tượng tương tự với những cuốn sách được viết có AI hỗ trợ. Lúc đầu thì ổn, nhưng qua vài chương thì phần mở đầu của mỗi chương lại lặp lại phần kết của chương trước, và dấu vết đặc trưng của LLM xuất hiện ngày càng thường xuyên hơn
      Càng có nhiều tài liệu để tham chiếu, nó càng phụ thuộc vào việc lặp lại những gì đã xuất hiện trước đó
      Cũng có thể là các tác giả càng về các chương sau càng ít chú ý hơn và bỏ ít công sức biên tập hơn
      Trên Amazon có số lượng khổng lồ, nhưng LLM vẫn chưa ở mức viết tốt
    • Tôi gặp hiện tượng tương tự khi lập kế hoạch qua nhiều vòng tương tác với Opus
      Khi nó đưa ra các giải pháp không tương thích và tôi bổ sung thêm ngữ cảnh cùng yêu cầu, nó có xu hướng bị cố định vào kiến trúc ban đầu và rất khó thích nghi
      Đôi khi nó còn cố lén nhét vào các thay đổi để phục vụ kế hoạch ban đầu
    • Có thể đây là cùng một vấn đề xuất hiện khi prompt cố áp đặt “alignment” hay “guardrail”. Hiệu năng bị giảm
      Có vẻ như những mảng lớn trong không gian lời giải khả dĩ trở nên không thể tiếp cận
      Ví dụ, khoảng một năm trước khi áp guardrail lên trình tạo ảnh thì mọi người bắt đầu trông giống nhau, còn trình tạo truyện thì bắt đầu chỉ dùng vài cái tên tiêu chuẩn
      Tôi tò mò liệu chuyện này có còn xảy ra ngay cả với các model tuyến đầu hiện nay hay không
    • Tôi cho rằng GPT 5.2, model tuyến đầu mạnh nhất được dùng trong nghiên cứu này, cũng chỉ vừa đủ dùng cho lập trình kiểu tác nhân
      Tôi không quá quan tâm đến việc phân tích điểm yếu của các model kiểu này. Theo kinh nghiệm của tôi, khi model mạnh hơn và tăng mức nỗ lực suy luận thì nhiều điểm yếu sẽ biến mất hoàn toàn
      Đặc biệt là khi bạn nói rõ hành vi mong muốn, và việc tỷ lệ thất bại tăng lên khi tiêu chí chấp nhận nhiều hơn thì không có gì đáng ngạc nhiên
  • Tình hình còn tệ hơn. Tác nhân không chỉ gặp khó hơn dưới các “ràng buộc cấu trúc”, mà còn tệ hơn nữa khi chính các ràng buộc cấu trúc đó cần phải thay đổi
    Khi thiết kế hệ thống hay thành phần, chúng ta đặt ra những ý tưởng làm bất biến
    Có bất biến lớn như kiến trúc tổng thể, cũng có bất biến nhỏ như lựa chọn cấu trúc dữ liệu
    Nhưng rồi cuối cùng cũng đến lúc ta muốn thêm một tính năng xung đột với những bất biến đó
    Khi ấy thường có ba lựa chọn: không thêm tính năng, chồng tính năng lên trên các bất biến một cách kém thanh lịch hoặc kém hiệu quả, hoặc quay lại thay đổi các bất biến
    Thường thì chỉ một trong số đó là đúng, và ít nhất một lựa chọn sẽ sai rất nghiêm trọng, dẫn đến kết quả tệ
    Tác nhân, ngay cả khi có thể tuân thủ ràng buộc, vẫn cực kỳ kém trong việc nhận ra thời điểm cần thay đổi ràng buộc

    • Kỳ vọng của tôi với lập trình kiểu tác nhân là rất hạn chế, nhưng tôi cũng đã dùng thử ở mức nào đó và hoàn toàn đồng ý với nhận định này
      Đây là một trong những ranh giới giữa nhận diện mẫu và suy luận, và trái với các tuyên bố marketing về chuỗi suy nghĩ, LLM thực ra không hề suy luận chút nào
      Mọi nỗ lực khiến nó trông như đang suy luận, theo tôi, gần giống với việc harness cố gắng nhốt tia chớp vào trong chai bằng những nỗ lực cô lập đệ quy
  • Điều này làm tôi nhớ đến một bài báo gần đây giao nhiều tác vụ chỉnh sửa tài liệu ở nhiều lĩnh vực cho LLM https://arxiv.org/abs/2604.15597
    Bài đó cho rằng lập trình là lĩnh vực duy nhất mà phần lớn LLM có thể thực hiện tác vụ đường chân trời dài mà không tích lũy lỗi và phá hỏng tài liệu
    Tôi mới chỉ đọc phần tóm tắt của bài này, nhưng có vẻ nó xem xét kỹ hơn việc lập trình và cho thấy hiện tượng tương tự
    Tuy vậy, có vẻ nó gần với một “đường chân trời phong cách dài” đối với một bó ràng buộc cấu trúc lớn hơn hơn là tác vụ đường chân trời dài
    Thảo luận liên quan: https://news.ycombinator.com/item?id=48073246

    • LLM không giỏi với những việc khó xác minh một cách dễ dàng
  • Đây là một bài báo rất thú vị và tôi hoàn toàn đồng ý, nhưng tôi không nghĩ đó là điều mới mẻ
    Ngay từ kỳ vọng ban đầu rằng chỉ cần thả một giải pháp coding kiểu agent vào dự án và ném cho nó danh sách công việc thì nó sẽ thần kỳ tuân theo các ràng buộc được định nghĩa sẵn của dự án đã hơi lệch rồi
    Tôi không tin có stack coding kiểu agent nào có thể làm được điều này ở trạng thái mặc định
    Để agent hiểu ngữ cảnh, ràng buộc và mục tiêu một cách ổn định thì vẫn cần những cơ chế phù hợp, và việc các phòng lab AI lớn liên tục cập nhật công cụ·kỹ năng·quy trình cho thấy đây vẫn là một lĩnh vực đang tiến triển
    Lớp bổ sung này có thể còn sinh lợi hơn nhiều so với bản thân mô hình thuần túy và mức tiêu thụ token
    Tôi nghĩ ngay cả những mô hình mở có vẻ như đã được thử nghiệm hiện nay, nếu vận hành đúng cách, cũng đã có thể tạo ra mã production tuân theo các ràng buộc mong muốn
    Tôi tò mò không biết mã production của mọi người trong vài tháng gần đây ra sao

  • Tôi đã thử nghiệm khá nhiều với coding kiểu agent đường chân trời dài https://medium.com/@vishvananda/i-spent-2-billion-tokens-wri..., và cũng thấy rằng việc ép buộc các mẫu kiến trúc cụ thể có thể làm hiệu năng của agent kém đi
    Nếu đưa các ràng buộc vào trong quá trình thực hiện thay vì thêm vào sau thì có khá hơn một chút
    Có một tác dụng phụ mà tôi gọi là vôi hóa: khi một mẫu nào đó bắt đầu xuất hiện trong codebase, agent sẽ bám theo mẫu đó, rồi nó chi phối ngữ cảnh và tự củng cố
    Trong codebase hiện có, điều này có thể là điểm mạnh hoặc điểm yếu tùy vào chất lượng mã
    Có lẽ sẽ có thêm nhiều insight hơn khi các lần chạy trên codebase mới với hướng dẫn kiến trúc ngay từ đầu hoàn tất

    • Tôi cũng đã thấy điều này. Agent và mô hình có phong cách riêng, và phần lớn có thể tóm gọn là quá dài dòng
      Ngoài ra, mô hình mô-đun hóa khá ổn khi nó còn khoảng trống để “lập kế hoạch” cho việc triển khai, nhưng hiếm khi tự kết luận rằng về sau nên trừu tượng hóa để có lợi
      Điều này đặc biệt đúng sau nhiều vòng lặp trên codebase mới hoặc khi được đưa vào codebase legacy, và thường dẫn tới các file khổng lồ
      Khi người dùng chỉ ra điều đó thì mô hình phê bình rất đúng, nhưng khá buồn cười vì đó lại là chính đoạn mã nó đã viết
  • Nghe như một phiên bản khác của chuyện “chat càng dài thì guardrail càng mờ đi”
    Lý do không thể dùng hết cửa sổ ngữ cảnh là vì ở phần cuối, đầu ra không còn tuân thủ ràng buộc hay guardrail nữa
    Nhưng để tạo mã cấp production một cách ổn định, mô hình phải có nhận thức rộng, và điều đó nhanh chóng lấp đầy cửa sổ ngữ cảnh
    Nó giống như nói “hãy ghi nhớ mọi thứ trong 6 thư mục này và thực hiện thay đổi này”, nhưng chỉ riêng việc ghi nhớ mọi thứ thôi cũng đã làm đầy cửa sổ ngữ cảnh và khiến nó mất khả năng tuân thủ ràng buộc

    • Đây không phải vấn đề mới. Đó chính là lý do chúng ta bắt đầu dùng mã mô-đun và interface chặt chẽ
    • Có lẽ chỉ cần cho nó guardrail mạnh hơn? Kiểu như Sonarcube chẳng hạn
      Tuy vậy, khi đó kiểu thất bại có lẽ sẽ chuyển sang việc nó tập trung vào làm hài lòng linter rồi dần quên mất yêu cầu
      Việc lặp lại thử/thất bại cũng sẽ hoàn toàn không tốt cho ngữ cảnh
  • Nghiên cứu này dùng các ngôn ngữ kiểu động như Python và JS
    Theo kinh nghiệm của tôi, codebase kiểu tĩnh dễ bảo trì hơn cho con người, nên có thể cũng như vậy với agent
    Khi dùng Codex hoặc Claude Code trên mã Go, tôi đã vô số lần thấy agent sửa đổi, chạy build để tìm lỗi, rồi sửa tiếp

    • Chỉ cần thêm type vào các quy tắc của harness và chạy ty sau mỗi thay đổi
      Dạo này các mô hình xử lý type của Python khá tốt
    • Thật lạ khi mọi người mặc định xem Python là ngôn ngữ kiểu động
      Trong Python, kiểu tĩnh mạnh đã là một lựa chọn từ vài năm nay, và đơn giản là nó nên trở thành mặc định
  • Bài viết nói “các tác vụ trải trên 8 web framework”, nên tôi tò mò không biết có ai cũng có trải nghiệm rằng LLM làm HTML+CSS+JS thuần tốt hơn là làm trên framework sẵn có không

    • Có vẻ web framework đã rơi vào “tình thế khó xử” kể từ gpt-5.4. Giờ thật khó hình dung việc dùng thứ như React nữa
      Tổ hợp ấn tượng nhất tôi thấy gần đây là Razor Pages với progressive enhancement bằng JavaScript
      Trong cấu hình này, các mô hình mới nhất phân biệt khá tốt việc gì nên diễn ra ở phía server (cshtml) và việc gì nên diễn ra ở phía client (js)
  • Tôi khuyên nên bỏ thời gian chỉnh một vài phần của codebase về dạng thành ngữ trước, rồi chỉ định các file đó bằng @ làm file ví dụ
    Cách này hiệu quả hơn rất nhiều so với cố điều khiển bằng Markdown
    Với các thứ như FastAPI thì khá ổn, nhưng JavaScript có vẻ là tệ nhất
    Ngay cả khi có chỉ dẫn và ví dụ, nó vẫn có xu hướng nhét hàng đống mã vô ích inline thay vì dùng API đã được chỉ định