다음을 통해 공유


벡터 데이터베이스에 대한 App Service 인증 및 권한 부여

이 문서에서는 App Service .NET 애플리케이션과 벡터 데이터베이스 솔루션 간의 연결을 관리하는 방법을 보여 줍니다. 지원되는 서비스에 대해 Microsoft Entra 관리 ID를 사용하고 다른 사용자를 위해 연결 문자열을 안전하게 저장하는 방법을 다룹니다.

애플리케이션에 벡터 데이터베이스를 추가하면 AI에 대해 [시맨틱 메모리 또는 벡터 저장소](벡터 저장소)를 활성화할 수 있습니다. .NET용 의미 체계 커널 SDK를 사용하면 기본 벡터 데이터베이스 솔루션을 사용하여 메모리 스토리지 및 호출을 쉽게 구현할 수 있습니다.

필수 조건

인증을 위해 Microsoft Entra 관리 ID 사용

벡터 데이터베이스 서비스가 Microsoft Entra 인증을 지원하는 경우 App Service에서 관리 ID를 사용하여 비밀을 수동으로 프로비전하거나 회전할 필요 없이 벡터 데이터베이스에 안전하게 액세스할 수 있습니다. Microsoft Entra 인증을 지원하는 Azure 서비스 목록은 Microsoft Entra 인증을 지원하는 Azure 서비스를 참조하세요.

App Service에 관리 ID 추가

애플리케이션에 두 가지 형식의 ID를 부여할 수 있습니다.

  • 시스템 할당 ID는 애플리케이션에 연결되어 있어 해당 앱을 삭제하면 이 ID도 삭제됩니다. 앱에는 시스템 할당 ID가 하나만 있을 수 있습니다.
  • 사용자 할당 ID는 앱에 할당할 수 있는 독립 실행형 Azure 리소스입니다. 앱에는 여러 사용자 할당 ID가 있을 수 있습니다.

시스템 할당 ID 추가

  1. Azure Portal에서 앱 페이지로 이동한 다음 설정 그룹까지 아래로 스크롤합니다.
  2. ID를 선택합니다.
  3. 시스템 할당 탭에서 상태켜기로 전환한 다음 저장을 선택합니다.

az webapp identity assign 명령을 실행하여 시스템 할당 ID를 만듭니다.

az webapp identity assign --name <appName> --resource-group <groupName>

사용자 할당 ID 추가

사용자 할당 ID를 앱에 추가하려면 ID를 만든 다음 해당 리소스 식별자를 앱 구성에 추가합니다.

  1. 이 지침에 따라 사용자가 할당한 관리 ID 리소스를 만듭니다.

  2. 앱 페이지의 왼쪽 탐색 창에서 설정 그룹까지 아래로 스크롤합니다.

  3. ID를 선택합니다.

  4. 사용자 할당>추가를 선택합니다.

  5. 이전에 만든 ID를 찾아 선택한 다음 추가를 선택합니다.

    Important

    추가를 선택하면 앱이 다시 시작됩니다.

  1. 사용자 할당 ID를 만듭니다.

    az identity create --resource-group <groupName> --name <identityName>
    
  2. 앱에 ID를 할당합니다.

    az webapp identity assign --resource-group <groupName> --name <appName> --identities <identityId>
    

관리 ID에 Azure 역할 추가

  1. Azure Portal에서 벡터 데이터베이스 액세스 권한을 부여하려는 범위로 이동합니다. 범위는 관리 그룹, 구독, 리소스 그룹 또는 특정 Azure 리소스일 수 있습니다.
  2. 왼쪽 탐색 창에서 액세스 제어(IAM)를 선택합니다.
  3. 추가를 선택한 다음, 역할 할당 추가를 선택합니다.
  4. 역할 탭에서 벡터 데이터베이스에 대한 읽기 권한을 부여하는 적절한 역할을 선택합니다.
  5. 멤버 탭에서 관리 ID를 선택합니다.
  6. 검토 + 할당 탭에서 검토 + 할당을 선택하여 역할을 할당합니다.

