Chuyển tới nội dung
cd /blog

Tự cải thiện đệ quy theo ngôn ngữ: Mài giũa trí tuệ mã nguồn trên khoảng 280 ngôn ngữ

[Kiến trúc][Ngôn ngữ][Tác nhân]

> Chúng tôi hỗ trợ trí tuệ mã nguồn cho khoảng 280 ngôn ngữ. Không con người nào có thể tự tay rà soát hết được. Vì vậy chúng tôi xây dựng một vòng lặp tự cải thiện đệ quy theo ngôn ngữ — kiểm tra ngẫu nhiên, dùng LLM làm giám khảo, sửa từng thứ một, xác thực lại — và chạy nó với một đội quân agent cách ly cho đến khi việc trích xuất thực sự đúng, chứ không chỉ xanh (green).

Các con số trong bài này phản ánh hệ thống tại thời điểm xuất bản (tháng 5/2026). Xem trang team của chúng tôi để biết số liệu hiện tại.

Maguyva trích xuất symbol, tham chiếu, và một đồ thị phụ thuộc từ mã nguồn trong khoảng 280 ngôn ngữ. Mỗi ngôn ngữ là một handler tree-sitter tùy chỉnh — truy vấn, heuristic, trường hợp biên — và mỗi handler đều có thể sai một cách tinh vi theo cách riêng của nó. Một lệnh gọi method bị phát ra như một lượt đọc. Một hàm bị gán cho sai phạm vi bao quanh. Một quan hệ đơn giản là không tồn tại.

Bạn không thể tự tay rà soát hết điều đó. Không đội nào có thể đọc kết quả trích xuất trên 280 ngữ pháp và phát hiện những cạnh (edge) sai. Vì vậy câu hỏi thú vị không phải là “việc trích xuất của chúng ta có đúng không” — mà là “làm sao bạn phát hiện ra nó sai, ở quy mô này, mà không cần con người trong mọi vòng lặp.” Câu trả lời của chúng tôi là tự cải thiện đệ quy theo ngôn ngữ: một vòng lặp chất lượng được điều khiển bởi các language agent, một LLM đóng vai giám khảo, và một quy tắc chúng tôi liên tục học lại: xanh (green) không đồng nghĩa với đúng.

Xanh không có nghĩa là đúng

Mỗi ngôn ngữ có một bộ fixture, và một cổng phát hành chấm điểm nó trên năm chiều — độ chính xác, tính toàn vẹn cấu trúc, độ đầy đủ, chất lượng, và hiệu năng. Một ngôn ngữ chỉ đạt XANH (GREEN) khi, trên các fixture của nó, precision ≥ 0,95, recall ≥ 0,99, và F1 ≥ 0,97, với ít nhất 20 edge kỳ vọng để có độ tin cậy thống kê. Dưới mức đó là VÀNG (YELLOW) hoặc ĐỎ (RED), và nó không được lên sóng.

Cổng đó là cần thiết nhưng chưa đủ. Fixture được xác thực dựa trên các fixture do chính chúng tôi viết. Chúng mã hóa những trường hợp chúng tôi đã nghĩ tới. Một handler có thể hoàn hảo trên các fixture của nó nhưng vẫn làm hỏng một mẫu chỉ xuất hiện trong mã thực tế — một thành ngữ macro, một method ràng buộc generic, một tính năng ngôn ngữ mà chưa ai viết fixture cho nó. XANH nghĩa là các fixture đều đạt. Nó không có nghĩa là một repo thực tế được trích xuất sạch sẽ. Vì vậy vòng lặp phải bỏ lại các fixture và nhìn ra thế giới hoang dã.

Vòng lặp trong: kiểm tra ngẫu nhiên, phán xét, sửa, chứng minh

