3rd-party 통합 기반 AI 기능

GitLab 15.11에 도입됨.

기능 플래그

모든 AI 기능 작업에 다음 기능 플래그를 적용하세요:

  • 모든 GitLab Duo 채팅 기능에 적용되는 일반 플래그(ai_duo_chat_switch). 기본으로 활성화됩니다.
  • 다른 모든 AI 기능에 적용되는 일반 플래그(ai_global_switch). 기본으로 활성화됩니다.
  • 해당 기능에 특화된 플래그. 해당 기능의 플래그 이름은 라이선스 기능을 나타내는 이름과 달라야 합니다.

모든 기능 플래그 목록 및 사용 방법은 기능 플래그 추적 epic을 참조하세요.

새로운 AI 작업 구현

새로운 AI 작업을 구현하려면 우선 선호하는 AI 공급업체에 연결하세요. 다음 중 하나를 사용하여이 API에 연결할 수 있습니다:

  • 실험적 REST API.
  • 추상화 계층.

모든 AI 기능은 실험적입니다.

로컬에서 자체 관리 AI 기능 테스트

AI Gateway 설정으로 이동

로컬에서 SaaS 전용 AI 기능 테스트

자동 설정

<test-group-name>을 사용하려는 그룹 이름으로 대체하세요. 그룹이 존재하지 않으면 새 그룹이 생성됩니다. 스크립트를 여러 번 다시 실행해야 할 수도 있으며 오류 해결 방법에 대한 문서 링크가 포함된 유용한 오류 메시지가 표시됩니다.

GITLAB_SIMULATE_SAAS=1 RAILS_ENV=development bundle exec rake 'gitlab:duo:setup[<test-group-name>]'

수동 방식

  1. 로컬 인스턴스에 EE 라이선스를 얻는 프로세스를 따랐는지 확인하고 Ultimate 라이선스를 적용하세요.
    1. 라이선스가 적용되었는지 확인하려면 관리 영역 > 구독으로 이동하여 구독 계획을 확인하세요.
  2. 인스턴스에서 EE 기능 사용을 허용하세요.
    1. 관리 영역 > 설정 > 일반 -> 계정 및 한도로 이동
    2. 라이선스가 있는 EE 기능 사용 허용을 활성화하세요.
  3. GDK를 사용하여 SaaS를 시뮬레이션하도록 설정하세요.
  4. 테스트하려는 그룹에 Ultimate 라이선스가 있는지 확인하세요.
    1. 관리 영역 > 개요 > 그룹으로 이동
    2. 선택한 그룹의 편집을 선택하세요.
    3. 권한 및 그룹 기능으로 이동
    4. 계획 목록에서 Ultimate을 선택하세요.
  5. 테스트하려는 기능에 대한 특정 기능 플래그를 활성화하세요.
  6. 그룹 AI 프레임워크에 할당된 모든 기능 플래그를 활성화하기 위해 Rake 작업 rake gitlab:duo:enable_feature_flags를 사용할 수 있습니다.
  7. AI Gateway 설정

GCP Vertex 액세스 구성

로컬 개발을 위해 GCP 서비스 키를 얻으려면 다음 단계를 따르세요:

  • 이 페이지를 방문하여 샌드박스 GCP 프로젝트를 만들거나 이 템플릿을 사용하여 기존 그룹 GCP 프로젝트에 액세스 권한을 요청하세요.
  • 개인 GCP 프로젝트를 사용하는 경우 Vertex AI API를 활성화해야 할 수도 있습니다:
    1. 환영 페이지를 방문하고 프로젝트를 선택하세요 (예 : jdoe-5d23dpe).
    2. API 및 서비스 > 활성화된 API 및 서비스로 이동합니다.
    3. + API 및 서비스 사용 설정을 선택하세요.
    4. Vertex AI API를 검색하세요.
    5. Vertex AI API를 선택한 다음 사용을 선택하세요.
  • gcloud CLI를 설치하세요.
  • gcloud auth application-default login 명령을 사용하여 로컬로 GCP에 인증하세요.
  • Rails 콘솔을 열어 설정을 업데이트하세요:
# PROJECT_ID = "your-gcp-project-name"

Gitlab::CurrentSettings.update(vertex_ai_project: PROJECT_ID)

Anthropic 액세스 구성

Gitlab::CurrentSettings.update!(anthropic_api_key: <API  삽입>)

임베딩 데이터베이스

임베딩은 VertexAI 텍스트 임베딩 API를 통해 생성됩니다.

GitLab 문서의 임베딩은 매주 월요일부터 금요일까지 05:00 UTC에 임베딩 cron 작업이 실행될 때마다 업데이트됩니다.

아래 섹션은 DB에 임베딩을 채우거나 스펙에서 사용할 임베딩을 추출하는 방법을 설명합니다.

설정

  1. GDK에서 pgvector를 활성화합니다.
  2. GDK에서 임베딩 데이터베이스를 활성화합니다.

      gdk config set gitlab.rails.databases.embedding.enabled true
    
  3. gdk reconfigure를 실행합니다.
  4. GDK의 gitlab 폴더에서 데이터베이스 마이그레이션을 실행하여 임베딩 데이터베이스를 생성합니다.

      RAILS_ENV=development bin/rails db:migrate
    

채우기

GitLab 문서의 임베딩을 개발용 데이터베이스에 시드하려면 다음 Rake 작업을 사용하십시오.

RAILS_ENV=development bundle exec rake gitlab:llm:embeddings:vertex:seed

이 Rake 작업은 GitLab 문서의 벡터화된 표현을 임베딩 데이터베이스에 채웁니다. Rake 작업이 사용하는 파일은 지난 과거에 GitLab 문서의 스냅숏이며 정기적으로 업데이트되지 않습니다. 결과적으로, 이 시드 작업은 날짜가 지난 GitLab 문서를 기반으로 임베딩을 생성합니다. 약간 오래된 문서 임베딩은 개발 환경에서 충분하며, 이 시드 작업의 사용 사례입니다.

임베딩과 관련된 테스트를 작성하거나 업데이트할 때, 임베딩 픽스처 파일을 업데이트하려면 다음과 같은 Rake 작업을 실행할 수 있습니다.

RAILS_ENV=development bundle exec rake gitlab:llm:embeddings:vertex:extract_embeddings

스펙에서 임베딩 사용

시드 Rake 작업은 모든 GitLab 문서에 대한 임베딩으로 개발용 데이터베이스를 채우고, extract_embeddings Rake 작업은 임베딩의 일부를 포함하는 픽스처 파일로 채웁니다.

Rake 작업 자체에 나열된 질문 세트는 픽스처 파일로 가져오는 임베딩을 결정합니다. 예를 들어, “GitLab 사용 방법”에 대한 질문 중 하나입니다. extract_embeddings 작업은 해당 질문에 대한 가장 관련성 높은 임베딩을 개발용 데이터베이스(시드 Rake 작업의 데이터)에서 추출하고 이러한 임베딩을 ee/spec/fixtures/vertex_embeddings에 저장합니다. 이 픽스처는 임베딩과 관련된 테스트에 사용됩니다.

임베딩 스펙에서 사용해야 하는 경우, RSpec :ai_embedding_fixtures 메타데이터를 사용합니다.

context 'GitLab 사용 방법에 대한 질문 시' , :ai_embedding_fixtures do
  # ...예시
end

로컬 개발 팁

  1. 응답이 사용자 인터페이스에 표시되기까지 시간이 오래 걸릴 때는 gdk restart rails-background-jobs를 실행하여 Sidekiq을 다시 시작하십시오. 그렇게 해도 작동하지 않으면 gdk kill을 실행한 다음 gdk start를 시도해 보십시오.
  2. 또는 Sidekiq을 완전히 우회하여 채팅 서비스를 동기적으로 실행할 수 있습니다. 이렇게 하면 GraphQL 오류가 이제 Sidekiq 로그가 아닌 네트워크 검사기에서 사용할 수 있어 오류를 디버깅하는 데 도움이 될 수 있습니다. Llm::CompletionWorker.perform_async 문을 Llm::CompletionWorker.perform_inline으로 일시적으로 변경하여 실행할 수 있습니다.

