
Cách xây dựng Bot truy vấn cơ sở dữ liệu được hỗ trợ bởi LLM cho ứng dụng web của bạn trong 1 ngày
URL bài viết: https://www.semicolonandsons.com/articles/how-to-build-an-llm-powered-database-query-bot-for-web-apps-quickly URL bình luận: https://news.ycombinator.com/item?id=49192627 Điểm: 1 Bình luận: 0
Ghi nhận đóng góp của Ramchandra Shahi Thakuri, một kỹ sư đã cùng tôi thực hiện dự án này, đưa ra các gợi ý và triển khai phần lớn mã nguồn.
Xuất bản ngày 7/12/2025
Những gì bạn sẽ xây dựng
Phương pháp này mô tả một cách tiếp cận độc lập với framework để một mô hình ngôn ngữ lớn (LLM) có thể giao tiếp với toàn bộ tập dữ liệu của bạn, dù đó là trong Django, Laravel, Flask, Rails, Express, v.v. Yêu cầu duy nhất là một cơ sở dữ liệu SQL. Tôi sẽ trình bày các khía cạnh về backend/LLM; phần frontend đơn giản và dành cho người đọc tự tìm hiểu.
Vấn đề
Khối lượng công việc dịch vụ khách hàng tại một trong những khách hàng của tôi đã tăng lên đáng kể. Đội ngũ CS liên tục cần lấy thông tin từ cơ sở dữ liệu, nhưng họ phải chờ các nhà phát triển viết truy vấn. Những câu hỏi đơn giản như "Địa chỉ email của người dùng kiran là gì?" hoặc "Chúng ta có bao nhiêu danh sách trong danh mục 'trăn bóng'?" yêu cầu họ phải truy cập trang quản trị phiền phức hoặc tốn thời gian kỹ thuật.
Chúng tôi cần một cách để các thành viên nhóm không chuyên về kỹ thuật có thể tự truy vấn cơ sở dữ liệu sản xuất.
Hiểu biết cốt lõi
Đây là nhận thức quan trọng đã làm cho dự án này trở nên đơn giản: Các mô hình AI đặc biệt giỏi trong việc viết SQL khi chúng có lược đồ cơ sở dữ liệu của bạn làm ngữ cảnh.
Bạn có thể tự kiểm tra điều này ngay bây giờ mà không cần viết bất kỳ mã nào:
1. Xuất lược đồ cơ sở dữ liệu của bạn: pg_dump -W --schema-only mydatabase > schema.sql
2. Tải lên Claude hoặc ChatGPT
3. Đặt các câu hỏi như "Viết một truy vấn để tìm tất cả người dùng đã đăng ký vào tuần trước"
4. Kiểm tra các truy vấn đó trong cơ sở dữ liệu của bạn
Nếu 80% hoạt động ngay lập tức, bạn đã sẵn sàng để xây dựng điều này. Phần còn lại là chi tiết: trong trường hợp của chúng tôi, chúng tôi đã xây dựng một bong bóng giao diện trò chuyện nơi các thành viên nhóm nội bộ có thể đặt câu hỏi. Sau đó, nó sẽ lấy đầu vào bằng tiếng Anh và:
1. Chuyển đổi thành một truy vấn SQL thích hợp
2. Thực thi truy vấn đó đối với cơ sở dữ liệu của chúng tôi
3. Định dạng kết quả theo cách dễ đọc (thông qua một cuộc gọi LLM thứ hai)
Chỉ vậy thôi! Và bạn có thể ngừng đọc ở đây nếu muốn và bắt đầu. Tổng cộng, toàn bộ quá trình triển khai mất một ngày, phần lớn là do AI đã viết hầu hết mã nguồn khi chúng tôi có kiến trúc.
Cách thức hoạt động: Kiến trúc & Triển khai
Mô hình cơ bản
Hệ thống sử dụng mô hình gọi công cụ (tool-calling pattern) trong đó AI có thể gọi một hàm duy nhất mà chúng tôi cung cấp:
Công cụ run_query:
- Nhận một tham số: một chuỗi truy vấn SQL
- Thực thi các truy vấn chỉ đọc đối với cơ sở dữ liệu
- Trả về kết quả cho AI để định dạng
Luồng hoạt động:
1. Người dùng hỏi: "Người dùng có ID 511 có đơn hàng nào chưa hoàn thành không?"
2. Hệ thống gửi đến AI với:
- Toàn bộ lược đồ cơ sở dữ liệu
- Mô tả công cụ cho `run_query`
- Hướng dẫn an toàn và ví dụ
3. AI tạo SQL và gọi công cụ `run_query`
4. Hệ thống của chúng tôi thực thi truy vấn
5. AI định dạng kết quả: "Có, người dùng 511 có 3 đơn hàng chưa hoàn thành: #4521, #4589, #4601"
Các biện pháp an toàn
Vì điều này truy vấn dữ liệu sản xuất, chúng tôi đã triển khai một số biện pháp bảo vệ:
Truy cập chỉ đọc ở cấp cơ sở dữ liệu: Đã tạo một người dùng cơ sở dữ liệu chỉ đọc với các quyền được thực thi ở cấp Postgres, không chỉ ở cấp ứng dụng. Điều này ngăn chặn mọi sửa đổi dữ liệu ngẫu nhiên.
Hạn chế ở cấp lời nhắc: Hướng dẫn AI không bao giờ tiết lộ mật khẩu, mã băm mật khẩu, mã thông báo xác thực hoặc thông tin nhạy cảm khác.
Xác thực truy vấn: Chỉ cho phép các câu lệnh SELECT.
Khi chúng tôi xây dựng sự tự tin, chúng tôi có thể nới lỏng một số hạn chế, nhưng những biện pháp bảo vệ này mang lại cho chúng tôi sự an tâm với dữ liệu sản xuất.
Lời nhắc hệ thống
Đây là mẫu lời nhắc mà chúng tôi sử dụng. Nó bao gồm lược đồ (không hiển thị ở đây), các quy tắc an toàn và ví dụ:
## CÁC QUY TẮC QUAN TRỌNG (đọc kỹ)
- Luôn tạo các truy vấn **PostgreSQL (ANSI SQL)**. Tránh các hàm của nhà cung cấp không phải Postgres; dựa vào các thao tác chuỗi/ngày tiêu chuẩn được Postgres hỗ trợ.
- Các truy vấn phải là **chỉ đọc**: chỉ sử dụng `SELECT` (không có INSERT/UPDATE/DELETE/DDL).
- Ưu tiên tên bảng đủ điều kiện khi cần thiết (ví dụ: public.accounts_users).
- **Không bao giờ tiết lộ thông tin nhạy cảm** bao gồm mật khẩu, mã băm mật khẩu, liên kết email xác nhận, mã thông báo 2FA hoặc bất kỳ bí mật xác thực nào khác.
## CÔNG CỤ CÓ SẴN
- **run_query**: Thực thi một truy vấn SQL chỉ đọc
- Tham số:
- `query` (bắt buộc): một chuỗi SQL duy nhất
## VÍ DỤ
### Ví dụ 1 -> Q: "Năm quảng cáo đắt nhất hiện đang được niêm yết là gì?"
Trợ lý phải gọi run_query
{
"query": "
SELECT s.id, s.title, s.price_currency, s.price, s.store_id
FROM public.listings_list s
WHERE s.active = 1 AND s.visibility = 1 AND s.state = 0
ORDER BY s.price DESC NULLS LAST
LIMIT 5
"
}
Sau đó tóm tắt: "Đây là năm quảng cáo đắt nhất hiện đang được niêm yết."
### Ví dụ 2 -> Q: "Hiển thị cho tôi các quảng cáo có từ 'yellow' trong tên của chúng."
Trợ lý phải gọi run_query:
{
"query": "
SELECT s.id, s.title, s.price_currency, s.price, s.store_id
FROM public.listings_list s
WHERE lower(s.title) LIKE '%yellow%'
ORDER BY s.first_listed DESC NULLS LAST, s.id DESC
LIMIT 100
"
}
Sau đó tóm tắt: "Các quảng cáo có tiêu đề chứa 'yellow'."
### Ví dụ 3 -> Q: "Hiện có bao nhiêu cuộc đấu giá đang diễn ra?"
(Tính ends_at từ created + (duration hours) + extra_time; đang chạy nếu now() nằm giữa created và ends_at)
Trợ lý phải gọi run_query:
{
"query": "
WITH spans AS (
SELECT
a.id,
a.created,
(a.created + (a.duration || ' hours')::interval + a.extra_time) AS ends_at
FROM public.auctions_auction a
)
SELECT COUNT(*) AS count
FROM spans
WHERE now() >= created AND now() < ends_at
"
}
Sau đó tóm tắt: "Hiện có N cuộc đấu giá đang diễn ra."
Hướng dẫn AI về Mô hình dữ liệu của bạn
Lược đồ (schema) không phải lúc nào cũng đủ. Bạn cần giải thích các điểm đặc biệt và quy ước:
Các đặc thù của mô hình dữ liệu:
Trong trường hợp của khách hàng của tôi, các danh sách có thể thuộc sở hữu của một Cửa hàng HOẶC một Người dùng (không có cửa hàng). Một danh sách có thể có store_id hoặc user_id được điền, nhưng không phải cả hai—mặc dù tất cả các cửa hàng cũng có một người dùng. Điều này tạo ra hai đường dẫn khi truy vấn "các danh sách thuộc về một người" và sẽ không rõ ràng từ lược đồ.
Thuật ngữ kinh doanh so với cấu trúc cơ sở dữ liệu:
Các thành viên nhóm không chuyên về kỹ thuật nói "quảng cáo đang giảm giá" nhưng cơ sở dữ liệu có state=0. Nếu có khoảng cách giữa cách mọi người nói về dữ liệu và

Nguồn tin: Hacker News LLM — Tác giả: shantanuo. Bản dịch tiếng Việt do AI thực hiện, có thể có sai sót.