RAG 응답 생성 및 처리

Completed

Tip

자세한 내용은 텍스트 및 이미지 탭을 참조하세요.

고객은 Mountain-500 자전거에 맞는 페달을 알고 싶어합니다. 벡터 검색을 사용하여 관련 제품을 찾고, JSON으로 서식을 지정하고, 접지 지침이 포함된 프롬프트를 작성합니다. 검색 및 확대 단계가 수행됩니다. 이제 RAG의 "G", 즉 생성이 다뤄집니다. 이 단계에서는 모든 항목을 언어 모델로 보내고 답변을 다시 가져옵니다.

모든 재료 (검색 된 데이터)를 수집하고 조리법 (증강 프롬프트)을 준비했으며 이제 최종 요리 (응답)를 굽기 위해 오븐 (모델 호출)에 넣습니다. 모델은 제공한 컨텍스트를 사용하여 기본 답변을 생성합니다.

SQL에서 모델 호출

이 단계에서는 T-SQL을 종료하고 애플리케이션 코드를 작성해야 한다고 생각할 수 있습니다. 그러나 SQL Server 및 Azure SQL Database는 다음을 사용하여 sp_invoke_external_rest_endpointREST 엔드포인트를 직접 호출할 수 있습니다. 이 저장 프로시저는 HTTPS 요청을 외부 서비스로 보내고 응답을 반환합니다. 저장 프로시저는 Azure SQL Database에서 기본적으로 사용하도록 설정되며 SQL Server 2025에서는 다음을 사용하여 sp_configure사용하도록 설정할 수 있습니다.

기본 패턴은 다음과 같습니다.

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;

매개 변수는 @url Azure OpenAI 배포 엔드포인트를 가리킵니다. 세대 요청의 경우 @method는 일반적으로 'POST'입니다. @payload 이전에 빌드한 JSON 프롬프트가 포함되어 있습니다. @credential는 인증 세부 정보를 포함하는 데이터베이스 범위 자격 증명을 참조합니다. 출력 매개 변수는 @response 모델의 응답을 캡처합니다.

보강 프롬프트를 사용하여 모델의 배포 엔드포인트를 호출하면 모델이 이를 처리하고 결과를 반환합니다. 저장 프로시저는 HTTP 호출이 2xx 상태 코드로 성공하거나 실제 HTTP 상태 코드가 실패할 때 0을 반환합니다.

엔드포인트를 사용하여 인증

매개 변수 @credential는 인증 세부 정보를 보유하는 데이터베이스 범위 자격 증명을 참조합니다. 관리 ID 또는 API 키를 사용하여 외부 모델을 만들 때 이러한 자격 증명을 설정합니다. 동일한 자격 증명은 외부 모델 호출과 직접 REST 엔드포인트 호출에서 모두 작동합니다 sp_invoke_external_rest_endpoint.

응답에서 답변 추출

모델이 프롬프트 sp_invoke_external_rest_endpoint 처리를 마치면 표준 봉투에 래핑된 결과를 반환합니다. 저장 프로시저는 HTTP 트랜잭션에 대한 메타데이터를 추가한 다음, 속성 내에 result 실제 API 응답을 중첩합니다.

{
  "response": {
    "status": {
      "http": {
        "code": 200,
        "description": "OK"
      }
    }
  },
  "result": {
    "choices": [
      {
        "message": {
          "role": "assistant",
          "content": "The Mountain-500 is compatible with several pedal options..."
        }
      }
    ]
  }
}

당신이 원하는 답은 $.result.choices[0].message.content에 있습니다. 거기에 도착하려면 JSON에서 스칼라 값을 추출하는 JSON_VALUE을 사용하십시오.

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

단일 값이 아닌 JSON 개체 또는 배열을 추출해야 하는 경우 대신 사용합니다 JSON_QUERY . 대부분의 RAG 시나리오에서 메시지 콘텐츠JSON_VALUE만 있으면 충분합니다.

