Generieren und Verarbeiten von RAG-Antworten
Ein Kunde möchte wissen, welche Pedale ihrem Mountain-500 Bike passen. Sie verwenden die Vektorsuche, um die relevanten Produkte zu finden, formatieren sie als JSON und erstellen eine Eingabeaufforderung mit Basisanweisungen. Die Schritte zum Abrufen und Erweitern sind abgeschlossen. Jetzt kommt das "G" in RAG: Generation. In diesem Schritt senden Sie alles an ein Sprachmodell und erhalten eine Antwort.
Denken Sie daran wie folgt: Sie haben alle Zutaten (abgerufene Daten) gesammelt, das Rezept vorbereitet (augmented prompt), und jetzt setzen Sie es in den Ofen (rufen das Modell auf), um das endgültige Gericht (die Antwort) zu backen. Das Modell verwendet den Kontext, den Sie zum Generieren einer geerdeten Antwort bereitgestellt haben.
Aufrufen des Modells aus SQL
Dieser Schritt erfordert möglicherweise das Verlassen von T-SQL und das Schreiben von Anwendungscode. Sql Server und Azure SQL-Datenbank können REST-Endpunkte jedoch direkt aufrufen.sp_invoke_external_rest_endpoint Diese gespeicherte Prozedur sendet HTTPS-Anforderungen an externe Dienste und gibt die Antwort zurück. Die gespeicherte Prozedur ist in der Azure SQL-Datenbank standardmäßig aktiviert und kann in SQL Server 2025 mithilfe von sp_configure aktiviert werden.
Hier ist das grundlegende Muster:
DECLARE @response NVARCHAR(MAX);
DECLARE @returnValue INT;
EXECUTE @returnValue = sp_invoke_external_rest_endpoint
@url = N'https://<endpoint>.openai.azure.com/openai/deployments/<model>/chat/completions?api-version=<api-version>',
@method = 'POST',
@payload = @payload,
@credential = [https://<endpoint>.openai.azure.com],
@response = @response OUTPUT;
Der @url Parameter verweist auf Ihren Azure OpenAI-Bereitstellungsendpunkt. Das @method ist in der Regel "POST" für Generierungsanforderungen.
@payload enthält die JSON-Eingabeaufforderung, die Sie zuvor erstellt haben.
@credential verweist auf eine datenbankweite Anmeldeinformation mit Ihren Authentifizierungsdaten. Der @response Ausgabeparameter erfasst die Antwort des Modells.
Wenn Sie den Bereitstellungsendpunkt Ihres Modells mit der erweiterten Eingabeaufforderung aufrufen, verarbeitet das Modell es und gibt das Ergebnis zurück. Die gespeicherte Prozedur gibt 0 zurück, wenn der HTTP-Aufruf mit einem 2xx-Statuscode oder dem tatsächlichen HTTP-Statuscode erfolgreich ausgeführt wird, wenn ein Fehler auftritt.
Authentifizieren mit dem Endpunkt
Der Parameter @credential verweist auf eine datenbankweite Anmeldeinformation mit Ihren Authentifizierungsdaten. Sie richten diese Anmeldeinformationen ein, wenn Sie ein externes Modell erstellen, entweder mithilfe der verwalteten Identität oder eines API-Schlüssels. Die gleichen Anmeldeinformationen funktionieren sowohl für externe Modellaufrufe als auch für direkte REST-Endpunktaufrufe mit sp_invoke_external_rest_endpoint.
Extrahieren Sie die Antwort aus der Antwortnachricht
Wenn das Modell die Verarbeitung der Eingabeaufforderung beendet hat, wird das Ergebnis zurückgegeben, sp_invoke_external_rest_endpoint das in einen Standardumschlag eingeschlossen ist. Die gespeicherte Prozedur fügt Metadaten zur HTTP-Transaktion hinzu und schachtelt dann die tatsächliche API-Antwort in einer result Eigenschaft:
{
"response": {
"status": {
"http": {
"code": 200,
"description": "OK"
}
}
},
"result": {
"choices": [
{
"message": {
"role": "assistant",
"content": "The Mountain-500 is compatible with several pedal options..."
}
}
]
}
}
Die Antwort, die Sie suchen, finden Sie unter $.result.choices[0].message.content. Um dorthin zu gelangen, verwenden Sie JSON_VALUE, die skalare Werte aus JSON extrahiert:
IF @returnValue = 0
BEGIN
DECLARE @answer NVARCHAR(MAX);
SET @answer = JSON_VALUE(@response, '$.result.choices[0].message.content');
SELECT @answer AS AssistantResponse;
END
ELSE
BEGIN
SELECT
@returnValue AS HttpStatus,
JSON_VALUE(@response, '$.response.status.http.description') AS ErrorDescription;
END
Verwenden Sie stattdessen, wenn Sie ein JSON-Objekt oder ein Array anstelle eines einzelnen Werts JSON_QUERY extrahieren müssen. In den meisten RAG-Szenarien wird nur JSON_VALUE im Nachrichteninhalt benötigt.
Verwalten von Fehlern und Wiederholversuchen
Durch aufrufen eines externen Diensts aus einer Datenbank können Fehlermodi auftreten, die bei lokalen Abfragen nicht auftreten. Der Endpunkt ist möglicherweise vorübergehend nicht verfügbar, Ihre Anforderung kann einer Ratenbegrenzung unterliegen, oder die Authentifizierung kann fehlschlagen. Ihre SQL-Abfragen müssen diese Bedingungen ordnungsgemäß behandeln.
Der Rückgabewert von sp_invoke_external_rest_endpoint gibt Ihnen an, was passiert ist. A 0 bedeutet, dass der HTTP-Aufruf mit einem 2xx-Status erfolgreich war. Bei Fehlern ist der Rückgabewert der HTTP-Statuscode selbst. Beispielsweise bedeutet ein 429-Status, dass der Dienst Ihre Anfragen zurückstuft. Ein 401- oder 403-Fehler weist auf Probleme mit den Anmeldeinformationen hin.
IF @returnValue = 0
SET @answer = JSON_VALUE(@response, '$.result.choices[0].message.content');
ELSE IF @returnValue = 429
RAISERROR('Service is busy. Try again later.', 16, 1);
ELSE IF @returnValue = 401 OR @returnValue = 403
RAISERROR('Authentication failed. Check your credential configuration.', 16, 1);
ELSE
BEGIN
DECLARE @errorMsg NVARCHAR(500) = 'API call failed with status ' + CAST(@returnValue AS NVARCHAR(10));
RAISERROR(@errorMsg, 16, 1);
END
Bei vorübergehenden Fehlern, wie Timeouts oder temporärer Dienstunverfügbarkeit, kann die gespeicherte Prozedur automatisch einen erneuten Versuch starten. Fügen Sie den @retry_count Parameter hinzu, und in diesem Beispiel wird der Aufruf bis zu dreimal versucht, bevor er aufgibt:
EXECUTE @returnValue = sp_invoke_external_rest_endpoint
@url = @url,
@payload = @payload,
@credential = @credentialName,
@retry_count = 3,
@response = @response OUTPUT;
Dieser Parameter behandelt den allgemeinen Fall, in dem eine Anforderung einmal fehlschlägt, aber beim nächsten Versuch erfolgreich ist.
Erstellen Sie eine vollständige gespeicherte RAG-Prozedur
Sie kennen jetzt jedes Stück des RAG-Puzzles. Lassen Sie uns sie in einer einzigen gespeicherten Prozedur zusammenfassen, die von einer Kundensupportanwendung aufgerufen werden kann. Das Verfahren akzeptiert eine Frage in natürlicher Sprache und gibt eine Antwort zurück, die in Ihren Produktdaten verankert ist.
So funktioniert das Verfahren:
- Wandelt die Frage in eine Einbettung um, damit Sie sie mit Ihren Produktbeschreibungen vergleichen können.
- Sucht die relevantesten Produkte mithilfe des Vektorabstands, um die Einbettung der Frage mit der vorkompilierten Beschreibung der einzelnen Produkte zu vergleichen.
- Erstellt die Eingabeaufforderung mit einer Systemmeldung, die dem Modell angibt, die bereitgestellten Daten beizubehalten, und eine Benutzernachricht, die die abgerufenen Produkte mit der ursprünglichen Frage kombiniert.
- Sendet alles an Azure OpenAI.
- Extrahiert die Antwort aus der Antwort und gibt sie an den Anrufer zurück.
CREATE PROCEDURE dbo.AskProductQuestion
@Question NVARCHAR(1000),
@Answer NVARCHAR(MAX) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @questionVector VECTOR(1536);
DECLARE @context NVARCHAR(MAX);
DECLARE @payload NVARCHAR(MAX);
DECLARE @response NVARCHAR(MAX);
DECLARE @returnValue INT;
-- Step 1:Convert question to embedding
SELECT @questionVector = AI_GENERATE_EMBEDDINGS(@Question USE MODEL my_embedding_model);
-- Step 2: Retrieve relevant products using vector search
SET @context = (
SELECT TOP 3
p.Name AS ProductName,
p.Color,
p.Size,
pm.Name AS Model
FROM Production.Product p
INNER JOIN Production.ProductModel pm ON p.ProductModelID = pm.ProductModelID
ORDER BY VECTOR_DISTANCE('cosine', p.DescriptionVector, @questionVector)
FOR JSON PATH
);
-- Step 3: Build augmented prompt
SET @payload = JSON_OBJECT(
'messages': JSON_ARRAY(
JSON_OBJECT('role': 'system', 'content': 'You are an Adventure Works product assistant. Answer questions using only the provided product data.'),
JSON_OBJECT('role': 'user', 'content': 'Products: ' + @context + ' Question: ' + @Question)
),
'max_tokens': 500,
'temperature': 0.5
);
-- Step 4: Call the model
EXECUTE @returnValue = sp_invoke_external_rest_endpoint
@url = N'https://adventureworks-openai.openai.azure.com/openai/deployments/gpt-5.2/chat/completions?api-version=2024-10-21',
@method = 'POST',
@payload = @payload,
@credential = [https://adventureworks-openai.openai.azure.com],
@response = @response OUTPUT;
-- Extract and return the answer
IF @returnValue = 0
SET @Answer = JSON_VALUE(@response, '$.result.choices[0].message.content');
ELSE
SET @Answer = 'Unable to process your question. Please try again.';
END;
Sie haben die RAG-Pipeline in T-SQL abgeschlossen. Ein Kunde fragt: "Welche Pedale sind mit dem Mountain-500 kompatibel?" Ihr Verfahren wandelt diese Frage in einen Vektor um, findet die relevantesten Produkte, sendet sie mit Hintergrundinformationen an das Modell und gibt eine Antwort basierend auf dem tatsächlichen Bestand zurück. Keine Middleware, kein externer Anwendungscode, nur SQL ruft KI auf und gibt Ergebnisse zurück.
Wichtige Erkenntnisse
Der Erzeugungsschritt ist der Ort, an dem Ihre RAG-Pipeline Einen Wert liefert. Sie senden die erweiterte Eingabeaufforderung mithilfe sp_invoke_external_rest_endpointvon Azure OpenAI, die die HTTP-Kommunikation verarbeitet, ohne T-SQL zu verlassen. Die Authentifizierung verwendet die gleichen Anmeldeinformationen, die Sie beim Erstellen von externen Modellen datenbankspezifisch eingerichtet haben. Wenn die Antwort zurückkommt, JSON_VALUE extrahiert die Antwort des Assistenten. Implementieren Sie eine Fehlerbehandlung, weil Netzwerkaufrufe ganz anders als lokale Abfragen fehlschlagen können. Mit allen drei RAG-Schritten, die in T-SQL ausgeführt werden, wird Ihre Datenbank mehr als Speicher. Es wird zu einem intelligenten Dienst, der Fragen mit Ihren Daten beantwortet.