22 điểm bởi GN⁺ 2025-06-13 | 1 bình luận | Chia sẻ qua WhatsApp
  • Bài viết này là phần thứ hai nói về quá trình thích nghi kinh nghiệm lập trình sẵn có với thế giới của máy tính hội thoại (LLM, tác tử)
  • Trong phần đầu tiên, "Cách lập trình cùng LLM", tác giả đã giải thích cách tích hợp LLM vào các công cụ hiện có để dùng như tự động hoàn thành hoặc thay thế tìm kiếm
  • Lần này, bài viết chia sẻ trải nghiệm thực tế và những hiểu biết về lập trình dựa trên tác tử, khó hơn nhưng cũng đáng giá hơn

Định nghĩa và thực tế của tác tử

  • Trong ngữ cảnh LLM (mô hình ngôn ngữ lớn), việc định nghĩa thuật ngữ "tác tử" là điều có ý nghĩa
  • Đây là từ khóa thịnh hành trong ngành AI đã được dùng từ lâu, nhưng chỉ gần đây mới định hình thành một cấu trúc thực sự hữu ích
  • Trong quá trình đó, rất nhiều lớp ngôn từ tiếp thị và màu sắc huyền bí đã được phủ lên nó
  • Từ góc nhìn của kỹ sư, giờ đây có thể định nghĩa rõ ràng và đơn giản: tác tử là 9 dòng mã, tức là một vòng lặp for có chứa lời gọi LLM
  • Bên trong vòng lặp này, LLM thực thi lệnh và có thể trực tiếp kiểm tra kết quả, lặp đi lặp lại mà không cần con người can thiệp
  • Nghe có vẻ đơn giản, nhưng trong thực tế, cấu trúc như vậy giúp năng lực lập trình tăng vọt so với chỉ dùng LLM thuần túy

Khác biệt giữa lập trình trên bảng trắng và tác tử

  • Hãy giả sử bạn đứng trước bảng trắng và viết bằng bút marker một hàm C để kiểm tra tính hợp lệ của chuỗi UTF-8
    • (Đây là tình huống phỏng vấn mà tác giả từng trải qua, đồng thời cũng là một bài tập phỏng vấn phổ biến)
    • Thành bại của việc này phụ thuộc vào kinh nghiệm lập trình của bạn, cũng như khả năng che lấp hạn chế khi không được tham khảo tài liệu bên ngoài
    • Bạn phải nhớ các quy tắc mã hóa UTF-8, và phải cẩn thận để cú pháp C không bị lẫn với các ngôn ngữ họ C khác (thứ tự tên-kiểu, kiểu-tên, v.v.)
    • Trong công việc hằng ngày thực tế, bạn có thể dùng phản hồi từ compiler, tra cứu tài liệu, printf và nhiều cách khác để kiểm chứng mã và tìm lỗi
  • Việc yêu cầu LLM viết mã mà không có tác tử giống như viết mã trên bảng trắng mà không có hỗ trợ bên ngoài
    • Đó là công việc phải moi lại ký ức mơ hồ, cố gắng khớp cú pháp theo cách kém hiệu quả, và tránh lỗi tưởng tượng ra những interface sai lệch
    • Thành tựu kỹ thuật khi LLM có thể tạo ra một chương trình hoàn toàn mới là rất ấn tượng, nhưng chỉ với một bảng trắng ảo gắn GPU thì năng suất lập trình thực tế không tăng lên nhiều
  • Nhưng nếu cung cấp cho LLM nhiều hơn một bảng trắng ảo thì sao?
    • Ví dụ, nếu nó có thể gọi compiler, xem lỗi biên dịch rồi tự sửa?
    • Nếu nó có thể đọc các tệp hiện có bằng grep, cat, vá nhiều tệp (bao gồm cả unit test) và lặp lại việc chạy test thì sao?
  • Tác tử chính là LLM dựa trên phản hồi như vậy.

Tác tử = LLM hoạt động trong môi trường phản hồi

  • Một LLM hoạt động tốt trong môi trường phản hồi như con người có thể thể hiện năng lực lập trình thực tế chỉ với vài công cụ quen thuộc
    • bash(cmd): chạy lệnh terminal (find, cat, grep, v.v.)
    • patch(hunks): vá tệp, áp dụng thay đổi mã
    • todo(tasks): quản lý danh sách công việc
    • web_nav(url), web_eval(script), web_logs(), web_screenshot() v.v.: duyệt web, đánh giá, log, screenshot, v.v.
    • keyword_search(keywords): tìm kiếm từ khóa
    • codereview(): review mã
  • Nhờ công cụ bash, nó có thể khám phá codebase hiệu quả, đồng thời tự động hóa cả quản lý phiên bản như git add/commit
  • Khác với LLM chỉ tạo mã đơn thuần mà không có các công cụ này, tác tử có những lợi thế nổi bật sau
    • Độ chính xác khi dùng API tăng mạnh (tự tìm tài liệu và phản ánh trực tiếp vào context)
    • Phản hồi từ compiler giúp giảm lỗi cú pháp và nhầm lẫn interface
    • Tăng cường khả năng quản lý dependency/phiên bản (có thể nắm bắt đặc tính của phiên bản cụ thể)
    • Cải thiện khả năng phát hiện lỗi qua test thất bại và thói quen viết mã kiểm thử
    • Xử lý codebase vượt qua giới hạn context window (chỉ đọc chọn lọc phần cần thiết)
    • Thử nghiệm trực tiếp kết quả thực thi: chạy mã, nhận phản hồi qua screenshot trang trình duyệt, tự điều chỉnh CSS, lần theo lỗi bằng log máy chủ và bổ sung test
  • Tuy vậy vẫn có nhược điểm
    • Chỉ với một yêu cầu bằng một câu, có thể phát sinh hàng chục nghìn token trung gian (gọi công cụ, tìm kiếm web, lặp test, v.v.), nên thời gian xử lý thường mất vài phút trở lên
    • Chi phí gọi API cũng tồn tại, nhưng có triển vọng dần biến mất nhờ tiến bộ phần cứng
  • Cuối cùng, CPU/GPU gánh thay phần lao động trung gian, tiết kiệm thời gian cho nhà phát triển và giúp hoàn thành được nhiều chương trình vốn muốn viết hơn
  • Trên thực tế, việc đưa tác tử vào dự án, giao cho nó những việc nhỏ và kiểm tra kết quả, là điều dễ làm

