1 điểm bởi GN⁺ 2025-05-16 | 1 bình luận | Chia sẻ qua WhatsApp
  • Thông qua trải nghiệm phát triển Sketch, trợ lý lập trình AI, bài viết nhấn mạnh cách triển khai ngắn gọn của cấu trúc vòng lặp kết hợp LLM và sử dụng công cụ
  • Chỉ với 9 dòng mã vòng lặp, các LLM hiện đại như Claude 3.7 Sonnet có thể nhanh chóng giải quyết các vấn đề thực tế
  • Chỉ cần một công cụ đa dụng như bash cũng có thể tự động hóa phần lớn các công việc lặp đi lặp lại và khó nhằn của lập trình viên
  • Không chỉ giải quyết vấn đề, việc kết nối thêm các công cụ chỉnh sửa văn bản hoặc công việc chuyên biệt còn có thể nâng cao chất lượng và tốc độ lặp lại của công việc
  • Xu hướng ngày càng nhiều vòng lặp tác nhân LLM tùy chỉnh được đưa vào tự động hóa công việc hằng ngày của lập trình viên

Mở đầu: trải nghiệm phát triển và dự án Sketch

  • Trong quá trình phát triển Sketch, công cụ hỗ trợ lập trình dựa trên AI, Philip Zelig và các đồng nghiệp đã ngạc nhiên trước hiệu quả cao của cấu trúc vòng lặp tác nhân đơn giản kết hợp LLM với việc tận dụng công cụ
  • Cấu trúc cốt lõi chỉ gồm 9 dòng mã vòng lặp, truyền system prompt, lịch sử hội thoại và tin nhắn mới nhất tới API của LLM
  • LLM tạo đầu ra và khi cần sẽ trả về tool_calls (yêu cầu gọi công cụ)

Tích hợp LLM và việc sử dụng công cụ

  • "Sử dụng công cụ" (tool use) là việc LLM trả về đầu ra phù hợp với schema được định nghĩa trước, đồng thời thông qua system prompt và prompt mô tả công cụ, LLM có thể truy cập các công cụ đa dụng như bash
  • Các LLM hiện đại (ví dụ: Claude 3.7 Sonnet) có thể nhanh chóng tự động hóa nhiều vấn đề chỉ với một công cụ đa dụng duy nhất, và một số trường hợp còn giải quyết được chỉ trong một lần chạy ("one shot")
  • Trước đây phải tìm, sao chép và dán các lệnh git phức tạp rồi tự merge thủ công, nhưng giờ chỉ cần yêu cầu Sketch là có thể xử lý ngay
  • Nhiều lỗi kiểm tra kiểu phát sinh sau khi thay đổi type cũng đã được Sketch tự động xử lý lần đầu tiên
  • Vòng lặp tác nhân hoạt động liên tục và thích ứng, tự động cài công cụ khi chưa có và tùy biến để phù hợp với khác biệt về tùy chọn lệnh
  • Trong lúc sử dụng, đôi khi LLM đưa ra các đề xuất bất ngờ như "bỏ qua test" khi test thất bại, nhưng nhìn chung chất lượng tự động hóa công việc vẫn được cải thiện

Đa dạng hóa và chuyên biệt hóa công cụ

  • Sketch nhận thấy rằng ngoài bash, việc sử dụng các công cụ bổ sung (ví dụ: công cụ chỉnh sửa văn bản) có thể nâng cao chất lượng công việc và giúp quy trình phát triển hiệu quả hơn
  • Việc để LLM chỉnh sửa chính xác văn bản bằng sed và các công cụ tương tự khó hơn dự đoán, và các công cụ theo kiểu trình biên tập trực quan (visual editor) tỏ ra tốt hơn

