PRODEgemen Avrupa BaaS platformuKontrol Panelini Aç →

Yerel yapay zeka · 10 dk. okuma

İşlev çağrısıyla Postgres aracısını güvenli hale getirin (öğretici)

Affane Daylami · Fondateur · 21 Mart 2026

Bloga geri dön

Postgres'i sorgulayan bir aracı, kodun ilk satırından önce belirli bir güvenlik sorusunu sorar: Modele hangi işlevi sunuyorsunuz? LLM'nin çağırabileceği araç doğrudan kendi yazdığı SQL'i çalıştırıyorsa, belirsiz bir soru veya hızlı bir enjeksiyon projedeki herhangi bir tabloyu okumak için yeterlidir.

Bu İngilizce metin, Fransızca orijinalinden otomatik olarak oluşturulmuştur ve henüz incelenmemiştir.
Bu sayfa otomatik olarak çevrildi. İngilizce versiyonu yetkilidir.

This tutorial builds an agent with function calling where the tool exposed to the model never executes arbitrary SQL. It combines two mechanisms already verified in the Aurabase code: the NL2SQL validator and a read-only Postgres transaction, two bricks of thenative AI integrated into thebackend. Prerequisites: an Aurabase project, its service_rolekey, and an account with one of the three native LLM providers (OpenAI, Anthropic, Gemini).

Temeller

  • Gerçek risk, kendisini çağıran fonksiyon değil, modele maruz kalan araçtır: ham bir execute_sql(query) ona tam SQL erişimi sağlar.
  • Güvenli mimari, doğrudan yürütme yerine sözdizimi ağacı doğrulayıcısına (yalnızca SELECT, sınırlı LIMIT, yalıtılmış şema) yetki veren bir query_database(question) aracını kullanıma sunar.
  • Aurabase bu doğrulayıcıyı yerel olarak kullanıma sunar (/nl2sql): Aracın bir uygulaması olarak yeniden kullanılması, SQL doğrulamasını kendiniz yeniden kodlama zorunluluğunu ortadan kaldırır.
  • Kaydedilen SQL daha sonra basit bir metin filtresi değil, gerçek bir salt okunur Postgres işlemi olan readOnly: truemodunda aura.db.sql() aracılığıyla yürütülür.
  • Aurabase'in yerel /chat uç noktası henüz bir tool rolünü veya bir tools parametresini (kodda doğrulanmıştır) kabul etmemektedir: aracı döngüsü şu anda Aurabase proxy'si aracılığıyla değil, LLM sağlayıcısının SDK'sı aracılığıyla çalışmaktadır.
  • service_role anahtarı, tasarımı gereği RLS'yi atlar: arka ucunuzdan asla ayrılmamalıdır ve aracı, kimliği doğrulanmış tipik bir kullanıcıdan daha geniş bir erişimi devralır.
#
Amaç

Ne inşa edeceksin

Modelin olduğu gibi çalışan SQL yazmasına asla izin vermeden, bir Postgres projesinde verilerle ilgili doğal dil sorularını yanıtlayan bir aracı oluşturacaksınız. Model, query_databaseadlı bir aracı çağırır, bu araç soruyu NL2SQL aracılığıyla doğrulanan SQL'e çevirir, ardından bu salt okunur SQL'i çalıştırır ve cevabını formüle etmesi için satırları modele döndürür.

Bilgi

Bu eğitimde, sunucu tarafında @aurabase/aurabase-js JavaScript SDK'sı (hiçbir zaman tarayıcı tarafında değil, service_role anahtarı istemciye gösterilmemelidir) ve aracı döngüsü için API çağıran OpenAI işlevi kullanılır. Aynı prensip Anthropic veya Gemini SDK'sı için de geçerlidir.

#
Kaputun altında

"Bu SQL'i çalıştır" aracı neden tehlikelidir?

Bazı resmi kılavuzlar da dahil olmak üzere çoğu Postgres aracısı öğreticisi tek bir araç tanımlar: bir SQL dizesini argüman olarak alan ve onu olduğu gibi yürüten bir execute_sql işlevi. Model, kullanıcının sorusuna ve bağlamda kendisine verilen şemaya dayanarak bu dizeyi kendisi yazar.