GitLab Duo Chat 작업

GitLab Duo Chat을 사용하는 방법에 대한 지침을 확인하세요.

AI 게이트웨이를 로컬에서 사용하여 AI 기능 테스트

SaaS 및 Self-managed GitLab 인스턴스와 호환되는 AI 기능을 개발하려면, 해당 기능은 직접 제3자 모델 제공업체에 요청하는 것이 아니라 AI 게이트웨이에 요청해야 합니다.

설정

  1. CustomersDot 설정 (선택 사항, 채팅 기능에 필수 사항 아님):
    1. CustomersDot 설치: 내부 비디오 튜토리얼
      • 이 비디오는 공식 설치 단계를 대략적으로 따릅니다.
      • 자체 호스팅 구독을 만드는 방법에 대한 안내도 제공합니다. 클라우드 활성화 코드가 반환됩니다.
        • 로컬에서 Ultimate Self-Managed Subscription을 생성하는 데 사용할 이 링크를 즐겨찾기에 추가하십시오.
        • 다른 구독 플랜 ID 목록은 여기에서 확인할 수 있습니다.
    2. GitLab 개발 키트 (GDK) 설정: 내부 비디오 튜토리얼
    3. 모든 AI 기능 플래그를 활성화하십시오:
      rake gitlab:duo:enable_feature_flags
    
  2. AI 게이트웨이 설정: 내부 비디오 튜토리얼
    1. AI 게이트웨이를 설치하십시오.
    2. 다음을 레일스 콘솔에서 호출하여 AI 기능을 검증하십시오:
Gitlab::Llm::AiGateway::Client.new(User.first).stream(prompt: "\n\nHuman: Hi, how are you?\n\nAssistant:")

GraphQL을 사용하여 설정 확인

  1. GraphQL 탐색기를 방문하세요.
  2. aiAction 뮤테이션을 실행하세요. 다음은 예시입니다:

    mutation {
      aiAction(
        input: {
          chat: {
            resourceId: "gid://gitlab/User/1",
            content: "Hello"
          }
        }
      ){
        requestId
        errors
      }
    }
    
  3. (GitLab Duo Chat 전용) 다음 쿼리를 실행하여 응답을 가져옵니다:

    query {
      aiMessages {
        nodes {
          requestId
          content
          role
          timestamp
          chunkId
          errors
        }
      }
    }
    

    응답을 가져올 수 없는 경우, 오류 정보가 포함되어 있는지 확인하려면 graphql_json.log, sidekiq_json.log, llm.log 또는 modelgateway_debug.log를 확인하세요.

AI 게이트웨이 설정을 피하기 위한 임시 해결책

참고: GitLab 16.8부터 AI 게이트웨이를 설정해야 합니다. AI 기능을 테스트하기 위한 권장하는 방법입니다. LLM에 직접 요청을 보내면 알지 못했던 버그가 발생할 수 있으므로 조심해야 합니다.

LLMs에 직접 요청을 보내려면 다음을 수행해야 합니다.

  1. 기능 플래그를 비활성화합니다.

      echo "Feature.disable(:gitlab_duo_chat_requests_to_ai_gateway)" | rails c
    
  2. 필요한 액세스 토큰을 설정합니다. 액세스 토큰을 받으려면:

    1. Vertex의 경우, 아래 지침을 따르세요.
    2. Anthropic의 경우, 액세스 요청을 생성하세요.

실험용 REST API

실험용 REST API 엔드포인트를 사용하여 AI 기능을 빠르게 실험하고 프로토타입을 만들 수 있습니다.

엔드포인트는 다음과 같습니다:

  • https://gitlab.example.com/api/v4/ai/experimentation/anthropic/complete
  • https://gitlab.example.com/api/v4/ai/experimentation/vertex/chat

이러한 엔드포인트는 프로토타입용이며, 고객에게 적용되는 기능이 아닙니다.

로컬 개발 환경에서는 기능 플래그가 활성화된 상태로 이러한 엔드포인트를 로컬에서 실험할 수 있습니다:

Feature.enable(:ai_experimentation_api)