Ví dụ: phát triển xác thực Github App

  • Đây là ví dụ thực tế triển khai luồng xác thực Github App của sketch.dev bằng tác tử
    • Chỉ với 3~4 lần phản hồi, toàn bộ luồng xác thực đã được hoàn thiện rất nhanh
    • Khi phát hiện lỗi hoặc yêu cầu, chỉ cần mô tả bằng một câu ngắn là nó lập tức cải thiện mã và hành vi
    • Nó giúp giảm tối đa những “việc vặt” trong thực tế như tích hợp API lặp đi lặp lại, build system/package management/cấu hình thư viện, từ đó duy trì momentum năng suất rất tốt
  • Ở yêu cầu ban đầu, tác giả đưa vào điều kiện “không lưu token theo từng người dùng mà chỉ dùng thông tin xác thực toàn cục của ứng dụng”, và tác tử đã triển khai đúng như vậy
    • Nhưng kết quả là phát sinh lỗ hổng bảo mật nghiêm trọng (ai cũng có thể xem mọi repo)
    • Khi phản hồi vấn đề đó chỉ bằng một câu, nó lập tức thêm kiểm tra quyền theo từng người dùng và tạo commit đã sửa
  • Sau đó, vấn đề hiệu năng xuất hiện
    • Với cấu trúc như dưới đây, API bị gọi cho mọi tổ hợp người dùng-repo nên nảy sinh vấn đề về khả năng mở rộng
      for install := range allAppInstallations {  
      	for r := range install.Repositories() {  
      		if r.IsCollaborator(user) {  
      			// add to available repositories  
      		}  
      	}  
      }  
      
    • Tác giả nhận ra nguyên nhân gốc rễ của vấn đề này chính là yêu cầu “không lưu token theo từng người dùng” do mình đặt ra
    • Khi thay đổi yêu cầu (cho phép lưu token theo từng người dùng), tác tử đã thiết kế lại theo cách gọi API hiệu quả hơn
  • Trên thực tế, số từ dùng để giải thích quá trình này trong bài viết còn nhiều hơn tổng số từ tác giả đã nhập vào Sketch để lấy được mã xác thực
  • Tóm lại, tác tử hiện chưa thể thay thế nhà phát triển, nhưng có thể giúp xử lý trong một ngày những công việc lặp lại vốn thường mất vài ngày
  • Mức độ tự động hóa thậm chí đủ để nhà phát triển vẫn có thể làm việc trong lúc dọn phòng cho con

Ví dụ: áp dụng quy tắc SQL dựa trên JSON

  • Một trong những việc tác tử thường xử lý là áp dụng kiểu SQL đặc biệt học được từ Tailscale
    • Mỗi bảng chỉ có một cột thực sự (dữ liệu JSON), còn các cột còn lại đều là generated column suy ra từ JSON
    • Ví dụ cấu trúc bảng:
      CREATE TABLE IF NOT EXISTS Cookie (  
        Cookie   TEXT    NOT NULL AS (Data->>'cookie')  STORED UNIQUE, -- PK  
        UserID   INTEGER NOT NULL AS (Data->>'user_id') STORED REFERENCES User (UserID),  
        Created  INTEGER NOT NULL AS (unixepoch(Data->>'created')) STORED,  
        LastUsed INTEGER AS (unixepoch(Data->>'last_used')) CHECK (LastUsed>0),  
        Data     JSONB   NOT NULL  
      );  
      
    • Cách làm này đóng vai trò như một loại poor man’s ORM, giúp việc mở rộng schema dễ hơn, đồng thời các ràng buộc SQL cũng hữu ích cho việc kiểm chứng chất lượng dữ liệu JSON
    • Nhược điểm là lượng dữ liệu lưu trên mỗi hàng tăng lên, và mọi thao tác INSERT/UPDATE đều phải diễn ra ở cấp độ JSON
  • Tuy nhiên, tác tử không phải lúc nào cũng tuân thủ nhất quán kiểu này
    • Khi tạo bảng mới thì đa phần làm tốt, nhưng nếu có ngoại lệ thì đôi khi bị rối hoặc tự ý đổi style
  • Giải pháp đơn giản: thêm một đoạn giải thích 3 câu ở đầu tệp schema SQL
    • Thêm câu khóa nêu rõ rằng “mỗi bảng chỉ có một cột JSON Data thực sự, còn mọi cột khác đều được suy ra từ đó”
    • Với những bảng không theo quy tắc này thì ghi chú riêng rằng đó là ngoại lệ
    • Sau đó, hành vi của tác tử cải thiện rõ rệt
  • Điều thú vị là, những lời giải thích và chú thích kiểu này thường bị kỹ sư con người bỏ qua hoặc đánh giá thấp giá trị của chúng, nhưng
    • tác tử dựa trên LLM lại tích cực phản ánh chú thích và giải thích đó vào quá trình viết mã
    • Chỉ cần chú thích tốt, chất lượng sinh mã cũng tăng lên rõ ràng

