3rd-party 통합 기반 AI 기능

GitLab 15.11에 도입됨

시작하기

접근

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

액세스 요청을 작성한 후, Anthropic 계정을 등록하고 API 키를 생성할 수 있습니다. 그런 다음 다음과 같이 구성하세요:

Gitlab::CurrentSettings.update!(anthropic_api_key: <insert API key>)

로컬 설정

SaaS 및 Self-Managed GitLab 인스턴스와 호환되는 AI 기능을 개발하려면, 해당 기능이 3rd party 모델 제공업체에 직접 요청하는 대신 AI Gateway에 요청해야 합니다.

  1. GitLab 개발 키트 (GDK) 설정: 내부 비디오 튜토리얼
    1. 별도의 GDK 인스턴스로 설치합니다.
    2. gdk config set license.customer_portal_url 'http://localhost:5000' 명령을 실행합니다.
    3. 여기의 gdk.test 호스트명으로 이동합니다.
    4. CustomersDot을 설치한 경우 로컬 CustomersDot 인스턴스가 GitLab 애플리케이션을 사용하도록 지침을 따릅니다.
    5. GitLab 엔터프라이즈 라이선스를 활성화합니다
    6. gdk start 명령으로 동일한 터미널 세션에서 이러한 환경 변수를 내보냅니다:
      • 환경 변수를 항상 내보내도록 터미널을 구성할 수도 있습니다(예: 환경 변수를 ~/.bash_profile 또는 ~/.zshrc에 추가).
      export AI_GATEWAY_URL=http://0.0.0.0:5052 # 로컬 AI Gateway 인스턴스의 URL
      export LLM_DEBUG=1                        # 디버그 로깅 활성화
      

      또는 위의 스니펫과 동일한 내용의 env.runit 파일을 GDK의 루트에 만들 수 있습니다.

    7. 모든 AI 피처 플래그를 활성화합니다:
      rake gitlab:duo:enable_feature_flags
    
  2. AI Gateway 설정: 내부 비디오 튜토리얼
    1. 설치합니다.
    2. 다음을 Rails 콘솔에서 호출하여 AI 기능을 확인합니다:
Gitlab::Llm::AiGateway::Client.new(User.first).stream(prompt: "\n\nHuman: Hi, how are you?\n\nAssistant:")

구독 테스트를 위한 추가 설정 (DuoChat 설정에 필수가 아님)

  1. CustomersDot 설정:
    1. 설치에 대한 내부 비디오 튜토리얼을 참조합니다(비디오 캡션에 포함된 비활성 구독 플랜 ID URL을 아래에서 제공하는 계획 ID가 포함된 링크의 활성 구독 플랜 ID로 교체합니다).
      • 이 비디오는 공식 설치 단계를 대략적으로 따릅니다.
      • 자체 호스팅되는 구독을 생성하는 방법에 대한 안내도 제공합니다. 그러면 클라우드 활성화 코드를 받게 됩니다.
        • 구독 플랜 ID 디렉터리은 Self-Managed Subscription을 생성하기 위해 여기에서 사용 가능합니다.
        • local에 Self-Managed Subscription을 생성하려면 클라우드 활성화 코드를 받게 됩니다
        • 이 비디오는 공식 링크를 따릅니다.

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에 오류 정보가 있는지 확인하세요.

SaaS 전용 기능

이러한 기능은 아키텍처 청사진을 아직 따르지 않기 때문에 AI Gateway를 사용하지 않고 LLM 공급자에 직접 연결합니다. 이러한 설정에서 개발된 기능은 시간이 지남에 따라 Self Managed 제공으로 이동될 예정입니다.

자동화된 설정

<test-group-name>을 사용할 그룹 이름으로 대체합니다. 그룹이 없는 경우 새 그룹을 만듭니다. 스크립트를 여러 번 다시 실행해야 할 수 있으며, 오류 메시지와 그것을 해결하는 방법에 대한 문서 링크가 표시됩니다.

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

AI Gateway는 자동화된 설정 사용 시에도 설정해야 합니다.