프로덕션 환경에서 실험용 엔드포인트는 GitLab 팀 멤버에게만 제공됩니다. 인증하려면 GitLab API 토큰을 사용하세요.

추상화 레이어

GraphQL API

추상화 레이어를 사용하여 AI 제공업체 API에 연결하려면 aiAction라는 확장 가능한 GraphQL API를 사용하세요. input은 키/값 쌍을 받아들이며, key는 수행해야 하는 동작입니다. 우리는 뮤테이션 요청 당 AI 동작을 하나만 허용합니다.

뮤테이션의 예시:

mutation {
  aiAction(input: {summarizeComments: {resourceId: "gid://gitlab/Issue/52"}}) {
    clientMutationId
  }
}

예를 들어 “코드 설명” 작업을 수행하려면, 새 explainCode 키로 input을 확장합니다. 뮤테이션은 다음과 같습니다:

mutation {
  aiAction(input: {explainCode: {resourceId: "gid://gitlab/MergeRequest/52", code: "foo() { console.log() }" }}) {
    clientMutationId
  }
}

그런 다음 GraphQL API는 Anthropic Client를 사용하여 응답을 보냅니다.

응답 받는 방법

AI 제공업체에 대한 API 요청은 백그라운드 작업으로 처리됩니다. 요청을 계속 유지하지 않으므로, Frontend가 구독의 응답과 일치시켜야 합니다.

경고: userIdresourceId만 사용되는 경우 요청에 대한 올바른 응답을 결정하는 것은 문제를 일으킬 수 있습니다. 예를 들어 두 AI 기능이 동일한 userIdresourceId를 사용하는 경우, 두 구독에서 서로 응답을 받을 수 있습니다. 이 혼선을 방지하기 위해 clientSubscriptionId를 도입했습니다.

aiCompletionResponse 구독에서 응답을 일치시키려면 aiAction 뮤테이션에 clientSubscriptionId를 제공할 수 있습니다.

  • clientSubscriptionId는 페이지 내에서 다른 AI 기능과 간섭하지 않도록 기능당 고유해야 합니다. UUID를 사용하는 것을 권장합니다.
  • aiAction의 일부로 clientSubscriptionId가 제공된 경우에만 aiCompletionResponse를 브로드캐스팅하는 데 사용됩니다.
  • clientSubscriptionId가 제공되지 않으면, aiCompletionResponse에는 userIdresourceId만 사용됩니다.

예를 들어 댓글을 요약하는 뮤테이션의 경우, randomId를 뮤테이션의 일부로 제공합니다:

mutation {
  aiAction(input: {summarizeComments: {resourceId: "gid://gitlab/Issue/52"}, clientSubscriptionId: "randomId"}) {
    clientMutationId
  }
}

그런 다음 컴포넌트에서는 userId, resourceId, clientSubscriptionId ("randomId")를 사용하여 aiCompletionResponse를 수신합니다:

subscription aiCompletionResponse($userId: UserID, $resourceId: AiModelID, $clientSubscriptionId: String) {
  aiCompletionResponse(userId: $userId, resourceId: $resourceId, clientSubscriptionId: $clientSubscriptionId) {
    content
    errors
  }
}

댓글을 위한 구독은 다르게 작동합니다.

많은 동시 구독을 피하려면, 뮤테이션이 보내진 후에만 skip()을 사용하여 구독해야 합니다.

현재 추상화 레이어 플로우

다음 그래프는 VertexAI를 예시로 사용합니다. 다른 제공 업체를 사용할 수 있습니다.

flowchart TD A[GitLab frontend] -->B[AiAction GraphQL mutation] B --> C[Llm::ExecuteMethodService] C --> D[One of services, for example: Llm::GenerateSummaryService] D -->|scheduled| E[AI worker:Llm::CompletionWorker] E -->F[::Gitlab::Llm::Completions::Factory] F -->G[`::Gitlab::Llm::VertexAi::Completions::...` class using `::Gitlab::Llm::Templates::...` class] G -->|calling| H[Gitlab::Llm::VertexAi::Client] H --> |response| I[::Gitlab::Llm::GraphqlSubscriptionResponseService] I --> J[GraphqlTriggers.ai_completion_response] J --> K[::GitlabSchema.subscriptions.trigger]