Mô hình mã “tài sản” và “nợ”

  • Một trong những chỉ trích phổ biến đối với công cụ sinh mã dựa trên LLM là bản thân việc sinh mã chỉ chiếm một phần rất nhỏ trong tổng chi phí phần mềm
    • Trên thực tế, phần lớn thời gian được dùng để quản lý dependency, độ rối và interface phức tạp của mã hiện có
    • Với sản phẩm lớn, lâu đời, có nhiều người dùng, chi phí bảo trì là áp đảo
    • Trong môi trường như vậy, việc yêu cầu LLM “hãy viết bubble sort bằng Fortran” có thể bị xem như đồ chơi hoặc thứ gây phiền nhiễu bất tiện
    • Cũng có các tranh luận ví nó với khái niệm “tài sản/nợ” trong tài chính, nhưng phép so sánh này cũng không hoàn toàn khớp
  • Tuy vậy, không phải toàn bộ kỹ nghệ phần mềm đều chỉ xoay quanh các dự án lớn và dài hạn như thế
    • Phần lớn chương trình phục vụ ít người dùng hoặc là dự án ngắn hạn
    • Không nên lấy kinh nghiệm bảo trì quy mô lớn để khái quát thành bản chất của cả ngành
  • Giá trị của tác tử không chỉ giới hạn ở sinh mã
    • Tác tử kết hợp nhiều công cụ với LLM để tự động hóa chính sự thay đổi, như đọc mã, sửa tệp, xóa/chỉnh sửa mã
    • Nó xử lý xóa mã/refactor cũng tự nhiên như khi thêm mã
  • Cuối cùng, mục tiêu của kỹ sư là tạo ra thay đổi (change)
    • Dù trong quá trình thay đổi vẫn có thêm công việc để người điều khiển hiểu được thay đổi đó, tác tử đã cho thấy năng lực tạo ra các thay đổi dần dần ngay cả với dự án quy mô trung bình
    • Dù hiện tại còn chưa đủ, tác tử vẫn đang phát triển rất nhanh theo đúng hướng
  • Ngoài ra còn có ý kiến rằng ngôn ngữ phức tạp hay build system phức tạp đóng vai trò như rào cản gia nhập của dự án
    • Có lập luận lo ngại rằng nếu các công cụ giúp viết mã dễ hơn (LMM, type safety, garbage collection, package management, tác tử, v.v.) hạ thấp rào cản này thì chất lượng sẽ suy giảm
    • Nếu mục tiêu là làm chậm tốc độ thay đổi hoặc tăng cường kiểm soát, thì các công cụ tự động hóa như tác tử sẽ không phù hợp

Vì sao là tác tử vào lúc này?

  • Khác với các nguyên lý AI phức tạp như transformer, việc thêm vòng phản hồi vào LLM là cách tiếp cận trực quan và rõ ràng
    • Từ góc nhìn của người làm công cụ cho nhà phát triển, đây là một hướng phát triển rất tự nhiên
    • Trên thực tế, phiên bản đầu tiên của sketch.dev cách đây một năm cũng chỉ ở mức nối LLM với các công cụ Go, nhưng so với tác tử đang dùng hiện nay thì khác biệt rất lớn về tính thực dụng
    • Ngay trong lĩnh vực ML, reinforcement learning (học dựa trên phản hồi) cũng đã là nguyên lý cơ bản hơn 50 năm nay
  • Sự xuất hiện thực sự của tác tử gắn liền trực tiếp với tiến hóa của LLM
    • LLM năm 2023 còn thiếu năng lực gọi công cụ nên vai trò tác tử bị hạn chế
    • LLM năm 2025 đã được tối ưu cho việc gọi công cụ và tác vụ lặp, nên việc dùng tác tử một cách thực chất trở nên khả thi
    • Các mô hình Frontier (thương mại tiên tiến nhất) vượt xa open model về năng lực tận dụng công cụ
    • Kỳ vọng là trong vòng 6 tháng tới, open model cũng sẽ bắt kịp
    • Khả năng gọi công cụ lặp lại một cách hữu ích là thay đổi lớn nhất của LLM hiện đại

