PRODSuwerenna europejska platforma BaaSOtwórz Panel →

Natywna sztuczna inteligencja · 8 min odczytu

Samouczek: zbuduj punkt końcowy NL2SQL na Postgres

Affane Daylami · Fondateur · 28 sierpnia 2026

Powrót do bloga

W tym samouczku pokazano, jak otrzymać pytanie w języku francuskim, przekształcić je w zweryfikowane i ograniczone zapytanie SQL, a następnie zwrócić wynik — bez wykonywania niesprawdzonego kodu SQL. Na każdym etapie wyświetlany jest faktycznie wygenerowany kod SQL, a nie tylko wynik końcowy.

Ten tekst w języku angielskim został wygenerowany automatycznie na podstawie francuskiego oryginału i nie był jeszcze recenzowany.
Ta strona została przetłumaczona automatycznie. Wersja angielska jest miarodajna.

Silnik NL2SQL Aurabase jest częścią natywnej sztucznej inteligencjizintegrowanej z backendem: nie jest to usługa strony trzeciej, którą można połączyć. Warunki wstępne korzystania z tego przewodnika: istniejący projekt Aurabase, prosty schemat bazy danych dla przykładu i klucz API projektu.

#
Cel

Co zbudujesz

Punkt końcowy, który odbiera pytanie w języku naturalnym, przekształca je w zweryfikowane i ograniczone zapytanie SQL, a następnie zwraca wynik. Silnik nigdy nie wykonuje wygenerowanego kodu SQL bez kontroli: każde zapytanie przechodzi przez weryfikację składniową przed dotarciem do bazy danych.

Informacje

W tym samouczku wykorzystano zestaw SDK języka JavaScript @aurabase/aurabase-js i odpowiadające mu surowe wywołanie HTTP, dzięki czemu można kontynuować naukę w dowolnym języku.

#
Pod maską

Jak działa silnik NL2SQL

Pytanie przechodzi przez skonfigurowaną LLM — OpenAI, Anthropic (Claude) lub Gemini, trzech natywnych dostawców — która generuje potencjalny kod SQL. Ten kod SQL nigdy nie jest wykonywany w niezmienionej postaci: przechodzi przez moduł sprawdzania poprawności, który analizuje jego drzewo składni (sqlparser), zezwala tylko na proste zapytania SELECT i dodaje ograniczony LIMIT, jeśli takiego brakuje.

Walidator jawnie odrzuca CTE/WITH, podzapytania, UNION, klauzule blokujące (FOR UPDATE) i wszelkie funkcje spoza białej listy (count, sum, avg, min, max, lower, upper, coalesce, date_trunc, now). Obsługiwane są złączenia wielu tabel.

Pytanie → LLM (OpenAI/Claude/Gemini) → Walidacja AST (sqlparser) → Ograniczony LIMIT → WYBIERZ wykonanie

Zapytany diagram nigdy nie jest dostarczany na Twoją prośbę: jest introspekcją z rzeczywistej podstawy projektu. Pole schema, allowed_schema lub schema_context wysłane w treści żądania jest jawnie odrzucane (błąd 400), a nie dyskretnie ignorowane — sam serwer decyduje, co faktycznie istnieje.

#
Krok 1

Skonfiguruj punkt końcowy NL2SQL

Dzięki pakietowi JavaScript SDK klient Aurabase udostępnia aura.ai.nl2sql(). Podpis to nl2sql(question, options): schemat nie jest jego częścią, jest introspekcji po stronie serwera.

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.nl2sql(
    question,
    { limit: 50 }
  )

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

W surowym protokole HTTP punktem końcowym jest POST /v1/ai/{project_id}/nl2sqluwierzytelniany kluczem API projektu.

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/nl2sql \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Combien de commandes ont été passées ce mois-ci par des clients premium ?",
    "limit": 50
  }'
Pola odrzucone przez serwer

Nie wysyłaj schema, ani allowed_schema, ani schema_context w treści żądania: schemat, którego dotyczy zapytanie, jest określany przez serwer, pola te są jawnie odrzucane (400), a nie dyskretnie nadpisywane.

#
Krok 2

Test z prawdziwym pytaniem w języku francuskim

Wysłane pytanie: „Ile zamówień złożyli w tym miesiącu klienci premium?”. Oto forma faktycznie wyrenderowanego kodu SQL (nazwy tabel i kolumny zależą od schematu):