Vòng lặp cốt lõi chạy từng ngôn ngữ một:

        ┌──────────────────────────────────────────────────────────┐
        │                                                          │
        ▼                                                          │
  1. corpus run ── clone real-world repos, extract relationships   │
        │                                                          │
        ▼                                                          │
  2. spot-check 100 edges (seed 42, then seed 123 to cross-check)  │
        │                                                          │
        ▼                                                          │
  3. LLM judge classifies every sampled edge:                      │
        CORRECT · FALSE_POSITIVE · TYPE_ERROR ·                    │
        SCOPE_ERROR · METADATA_ERROR                               │
        │                                                          │
        ▼                                                          │
  4. fix ONE thing — handler .py, .scm query, or config           │
        │                                                          │
        ▼                                                          │
  5. re-validate — F1 + re-classify + manifest diff (no regressions)│
        │                                                          │
   better? ──no──► revert, try a different fix ────────────────────┤
        │ yes                                                       │
        ▼                                                           │
  6. promote the fix into fixtures (a permanent regression guard) ──┘

Có vài điều khiến cách này thực sự hiệu quả thay vì chỉ quẫy đạp vô ích.

Giám khảo là agent, không phải một lệnh gọi API. Khi chúng tôi nói “LLM làm giám khảo,” chúng tôi có ý là chính language agent đọc từng edge được lấy mẫu, đối chiếu với mã nguồn thực, và phân loại nó theo một rubric cố định gồm năm hạng mục: edge này đúng, là dương tính giả, là đúng quan hệ nhưng sai loại, gắn sai phạm vi, hay mang sai metadata? Rubric đó là toàn bộ trò chơi — “tỷ lệ lỗi 23%” vô nghĩa cho đến khi bạn biết liệu đó có phải là lỗi thực sự hay là giám khảo đếm sai.

Sửa một thứ, rồi chứng minh nó. Mỗi lần lặp thay đổi đúng một tài sản có thể chỉnh sửa, sau đó chạy lại trên một bộ khai thác (harness) cố định và chỉ giữ lại thay đổi nếu F1 cải thiện và việc phân loại lại trông tốt hơn. Nếu không, nó bị hoàn tác. Không có lô chỉnh sửa mang tính suy đoán, không có kiểu “chắc sẽ tốt hơn.” Một thay đổi phải giành được vị trí của nó hoặc biến mất. Và khi một bản sửa đứng vững, nó được đưa vào bộ fixture — để lỗi mà nó sửa không bao giờ có thể âm thầm quay lại. Bước thăng cấp đó chính là điều khiến vòng lặp đệ quy chứ không chỉ đơn thuần lặp lại: mỗi lượt chạy làm cứng thêm cái oracle mà lượt chạy tiếp theo sẽ xác thực dựa vào.

Bài học chúng tôi liên tục học lại: các chỉ số báo cáo thổi phồng

Đây là cái bẫy, và chúng tôi đã đi thẳng vào nó. Các chỉ số corpus phụ — tần suất một đích được trích xuất không có symbol có thể giải quyết, bao nhiêu symbol trông “mồ côi,” v.v. — báo cáo thổi phồng vấn đề một cách khủng khiếp. Chúng phần lớn là tàn tích của hệ hình (paradigm), không phải lỗi.

Ví dụ rõ ràng nhất: llvm từng cho thấy tỷ lệ “nguồn không có symbol” là 73% và bị gắn nhãn thảm họa. Chúng tôi đào sâu vào. Độ chính xác thực sự là 98,5%. Những “symbol thiếu” đó gần như toàn bộ là các tham chiếu bên ngoài hợp lệ — lệnh gọi vào thư viện chuẩn, vào framework, vào mã nằm ngoài repo. Chỉ số đó đang đo một đặc tính của ngôn ngữ, không phải một lỗi trong handler. Các ngôn ngữ như Zig, COBOL, và Odin cho tỷ lệ “mồ côi” 65–70% và hoàn toàn đúng; COBOL không có lỗi thực sự nào.

Nếu chúng tôi để những con số đó dẫn dắt công việc, chúng tôi đã tốn hàng tuần “sửa” các handler vốn đã đúng và bỏ qua những ngôn ngữ có lỗi thực sự nhưng thầm lặng. Kết luận rất thẳng thắn: các chỉ số tổng hợp cùng lắm chỉ là một tín hiệu phân loại sơ bộ. Tín hiệu chất lượng thực sự là kiểm tra ngẫu nhiên kèm phân loại edge — nhìn vào các edge thực tế trong các repo thực tế và phán xét từng cái một. Dữ liệu hơn trực giác, nhưng chỉ khi bạn biết dữ liệu nào đang nói thật.

