AI 기능 기반의 타사 통합

GitLab 15.11에 도입.

피처 플래그

모든 AI 기능 작업에 다음 피처 플래그를 적용합니다:

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

모든 피처 플래그 디렉터리 및 사용 방법은 피처 플래그 추적 Epic에서 확인하세요.

새로운 AI 작업 구현

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

  • 실험적인 REST API.
  • 추상화 레이어.

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

로컬에서 Self-managed 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 라이선스를 얻는 과정을 따랐는지 확인합니다.
    1. 라이선스가 적용되었는지 확인하려면 관리자 영역 > 구독으로 이동하고 구독 플랜을 확인합니다.
  2. 인스턴스에서 EE 기능 사용을 허용합니다.
    1. 관리자 영역 > 설정 > 일반 -> 계정 및 제한으로 이동합니다.
    2. 라이선스된 EE 기능 사용 허용을 활성화합니다.
  3. GDK를 사용하여 SaaS 시뮬레이션을 설정합니다.
  4. 테스트하려는 그룹이 Ultimate 라이선스를 갖도록 확인합니다.
    1. 관리자 영역 > 개요 > 그룹으로 이동합니다.
    2. 선택한 그룹을 편집합니다.
    3. 권한 및 그룹 기능으로 이동합니다.
    4. 계획 디렉터리에서 Ultimate를 선택합니다.
  5. 테스트하려는 기능에 대한 특정 피처 플래그를 활성화합니다.
  6. 그룹 AI Framework에 할당된 모든 피처 플래그를 활성화하려면 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: <insert API key>)

임베딩 데이터베이스

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

GitLab 문서의 임베딩은 임베딩 크론 작업이 실행되는 평일 오전 05:00 UTC의 최신 변경사항을 기반으로 업데이트됩니다.

아래 섹션에서는 데이터베이스에 임베딩을 생성하거나 스펙에서 사용할 임베딩을 추출하는 방법에 대해 설명합니다.

설정

  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
    

채우기

이 Rake 작업을 사용하여 GitLab 문서의 임베딩을 개발 데이터베이스에 시드하세요.

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

이 Rake 작업은 GitLab 문서의 벡터화된 표현을 가진 임베딩 데이터베이스를 채웁니다. 해당 Rake 작업이 사용하는 파일은 과거에 GitLab 문서의 스냅샷이며 정기적으로 업데이트되지 않습니다. 결과적으로, 이 시드 작업이 낡은 GitLab 문서를 기반으로 임베딩을 생성한다는 점을 알고 계시면 도움이 됩니다. 약간 떨어진 문서 임베딩은 개발 환경에 충분하며, 이는 시드 작업의 사용 사례입니다.

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

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

스펙에서 임베딩 사용

seed Rake 작업은 모든 GitLab 문서에 대한 임베딩을 개발 데이터베이스에 채웁니다. extract_embeddings Rake 작업은 임베딩의 일부분으로 픽스처 파일을 채웁니다.

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

임베딩 스펙에서 사용해야 하는 질문을 변경하고 싶다면, extract_embeddings Rake 작업을 업데이트하고 다시 실행하세요.

임베딩이 필요한 스펙에서는 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 채팅 작업

GitLab Duo 채팅을 사용하는 데 참고할 사항은 가이드라인을 확인하세요.

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

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