tool-schema-dangereux.json (anti-desen)json
{
  "name": "execute_sql",
  "parameters": {
    "query": { "type": "string" }  // model doğrudan SQL'i yazar
  }
}

Bu seçim, modele güvenilir bir şekilde yerine getiremeyeceği bir sorumluluk yükler. Sorunun içine anında yapılan bir enjeksiyon, aracın "meşru" bir sorgunun nasıl görünmesi gerektiğine dair hiçbir fikri olmadığı için, aracın ayrım gözetmeksizin yürüttüğü yıkıcı SQL üretebilir. Özel makalemiz bu saldırı vektörünün ayrıntılarını vermektedir: NL2SQL'in SQL enjeksiyonuna karşı güvenliğinin sağlanması.

Bu eğitimde yerleşik olan alternatif, daha dar bir araç olan query_database(question)'yi ortaya çıkarır. Model artık SQL'i doğrudan yazamaz: yalnızca kendi araç çağrısında soru sorabilir. Bu soruyu sözdizimsel bir ağaç doğrulayıcıdan (yalnızca SELECT, alt sorgu yok, on işlev yetkili, sınırlı LIMIT) geçirmeden önce SQL'e çeviren Aurabase NL2SQL motoru'dir.

Sistem istemi bir güvenlik kontrolü değildir

Bir execute_sql(query: string) aracı, sistem isteminizin ne kadar iyi olduğuna bakılmaksızın modele tam SQL erişimi sağlar. Bir talimat ("yalnızca SELECT'leri çalıştırır"), modelin izleyebileceği, yanlış yorumlayabileceği veya kullanıcının sorusuna eklenen bir enjeksiyonla atlatıldığını görebileceği bir talimat olarak kalır.

#
1. Adım

Modele maruz kalan aracın şemasını tanımlayın

Aurabase'in üç yerel LLM sağlayıcısı (OpenAI, Anthropic, Gemini), JSON Schema formatındaki araç tanımları tablosunu kabul eder. Bu aracı için tek bir araç yeterlidir: query_database, doğal dilde bir soru alır, başka hiçbir şey yapmaz. Model ne SQL şemasını ne de kendi başına doldurabileceği bir query alanını görüyor.

lib/agent-tools.tstypescript
export const tools = [
  {
    type: 'function',
    function: {
      name: 'query_database',
      description:
        "Interroge les données du projet en langage naturel. N'accepte pas de SQL : posez une question.",
      parameters: {
        type: 'object',
        properties: {
          question: {
            type: 'string',
            description: 'Question en français sur les données du projet.'
          },
        },
        required: ['question'],
        additionalProperties: false
      },
    },
  },
]
#
2. Adım

Aracı uygulayın: NL2SQL ve ardından salt okunur

Araç işleyicisi arka uçta çalışır, asla tarayıcıda çalışmaz. Tasarım gereği RLS'yi atlayan ve bu nedenle hiçbir zaman istemciye açıklanmaması gereken service_roleproje anahtarını taşır. Aurabase SDK'ya iki çağrı yapar.

İlk çağrı, soruyu aura.ai.nl2sql()aracılığıyla doğrulanan SQL'e çevirir: Yalnızca SELECT, LIMIT sınırlı, sistem kataloğuna erişim yok. İkincisi, aura.db.sql()aracılığıyla zaten doğrulanmış olan bu SQL'i readOnly: true seçeneğiyle çalıştırır: Postgres'in kendisi, NL2SQL yukarı akış tarafından halihazırda uygulanan metinsel doğrulamadan bağımsız olarak bu işlemdeki herhangi bir yazmayı reddeder.

server/tools/query-database.tstypescript
// İstemci service_role anahtarıyla başlatıldı, hiçbir zaman tarayıcı tarafında değil
import { aura } from '@/lib/aurabase'