오류 관리 및 다시 시도

데이터베이스에서 외부 서비스를 호출하면 로컬 쿼리에서 발생하지 않는 오류 모드가 발생할 수 있습니다. 엔드포인트를 일시적으로 사용할 수 없거나, 요청 속도가 제한되거나, 인증이 실패할 수 있습니다. SQL 쿼리는 이러한 조건을 정상적으로 처리해야 합니다.

sp_invoke_external_rest_endpoint의 반환 값은 무슨 일이 일어났는지를 알려줍니다. 0은 HTTP 호출이 2xx 상태로 성공했음을 의미합니다. 실패의 경우 반환 값은 HTTP 상태 코드 자체입니다. 예를 들어 429 상태는 서비스가 요청을 제한하고 있다는 것을 의미합니다. 401 또는 403은 자격 증명 문제를 가리킵니다.

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

시간 제한 또는 임시 서비스 사용 불가와 같은 일시적인 오류의 경우 저장 프로시저가 자동으로 다시 시도할 수 있습니다. 매개 변수를 @retry_count 추가하고 이 예제에서는 다음을 포기하기 전에 최대 세 번까지 호출을 시도합니다.

EXECUTE @returnValue = sp_invoke_external_rest_endpoint
    @url = @url,
    @payload = @payload,
    @credential = @credentialName,
    @retry_count = 3,
    @response = @response OUTPUT;

이 매개 변수는 요청이 한 번 실패하지만 다음 시도에서 성공하는 일반적인 경우를 처리합니다.

전체 RAG 저장 프로시저 빌드

이제 RAG 퍼즐의 각 조각을 알고 있습니다. 고객 지원 애플리케이션에서 호출할 수 있는 단일 저장 프로시저로 합시다. 이 절차는 자연어 질문을 수락하고 제품 데이터에 근거한 답변을 반환합니다.

이 절차는 다음과 같습니다.

  1. 질문을 임베딩으로 변환하여 제품 설명과 비교할 수 있습니다.
  2. 각 제품의 사전 계산 설명 포함과 질문 포함을 비교하기 위해 벡터 거리를 사용하여 가장 관련성이 큰 제품을 찾습니다.
  3. 제공된 데이터를 유지하도록 모델에 지시하는 시스템 메시지와 검색된 제품을 원래 질문과 결합하는 사용자 메시지로 프롬프트를 빌드합니다.
  4. 모든 항목을 Azure OpenAI로 보냅니다.
  5. 응답에서 답변을 추출하고 호출자에게 반환합니다.
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;

T-SQL에서 RAG 파이프라인을 완료했습니다. 한 고객이 "Mountain-500과 함께 작동하는 페달은 무엇인가요?" 하고 묻습니다. 프로시저는 해당 질문을 벡터로 변환하고, 가장 관련성이 큰 제품을 찾고, 접지 지침을 사용하여 모델에 보내고, 실제 인벤토리에 따라 답변을 반환합니다. 미들웨어가 없고, 외부 애플리케이션 코드가 없으며, SQL에서 AI를 호출하고 결과를 반환합니다.

주요 내용

생성 단계는 RAG 파이프라인이 값을 제공하는 위치입니다. T-SQL을 종료하지 않고 HTTP 통신을 처리하는 Azure OpenAI sp_invoke_external_rest_endpoint에 증강 프롬프트를 보냅니다. 인증은 외부 모델을 만들 때 설정한 것과 동일한 데이터베이스 범위 자격 증명을 사용합니다. 응답이 돌아오면 JSON_VALUE 도우미의 대답을 꺼냅니다. 네트워크 호출이 로컬 쿼리와 다르게 실패할 수 있으므로 오류 처리를 포함하여 구축하세요. 세 RAG 단계가 모두 T-SQL에서 실행되면 데이터베이스는 스토리지 이상의 상태가 됩니다. 데이터를 사용하여 질문에 대답하는 지능형 서비스가 됩니다.