Hướng đi sắp tới: container và thực thi song song

  • Lĩnh vực tác tử LLM vẫn đang ở giai đoạn đầu và thay đổi rất nhanh, nơi phần lớn kỹ sư vẫn chưa thực sự áp dụng
  • Ở thời điểm hiện tại, tác tử chủ yếu được dùng để chạy trong IDE hoặc kho mã cục bộ
    • Có thể bắt đầu dễ dàng bằng cách cài một fork của VSCode hoặc công cụ dòng lệnh
    • Nhưng có hai giới hạn quan trọng
      • Thứ nhất, thiếu cơ chế an toàn: có nguy cơ lộ thông tin nhạy cảm như thông tin xác thực vận hành thật được lưu trên máy tính thật
        • Nếu tác tử vô tình chạy những lệnh như script triển khai thì có thể gây ra sự cố bảo mật nghiêm trọng
        • Dù có yêu cầu xác nhận thủ công cho mỗi lần chạy lệnh, khả năng vô tình lộ bí mật nhạy cảm vẫn còn đó
      • Thứ hai, giới hạn về chạy song song và tự động hóa: vì mỗi nhà phát triển chỉ chạy được từng tác tử trong môi trường riêng của mình
        • Mỗi lượt chạy tác tử đều mất vài phút, nên rất khó và kém hiệu quả nếu muốn xử lý nhiều việc cùng lúc
  • Để giải quyết các giới hạn này, sketch.dev đang thử hướng tiếp cận bằng môi trường container
    • Tạo container phát triển cách ly cho từng tác vụ, sao chép source code vào đó và chỉ xuất ra ngoài những thứ như git commit
    • Có thể chạy nhiều tác tử cùng lúc, và các tác tử khác cũng đang khám phá cách làm này
  • Ví dụ thực tế: vừa làm việc xác thực Github, vừa xử lý cải thiện UI form trong một phiên tác tử riêng
    • Không cần tạo issue tracker riêng, chỉ bằng screenshot và một dòng yêu cầu ngắn là đã có thể phản hồi cải thiện thiết kế form
    • Chỉ đầu tư 30 giây cũng mang lại trải nghiệm có kết quả đạt mức chấp nhận được
  • Kết quả thử nghiệm UX trong 6 tháng qua:
    • Đi đến kết luận rằng container (môi trường thực thi cách ly) là cách thực dụng nhất cho phát triển dựa trên tác tử

IDE sẽ trở thành gì?

  • Trong môi trường phát triển dựa trên tác tử, vai trò của IDE (môi trường phát triển tích hợp) sẽ là gì vẫn còn là một câu hỏi bỏ ngỏ
    • Một workflow thực tế có thể là nhập chỉ thị cho tác tử để bắt đầu việc, chạy nó trong môi trường container, kiểm tra thay đổi bằng diff rồi đẩy lên branch/PR
  • Trên thực tế, phần lớn các commit do tác tử tạo ra đều cần một mức độ chỉnh tay nhất định từ con người
    • Ban đầu gần như mọi commit đều cần sửa thủ công, nhưng khi kỹ năng viết prompt tăng lên thì lượng chỉnh sửa dần giảm xuống
    • Nội dung sửa có thể từ đơn giản như chỉnh comment, đổi tên biến, cho tới refactor phức tạp hơn
    • Câu hỏi then chốt là làm sao chỉnh sửa như vậy một cách hiệu quả trong môi trường container
  • Workflow đang được thử nghiệm trong sketch.dev và các nơi khác
    • Cung cấp giao diện có thể chỉnh trực tiếp trên diff view
      • Khi chỉnh mã trực tiếp ở bên phải màn hình diff của Sketch, thay đổi đó sẽ được phản ánh vào commit và đẩy đi ngay
      • Rất hiệu quả cho các chỉnh sửa nhỏ chỉ một dòng
    • Cung cấp truy cập SSH vào container để
      • có thể vào shell trực tiếp hoặc thao tác mã qua web terminal
      • mở bằng URL vscode:// để làm việc trong IDE truyền thống
    • Có thể để lại comment kiểu code review trực tiếp trên diff và chuyển chúng thành phản hồi cho tác tử
      • Tận dụng kinh nghiệm review mã để truyền đạt mô tả/yêu cầu cần thiết chỉ với lượng nhập liệu tối thiểu
  • Tổng kết
    • Môi trường container giúp tích hợp xuyên suốt việc sinh mã-sửa đổi-kiểm chứng-review, qua đó cho phép phát triển dựa trên tác tử thực sự vượt ra ngoài việc chỉ viết mã đơn thuần
    • Trước đây tác giả không muốn phát triển trong container, nhưng trải nghiệm dọn dẹp/chỉnh sửa diff do tác tử tạo ra trong container lại rất thú vị và năng suất

