Xây dựng Hệ Thống LLM Tự Sửa Lỗi: Mô Hình Đánh Giá-Tối Ưu
Hệ thống LLM (Large Language Models) ngày càng trở nên phổ biến trong việc tự động hóa các tác vụ, đặc biệt là trong việc tạo SQL. Tuy nhiên, việc đảm bảo rằng các truy vấn SQL được tạo ra là chính xác luôn là một thách thức lớn. Bài viết này sẽ giới thiệu về cách để hướng dẫn LLM tự sửa lỗi SQL của chúng bằng cách sử dụng phản hồi có cấu trúc và quy trình lặp lại.
Giới thiệu
Bạn có bao giờ gặp tình huống khi truy vấn SQL do LLM tạo ra không chạy đúng không? Những lỗi như vậy có thể gây ra sự thất vọng lớn và lãng phí thời gian quý báu của lập trình viên. Thay vì cố gắng làm cho LLM hoàn hảo ngay từ lần thử đầu tiên, chúng tôi đã xây dựng một hệ thống nơi mà LLM có thể học hỏi từ những sai lầm của chính nó theo thời gian thực. Bằng cách sử dụng mô hình đánh giá-tối ưu, chúng ta có thể biến những lỗi SQL thành cơ hội học tập, từ đó cải thiện chất lượng đầu ra của LLM.
Tại sao cần có mô hình tự sửa lỗi?
Trong môi trường phát triển ngày nay, khả năng tự sửa lỗi không chỉ tiết kiệm thời gian mà còn giúp tăng cường độ tin cậy của hệ thống. Mô hình đánh giá-tối ưu sẽ giúp LLM xác định và sửa chữa các lỗi cú pháp mà không cần phải huấn luyện lại mô hình.
Thách thức: Giới hạn tỷ lệ và Logic thử lại
Khi làm việc với nhiều nhà cung cấp LLM khác nhau, chúng tôi đã gặp phải những giới hạn tỷ lệ và yêu cầu thử lại khác nhau. Ví dụ, OpenAI có thể trả về tiêu đề thử lại là 196 giây, trong khi Anthropic có những mẫu khác hoàn toàn.
Giải pháp của chúng tôi là triển khai logic thử lại thông minh:
- Tôn trọng độ trễ dài: Xử lý đúng tiêu đề thử lại vượt quá giới hạn thời gian chờ thông thường.
- Sử dụng Exponential Backoff: Triển khai jitter để ngăn ngừa các vấn đề thảm họa.
- Thử lại chọn lọc: Chỉ thử lại khi có lỗi giới hạn tỷ lệ (HTTP 429), không thử lại cho các lỗi thực sự.
Cách tiếp cận này giúp giảm thiểu các cuộc gọi API không cần thiết và cải thiện độ tin cậy của hệ thống.
Đánh Giá-Tối Ưu: Hướng dẫn LLM mà không cần huấn luyện lại
LLM thường tạo ra SQL với ý định đúng nhưng cú pháp sai - ví dụ như sử dụng các mẫu MySQL trong ClickHouse, nhớ sai tên cột hoặc vi phạm các quy tắc tổng hợp.
Thay vì huấn luyện lại hoặc tinh chỉnh mô hình (một quá trình tốn kém và làm bạn bị khóa vào các phiên bản cụ thể), chúng tôi đã triển khai mô hình đánh giá-tối ưu của Anthropic để sửa các truy vấn ngay lập tức. Thông điệp chính: bảo tồn mục tiêu phân tích ban đầu trong khi sửa lỗi cú pháp theo từng bước.
Cách chúng tôi hướng dẫn mô hình tự sửa lỗi
Hệ thống hoạt động trên một nguyên tắc đơn giản: duy trì ngữ cảnh trong khi sửa lỗi cú pháp. Dưới đây là quy trình làm việc:
Bước 1: Bảo tồn Ý Định
Khi một truy vấn thất bại, chúng tôi ghi lại:
- Mục tiêu phân tích ban đầu ("tìm kiếm các điểm cuối chậm")
- Các dịch vụ mục tiêu và khoảng thời gian
- Các chỉ số và nhóm mong muốn
Bước 2: Đánh Giá Chính Xác
EXPLAIN ASTxác thực cú pháp (10ms, không quét dữ liệu)SELECT ... LIMIT 1kiểm tra thực thi (50ms, chi phí tối thiểu)- Bộ phân loại lỗi xác định các vấn đề cụ thể (tên bảng sai, tổng hợp không hợp lệ)
Bước 3: Tối Ưu Hóa Sử Dụng Cùng Ngữ Cảnh
Thay vì tái tạo từ đầu, chúng tôi hướng dẫn mô hình:
Truy vấn của bạn cho "tìm kiếm các điểm cuối chậm của dịch vụ giỏ hàng" đã thất bại với:
Lỗi 215: 'count() * duration_ns' - duration_ns phải nằm dưới hàm tổng hợp.
Sửa: Thay thế bằng sum(duration_ns) để có tổng thời gian.
Giữ lại: Bộ lọc dịch vụ và nhóm của bạn là chính xác.
Bước 4: Áp Dụng Các Mẫu Học Được
Khi LLM không tự sửa được, các sửa chữa dựa trên quy tắc sử dụng các mẫu thông thường đảm bảo rằng truy vấn vẫn chạy. Những mẫu này có thể được tích hợp vào các lời nhắc trong tương lai để cải thiện tỷ lệ thành công trong lần thử đầu tiên.
Ví dụ: Những Lỗi Phát Sinh Khi Tạo SQL
Người dùng hỏi: "Tính tổng thời gian yêu cầu cho các dịch vụ frontend và backend"
-- Cố gắng 1: LLM tạo ra (lỗi phổ biến giữa TẤT CẢ các mô hình)
SELECT
service_name,
count() * (duration_ns/1000000) as total_duration_ms,
count() as request_count
FROM otel.traces
WHERE service_name IN ('frontend', 'backend')
GROUP BY service_name
ORDER BY total_duration_ms DESC
Người đánh giá tìm thấy 2 lỗi nghiêm trọng:
- Lỗi 215 (NOT_AN_AGGREGATE):
count() * (duration_ns/1000000)- ClickHouse yêu cầuduration_nsphải nằm dưới một hàm tổng hợp. - Lỗi 60 (UNKNOWN_TABLE):
otel.traces- Kết nối ClickHouse đã chỉ định sẵn cơ sở dữ liệu.
Người tối ưu hóa hướng dẫn với ngữ cảnh đã bảo tồn:
Mục tiêu phân tích không thay đổi: "Tính tổng thời gian yêu cầu"
Logic của bạn là đúng nhưng cú pháp cần điều chỉnh:
1. Thay thế count() * duration bằng sum(duration)
- Bạn muốn tổng thời gian, sum() sẽ cho bạn điều đó trực tiếp.
2. Sử dụng 'traces' không phải 'otel.traces'
- Cơ sở dữ liệu đã được chọn trong kết nối.
Giữ lại bộ lọc dịch vụ và nhóm của bạn - những điều đó là hoàn hảo.
-- Cố gắng 2: Mô hình tự sửa với sự hướng dẫn
SELECT
service_name,
sum(duration_ns/1000000) as total_duration_ms,
count() as request_count,
avg(duration_ns/1000000) as avg_duration_ms
FROM traces
WHERE service_name IN ('frontend', 'backend')
GROUP BY service_name
ORDER BY total_duration_ms DESC
Thành công! Mô hình còn thêm avg_duration_ms để phân tích tốt hơn. Mục tiêu giống nhau đã đạt được với cú pháp ClickHouse chính xác.
Tại sao Mô Hình Này Hoạt Động
Cách tiếp cận đánh giá-tối ưu thành công vì nó khớp với cách mà các lập trình viên thực sự gỡ lỗi:
- Tiêu chí đánh giá rõ ràng: SQL hoặc thực thi hoặc trả về mã lỗi cụ thể.
- Cải thiện có thể chứng minh: Mỗi lần lặp sửa một vấn đề đã xác định.
- Bảo tồn ngữ cảnh: Mục tiêu phân tích không bao giờ thay đổi, chỉ có cú pháp được sửa đổi.
- Hiệu quả chi phí: Sửa cú pháp rẻ hơn so với tái tạo toàn bộ truy vấn.
Khi LLM không thể tự sửa, các biện pháp khôi phục dựa trên quy tắc sẽ bắt kịp các mẫu thông thường như:
count() * cột→sum(cột)otel.traces→traces- Tổng hợp trong WHERE → Di chuyển về HAVING
Điều này phản ánh mô hình đánh giá-tối ưu của Anthropic: một thành phần đánh giá (ClickHouse), một thành phần tối ưu hóa (LLM + quy tắc), lặp đi lặp lại cho đến khi thành công. Không cần huấn luyện lại mô hình - chỉ cần hướng dẫn theo thời gian thực sử dụng cùng một ngữ cảnh.
Giai Đoạn 3: Sửa Chữa Dựa Trên Quy Tắc
Khi tối ưu hóa LLM thất bại hoặc trả về kết quả trống, các sửa chữa dựa trên quy tắc sẽ cung cấp độ tin cậy:
// Ví dụ thực từ sản xuất
const input = "SELECT count() * duration_ns FROM otel.traces WHERE avg(duration) > 1000"
const output = applyRuleBasedOptimization(input)
// Kết quả: "SELECT sum(duration_ns) FROM traces GROUP BY service_name HAVING avg(duration) > 1000"
// Ba sửa chữa trong một lần:
// 1. count() * duration_ns → sum(duration_ns)
// 2. otel.traces → traces
// 3. WHERE avg() → HAVING avg()
Bình Luận Siêu Dữ Liệu Toàn Diện
Mỗi truy vấn SQL bao gồm siêu dữ liệu chi tiết để hoàn toàn quan sát:
-- Mô hình: gpt-4-turbo-2024-04-09
-- Chế độ: ClickHouse AI (Mô hình tổng quát cho tạo SQL)
-- Được tạo: 2025-09-20T16:17:16.281Z
-- Mục tiêu phân tích: Phân tích các mẫu độ trễ dịch vụ cho thấy p50, p95, p99 phần trăm theo thời gian để giám sát hiệu suất.
-- Dịch vụ: frontend, cart, checkout, payment, email
-- Tokens: 2190 (prompt: 1305, completion: 885)
-- Thời gian tạo: 18970ms
-- Lý do: Cấu trúc truy vấn là tối ưu cho việc gỡ lỗi theo thời gian thực của luồng thanh toán bằng cách tập trung vào các bản ghi gần đây, có vấn đề và cung cấp các chỉ số chi tiết, có thể hành động. Bằng cách phân đoạn phân tích theo dịch vụ và hoạt động và xếp hạng theo mức độ nghiêm trọng, nó cho phép xác định và ưu tiên nhanh chóng các vấn đề có thể ảnh hưởng đến các quy trình kinh doanh quan trọng.
-- =========================================
-- ========== CÁC NỖ LỰC XÁC THỰC ==========
-- Tổng số nỗ lực: 1
-- Nỗ lực 1: ✅ HỢP LỆ
-- Thời gian thực thi: 96ms
-- Trạng thái cuối: ✅ Truy vấn đã được xác thực thành công
-- =========================================
SELECT
service_name,
operation_name,
quantile(0.50)(duration_ns/1000000) as p50_ms,
quantile(0.95)(duration_ns/1000000) as p95_ms,
quantile(0.99)(duration_ns/1000000) as p99_ms,
count() as request_count,
toStartOfInterval(timestamp, INTERVAL 5 minute) as time_bucket
FROM traces
WHERE service_name IN ('frontend', 'cart', 'checkout', 'payment', 'email')
AND timestamp >= now() - INTERVAL 1 HOUR
GROUP BY service_name, operation_name, time_bucket
HAVING request_count > 10
ORDER BY p99_ms DESC
LIMIT 100
Tập Trung Cấu Hình với Bộ Nhớ Cache Thông Minh
Bộ khách Portkey triển khai bộ nhớ cache cấu hình thông minh với việc làm mới nội dung:
const loadPortkeyConfig = (): Effect.Effect<PortkeyConfig, LLMError, never> =>
Effect.gen(function* () {
const rawConfig = readFileSync(configPath, 'utf8')
// Tính toán hash của nội dung thô
const currentHash = calculateHash(rawConfig)
// Kiểm tra xem cấu hình có thay đổi không
if (configCache.config && configCache.contentHash === currentHash) {
return configCache.config // Cấu hình không thay đổi, sử dụng cache
}
// Xử lý các biến và tham số môi trường
let processedConfig = rawConfig.replace(/\$\{([^}]+)\}/g, (match, envVar) => {
const [varName, defaultValue] = envVar.split(':-')
return process.env[varName.trim()] || defaultValue?.trim() || match
})
// Cập nhật cache với cấu hình mới
configCache = {
config: JSON.parse(processedConfig),
contentHash: currentHash,
lastLoaded: new Date()
}
return configCache.config
})
Tác Động: Điều Gì Thực Sự Đã Thay Đổi
Trước Khi Triển Khai
- Gỡ lỗi thủ công: Kỹ sư phải dành hàng giờ để sửa chữa SQL do LLM tạo ra.
- Thất bại không thể đoán trước: Những lỗi khác nhau từ các mô hình khác nhau.
- Không có việc học: Những sai lầm giống nhau được lặp lại qua các phiên.
- Chi phí hoạt động cao: Cả chi phí cuộc gọi API và thời gian kỹ thuật.
Sau Khi Triển Khai
- Khôi phục tự động: Mô hình đánh giá-tối ưu sửa hầu hết các lỗi tự động.
- Cải thiện nhất quán: Mỗi truy vấn được sửa dạy hệ thống.
- Định tuyến theo mô hình: Sử dụng mô hình phù hợp cho loại truy vấn phù hợp.
- Giảm chi phí: Ít cuộc gọi API hơn thông qua việc thử lại thông minh và bộ nhớ cache.
Những Mẫu Lỗi Phổ Biến Mà Chúng Tôi Hiện Đang Xử Lý
Lỗi tổng hợp: count() * cột → sum(cột)
Tham chiếu bảng: otel.traces → traces
WHERE và HAVING: Các tổng hợp tự động di chuyển về HAVING
Tên cột: Đối sánh mờ cho các lỗi chính tả và biến thể
Cú pháp hàm: Chuyển đổi MySQL/PostgreSQL → ClickHouse
Bài Học: Hướng Dẫn Thay Vì Huấn Luyện
Mô hình đánh giá-tối ưu chứng minh một điểm quan trọng: bạn không cần phải huấn luyện lại các mô hình để cải thiện đầu ra của chúng. Bằng cách triển khai xử lý lỗi thông minh và hướng dẫn ngữ cảnh, chúng tôi đã biến SQL không đáng tin cậy do LLM tạo ra thành một hệ thống sẵn sàng cho sản xuất.
Cách tiếp cận này đơn giản nhưng mạnh mẽ:
- Đánh Giá với tiêu chí rõ ràng (SQL có thực thi không?)
- Tối Ưu Hóa dựa trên các lỗi cụ thể (không phải thử lại chung chung)
- Bảo Tồn ý định ban đầu trong khi sửa lỗi cú pháp
- Học Hỏi từ các mẫu để ngăn chặn lỗi trong tương lai
Mô hình này có thể áp dụng cho bất kỳ đầu ra nào của LLM mà có tiêu chí thành công rõ ràng.
Phần của loạt bài về nền tảng quan sát AI trong 30 ngày. Theo dõi khi chúng tôi xây dựng cơ sở hạ tầng AI sẵn sàng cho sản xuất.