리소스 범위

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/subscriptions/<subscriptionId>/resourcegroups/<resourceGroupName>/providers/<providerName>/<resourceType>/<resourceSubType>/<resourceName>"

리소스 그룹 범위

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/subscriptions/<subscriptionId>/resourcegroups/<resourceGroupName>"

구독 범위

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/subscriptions/<subscriptionId>"

관리 그룹 범위

az role assignment create --assignee "<managedIdentityObjectID>" \
--role "<myVectorDbReaderRole>" \
--scope "/providers/Microsoft.Management/managementGroups/<managementGroupName>"

벡터 데이터베이스로 토큰 기반 인증 구현

다음 코드 샘플에는 다음과 같은 추가 라이브러리가 필요합니다.

  1. 앱의 관리 ID를 선택하려면 DefaultAzureCredential 개체를 초기화합니다.

    // Initialize a DefaultAzureCredential.
    // This credential type will try several authentication flows in order until one is available.
    // Will pickup Visual Studio or Azure CLI credentials in local environments.
    // Will pickup managed identity credentials in production deployments.
    TokenCredential credentials = new DefaultAzureCredential(
        new DefaultAzureCredentialOptions
        {
            // If using a user-assigned identity specify either:
            // ManagedIdentityClientId or ManagedIdentityResourceId.
            // e.g.: ManagedIdentityClientId = "myIdentityClientId".
        }
    );
    
  2. 벡터 데이터베이스의 IMemoryStore 개체를 초기화한 후 이를 사용하여 ISemanticTextMemory를 빌드합니다.

    // Retrieve the endpoint obtained from the Azure AI Search deployment.
    // Retrieve the endpoint and deployments obtained from the Azure OpenAI deployment.
    // Must use the deployment name not the underlying model name.
    IConfigurationRoot config = new ConfigurationBuilder().AddUserSecrets<Program>().Build();
    string searchEndpoint = config["AZURE_AISEARCH_ENDPOINT"]!;
    string openAiEndpoint = config["AZURE_OPENAI_ENDPOINT"]!;
    string embeddingModel = config["AZURE_OPENAI_EMBEDDING_NAME"]!;
    
    // The Semantic Kernel SDK provides a connector extension for Azure AI Search.
    // Initialize an AzureAISearchMemoryStore using your managed identity credentials.
    IMemoryStore memoryStore = new AzureAISearchMemoryStore(searchEndpoint, credentials);
    
    // Build a SemanticMemoryStore with Azure AI Search as the store.
    // Must also include a text embedding generation service.
    ISemanticTextMemory memory = new MemoryBuilder()
        .WithOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint)
        .WithMemoryStore(memoryStore)
        .Build();
    
  3. Kernel 개체를 빌드한 후 TextMemoryPlugin을 사용하여 ISemanticTextMemory 개체를 가져옵니다.

    // Build a Kernel, include a chat completion service.
    string chatModel = config["AZURE_OPENAI_GPT_NAME"]!;
    Kernel kernel = Kernel
        .CreateBuilder()
        .AddAzureOpenAIChatCompletion(chatModel, openAiEndpoint, credentials)
        .Build();
    
    // Import the semantic memory store as a TextMemoryPlugin.
    // The TextMemoryPlugin enable recall via prompt expressions.
    kernel.ImportPluginFromObject(new TextMemoryPlugin(memory));
    
  4. 메모리 회수가 포함된 프롬프트를 호출하려면 Kernel 개체를 사용합니다.

    // Must configure the memory collection, number of memories to recall, and relevance score.
    // The {{...}} syntax represents an expression to Semantic Kernel.
    // For more information on this syntax see:
    // https://learn.microsoft.com/semantic-kernel/prompts/prompt-template-syntax
    string memoryCollection = config["AZURE_OPENAI_MEMORY_NAME"]!;
    string? result = await kernel.InvokePromptAsync<string>(
        "{{recall 'where did I grow up?'}}",
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollection,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    Console.WriteLine($"Output: {result}");
    

Key Vault를 사용하여 연결 비밀 저장

벡터 데이터베이스가 Microsoft Entra 인증을 지원하지 않는 경우 Key Vault를 사용하여 연결 비밀을 저장하고 App Service 애플리케이션으로 검색할 수 있습니다. Key Vault를 사용하여 연결 비밀을 저장하면 이를 여러 애플리케이션과 공유하고 애플리케이션별로 개별 비밀에 대한 액세스를 제어할 수 있습니다.

이 단계를 수행하기 전에 벡터 데이터베이스에 대한 연결 문자열을 검색합니다. 예를 들어, ASP.NET Core 웹앱에서 Azure Cache for Redis 사용을 참조하세요.

Key Vault에 연결 문자열 추가

Important

이 단계를 수행하기 전에 Azure Portal을 사용하여 Key Vault를 만들었는지 확인합니다.

  1. Azure Portal에서 키 자격 증명 모음으로 이동합니다.
  2. Key Vault 왼쪽 탐색에서 개체를 선택한 다음 비밀을 선택합니다.
  3. + 생성/가져오기를 선택합니다.
  4. 비밀 만들기 화면에서 다음 값을 선택합니다.
    • 업로드 옵션: Manual.
    • 이름: 비밀의 이름을 입력합니다. 비밀 이름은 키 자격 증명 모음 내에서 고유해야 합니다.
    • : 벡터 데이터베이스의 연결 문자열입니다.
    • 다른 값은 기본값으로 그대로 둡니다. 만들기를 실행합니다.
  5. 비밀이 성공적으로 만들어졌다는 메시지를 받으면 애플리케이션에서 사용할 준비가 된 것입니다.

Important

이 단계를 수행하기 전에 Azure CLI를 사용하여 Key Vault를 만들었는지 확인합니다.

  1. RBAC(역할 기반 액세스 제어)를 통해 사용자 계정에 키 자격 증명 모음에 대한 권한을 부여하고, Azure CLI 명령 az role assignment create를 사용하여 역할을 할당합니다.

    az role assignment create \
    --role "Key Vault Secrets User" \
    --assignee "<yourEmailAddress>" \
    --scope "/subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName>/providers/Microsoft.KeyVault/vaults/<keyVaultName>"
    
  2. Azure CLI 명령 az keyvault secret set를 사용하여 Key Vault에 연결 문자열을 추가합니다.

    az keyvault secret set \
    --vault-name "<keyVaultName>" \
    --name "<secretName>" \
    --value "<connectionString>"
    

App Service에 Key Vault에 대한 액세스 권한 부여

  1. App Service에 관리 ID를 할당합니다.
  2. 관리 ID에 Key Vault Secrets UserKey Vault Reader 역할을 추가합니다.

Key Vault에서 연결 문자열 검색 구현

다음 코드 샘플을 사용하려면 다음과 같은 추가 라이브러리가 필요합니다.

이러한 코드 샘플은 Redis 데이터베이스를 사용하지만 연결 문자열을 지원하는 모든 벡터 데이터베이스에 적용할 수 있습니다.

  1. 앱의 관리 ID를 선택하려면 DefaultAzureCredential 개체를 초기화합니다.

    // Initialize a DefaultAzureCredential.
    // This credential type will try several authentication flows in order until one is available.
    // Will pickup Visual Studio or Azure CLI credentials in local environments.
    // Will pickup managed identity credentials in production deployments.
    TokenCredential credentials = new DefaultAzureCredential(
        new DefaultAzureCredentialOptions
        {
            // If using a user-assigned identity specify either:
            // ManagedIdentityClientId or ManagedIdentityResourceId.
            // e.g.: ManagedIdentityClientId = "myIdentityClientId".
        }
    );
    
  2. 구성을 빌드할 때 Key Vault를 추가하면 Key Vault 비밀이 IConfigurationRoot 개체에 매핑됩니다.

    // User secrets let you provide connection strings when testing locally
    // For more info see: https://learn.microsoft.com/aspnet/core/security/app-secrets
    IConfigurationRoot config = new ConfigurationBuilder()
        .AddUserSecrets<Program>()
        .AddAzureKeyVault(new Uri("{vaultURI}"), credentials)
        .Build();
    
    // Retrieve the Redis connection string obtained from the Key Vault.
    string redisConnectionString = config["AZURE_REDIS_CONNECT_STRING"]!;
    
  3. Key Vault의 벡터 데이터베이스 연결 문자열을 사용하여 IMemoryStore 개체를 초기화한 다음 이를 사용하여 ISemanticTextMemory를 빌드합니다.

    // Use the connection string to connect to the database
    IDatabase database = (
        await ConnectionMultiplexer.ConnectAsync(redisConnectionString)
    ).GetDatabase();
    
    // The Semantic Kernel SDK provides a connector extension for Redis.
    // Initialize an RedisMemoryStore using your managed identity credentials.
    IMemoryStore memoryStore = new RedisMemoryStore(database);
    
    // Retrieve the endpoint and deployments obtained from the Azure OpenAI deployment.
    // Must use the deployment name not the underlying model name.
    string openAiEndpoint = config["AZURE_OPENAI_ENDPOINT"]!;
    string embeddingModel = config["AZURE_OPENAI_EMBEDDING_NAME"]!;
    
    // Build a SemanticMemoryStore with Azure AI Search as the store.
    // Must also include a text embedding generation service.
    ISemanticTextMemory memory = new MemoryBuilder()
        .WithOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint)
        .WithMemoryStore(memoryStore)
        .Build();
    
  4. Kernel 개체를 빌드한 후 TextMemoryPlugin을 사용하여 ISemanticTextMemory 개체를 가져옵니다.

    // Build a Kernel, include a chat completion service.
    string chatModel = config["AZURE_OPENAI_GPT_NAME"]!;
    Kernel kernel = Kernel
        .CreateBuilder()
        .AddAzureOpenAIChatCompletion(chatModel, openAiEndpoint, credentials)
        .Build();
    
    // Import the semantic memory store as a TextMemoryPlugin.
    // The TextMemoryPlugin enable recall via prompt expressions.
    kernel.ImportPluginFromObject(new TextMemoryPlugin(memory));
    
  5. 메모리 회수가 포함된 프롬프트를 호출하려면 Kernel 개체를 사용합니다.

    // Must configure the memory collection, number of memories to recall, and relevance score.
    // The {{...}} syntax represents an expression to Semantic Kernel.
    // For more information on this syntax see:
    // https://learn.microsoft.com/semantic-kernel/prompts/prompt-template-syntax
    string memoryCollection = config["AZURE_OPENAI_MEMORY_NAME"]!;
    string? result = await kernel.InvokePromptAsync<string>(
        "{{recall 'where did I grow up?'}}",
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollection,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    Console.WriteLine($"Output: {result}");
    

애플리케이션 설정을 사용하여 연결 비밀 저장

벡터 데이터베이스가 Microsoft Entra 인증을 지원하지 않는 경우 App Service 애플리케이션 설정을 사용하여 연결 비밀을 저장할 수 있습니다. 애플리케이션 설정을 사용하면 추가 Azure 리소스를 프로비전하지 않고도 연결 비밀을 저장할 수 있습니다.

이 단계를 수행하기 전에 벡터 데이터베이스에 대한 연결 문자열을 검색합니다. 예를 들어, .NET Framework에서 Azure Cache for Redis 사용을 참조하세요.

애플리케이션 설정에 연결 문자열 추가

  1. Azure Portal에서 앱 페이지로 이동합니다.
  2. 앱의 왼쪽 메뉴에서 구성>애플리케이션 설정을 선택합니다.
    • 기본적으로 애플리케이션 설정 값은 보안을 위해 포털에서 숨겨져 있습니다.
    • 애플리케이션 설정의 숨겨진 값을 보려면 해당 값 필드를 선택합니다.
  3. 새 연결 설정을 선택합니다.
  4. 연결 문자열 추가/편집 화면에서 다음 값을 선택합니다.
    • 이름: 설정 이름을 입력합니다. 설정 이름은 고유해야 합니다.
    • : 벡터 데이터베이스의 연결 문자열입니다.
    • 형식: 연결 형식, 적용되는 다른 형식이 없으면 Custom입니다.
    • 다른 값은 기본값으로 그대로 둡니다. 확인을 선택합니다.
  5. 구성 페이지에서 다시 저장을 선택합니다.

Azure CLI 명령 az webapp config connection-string set를 사용하여 앱 설정을 추가하거나 편집합니다.

az webapp config connection-string set \
--name "<appName>" \
--resource-group "<groupName>" \
--connection-string-type "<connectionType>" \
--settings <connectionName>='<connectionString>'

앱 설정에서 연결 문자열 검색 구현

다음 코드 샘플을 사용하려면 다음과 같은 추가 라이브러리가 필요합니다.

이러한 코드 샘플은 Redis 데이터베이스를 사용하지만 연결 문자열을 지원하는 모든 벡터 데이터베이스에 적용할 수 있습니다.

  1. 구성을 빌드할 때 환경 변수를 추가하면 연결 문자열이 IConfigurationRoot 개체에 매핑됩니다.

    // User secrets let you provide connection strings when testing locally
    // For more info see: https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets
    IConfigurationRoot config = new ConfigurationBuilder()
        .AddUserSecrets<Program>()
        .AddEnvironmentVariables()
        .Build();
    
    // Retrieve the Redis connection string obtained from the app settings.
    // The connection string name should match the entry in application settings
    string redisConnectionString = config.GetConnectionString("AZURE_REDIS")!;
    
  2. 앱 설정의 벡터 데이터베이스 연결 문자열을 사용하여 IMemoryStore 개체를 초기화한 다음 이를 사용하여 ISemanticTextMemory를 빌드합니다.

    // Use the connection string to connect to the database
    IDatabase database = (
        await ConnectionMultiplexer.ConnectAsync(redisConnectionString)
    ).GetDatabase();
    
    // The Semantic Kernel SDK provides a connector extension for Redis.
    // Initialize an RedisMemoryStore using your managed identity credentials.
    IMemoryStore memoryStore = new RedisMemoryStore(database);
    
    // Retrieve the endpoint and deployments obtained from the Azure OpenAI deployment.
    // Must use the deployment name not the underlying model name.
    string openAiEndpoint = config["AZURE_OPENAI_ENDPOINT"]!;
    string embeddingModel = config["AZURE_OPENAI_EMBEDDING_NAME"]!;
    
    // Build a SemanticMemoryStore with Azure AI Search as the store.
    // Must also include a text embedding generation service.
    ISemanticTextMemory memory = new MemoryBuilder()
        .WithOpenAITextEmbeddingGeneration(embeddingModel, openAiEndpoint)
        .WithMemoryStore(memoryStore)
        .Build();
    
  3. Kernel 개체를 빌드한 후 TextMemoryPlugin을 사용하여 ISemanticTextMemory 개체를 가져옵니다.

    // Build a Kernel, include a chat completion service.
    string chatModel = config["AZURE_OPENAI_GPT_NAME"]!;
    Kernel kernel = Kernel
        .CreateBuilder()
        .AddAzureOpenAIChatCompletion(chatModel, openAiEndpoint, credentials)
        .Build();
    
    // Import the semantic memory store as a TextMemoryPlugin.
    // The TextMemoryPlugin enable recall via prompt expressions.
    kernel.ImportPluginFromObject(new TextMemoryPlugin(memory));
    
  4. 메모리 회수가 포함된 프롬프트를 호출하려면 Kernel 개체를 사용합니다.

    // Must configure the memory collection, number of memories to recall, and relevance score.
    // The {{...}} syntax represents an expression to Semantic Kernel.
    // For more information on this syntax see:
    // https://learn.microsoft.com/semantic-kernel/prompts/prompt-template-syntax
    string memoryCollection = config["AZURE_OPENAI_MEMORY_NAME"]!;
    string? result = await kernel.InvokePromptAsync<string>(
        "{{recall 'where did I grow up?'}}",
        new()
        {
            [TextMemoryPlugin.CollectionParam] = memoryCollection,
            [TextMemoryPlugin.LimitParam] = "2",
            [TextMemoryPlugin.RelevanceParam] = "0.79",
        }
    );
    Console.WriteLine($"Output: {result}");