export async function queryDatabase(question: string) {
  const { data: validated, error } = await aura.ai.nl2sql(
    question,
    undefined,
    { limit: 50 },
  )
  if (error) return { error: error.message }

  const { data: rows, error: execError } = await aura.db.sql(
    validated.sql,
    [],
    { readOnly: true },
  )
  if (execError) return { error: execError.message }

  return { sql: validated.sql, rows }
}
Astuce

readOnly: true gerçek bir salt okunur Postgres işlemini tetikler: motor yazmayı reddeder, istek metnine uygulanan bir filtre değildir. NL2SQL'in yalnızca SELECT doğrulaması ile birleştirildiğinde, aracının iki bağımsız katmanı vardır: birinde kusur varsa diğeri hala geçerlidir.

#
3. Adım

Aracı döngüsü: tedarikçinin SDK tarafında çağrılan işlev

Aurabase üç yerel LLM sağlayıcısını kullanıma sunuyor ancak /chat uç noktası henüz bir tools parametresini veya toolrolünü aktarmıyor. ChatOptions yalnızca temperature, max_tokens ve modeltaşır ve kabul edilen roller system, user ve assistant (llm/mod.rs ve handlers/chat.rsiçinde doğrulanmıştır) ile sınırlıdır. Bu nedenle işlev çağırma döngüsü, bugün Aurabase proxy'si aracılığıyla değil, doğrudan sağlayıcının SDK'sı aracılığıyla çalışır.

Akım sınırlaması, kesin bir seçim değil

Aurabase, araç çağrılarını yerel olarak düzenlemediği sürece, arka ucunuz döngüyü OpenAI, Anthropic veya Gemini SDK ile kendisi yönetmelidir. NL2SQL ve SQL yürütme, bu döngü içinde klasik Aurabase çağrıları olmaya devam ediyor.

server/agent.tstypescript
import OpenAI from 'openai'
import { tools } from './lib/agent-tools'
import { queryDatabase } from './tools/query-database'

const openai = new OpenAI()

export async function askAgent(question: string) {
  const messages = [{ role: 'user', content: question }]

  const first = await openai.chat.completions.create({
    model: 'gpt-4.1', messages, tools,
  })

  const call = first.choices[0].message.tool_calls?.[0]
  if (!call) return first.choices[0].message.content

  const args = JSON.parse(call.function.arguments)
  const result = await queryDatabase(args.question)

  const second = await openai.chat.completions.create({
    model: 'gpt-4.1',
    messages: [
      ...messages,
      first.choices[0].message,
      { role: 'tool', tool_call_id: call.id, content: JSON.stringify(result) },
    ],
  })

  return second.choices[0].message.content
}

Aracıyı LangChain veya Azure AI Agent gibi bir hizmetle düzenlerseniz prensip aynı kalır: çerçevede bildirilen araç aynı kalmalı query_database, asla ham bir SQL yürütücüsü olmamalıdır. Karşılaştırma ayrıntılarımız LangChain ve LlamaIndex'in Postgres'te gerçek değer sağladığı ve özellikle karmaşıklık kattığı noktalardır: LangChain veya LlamaIndex'li Postgres aracıları.

#
4. Adım

Gerçek bir soruyla test edin

Temsilciye gönderilen soru: "Bu ay kaç premium müşteri sipariş verdi?" ". Şablon, herhangi bir SQL görmeden veya yazmadan bu soruyla birlikte query_database öğesini çağırır. Araç tarafından tetiklenen iki dahili çağrının sonucu aşağıdadır.

araç sonucu (çıkarma)json
{
  "sql": "SELECT count(*) FROM orders WHERE customer_plan = 'premium' AND created_at >= date_trunc('month', now()) LIMIT 50",
  "rows": [{ "count": 128 }]
}

Modelin nihai cevabı bir tahmine değil, bu gerçek satırlara dayanmaktadır. Araç sıfır satır döndürürse sayı halüsinasyonu olasılığı, doğrulanmış veriler olmadan yanıt veren bir modele göre önemli ölçüde daha az olur.

#
Güvenlik