Vòng lặp ngoài: một đội quân, không phải một cuộc marathon

Làm từng ngôn ngữ một sẽ mất mãi mãi trên cả 280 ngôn ngữ, nên vòng lặp trong được bọc trong một vòng lặp ngoài chạy nhiều ngôn ngữ song song.

   pick a wave of near-GREEN / high-error languages


   fan out 10–15 agents, each ISOLATED in its own git worktree,
   each grinding ONE language, committing to its own branch


   orchestrator integrates serially: file-scoped apply, then
   `manifest diff` — any cross-language regression blocks the batch


   gated push (reviewed and confirmed) ──► rotate to the next wave

Mỗi agent làm việc trong một worktree dùng một lần để chúng không thể giẫm chân lên nhau. Orchestrator tích hợp các bản sửa của chúng từng cái một, mỗi cái đứng sau một lượt kiểm tra hồi quy toàn bộ manifest: một thay đổi giúp ích cho ngôn ngữ của chính nó nhưng âm thầm phá vỡ ba ngôn ngữ khác sẽ không được lên sóng. Việc tích hợp được kiểm soát qua cổng và xác nhận trước khi bất cứ thứ gì được đẩy lên — cổng hồi quy quyết định cái gì an toàn, con người vẫn quyết định cái gì được lên sóng. Sau đó nhóm agent xoay vòng sang tập ngôn ngữ tiếp theo và toàn bộ quá trình lại chạy lại.

Những gì vẫn chưa hoàn hảo

Giám khảo có thể sai, và sự sai lệch có một hướng: một agent chạy với quá ít ngữ cảnh sẽ báo cáo thổi phồng. Trong một lô, tám ngôn ngữ bị gắn cờ với 5–20% lỗi; khi kiểm tra kỹ, chỉ một trong số đó là lỗi thực sự theo từng ngôn ngữ — phần còn lại là sai sót của giám khảo do bỏ lỡ ngữ nghĩa riêng của ngôn ngữ đó (một dòng nguồn hợp lệ phát ra nhiều edge, các ràng buộc tham số được mô hình hóa như phép gán, các ngôn ngữ tham chiếu-theo-từng-định-danh). Đó là lý do chúng tôi lấy mẫu với hai seed và đối chiếu chéo, và vì sao sự bất đồng giữa giám khảo và fixture được xem là tín hiệu thú vị nhất, không phải một phán quyết đã chốt — đôi khi chính fixture mới là thứ sai.

Chúng tôi cũng thành thật về mục tiêu. Mục tiêu là zero lỗi thực sự, chấm hết — nhưng “zero” là một hướng đi mà chúng tôi mài giũa dần, từng ngôn ngữ một, không phải một ô được đánh dấu xong. Luôn luôn có một repo khác với một thành ngữ khác.

Xứng đáng đạt được, không phải khẳng định suông

Mọi thứ Maguyva làm cho một agent — tìm một symbol, theo dõi một phụ thuộc, trả lời một câu hỏi với mã được trích dẫn — đều dựa vào việc trích xuất bên dưới là đúng. Trên 280 ngôn ngữ, “đúng” không thể chỉ khẳng định suông; nó phải liên tục xứng đáng đạt được dựa trên mã thực tế. Vòng lặp là cách chúng tôi giành được điều đó: một chu trình kiểm tra-và-sửa tự động luôn nghi ngờ chính các chỉ số của mình, chứng minh mọi thay đổi, và biến mỗi bản sửa thành một lớp bảo vệ chống lại lần hồi quy tiếp theo. Nó không hào nhoáng. Đó là công việc cho phép chúng tôi nói “chúng tôi hỗ trợ ngôn ngữ của bạn” và thực sự có ý đó. Xanh thì dễ. Đúng thì phải giành được.

Đọc thêm liên quan

Thêm từ nhật ký xây dựng Maguyva