Triển vọng tương lai và thay đổi trong quy trình làm việc

  • Cấu trúc vòng lặp tác nhân được dự đoán sẽ ngày càng được dùng nhiều hơn cho các công việc lặp lại trong đời sống hằng ngày của lập trình viên, vốn khó xử lý bằng các công cụ tự động hóa đa dụng trước đây
  • Ví dụ, những công việc phiền phức và lặp đi lặp lại như phân tích mối tương quan giữa stack trace và git commit cũng có thể được LLM xử lý nhanh ở bước đầu
  • Trong tương lai, có thể kỳ vọng nhiều vòng lặp tác nhân LLM tùy biến, dùng một lần sẽ được sử dụng trong thư mục bin/ của lập trình viên và các môi trường tương tự
  • Người dùng chỉ cần chuẩn bị bearer token mong muốn là có thể dễ dàng thử nghiệm trong môi trường của mình

Liên kết tham khảo

1 bình luận

 
GN⁺ 2025-05-16
Ý kiến Hacker News
  • Tôi cũng rất muốn mạnh mẽ giới thiệu bài blog này. Đây là một phiên bản trình bày cùng luận điểm nhưng chi tiết và thuyết phục hơn nhiều. Tác giả thực sự đã tự tay xây dựng một coding agent từ đầu. Xem https://ampcode.com/how-to-build-an-agent. Đây thật sự là một trải nghiệm đáng kinh ngạc về việc LLM có thể xử lý tốt đến mức nào nhiều loại tác vụ khác nhau trong một vòng lặp nơi nó có thể gọi công cụ. Dĩ nhiên nó không hoàn hảo, và vẫn có những vấn đề như chưa thể đạt độ tin cậy 100%. Nhưng tôi nghĩ ít nhất vẫn có điều gì đó đáng để thán phục. Nếu tự làm thử thì có thể làm theo trong vòng 30 phút. Đây là phần khiến người ta vừa có thể cảm thấy kinh ngạc, vừa vẫn giữ được sự hoài nghi lành mạnh về việc AI có hiệu quả cho một mục đích cụ thể hay không. “Hiệu quả bất thường” này của việc đặt LLM vào trong một vòng lặp chính là lý do hiện nay có vô số code generation agent xuất hiện: Claude Code, Windsurf, Cursor, Cline, Copilot, Aider, Codex v.v., chưa kể cũng có rất nhiều dự án làm theo. Đó là lý do không có bí kíp đặc biệt nào cả, và 95% phép màu cuối cùng vẫn là bản thân LLM cùng với việc nó được fine-tune để thực hiện tool calling. Đây là điều mà lead developer của Claude Code cũng đã thẳng thắn thừa nhận trong một cuộc phỏng vấn gần đây. Tất nhiên, để những công cụ này hoạt động tốt thì vẫn cần rất nhiều công sức, nhưng về căn bản thì chúng gần như đều có cùng một cấu trúc lõi đơn giản
    • Tôi đã tìm kiểu bài viết như thế này từ rất lâu rồi, nên thực sự thấy biết ơn. Nhiều người nhìn vào Agents và phản ứng kiểu “chắc nó không giải được những vấn đề thực sự phức tạp đâu nhỉ?”, nhưng theo tôi thì đó không phải luận điểm cốt lõi của agent. LLM hoạt động cực tốt khi có nhiều context, và agent là cấu trúc giúp LLM tìm thêm context để nâng cao chất lượng câu trả lời cho câu hỏi
    • Theo trải nghiệm của tôi, không nghĩ ra được nhiều công việc mà LLM có thể tự làm tốt trong vòng lặp quá vài lần mà không cần chỉ dẫn thêm. Lặp vài lần là kiểu gì cũng đến lúc tôi phải can thiệp
    • Có một tutorial làm thứ tương tự bằng thư viện trừu tượng hóa đồ thị tên là pocketflow. Tôi đã dùng thử thực tế và rất hài lòng vì nó khá đơn giản. https://github.com/The-Pocket/PocketFlow-Tutorial-Cursor/blob/main/blog.md
    • Giờ tôi mới nhận ra tác giả là Thorsten Ball. Tôi nhớ đã đọc rất thích cuốn “làm interpreter” của ông ấy. Có lẽ giờ tôi cũng sẽ thử làm agent
    • Trước khi mở link ở trên, tôi phân vân có nên thêm ?utm_source=hn&utm_medium=browser hay không
  • Hôm nay lần đầu tôi trực tiếp thử “vibe-coding” với GPT-4o và 4.1. Cách làm là thủ công nhập lỗi biên dịch, cảnh báo và gợi ý qua giao diện canvas theo kiểu chạy vòng lặp. File khá nhỏ, khoảng 150 dòng. Tôi bắt đầu với 4o, nhưng nó dùng package đã lỗi thời. Ngay cả khi tôi chỉ ra điều đó, nó cũng không cập nhật mọi chỗ sử dụng và tôi phải tự sửa. Khi tôi đề xuất thay đổi logic thì nó làm hỏng hoàn toàn cú pháp, và sau đó không bao giờ khôi phục lại được. Dù tôi liên tục nhập lỗi biên dịch, nó vẫn không hiểu vấn đề cú pháp mà chỉ sửa ngẫu nhiên các phần khác của mã. Vì thế tôi kỳ vọng 4.1 sẽ làm tốt hơn, nhưng 4.1 lại từ chối dùng canvas và chỉ giải thích suông. Kiểu như bảo tôi tự sửa lấy. Tôi phải thuyết phục mãi nó mới chịu xuất code vào canvas, nhưng lần này thì phần giữa lại bị cắt kiểu “// omitted for brevity” nên không dùng được. Tôi bỏ cuộc ở đó. Không biết các agent có giải quyết được vấn đề này không. Hiện tại tôi cảm thấy trải nghiệm này hoàn toàn hỏng hóc, và trong trạng thái như vậy thì việc cho quyền truy cập bash là quá nguy hiểm
    • Việc “dùng package lỗi thời” là do mốc dữ liệu huấn luyện của model bị cắt. Đó là điểm luôn phải chú ý khi dùng LLM. Tôi thường chuyển sang dùng o4-mini-high trong ChatGPT. Model này còn có thể dùng tính năng search để tìm tài liệu mới nhất. Nếu yêu cầu kiểu “hãy kiểm tra phiên bản mới nhất của thư viện X rồi dùng nó”, đôi khi nó xử lý khá tốt. Gần đây tôi có việc chuyển một phần mã JavaScript sang thư viện mới được Google khuyến nghị; tôi chỉ cần dán mã cũ vào và yêu cầu nó port sang thư viện mới, nó đã tự tìm tài liệu và port rất chính xác. https://simonwillison.net/2025/Apr/21/ai-assisted-search/#lazily-porting-code-to-a-new-library-version-via-search
    • GPT 4.1 và 4o có điểm rất thấp trên benchmark code của Aider. Theo trải nghiệm thực tế thì phải trên 70% thì kết quả mới thực sự hữu ích. Dù vậy, với việc phức tạp thì vẫn cần hỗ trợ đáng kể. Dùng dần thì sẽ có cảm giác cái gì làm tốt, cái gì không. https://aider.chat/docs/leaderboards/
    • Có thể bạn không thích nghe câu “đó là vấn đề kỹ năng”, nhưng dùng LLM rõ ràng là một lĩnh vực đòi hỏi kỹ năng riêng. Cần hiểu ưu nhược điểm của nhiều công cụ, thử nghiệm nhiều kỹ thuật, và luyện tập là thành phần bắt buộc. Nếu cho quyền truy cập bash thì tôi cũng sẽ chỉ dùng trong môi trường container (docker)
    • Thế thì chưa thể gọi là vibe coding. Muốn vibe coding thì phải dùng công cụ có thể tự động áp dụng thay đổi vào mã. Nếu cứ phản hồi thủ công từng cái một thì sẽ bị mắc kẹt ở lỗi và dừng lại. Cốt lõi của vibe coding là có thể hoàn tác, chạy lại, dễ dàng ném ra rồi bỏ đi nhiều cách giải khác nhau. Muốn có trải nghiệm đó thì cần tooling
    • Cách đây không lâu tôi đã dùng plugin Cline với Claude trong VSCode để tạo nguyên mẫu một ứng dụng Android “từ con số 0”. Tôi bắt đầu từ template mặc định của Android Studio, rồi nó sinh ra hàng nghìn dòng mã mà không có nổi một lỗi biên dịch. Ứng dụng chạy đúng như mong đợi, và vài bug phát hiện được cũng không phải do LLM mà vì hành vi Android API kỳ quặc. Tôi chỉ ra bug cho LLM và cung cấp output debug log, nó tự sửa được. Ban đầu sửa có hơi vụng, nhưng sau vài lần phản hồi qua lại thì giải quyết ổn. Nếu chạy code writing agent và code review agent trong vòng lặp thì có lẽ những phần này còn có thể được xử lý tốt hơn một cách phổ quát
  • Tôi đã dùng Claude Code, tức giao diện terminal của Sonnet 3.7, từ đúng ngày ra mắt. Tôi đã viết ứng dụng CLI khá lớn, hệ thống web full-stack, và vô số utility bằng nó. Tôi thấy mình dám nhận những thử thách tham vọng hơn hẳn, giống như hồi còn dẫn dắt một team lập trình. Về mặt cấu trúc thì chắc nó cũng không khác các tool khác bao nhiêu, nhưng có cảm giác Anthropic đã thêm vào rất nhiều tính năng cực kỳ hữu ích. Không có gì là hoàn hảo, và để có chất lượng code tốt thì giờ đây vẫn cần mức nỗ lực tương tự như trước. Những thứ khá phức tạp vẫn có thể chạy được, nhưng cũng thường rơi vào tình huống khó thêm tính năng tiếp theo. Khi đã quen cách sử dụng thì lượng refactor và vá víu giảm đi rất nhiều. Có lẽ đây là thứ sẽ không bao giờ biến mất hoàn toàn. Thành thật mà nói, tôi khó có thể hình dung ra vấn đề mà kgeist gặp phải. Claude đôi khi cũng làm điều ngu ngốc hoặc khác với lựa chọn của tôi, nhưng chưa bao giờ đến mức khiến tôi muốn bỏ cuộc. Nó gần như luôn cho ra kết quả ổn, và mức độ gỡ bớt gánh nặng khỏi đầu óc tôi là cực lớn. Hơn nữa, nó refactor cực kỳ giỏi. Cứ định kỳ xem lại code rồi bảo Claude giải thích cách làm tốt hơn thì độ phức tạp giảm hẳn. Những yêu cầu như “thay đổi cấu trúc dữ liệu” cũng được xử lý ngay. Đó là một tính năng cực kỳ hay. Và cho vui, tôi còn mở cả một thư mục archive 30 năm tuổi chất đầy đủ thứ linh tinh không phải code. Hỏi kiểu “trong thư mục này có gì?”, “đọc CV cũ của tôi rồi viết lại giúp”, “tên các con tôi là gì?” v.v. mà cũng thật sự rất ấn tượng. Dù vẫn còn ở giai đoạn đầu, tôi vẫn thấy rất hạnh phúc
    • Gần đây tôi có tình huống phải xử lý tất cả cùng lúc: định nghĩa cấu trúc dữ liệu từ xa, đặc tả API, triển khai parsing và lưu trữ, rồi hiển thị cho người dùng. Claude đã quản lý tốt toàn bộ việc này cùng một lúc, giúp tôi lập tức thấy được những thay đổi nhỏ ở hai đầu ảnh hưởng ra sao đến tầng trung gian. Tôi lặp thử rất nhanh nhiều ý tưởng để tìm ra cách giải tốt nhất. Điều gây ấn tượng là khả năng khám phá nhiều tầng có độ phức tạp cao với tốc độ lặp nhanh như vậy vừa tăng năng suất, vừa nâng cao hiểu biết của tôi về cấu trúc tổng thể của hệ thống
    • Cái việc refactor nói ở trên thực sự là một trải nghiệm rất vui. Những việc trước đây còn khó mà đưa vào sprint thì giờ làm xong trong 5 phút. Cảm giác như có sẵn cả một team đã chuẩn bị xong, chỉ chờ tôi yêu cầu. Nếu không thích kết quả thì từ chối ngay cũng được, và mọi lo lắng về review không cần thiết hay lên lịch dường như đều biến mất
  • Việc LLM hay nói kiểu “à, test này không chạy được... thôi bỏ qua đi” thật sự quá bực. Tôi có một ý tưởng để suy nghĩ thêm. Đó là chạy kèm một policy-enforcing LLM độc lập và song song để buộc LLM chính hành động theo chỉ thị. Ví dụ, LLM phụ có thể điều chỉnh xác suất đầu ra để sau “let's just” không thể xuất hiện từ “skip”. Tức là nếu cấm “skip”, ta có thể bẻ hướng mô hình ra khỏi hành vi không mong muốn. Nó sẽ hoạt động kiểu như JSON mode hay structured output, nhưng theo cách động, thời gian thực, nơi LLM phụ kiểm soát policy. Nếu cách này hiệu quả, có thể phát triển dalshe để đưa vào prompt của LLM phụ nhiều vi phạm policy khác như xóa mã test để làm test pass, hoặc in ra các comment vô dụng, rồi để LLM phụ giám sát và điều khiển theo thời gian thực. Tôi tò mò không biết team Outlines sẽ nghĩ gì về kiến trúc như vậy
    • Nếu một LLM có thể kiểm tra đầu ra của LLM khác, thì liệu trong một LLM “mixture of experts” có thể phân một thuật toán chuyên trách làm vai trò giám sát/kiểm toán hay không? Hoặc có thể tách một luồng suy nghĩ riêng để tự xác minh đầu ra của chính nó, rồi nếu cần thì lại thêm một luồng khác để kiểm tra cả bộ xác minh đó, khiến hệ thống ngày càng vững hơn
    • Trong bối cảnh này, cũng có thể nghĩ đến cấu trúc mà khi LLM chính đi sai hướng thì LLM giám sát sẽ “rewind” mô hình về thời điểm đó; ví dụ nếu phát hiện “let's just skip the test” thì rollback về ngay sau “just ” rồi tiếp tục áp bias để ngăn một số từ nhất định xuất hiện. Để làm kiểu này thì nhà cung cấp model bạn dùng có thể sẽ bị hạn chế, và đặc biệt OpenAI gần đây có vẻ không thân thiện với những tính năng power-user như vậy
  • Sáng nay tôi dùng cursor để tách một phần phức tạp trong main loop của prototype game, rồi tự động sinh cả một bộ mã test cho phần đó. Tổng cộng có 341 test, bao phủ toàn bộ core math và các component cốt lõi. Đôi lúc cảm giác như chăn mèo, nhưng càng đưa nhiều ràng buộc hơn như hàm cần dùng cụ thể, vị trí, file template, những thứ cần tránh, thì kết quả càng tốt dần lên. Tổng cộng 3500 dòng mã test mà tôi không phải tự viết, và khi có vấn đề thì lúc nào cũng có thể xóa đi rồi sinh lại. Tôi cũng được hỗ trợ trong đủ thứ khác như tinh chỉnh độ khó, biến thể nhiệm vụ v.v.
    • Theo kinh nghiệm của tôi, tự động sinh test là trường hợp sử dụng tốt nhất của LLM. Nó xóa bỏ một cục lao động nhàm chán, lặp đi lặp lại vốn có thể tốn hàng giờ hoặc hàng ngày chỉ trong một lần. Nó còn tự cover rất nhiều edge case mà tôi không nghĩ ra, đồng thời tăng độ an toàn của code. Thật sự là một tính năng tuyệt vời trên nhiều phương diện
  • Gần đây tôi rất phấn khích với khả năng dùng công cụ của LLM. Thực ra mẹo này không mới, tôi biết đến nó lần đầu từ paper ReAcT cách đây 2 năm. Sau đó nó được dùng trong ChatGPT plugin, MCP v.v., và giờ thì hầu hết model đều được huấn luyện với ý định hỗ trợ tool call/function calling. Điều thú vị ở hiện tại là hiệu năng đã tăng nhiều đến đâu. Khả năng search rất mạnh của o3/o4-mini cũng dựa trên năng lực tool call. Qwen3 4B (Ollama 2.6GB, chạy tốt cả trên Mac) cũng làm tốt việc này. Hôm qua tại PyCon US tôi có tổ chức một workshop về xây dựng phần mềm dựa trên LLM, và nhân dịp đó đã thêm tính năng dùng công cụ vào công cụ dòng lệnh LLM của mình. Xem https://building-with-llms-pycon-2025.readthedocs.io/en/latest/tools.html. Giờ với package LLM của tôi, những việc như “đếm xem trong strawberry có bao nhiêu chữ R” có thể được xử lý ổn định bằng shell one-liner
    • Tôi rất thích cái sự kết hợp kỳ lạ giữa cảm giác vui nhộn và sức mạnh mà tính năng này mang lại
    • Không biết workshop đó có được ghi hình lại không
  • Tôi tò mò không biết agent nào dùng nhiều token nhất. cline có vẻ nằm ở nhóm đầu, còn roo thì dường như dùng ít hơn cline. Tôi muốn biết có agent nào cho phép tự cấu hình cách tương tác không, và Claude code so với các agent khác thì thế nào
  • Điểm đáng sợ là “nếu không có tool cần thiết thì nó sẽ cài thêm”. LLM quá “vâng lời”, hễ ai bảo là làm ngay. Đây là mối lo bảo mật còn nghiêm trọng hơn cả SQL injection
    • Thỉnh thoảng tôi tự hỏi không biết bao giờ thảm họa agent-based đầu tiên sẽ nổ ra. (Nhất là trong bầu không khí thị trường AI đang đổ xô gấp gáp như hiện nay.) Tôi lo rằng chỉ là vấn đề thời gian trước khi xảy ra một thảm họa không thể đảo ngược
  • Tiêu đề có vẻ lấy cảm hứng từ bài báo của Eugene Wigner “The Unreasonable Effectiveness of Mathematics in the Natural Sciences”
    • Có thể bài báo đó là nguồn gốc, nhưng tôi nghĩ nó đã trở thành một thành ngữ mang tính meme từ lâu rồi. https://scholar.google.com/scholar?q=unreasonable+effectiveness
    • Tôi lại tưởng tiêu đề lấy từ bài “Unreasonable Effectiveness of RNNs” năm 2015 của Karpathy. Tất nhiên cũng có thể suy đoán rằng chính Karpathy lại mượn tiếp từ bài của Wigner. https://karpathy.github.io/2015/05/21/rnn-effectiveness/
    • Mỗi lần thấy tiêu đề có cụm “unreasonable effectiveness”, trải nghiệm của tôi là hầu như luôn không thể đồng ý mạnh với kết luận của tác giả. Kể cả bài của Wigner. Giờ nó gần như tạo cảm giác giống định luật Betteridge
  • Chúng tôi xây dựng các công cụ để cung cấp thêm context cho chatbot AI nhúng trong sản phẩm của công ty. Chúng tôi đã thêm nhiều tính năng như log hoạt động gần đây, định nghĩa object hiện tại, tìm kiếm và duyệt các bài viết trợ giúp. Sau vài tháng trôi qua, chất lượng chatbot vẫn khiến tôi ngạc nhiên. Nếu chatbot trả lời sai điều gì, quy trình của chúng tôi là cập nhật bài viết trợ giúp liên quan cho cụ thể hơn