odpowiedź (fragment)json
{
  "data": {
    "sql": "SELECT count(*) FROM orders WHERE customer_plan = 'premium' AND created_at >= date_trunc('month', now()) LIMIT 50",
    "explanation": "Compte les commandes de ce mois pour les clients premium.",
    "confidence": 0.85,
    "tables": ["orders"],
    "columns": ["customer_plan", "created_at"],
    "limit": 50,
    "limit_injected": false
  },
  "meta": null
}

limit_injected wskazuje, czy LIMIT pochodzi z szablonu, czy został dodany przez serwer. confidence to heurystyka formy odpowiedzi (dobrze sformułowany blok SQL lub nie) — a nie miara poprawności semantycznej wygenerowanego kodu SQL. Źle sformułowane pytanie zwraca jawny błąd, a nie halucynacyjny SQL: na przykład, jeśli wygenerowany SQL zapyta o tabelę, która nie znajduje się w twoim schemacie, komunikat zawiera nazwy faktycznie dostępnych tabel.

#
Krok 3

Bezpieczna produkcja

Trzy kontrole przed wdrożeniem: czy pułap wierszy (LIMIT) jest dostosowany do wolumenu, czy rola Postgres używana przez silnik pozostaje ograniczona do schematu projektu i czy wrażliwe tabele mają aktywną politykę RLS — NL2SQL odpytuje tę samą bazę danych, co reszta aplikacji, domyślnie nie ma rozszerzonych praw dostępu.

  • Domyślny limit linii można skonfigurować po stronie serwera; żądana wartość powyżej limitu serwera jest jawnie odrzucana, a nie dyskretnie zmniejszana.
  • Dostęp do katalogu systemowego (pg_catalog, information_schema) i schematów innych niż projektowe jest blokowany przez walidator, niezależnie od Twoich zasad RLS.
  • RLS pozostaje ostatnią linią obrony w przypadku wrażliwych tabel: walidator ogranicza formę kodu SQL, a nie prawa biznesowe do danych.
#
Uczciwość

Aktualne ograniczenia, o których należy pamiętać

Silnik jest ściśle czytelny: akceptowane są tylko żądania SELECT. Każda próbaINSERT, UPDATE, DELETE, DROP, CREATE lub ALTER wygenerowana przez szablon jest odrzucana przed wykonaniem — nie jest to konwencja podpowiedzi, jest to reguła narzucona na poziomie drzewa składni.

Inne ograniczenia strukturalne: brak podzapytań, brak CTE/WITH, brak UNION i zamknięta biała lista dziesięciu funkcji SQL. Pytanie, które w naturalny sposób wymaga podzapytania („klienci, którzy nigdy nie składali zamówienia”), należy przeformułować, aby pasowało do prostego SELECTlub obsłużyć je inaczej po stronie aplikacji.

#
Idź dalej

RAG i agenci

NL2SQL obejmuje ustrukturyzowane pytania dotyczące danych relacyjnych. W przypadku pytań dotyczących treści nieustrukturyzowanych (dokumenty, notatki, bilety) natywny RAG Aurabase opiera się na wyszukiwaniu pgvector i HNSW. Obie możliwości — i sposób ich łączenia w agencie — są szczegółowo opisane na stronie Natywnej sztucznej inteligencji na stronie Postgres.

#
Często zadawane pytania

Często zadawane pytania

Czy NL2SQL działa ze złożonym schematem (wiele złączeń)?+
Złączenia wielu tabel są obsługiwane przez moduł sprawdzania poprawności. Z drugiej strony podzapytania i CTE/WITH są jawnie odrzucane: pytanie, które w naturalny sposób wywołuje podzapytanie, musi zostać przeformułowane, aby pasowało do prostego SELECT ze złączeniami, lub w inny sposób obsługiwane po stronie aplikacji.
Którego dostawcę LLM wybrać dla NL2SQL?+
Trzej natywni dostawcy (OpenAI, Anthropic/Claude, Gemini) są traktowani przez walidatora jednakowo: żaden nie ma strukturalnej przewagi w zakresie walidacji wygenerowanego SQL. Koszt i opóźnienia zależą od konkretnego modelu skonfigurowanego dla Twojego projektu — porównaj je na własnym woluminie, zamiast kierować się ogólnymi zaleceniami.

GOTOWY DO WDROŻENIA?

Twój backend w pięć minut.

Karta kredytowa nie jest wymagana · 500 MB za darmo · 50 000 MAU