매뉴얼 방식

  1. 로컬 인스턴스에 EE 라이선스를 얻는 절차를 따랐는지 확인하고 Ultimate 라이선스를 적용했는지 확인합니다.
    1. 라이선스가 적용된 것을 확인하려면 Admin Area > Subscription으로 이동하고 구독 플랜을 확인합니다.
  2. 인스턴스에서 EE 기능을 사용할 수 있도록 허용합니다.
    1. Admin Area > Settings > General로 이동합니다.
    2. Account and limit 섹션을 확장합니다.
    3. Licensed EE features 사용 허용을 활성화합니다.
  3. SaaS를 시뮬레이션하기 위해 GDK를 시뮬레이션합니다.
  4. 테스트하려는 그룹이 권한을 갖는 Ultimate 라이선스를 가지고 있는지 확인합니다.
    1. Admin Area > Overview > Groups로 이동합니다.
    2. 원하는 그룹을 선택한 다음 편집을 선택합니다.
    3. 권한 및 그룹 피처로 이동합니다.
    4. 플랜 디렉터리에서 Ultimate를 선택합니다.
  5. 그룹 AI Framework에 할당된 모든 피처 플래그를 활성화합니다.
  6. 원하는 기능에 대한 특정 피처 플래그를 활성화합니다.
  7. 특정 피처 플래그를 모두 활성화하려면 Rake 작업 rake gitlab:duo:enable_feature_flags를 사용합니다.
  8. AI Gateway를 설정합니다.

도움말

로컬 개발 팁

  1. 사용자 인터페이스에서 응답이 너무 오래 걸릴 때에는 gdk restart rails-background-jobs를 실행하여 Sidekiq를 재시작하는 것을 고려해보세요. 이것이 도움이 되지 않는다면, gdk kill을 시도한 후 gdk start를 해보세요.
  2. 또는, Sidekiq를 완전히 우회하고 서비스를 동기적으로 실행할 수 있습니다. GraphQL 오류가 Sidekiq 로그가 아닌 네트워크 검사기에서 사용 가능해지므로 이것은 디버깅 오류에 도움이 될 수 있습니다. 이를 위해서는 Llm::CompletionWorker 클래스의 perform_for 메서드를 일시적으로 수정하여 perform_asyncperform_inline로 변경하면 됩니다.

기능 개발 (추상화 레이어)

피처 플래그

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

  • 모든 GitLab Duo Chat 기능에 적용되는 일반 플래그(ai_duo_chat_switch). 기본적으로 활성화됩니다.
  • 다른 모든 AI 기능에 적용되는 일반 플래그(ai_global_switch). 기본적으로 활성화됩니다.
  • 해당 기능에 특화된 플래그. 피처 플래그 이름은 라이선스가 있는 기능 이름과 다른 이름이어야 합니다.

모든 피처 플래그 디렉터리 및 사용 방법은 피처 플래그 추적 Epic을 참조하세요.

실험적 REST API

빠르게 실험하고 AI 기능을 프로토타입화하기 위해 실험적 REST API 엔드포인트를 사용하세요.

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

  • 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)

Production에서 실험적 엔드포인트는 GitLab 팀 멤버에게만 제공됩니다. 인증을 위해 GitLab API 토큰을 사용하세요.

GraphQL API

추상화 레이어를 사용하여 AI 제공 업체 API에 연결하려면, aiAction이라는 확장 가능한 GraphQL API를 사용하세요(https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/graphql/mutations/ai/action.rb). input은 키/값 쌍을 허용하는데, 여기서 는 수행해야 하는 동작입니다. 하나의 GraphQL 요청당 하나의 AI 동작만 허용됩니다.

변이 예시:

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

예를 들어, “코드 설명” 동작을 구현하려면, 새로운 키 explainCodeinput을 확장합니다.

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

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

응답 수신 방법

AI 제공자에 대한 API 요청은 백그라운드 작업으로 처리됩니다. 따라서 요청을 유지하지 않고 Frontend에서 구독에 대한 응답을 매치시키어야 합니다.

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

“댓글 요약”에 대한 예시 변이에서 mutationclientSubscriptionId를 제공합니다:

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

그런 다음 컴포넌트에서 aiCompletionResponse를 청취하여 userId, resourceId, 그리고 clientSubscriptionId("randomId")를 사용합니다.

채팅에 대한 구독과 다르게 동작합니다.

많은 동시 구독을 하지 않기 위해, skip()을 사용하여 변수를 설정하기 전에 한 번만 구독해야 합니다.

현재 추상화 레이어 흐름

다음 차트는 예시로 VertexAI를 사용합니다. 여러분은 다른 제공 업체를 사용할 수 있습니다.

flowchart TD A[GitLab 프론트엔드] -->B[AiAction GraphQL 변이] B --> C[Llm::ExecuteMethodService] C --> D[여러 서비스 중 하나, 예: Llm::GenerateSummaryService] D -->|예약된| E[AI worker:Llm::CompletionWorker] E -->F[::Gitlab::Llm::Completions::Factory] F -->G[`::Gitlab::Llm::VertexAi::Completions::...` 클래스에서 `::Gitlab::Llm::Templates::...` 클래스를 사용] G -->|호출| H[Gitlab::Llm::VertexAi::Client] H --> |응답| 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 관심사를 포함하는 모든 객체가 될 수 있습니다. 예를 들어, 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