설정

  1. CustomersDot 설정 (옵션, 채팅 기능에 필요하지 않음):
    1. CustomersDot 설치: 내부 비디오 튜토리얼
      • 이 비디오는 공식 설치 단계를 대략 따릅니다.
      • 또한 Self-managed 구독을 생성하는 방법에 대한 안내도 제공됩니다. 결과로 cloud activation code를 받게 됩니다.
        • 로컬에서 Ultimate Self-managed Subscription을 생성하기 위한 이 링크를 책갈피에 추가하세요.
        • 다른 구독 플랜 ID 디렉터리은 여기에서 확인할 수 있습니다.
  2. GitLab 개발 키트 (GDK) 설정: 내부 비디오 튜토리얼
    1. 개발 키트를 별도의 GDK 인스턴스로 설치하세요.
    2. gdk config set license.customer_portal_url 'http://localhost:5000' 실행하세요.
    3. gdk.test 호스트 이름 설정하세요.
    4. 로컬 CustomersDot 인스턴스가 GitLab 애플리케이션을 사용하도록 지시하세요 (만약 CustomersDot을 설치했다면).
    5. GitLab Enterprise 라이선스를 활성화하세요
    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
    
  3. AI Gateway 설치: 내부 비디오 튜토리얼
    1. 설치하세요.
    2. 다음을 Rails 콘솔에서 호출하여 AI 기능을 확인하세요:
Gitlab::Llm::AiGateway::Client.new(User.first).stream(prompt: "\n\nHuman: Hi, how are you?\n\nAssistant:")
#### GraphQL로 설정 확인

1. [GraphQL explorer](../../api/graphql/index.md#interactive-graphql-explorer)를 방문하세요.
1. `aiAction` 뮤테이션을 실행합니다. 다음은 예시입니다:
   
   ```graphql
   mutation {
     aiAction(
       input: {
         chat: {
           resourceId: "gid://gitlab/User/1",
           content: "Hello"
         }
       }
     ){
       requestId
       errors
     }
   }
  1. (GitLab Duo Chat 전용) 다음 쿼리를 실행하여 응답을 가져옵니다:

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

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

AI 게이트웨이 설정을 피하는 임시 해결 방법

note
GitLab 16.8부터 AI 게이트웨이를 설정해야 합니다. AI 기능을 테스트하는 권장 방법입니다. LLMs에 직접 요청을 보내면 알 수 없는 버그가 발생할 수 있습니다. 이 임시 해결책을 사용할 때 주의하세요.

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를 사용하세요. inputkey/value 쌍을 허용하며, key는 수행해야 하는 액션입니다. 뮤테이션 요청당 AI 액션을 하나만 허용합니다.

뮤테이션의 예시:

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

예를 들어, “코드 설명” 액션을 만들고 싶다고 가정해보겠습니다. 이를 위해 input을 새로운 키 explainCode로 확장합니다. 뮤테이션은 다음과 같습니다:

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

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

응답 수신 방법

AI 제공업체로의 API 요청은 백그라운드 작업으로 처리됩니다. 따라서 요청을 계속 유지하지 않으며 프론트엔드에서 요청을 구독한 응답과 일치시켜야 합니다.

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

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

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

예시로, 댓글을 요약하는 뮤테이션에 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 프론트엔드] -->B[AiAction GraphQL 뮤테이션] B --> C[Llm::ExecuteMethodService] C --> D[서비스 중 하나, 예: Llm::GenerateSummaryService] D -->|예약된 상태| E[AI 워커: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`로 이동하여 새로운 서비스 클래스로 새 메소드를 추가합니다.

```ruby
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) 호출을 구현해야 합니다. 예를 들어, summarize comments feature의 이슈 정책을 살펴볼 수 있습니다.

응답과 요청 매핑

여러 사용자의 요청이 병렬로 처리될 수 있기 때문에 응답을 받을 때 요청을 해당 원래 요청과 매핑하는 것이 어려울 수 있습니다. requestId 필드는 요청과 응답이 동일한 requestId UUID를 가지고 있기 때문에 이러한 목적으로 사용할 수 있습니다.

캐싱

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

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

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

캐싱에는 다음과 같은 제한이 있습니다.

  • 메시지는 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를 사용하여 두 개의 새 클래스를 구현할 것입니다.

# /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
            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)

AI 작업 모니터링

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

GraphQL에 AI 작업 추가

TODO

보안

인공 지능 (AI) 기능에 대한 보안 코딩 가이드라인을 참조하십시오.