Üretime geçmeden önce temsilciyi emniyete alın

  • service_role anahtarı hiçbir zaman arka ucunuzdan ayrılmaz: ne modele gönderilen istemde, ne bir günlükte, ne de istemci tarafı ortam değişkeninde.
  • readOnly: true, projenizin uygulamanın başka bir yerinde yazılması gerekse bile, bu özel araç için aura.db.sql() üzerinde etkin kalır.
  • service_role tasarım gereği RLS'yi atlar. Aracının, soruyu soran kullanıcıya bağlı olarak farklı yanıt vermesi gerekiyorsa, SQL'de açıkça filtre uygulayın veya RLS'ye saygı duyan klasik PostgREST uç noktalarına geri dönün. çok kiracılı RLS yalıtımıkonusuna bakın.
  • Her araç çağrısını günlüğe kaydedin (sorulan soru, SQL'in doğrulanması, satır sayısı): Bir sorunun beklenmeyen bir sonuç üretmesi durumunda kullanılabilen tek iz budur.
  • Aurabase'in oran sınırlaması ve aylık kotası /nl2sql'de proje başına zaten geçerlidir: konuşkan bir temsilci yapay zeka bütçenizi sessizce aşamaz.
#
Dürüstlük

Dikkat edilmesi gereken mevcut sınırlar

query_database aracı, NL2SQL doğrulayıcısının tüm sınırlamalarını devralır: alt sorgu yok, CTE/WITH yok, UNION yok ve on SQL işlevinden oluşan kapalı bir liste. Doğal olarak bir alt sorgu gerektiren bir sorunun (“hiç sipariş vermemiş müşteriler”) yeniden formüle edilmesi veya NL2SQL'e zorlanmak yerine ikinci bir özel araç tarafından işlenmesi gerekir.

Bugün Aurabase /chat proxy'sinde araç çağrılarının düzenlenmesi mevcut değildir: burada açıklanan aracı döngüsü, yönetilen bir hizmette değil, uygulama kodunuzda bulunur. Aracının birden fazla aracı zincirlemesi gerekiyorsa (örneğin, veritabanı ve belgesel RAG), iki çağrıyı düzenleyen sizin arka ucunuzdur.

#
Daha ileri git

RAG ve işlev çağrısı birleştirildi

Bu eğitimde ilişkisel verilerle ilgili yapılandırılmış sorular ele alınmaktadır. Yapılandırılmamış içerikle (belgeler, biletler, notlar) ilgili sorular için aynı temsilci, Aurabase'in yerel RAG'sine (pgvector, HNSW arama) bağlı ikinci bir aracı kullanıma sunabilir. İki yetenek ve bunların eklemlenmesi Postgres'te Yerel Yapay Zekasayfasında ayrıntılı olarak açıklanmıştır.

#
Sıkça Sorulan Sorular

SSS

Aracıya yazma erişimi (INSERT/UPDATE) verebilir miyim?+
Teknik olarak evet, readOnly seçeneğini kaldırarak ve ayrı bir araca işaret ederek, ancak NL2SQL'in bugün yaptığı bu değil: doğrulayıcı, istemci tarafında seçilen yürütme seçeneğinden bağımsız olarak yalnızca SELECT sorgularına izin verir. Bir yazma aracısı, kendi beyaz liste işlevlerine ve muhtemelen yürütmeden önce insan onayına sahip ayrı bir doğrulayıcı talep eder.
LangChain, LlamaIndex veya Azure AI Agent gibi bir hizmetle uyumlu mu?+
Evet: bu çerçeveler sizin için işlev çağırma döngüsünü düzenler, ancak aracın uygulanması size aittir. Aynı işleyici (NL2SQL daha sonra salt okunur yürütme), ham SQL'i yürütmelerine izin vermek yerine, kendisini LangChain'de veya Azure aracısında bildirilen aracın bir işlevi olarak bağlar.

DAĞITILMAYA HAZIR MISINIZ?

Beş dakika içinde arka ucunuz.

Kredi kartı gerekmez · 500 MB ücretsiz · 50.000 MAU