권한 부여

기능에 대한 권한을 처리하기 위해 정책을 사용하는 것을 권장합니다. 현재 다음 확인 사항을 확인해야 합니다.

  1. GitLab Duo Chat 기능의 경우 ai_duo_chat_switch가 활성화되어 있는지 확인해야 합니다.
  2. 다른 일반적인 AI 기능의 경우 ai_global_switch가 활성화되어 있는지 확인해야 합니다.
  3. 특정 기능의 feature flag가 활성화되어 있는지 확인해야 합니다.
  4. 네임스페이스에는 해당 기능에 필요한 라이선스가 있는지 확인해야 합니다.
  5. 사용자가 그룹/프로젝트의 구성원인지 확인해야 합니다.
  6. 네임스페이스experiment_features_enabled 설정이 설정되어 있는지 확인해야 합니다.

예를 들어, 우리의 예제에서는 allowed?(:amazing_new_ai_feature) 호출을 구현해야 합니다. 예를 들어, Summarize Comments 기능의 이슈 정책을 확인할 수 있습니다. 우리의 예제 경우, 이슈에 대한 기능을 구현하려고 합니다:

:::ruby # 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 스트림에 저장됩니다.
  • 사용자당 메시지의 단일 스트림이 있습니다. 즉, 현재 모든 서비스가 동일한 캐시를 공유합니다. 필요한 경우 Redis가 추정된 메시지 양을 처리할 수 있는지 인프라 팀과 확인한 후 여러 사용자당 여러 스트림으로 확장할 수 있습니다.
  • 마지막 50개의 메시지(요청 + 응답)만 보관됩니다.
  • 스트림의 만료 시간은 마지막 메시지 추가 이후 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를 사용하고 두 개의 새로운 클래스를 구현할 것입니다:

:::ruby # /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

:::ruby # /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
        You are an assistant that writes code for the following context:
        
        context: #{user_input}
        PROMPT
      end
    end
  end
end   end end

이 예제의 경우 다른 AI 제공업체도 지원하므로, 이러한 제공업체를 위해 비슷한 방법으로 사용할 수 있습니다:

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

GraphQL에 AI 작업 추가

TODO

임베딩 데이터베이스

임베딩은 채팅 문서 도구에서 작동하려면 생성되어야 합니다. 현재 시점에서 문서 도구는 Saas에서만 작동합니다.

GitLab 문서의 임베딩은 최신 변경 사항을 기반으로 업데이트됩니다. UTC 시간 05:00에 매주 월요일부터 일요일까지 가장 최근의 변경 사항을 반영하기 위해서임베딩 레일스의 잡 크론 잡이 실행됩니다.

아래 섹션에서는 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 문서의 모든 vectorized 표현을 데이터베이스 내 개발용 씨드를 생성합니다. Rake 작업이 사용하는 파일은 지난 시점의 GitLab 문서 스냅샷이며 정기적으로 업데이트되지 않습니다. 따라서 이 씨드 작업은 구식 문서에 기반한 임베딩을 생성합니다. 약간 구식화된 문서 임베딩은 개발 환경에 충분하며, 이는 씨드 작업의 사용 목적입니다.

임베딩과 관련된 테스트를 작성하거나 업데이트할 때, 임베딩 픽스처 파일을 업데이트하는 것이 좋을 수 있습니다.

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

사양에서 사용하기

seed Rake 작업은 GitLab 문서의 모든 포함 항목을 개발용 데이터베이스에 채웁니다. extract_embeddings Rake 작업은 포함 항목의 일부를 담은 fixture 파일을 작성합니다.

Rake 작업에 나열된 질문 세트 자체가 fixture 파일로 가져오는 포함 항목을 결정합니다. 예를 들어, 하나의 질문은 “비밀번호를 재설정하는 방법”입니다. extract_embeddings 작업은 이 질문에 대한 가장 관련성 있는 포함 항목을 개발용 데이터베이스(여기에는 seed Rake 작업의 데이터가 포함됨)에서 추출하여 이러한 포함 항목을 ee/spec/fixtures/vertex_embeddings에 저장합니다. 이 fixture는 포함 항목과 관련된 테스트에 사용됩니다.

포함 항목에서 포함 항목을 사용해야 하는 경우, RSpec :ai_embedding_fixtures 메타데이터를 사용하세요.

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

모니터링

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

보안

인공 지능 (AI) 기능을 위한 안전한 코딩 지침을 참조하세요.