새로운 액션 구현 방법

새로운 메소드 등록

Llm::ExecuteMethodService로 이동하여 새로운 서비스 클래스로 새로운 메소드를 추가하세요.

class ExecuteMethodService < BaseService
  METHODS = {
    # ...
    amazing_new_ai_feature: Llm::AmazingNewAiFeatureService
  }.freeze

서비스 생성

  1. ee/app/services/llm/ 아래에 새로운 서비스를 생성하고 BaseService를 상속받으세요.
  2. resource는 우리가 작업하고 싶은 객체입니다. Ai::Model concern을 포함하는 모든 객체가 될 수 있습니다. 예를 들어, Project, MergeRequest, 또는 Issue 등이 될 수 있습니다.
# ee/app/services/llm/amazing_new_ai_feature_service.rb

module Llm
  class AmazingNewAiFeatureService < BaseService
    private

    def perform
      ::Llm::CompletionWorker.perform_async(user.id, resource.id, resource.class.name, :amazing_new_ai_feature)
      success
    end

    def valid?
      super && Ability.allowed?(user, :amazing_new_ai_feature, resource)
    end
  end
end

권한

기능에 대한 권한 부여를 처리하기 위해 policies를 사용하는 것을 권장합니다. 현재 우리는 다음과 같은 확인 사항을 처리해야 합니다:

  1. GitLab Duo Chat 기능의 경우 ai_duo_chat_switch가 활성화되어 있어야 합니다.
  2. 다른 일반 AI 기능의 경우 ai_global_switch가 활성화되어 있어야 합니다.
  3. 특정 기능 특성 플래그가 활성화되어 있어야 합니다.
  4. 기능에 필요한 라이선스를 소유하고 있어야 합니다.
  5. 사용자가 그룹/프로젝트의 구성원이어야 합니다.
  6. experiment_features_enabled 설정이 Namespace에서 설정되어 있어야 합니다.

위 예제에서는 allowed?(:amazing_new_ai_feature) 호출을 구현해야 합니다. 예를 들어, 요약 코멘트 기능을 위한 Issue Policy 확인을 참고할 수 있습니다. 우리의 예제에서는 Issue를 위해 기능을 구현하고 싶습니다:

# ee/app/policies/ee/issue_policy.rb

module EE
  module IssuePolicy
    extend ActiveSupport::Concern
    prepended do
      with_scope :global
      condition(:ai_available) do
        ::Feature.enabled?(:ai_global_switch, type: :ops)
      end

      with_scope :subject
      condition(:amazing_new_ai_feature_enabled) do
        ::Feature.enabled?(:amazing_new_ai_feature, subject_container) &&
          subject_container.licensed_feature_available?(:amazing_new_ai_feature)
      end

      rule do
        ai_available & amazing_new_ai_feature_enabled & is_project_member
      end.enable :amazing_new_ai_feature
    end
  end
end

요청과 응답을 짝지어주기

여러 사용자의 요청이 병렬로 처리될 수 있기 때문에, 응답을 받을 때 원본 요청과 매칭하는 것은 어려울 수 있습니다. 이를 위해 requestId 필드를 사용할 수 있습니다. 왜냐하면 요청과 응답은 동일한 requestId UUID를 가지고 있음이 보장되기 때문입니다.

캐싱

AI 요청과 응답은 캐싱될 수 있습니다. 캐싱된 대화는 사용자가 AI 기능과 상호 작용을 표시하는 데 사용됩니다. 현재의 구현에서는 이 캐시가 사용자가 요청을 반복할 때 AI 서비스에 연이어 호출을 건너뛰기 위해 사용되지 않습니다.

query {
  aiMessages {
    nodes {
      id
      requestId
      content
      role
      errors
      timestamp
    }
  }
}

이 캐시는 특히 채팅 기능에 유용합니다. 다른 서비스의 경우에는 캐싱이 비활성화되어 있습니다. (서비스에 cache_response: true 옵션을 사용하여 캐싱을 활성화시킬 수 있습니다.)