Lời kết

  • Quá trình học hỏi và thử nghiệm công nghệ dựa trên LLM là khoảng thời gian học được sự khiêm tốn
    • Trước đây, mỗi khi bản chất của lập trình thay đổi như đa lõi, SSD hay mở rộng mạng lưới, tác giả đều thấy hứng thú, nhưng
      LLM, đặc biệt là tác tử, đang làm mới hoàn toàn chính “quy trình” coding
    • Khác với những thay đổi từng ảnh hưởng đến lựa chọn thuật toán, ngôn ngữ hay thư viện,
      tác tử đang buộc chúng ta xem xét lại tận gốc mọi giả định về chính cách làm việc
    • Mức thay đổi lớn đến mức đôi khi tác giả cảm thấy “có lẽ sẽ tốt hơn nếu học lại từ đầu trong trạng thái hoàn toàn không biết lập trình”
    • Và sự thay đổi này vẫn đang tiếp diễn ngay lúc này
  • Cách chúng ta đang trải nghiệm hiện nay đã hoàn toàn khác cả 6 tháng trước, và vẫn chưa hề ổn định
    • Các chuẩn mực về văn hóa phát triển như cộng tác nhóm hay review cũng có vẻ sẽ sớm thay đổi lớn
    • Ví dụ, code review mang tính hình thức không còn giải quyết được vấn đề thực chất nữa
      • Đã đến lúc phải phát minh lại chính quy trình code review
    • IDE cũng vậy, trái với tính tích hợp mà nó từng theo đuổi, giờ là lúc phải đại tu hoàn toàn
    • Trong ngành, người ta cũng đã nhận ra sự thay đổi này, nhưng cách tiếp cận lấy tác tử làm trung tâm mới chỉ đang ở giai đoạn khởi đầu
    • Những thay đổi lớn hơn nữa đã được báo trước, và
      sự tò mò và khiêm tốn là cách duy nhất để đi qua thay đổi đó một cách tốt đẹp
    • Thậm chí, lúc này có lẽ tốt hơn là tránh xa các diễn đàn Internet về công nghệ,
      giao cả những cuộc thảo luận và tóm tắt kiểu này cho tác tử

1 bình luận

 
GN⁺ 2025-06-13
Ý kiến trên Hacker News
  • Tôi chủ yếu chỉ code cho các công cụ của riêng mình, nên thật lòng không thấy nhiều giá trị ở việc để một ai đó hoặc một thứ gì đó khác viết code thay mình, rồi sau đó tôi lại phải đọc, hiểu và sửa nó; tất nhiên, nếu nhờ LLM tìm đúng phần tôi cần trong tài liệu API thì rất hữu ích và tiết kiệm thời gian đáng kể, nên bất kể hiệu năng tương lai của LLM có cải thiện hay không, tôi vốn đã không thích đọc code của người khác

    • Với tôi, có những trường hợp LLM thực sự hữu ích, ví dụ trong code có tính khuôn mẫu thì nó có thể khiến macro hay code generator trở nên không cần thiết; tuy chậm và khó cập nhật toàn bộ một lần như macro, nhưng với những đoạn code lặp lại có khác biệt nhỏ thì LLM lại hữu ích hơn macro; thêm nữa, khi dùng một API quen thuộc nhưng không nhớ từng dòng code, tôi có thể làm việc ngay mà không cần Google hay lục tài liệu; vì tôi dùng ngôn ngữ có kiểu nên nếu LLM nói linh tinh thì type checker hoặc test sẽ chặn lại, nên cũng không quá lo; và khi cần thay đổi trải dài hơn 10 file, việc nó lập kế hoạch thay đổi bằng Markdown thực sự tiết kiệm rất nhiều thời gian; cuối cùng, lúc mệt tôi dễ bỏ qua style hay quy tắc đặt tên, còn LLM thì giữ khá tốt phong cách sẵn có của dự án nên điều đó rất hay
    • Gần đây tôi ngày càng thích làm việc theo kiểu này hơn: trước hết lên kế hoạch cho toàn bộ thiết kế code, rồi giải thích các bước cụ thể cho LLM, trong lúc tôi đọc, hiểu, sửa code và lên bước tiếp theo thì LLM làm trước phần code của mục tiếp theo; có thể nói là tôi và LLM làm việc song song; nó giống như đầu bếp trong nhà hàng, khi có order thì lập tức hình dung toàn bộ các bước nấu, rồi trong lúc nướng steak vẫn tranh thủ làm các khâu chuẩn bị khác thay vì ngồi chờ; LLM gần với các dụng cụ bếp như lò nướng hay food processor hơn; ví dụ có thể bào phô mai bằng tay, nhưng cho vào food processor thì tiết kiệm được vài phút; đầu bếp chuyên nghiệp tăng hiệu quả bằng cách tận dụng đủ loại công cụ để multitask, và tôi nghĩ sau này việc code cũng có thể chuyển từ kiểu từng dòng từng bước sang cấu trúc multitasking
    • Về câu hỏi lợi ích của việc đẩy trách nhiệm viết code sang thứ khác rồi cuối cùng vẫn phải đọc, hiểu và tự sửa, tôi dùng từ “ma sát”; nhiều người thấy khó bắt đầu một việc mới, kiểu writer’s block, và nếu đã có sẵn một lời giải do ai đó tạo ra thì việc chỉnh lại theo cách của mình rồi module hóa sẽ làm giảm đáng kể rào cản nhập cuộc; tôi và đồng nghiệp có nhiều người thấy gánh nặng rất lớn khi phải dựng toolchain và bootstrap dự án từ số 0; nếu có đủ ngữ cảnh và tài nguyên, LLM còn có thể quét nhanh cả codebase để phát hiện kiểu như “trong code này đã có hai cơ chế audit rồi, hãy tách phần chung ra”, tức là tự động chỉ ra cả những điểm mà chính tôi có thể bỏ sót
    • Ở một codebase tôi làm việc có rất nhiều tác vụ phải sửa đi sửa lại nhiều file một cách nhỏ lẻ; loại việc này không đòi hỏi sáng tạo hay thử thách gì, chỉ đơn thuần là mở nhiều file và chỉnh sửa lặp đi lặp lại; trước đây mất 3–4 tiếng, nhưng nếu mô tả công việc cho AI agent thì nó tự lo được 99%, và thời gian chỉ còn 3–4 phút
    • Có những người là kiểu không có công cụ thì chẳng làm được gì; những người này trở thành early adopter và power user, rồi lan truyền các khám phá mới; giá trị của GitHub là tạo ra một môi trường nơi lập trình viên bình thường có thể trông như đang làm việc hiệu quả thông qua PR, review, ô xanh, danh sách todo, v.v.; LLM cũng vậy: nó cho phép lập trình viên bình thường chạy những công cụ và agent không mấy quan trọng mà vẫn tạo được hình ảnh năng suất, nên các manager rất thích
  • Tôi hoàn toàn đồng ý với tác giả ở đoạn nói rằng code review hiện rất hời hợt và gần như không hoạt động đúng nghĩa; trong thời đại agent viết code, nút thắt thật sự không còn là viết mà là đọc code; nếu mọi người review qua loa hoặc chỉ dùng review như chỗ thể hiện sở thích cá nhân, agent hoàn toàn có thể nhét vào các vấn đề nghiêm trọng về bảo mật hay hiệu năng; nói thật, vấn đề thực sự thường không lộ ra chỉ bằng cách đọc code, mà cần tự tay debug hoặc kiểm chứng các giả định

    • Tôi thấy chưa rõ code agent/AI sẽ giải quyết bài toán “review hời hợt” này như thế nào; mọi người vốn đã không muốn review code vì nó chán; tôi lo rằng phần thú vị là “viết code” sẽ bị giao cho AI, còn con người thì chỉ còn lại việc đọc và kiểm tra code bất tận
    • Điểm thiếu nhất trên thị trường hiện tại là làm sao đọc, review đúng cách và hiểu hiệu quả code, diff và toàn bộ codebase do LLM tạo ra; nếu trong dự án chỉ còn lại rất ít người, tôi lo liệu họ có thực sự đọc code hay chỉ lướt qua cho xong
    • Điểm cốt lõi của agent là nếu có test coverage đủ tốt thì AI có thể viết code và còn nhận được phản hồi về độ an toàn/hiệu năng; hơn nữa chính AI cũng hỗ trợ viết test
  • Cuối cùng cũng thấy một bài phân tích thực tế về LLM; việc dùng từ “agent” làm tôi hơi bức bối vì về cơ bản nó chỉ là cái tên đặt cho một vòng for gọi LLM một cách đệ quy, nhưng khả năng đặt tên của ngành này xưa nay cũng vốn chẳng cao hơn mức trung bình bao nhiêu nên cứ chấp nhận vậy

    • Tôi không hoàn toàn cùng định nghĩa “agent” với người viết; thực ra nó là cấu trúc trong đó LLM gọi công cụ và tài nguyên theo vòng lặp; khác biệt tuy nhỏ nhưng liên quan đến việc xác định đâu mới là chủ thể chính
    • Tôi thích cách nói “agent là công cụ được đặt trong một vòng lặp”; tôi nhớ Simon từng nói như vậy
    • Tôi hơi khác quan điểm với định nghĩa agent của OP; đặc trưng thực sự không chỉ là LLM chạy vòng lặp, mà là hành vi của LLM được ràng buộc hoặc dẫn dắt bởi các thành phần logic khác; một số thành phần là quyết định luận, số khác dựa trên ML, bao gồm cả LLM; nói cách khác, ta có thể tạo thêm ích lợi bằng cách buộc LLM trong một hệ thống được thiết kế sẵn phải lập kế hoạch theo cách nào đó, hoặc tự động kích hoạt build và chạy test sau khi chỉnh sửa code; mô tả “agent tự nhận đầu vào rồi tự vận hành” không hẳn sai, nhưng bản chất hơn là có nhiều thành phần thường xuyên giám sát và định hướng hành vi của LLM
    • Bản thân cách đặt tên “Agent” tôi thấy vẫn ổn vì người ta dễ hiểu trực giác, nhưng nếu cần một lựa chọn khác thì tôi từng nghĩ đến cái tên như LoopGPT
  • Liên quan đến đoạn “chúng ta đồng ý rằng container hữu ích và cần thiết trong lập trình”, có giải thích vì sao Solomon Hykes, người tạo ra Docker, gần đây open source dự án Container Use: để agent có thể chạy song song một cách an toàn; một số nền tảng như Sketch có sẵn môi trường phát triển cục bộ cách ly, nhưng các coding agent khác thì không; ngoài ra cũng khuyên xem thêm video YouTube

  • Vòng lặp agent, bộ não trong máy, về cơ bản trông giống một vật thay thế cho rules engine; nó vẫn có những nhược điểm riêng, nhưng tôi nghĩ nhiều cao thủ đã chỉ ra đúng bản chất; kiểu như “nối các công cụ cho agent, prompt theo yêu cầu người dùng, cứ chạy và lặp, còn bản thân prompt cũng thay đổi động theo ngữ cảnh”; ngay cả khi không cố bắt chước tương tác hay cách giải quyết vấn đề của con người thì nó vẫn cực kỳ hữu ích cho orchestration/nhiều bước, thay thế hay tự động hóa các tác vụ mơ hồ; trước đây phải tự code phần mơ hồ đó, giờ có thể không còn cần nữa; trong môi trường production vẫn có lo ngại khi cho chạy mà không có dry run, nhưng tôi nghĩ bản thân công cụ và dịch vụ sẽ tiếp tục tiến hóa; nếu hơn 100 dịch vụ tương tự được nối với thế giới bên ngoài bằng một giao diện nhất quán, ví dụ SMS, mail, thời tiết, mạng xã hội, thì có thể xuất hiện những assistant mạnh hơn rất nhiều, thậm chí vượt xa mức đó

    • Có một toy project thú vị nối agent với nhiều dịch vụ như lịch, thời tiết để tạo thành giao diện game, link
    • Nếu abstraction được thống nhất cho mọi công cụ sử dụng thì nó có thể vượt xa các assistant hiện tại, nhưng đồng thời cũng phải chấp nhận khả năng xảy ra sự cố và lỗi ở mức khổng lồ; các vấn đề như reliability engineering, QA, quản lý quyền hạn, bảo mật, quyền riêng tư sẽ ngày càng quan trọng hơn; tôi đoán đó cũng có thể là lý do Apple chưa tung ra một voice assistant mới vượt qua giới hạn của Siri, vì bài toán quản trị rủi ro này
  • Đọc code từ trước đến nay vẫn luôn quan trọng ngang với viết code, nhưng giờ thì nó ngày càng quan trọng hơn; đúng là cơn ác mộng của tôi; viết code đôi khi còn vui, chứ đọc code thì lúc nào cũng là lao động

    • Dù vậy, có thể niềm vui ở việc “sửa code” vẫn còn nguyên, hoặc thậm chí còn tăng lên
  • Tôi tò mò không biết trong số những người dùng agent, có bao nhiêu người thực sự thích “lập trình”, tức là thích cả việc suy nghĩ cách giải quyết vấn đề lẫn niềm vui diễn đạt nó bằng code; nhìn nhiều cách dùng agent hiện nay thì quá trình đó dường như biến mất, thay vào đó chỉ còn mô tả yêu cầu bằng ngôn ngữ tự nhiên rồi hy vọng LLM đừng tạo bug

    • Tôi là kiểu người thích việc code, và khi LLM làm ra ngay một parser mà lẽ ra tôi sẽ thấy vui khi tự viết thì tôi cũng có cảm giác hụt hẫng; nhưng bù lại tôi có thể tập trung vào mục tiêu lớn hơn thay vì tốn thời gian cho parser; việc chỉ cần định nghĩa sẵn type/chữ ký hàm mong muốn rồi để LLM điền phần triển khai chi tiết, từ đó có thể chuyển ngay sang bước tiếp theo, là điều rất ấn tượng; trước đây những chỉnh sửa toàn cục kiểu “nên sửa thì tốt nhưng lười quá” là gánh nặng lớn, còn giờ LLM hỗ trợ cả việc làm sạch code, tạo test, đồng bộ README và gợi ý refactor, nên mức độ hoàn thiện và tham vọng của dự án lại tăng lên; nếu điều chỉnh được tư duy thì đây có thể xem là thiên đường cho những builder thích làm phần mềm
    • Ở chiều ngược lại, với những bài toán tôi đã giải đi giải lại hàng nghìn lần thì tôi chẳng thiết tự tay hiện thực nữa; lúc đó tôi dùng dictionary chứ không đi viết lại hash table; nếu bảo “hãy viết compiler cho ngôn ngữ này” hoặc “hãy giải bằng DFS” mà kết quả ra hoàn hảo thì chưa chắc niềm vui lập trình lại giảm; ngôn ngữ tự nhiên có giới hạn là ở mức độ phức tạp cao nó dễ thiếu chính xác hoặc dẫn đến mâu thuẫn khi mô tả quy trình tính toán; dù theo hướng nào thì cũng chẳng ai khuyến khích dùng LLM một cách vô thức, và rốt cuộc tôi vẫn phải chịu trách nhiệm về kết quả
    • Tôi dẫn EWD667 làm cơ sở cho quan điểm rằng ngôn ngữ tự nhiên không phù hợp để lập trình; đúng là LLM có ích với các câu hỏi-đáp kiểu stackoverflow, nhưng nếu sau này dữ liệu của SO giảm đi thì ngay cả điểm đó cũng sẽ gặp giới hạn
    • Tôi thì không đồng ý; phần lớn những gì LLM đang làm là công việc triển khai lặp đi lặp lại và nhàm chán; tôi vẫn giữ lại những phần thú vị như kiến trúc dự án, hay các phần sáng tạo/độ khó cao mà ngay cả LLM cũng khó; có thể một năm nữa mọi thứ sẽ khác, nhưng hiện tại tôi hài lòng vì có thể chỉ tập trung vào phần thực sự cần suy nghĩ
    • Tôi là tác giả bài viết, và tôi thích cả lập trình lẫn agent
  • Có vài lĩnh vực khi code mà tôi rất thích dùng AI (đúng là tôi tự viết điều này đấy!):

    • CSS: Tôi ghét làm CSS ở bất kỳ website nào, nhưng AI nhớ hết các mẹo CSS phức tạp nên rút ngắn đáng kể thời gian; ví dụ cả trong một hệ WordPress phức tạp, căn giữa một div cụ thể cũng làm được khá nhanh chỉ sau vài lần thử sai
    • Unit test: Khi dữ liệu code mà AI được học chưa quá cũ thì trải nghiệm tạo test cũng khá thú vị
    • Tóm tắt commit: Bản nháp đầu tiên là đủ dùng
    • Cả những bài tập rất nhỏ ở mức năm nhất cũng xử lý nhanh được
    • Thú vị là ở phía tôi, AI lại có vẻ không viết CSS tốt lắm nên có lúc tôi thấy nó khá vô dụng; nhưng tôi hoàn toàn đồng cảm với việc nó làm thay những công việc mình không thích; với tôi, ví dụ đó là viết mô tả ticket, AI làm tốt hơn tôi nhiều
    • Nếu tôi hiểu nhầm thì xin lỗi, nhưng nếu bạn chưa quen với xu hướng CSS gần đây thì có thể đáng để dành vài tiếng cập nhật, vì CSS bây giờ ít phức tạp và dễ quản lý hơn trước nhiều; dù vậy, bản thân tôi cũng dùng AI khá nhiều cho việc styling
  • Đoạn về “tài sản” và “nợ” thì thú vị nhưng tôi không đồng ý; nhiều chương trình ban đầu chỉ dành cho một nhóm nhỏ người dùng rồi sau đó lại thành dự án lớn là chuyện rất thường; trước đây tôi đã quá nhiều lần thấy những đoạn code khoa học viết qua loa để dùng một lần rồi vô tình bị kéo dài thời gian sử dụng hoặc mở rộng phạm vi vượt ngoài dự tính; vì vậy tôi viết code với sự cân nhắc rằng nó có thể được dùng lâu hơn và rộng hơn nhiều, thậm chí là vì sự tôn trọng đối với chính mình và người khác; nếu từng thấy một side project cá nhân của đồng nghiệp bị manager nâng thành dự án cấp phòng ban thì hẳn sẽ đồng cảm với vấn đề này

    • Dù vậy tôi vẫn băn khoăn “thế lựa chọn khác là gì?”; con người rất kém trong việc dự đoán thứ gì sẽ được chấp nhận rộng rãi; thực tế thường là dự án được đầu tư công sức lại chẳng ai dùng, còn dự án lỏng lẻo nhưng làm nhanh thì thành công vì chịu áp lực tiến hóa theo hướng đó; ở đây có thể nhắc tới bài kinh điển “worse is better” (link)
  • Tôi nghĩ dùng LLM cho code review, chứ không phải viết hay thiết kế code, mới có thể là tính năng killer thực sự; hiện tại bản thân code review đã hỏng ở nhiều khía cạnh, và về sau tôi kỳ vọng vai trò của LLM sẽ tăng lên trong các việc như bảo mật, undefined behavior, phát hiện lạm dụng chức năng, hay kiểm tra chéo các cảnh báo của compiler; cá nhân tôi chủ yếu dùng LLM như một kiểu search engine để chẩn đoán lỗi hoặc debug, tỷ lệ đúng cỡ 50% và như vậy là đủ khiến tôi hài lòng

    • Nếu là vấn đề đã được bàn luận nhiều trên web thì ChatGPT đã rất giỏi cho việc debug; nó tóm tắt và tổng hợp kiến thức kiểu Stack Overflow nên tiết kiệm rất nhiều thời gian so với việc đi tìm từng trường hợp; tuy nhiên câu trả lời của LLM vẫn lẫn cả bịa đặt/hallucination nên còn khá nhiều nhiễu; nếu review toàn bộ code thì nó có thể tìm được dạng lỗi hoặc hàm/lời gọi có vấn đề khá tốt, nhưng ngược lại chắc chắn cũng sẽ có nhiều false positive; tôi tò mò không biết có ai đang thực sự dùng LLM cho auto review code một cách bài bản không
    • Nếu cứ lặp đi lặp lại yêu cầu “hãy review đoạn code này”, chatbot có thể bảo đổi X thành Y, rồi một lúc sau lại bảo đổi Y về X; nó có hiệu quả ở mức nào đó cho code review, nhưng cuối cùng vẫn phải tự quyết định cái nào nên chấp nhận, cái nào nên bỏ; với người đủ tỉnh táo để phân biệt thì nó thực sự là công cụ đưa ra các thay đổi ứng viên rất tăng năng suất
    • Tôi tự hỏi vì sao chủ đề này không được thảo luận rộng hơn; các dev quanh tôi có mức độ hứng thú với công nghệ rất khác nhau, thường người càng ít năm kinh nghiệm càng dùng tích cực, còn senior thì ít quan tâm hơn; tôi gần như chưa nghe ai nói về việc dùng AI cho review/xác minh code, có lẽ vì cần một tính năng tự động làm việc đó ngay tại thời điểm commit
    • LLM chuyên cho code review đã có trong GitHub Copilot dưới dạng reviewer mode, thay vì code review/design; tuy chưa phải đỉnh cao nhất nhưng chất lượng đã đủ ổn để đưa vào loop sử dụng
    • Đồng ý, chúng tôi đang làm việc đó tại sourcery.ai