캐싱에는 다음과 같은 제한 사항이 있습니다:

  • 메시지는 Redis 스트림에 저장됩니다.
  • 사용자 당 하나의 메시지 스트림이 있습니다. 이는 현재 모든 서비스가 동일한 캐시를 공유함을 의미합니다.
  • 마지막 메시지 추가 후 3일의 만료 기간이 있습니다.
  • 사용자는 자신의 메시지에만 액세스할 수 있습니다. 캐싱 레벨에서 권한이 없으며, (현재 사용자가 아닌 경우 액세스할 경우) 모든 권한은 서비스 레이어에서 예상됩니다.

네임스페이스 설정에 따라 리소스에서 기능이 허용되는지 확인하세요

루트 네임스페이스 수준에서 AI 기능의 사용을 제한하는 한 가지 설정이 허용됩니다:

  • experiment_features_enabled

주어진 네임스페이스에 대해 해당 기능이 허용되었는지 확인하려면 다음을 호출하세요:

Gitlab::Llm::StageCheck.available?(namespace, :name_of_the_feature)

기능의 이름을 Gitlab::Llm::StageCheck 클래스에 추가하세요. 실험 및 베타 기능을 구분하는 배열이 있습니다.

이렇게 하면 다음과 같은 다양한 경우에 대비할 수 있습니다:

  • 기능이 어느 배열에도 없는 경우 검사가 true를 반환합니다. 예를 들어, 해당 기능이 GA(일반적 이용 가능)로 전환된 경우입니다.

실험 단계에서 기능을 베타 단계로 이동하려면 EXPERIMENTAL_FEATURES 배열에서 기능의 이름을 BETA_FEATURES 배열로 이동하세요.

AI API 및 프롬프트 호출 구현

CompletionWorkerCompletions::Factory를 호출하고 서비스를 초기화하고 API에 대한 실제 호출을 실행할 것입니다. 이 예시에서는 VertexAI를 사용하여 두 가지 새로운 클래스를 구현할 것입니다:

# /ee/lib/gitlab/llm/vertex_ai/completions/amazing_new_ai_feature.rb

module Gitlab
  module Llm
    module VertexAi
      module Completions
        class AmazingNewAiFeature < Gitlab::Llm::Completions::Base
          def execute
            prompt = ai_prompt_class.new(options[:user_input]).to_prompt

            response = Gitlab::Llm::VertexAi::Client.new(user).text(content: prompt)

            response_modifier = ::Gitlab::Llm::VertexAi::ResponseModifiers::Predictions.new(response)

            ::Gitlab::Llm::GraphqlSubscriptionResponseService.new(
              user, nil, response_modifier, options: response_options
            ).execute
          end
        end
      end
    end
  end
end
# /ee/lib/gitlab/llm/vertex_ai/templates/amazing_new_ai_feature.rb

module Gitlab
  module Llm
    module VertexAi
      module Templates
        class AmazingNewAiFeature
          def initialize(user_input)
            @user_input = user_input
          end

          def to_prompt
            <<~PROMPT
            다음 컨텍스트에 대한 코드를 작성하는 어시스턴트입니다:

            컨텍스트: #{user_input}
            PROMPT
          end
        end
      end
    end
  end
end

동일한 예시에 대해 여러 AI 제공업체를 지원하므로 이러한 제공업체도 사용할 수 있습니다:

Gitlab::Llm::VertexAi::Client.new(user)
Gitlab::Llm::Anthropic::Client.new(user)

AI 작업 모니터링

  • 각 AI 작업에 대한 오류 비율 및 응답 대기 시간 apdex는 Sidekiq Service 대시보드SLI 상세정보: llm_completion에서 찾을 수 있습니다.
  • 사용된 토큰, 각 AI 기능의 사용 및 기타 통계는 periscope 대시보드에서 찾을 수 있습니다.

GraphQL에 AI 작업 추가

TODO

보안

인공 지능 (AI) 기능에 대한 안전 코딩 가이드라인은 인공 지능 (AI) 기능을 위한 안전한 코딩 가이드라인을 참조하세요.