서드파티 통합 기반 AI 기능
GitLab v19.5요약
GitLab Duo 기능은 AI 모델과 통합을 기반으로 동작합니다. 개발 환경에서 GitLab Duo 라이선스를 설정하는 자세한 방법은 로컬 개발용 GitLab Duo 라이선스를 참고합니다. GDK가 없는 새 컴퓨터에서 AI 개발이 가능한 상태까지 거쳐야 하는 주요 단계는 다음과 같습니다.
GitLab Duo 기능은 AI 모델과 통합을 기반으로 동작합니다. 이 문서는 GitLab에서 AI 기능을 개발하는 방법의 개요를 제공합니다.
개발 환경에서 GitLab Duo 라이선스를 설정하는 자세한 방법은 로컬 개발용 GitLab Duo 라이선스를 참고합니다.
로컬 개발 환경 설정#
GDK가 없는 새 컴퓨터에서 AI 개발이 가능한 상태까지 거쳐야 하는 주요 단계는 다음과 같습니다.
GDK 준비#
로컬 개발용 GitLab Duo를 설정하려면 GitLab Development Kit의 안내를 따릅니다. 이 안내는 로컬 환경에서 사전 요구 사항을 충족하고 핵심 백엔드 구성 요소를 설정하는 방법을 설명합니다.
기존 GDK 업데이트#
GDK가 이미 설치되어 있더라도 올바른 환경 변수, NGINX, Anthropic 키 등과 함께 DAP를 설정하려면 GitLab Development Kit 안내를 참고해야 합니다.
gitlab:duo:setup 태스크 실행#
gitlab:duo:setup Rake 태스크를 실행해 GitLab Duo 기능이 활성화된 테스트 그룹과 프로젝트를 시드합니다.
이 태스크는 멱등적이며 gitlab-duo 그룹이 이미 있으면 재시드를 건너뜁니다.
이 태스크에서 재시드를 강제하려면 GITLAB_DUO_RESEED=1을 설정합니다.
사용되는 시드의 자세한 내용은 개발 시드 파일을 참고합니다.
이 태스크는 인스턴스나 그룹이 GitLab Duo 기능을 로컬에서 테스트하는 데 필요한 라이선스, 설정, 기능 플래그를 갖추도록 합니다. 아래에 여러 선택지가 있습니다. 어느 쪽인지 확실하지 않으면 1번을 사용합니다.
이 스크립트를 실행하면 Duo Core 애드온은 항상 생성됩니다.
Rake 태스크는 GDK 루트 디렉터리가 아니라 GitLab Rails 루트 디렉터리(일반적으로 /path/to/gdk/gitlab)에서 실행합니다.
-
GitLab.com 모드
GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup'이 명령은 다음을 수행합니다.
test라는 프로젝트를 포함한gitlab-duo테스트 그룹을 생성합니다- 그룹에 Ultimate 라이선스를 적용합니다
- 그룹에 GitLab Duo Enterprise 시트를 설정합니다
- 그룹의 모든 기능 플래그를 활성화합니다
- 사용 가능한 모든 GitLab Duo 기능이 켜지도록 그룹 설정을 업데이트합니다
그룹에 GitLab Duo Pro 라이선스를 대신 추가하려면(일부 기능만 활성화됩니다) 다음을 실행합니다.
GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup[duo_pro]'Duo Core 기능만 테스트하려면 다음을 실행합니다.
GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup[duo_core]' -
GitLab Self-Managed / Dedicated 모드
GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup'이 명령은 다음을 수행합니다.
test라는 프로젝트를 포함한gitlab-duo테스트 그룹을 생성합니다- 인스턴스에 Ultimate 라이선스를 적용합니다
- 인스턴스에 GitLab Duo Enterprise 시트를 설정합니다
- 인스턴스의 모든 기능 플래그를 활성화합니다
- 사용 가능한 모든 GitLab Duo 기능이 켜지도록 인스턴스 설정을 업데이트합니다
인스턴스에 GitLab Duo Pro 애드온을 대신 추가하려면(일부 기능만 활성화됩니다) 다음을 실행합니다.
GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup[duo_pro]'Duo Core 기능만 테스트하려면 다음을 실행합니다.
GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup[duo_core]'
스크립트가 오류 없이 끝나면 gitlab-duo/test로 이동해 GitLab Duo Chat이 보이는지 확인합니다. Chat에 질문을 보내 오류가 없는지 확인합니다.
문제 해결#
대부분의 경우 ai-services 스크립트를 실행해 GDK 환경 변수를 재설정하는 것만으로 발생한 오류를 해결할 수 있습니다.
A9999 오류가 발생하면 이는 포괄적인 오류입니다. 가장 흔한 원인은 AI Gateway 설치 안내에 설명된 대로
AI Gateway URL을 올바르게 설정하지 않은 경우입니다.
그렇지 않다면 gitlab-ai-gateway 리포지터리에서 make test로 테스트가 통과하는지, gdk tail gitlab-ai-gateway가 오류를 반환하지 않는지 확인합니다.
A1003은 권한 쪽에 가까우며, Anthropic 토큰이 잘못되었거나 없는 경우 또는 gcloud 구성이 잘못된 경우입니다.
Agentic Chat에서는 인증 오류가 발생해도 A1003 오류로 이어지지 않을 수 있습니다. gdk tail duo-workflow-service로 워크플로 서비스가 문제 없이 동작하는지 확인합니다. 인증 오류가 보이면 새 Anthropic 키를 발급하고 ai-setup 스크립트를 다시 실행해야 합니다
로컬 개발 팁#
- 사용자 인터페이스에 응답이 나타나기까지 너무 오래 걸리면
gdk restart rails-background-jobs로 Sidekiq을 재시작해 봅니다. 그래도 해결되지 않으면gdk kill후gdk start를 시도합니다. - 또는 Sidekiq을 완전히 우회해 서비스를 동기적으로 실행합니다.
GraphQL 오류가 Sidekiq 로그가 아니라 네트워크 인스펙터에 표시되므로
오류 디버깅에 도움이 됩니다. 이를 위해
Llm::CompletionWorker클래스의perform_for메서드에서perform_async를perform_inline으로 일시적으로 바꿉니다. - 모델 선택을 테스트할 때는
env.runit파일에export FETCH_MODEL_SELECTION_DATA_FROM_LOCAL=1을 추가해 GDK가 클라우드 연결형 AIGW가 아니라 로컬 AI Gateway에서 모델 정보를 가져오도록 합니다.
기능 개발(추상화 레이어)#
기능 플래그#
모든 AI 기능 작업에는 다음 기능 플래그를 적용합니다.
- 다른 모든 AI 기능에 적용되는 일반 플래그(
ai_global_switch). 기본적으로 활성화되어 있습니다. - 해당 기능 전용 플래그. 기능 플래그 이름은 라이선스 기능 이름과 달라야 합니다.
전체 기능 플래그 목록과 사용 방법은 기능 플래그 트래커 에픽을 참고합니다.
AI Gateway로 기능 플래그 푸시#
기능 플래그를 AI Gateway로 푸시할 수 있습니다. 기능이 AI Gateway에 있더라도 사용자에게 노출되는 변경을 점진적으로 출시하는 데 유용합니다. 다음 예시를 참고합니다.
# Push a feature flag state to AI Gateway.
Gitlab::AiGateway.push_feature_flag(:new_prompt_template, user)
이후 AI Gateway에서 다음과 같이 기능 플래그 상태를 사용할 수 있습니다.
from ai_gateway.feature_flags import is_feature_enabled
# Check if the feature flag "new_prompt_template" is enabled.
if is_feature_enabled('new_prompt_template'):
# Build a prompt from the new prompt template
else:
# Build a prompt from the old prompt template
중요: 정리 단계에서는 GitLab-Rails 리포지터리의 플래그를 제거하기 전에 AI Gateway 리포지터리의 기능 플래그를 먼저 제거합니다. GitLab-Rails 리포지터리의 플래그를 먼저 정리하면 AI Gateway의 기능 플래그가 기본 상태로 즉시 비활성화되어 예상치 못한 동작이 나타날 수 있습니다.
중요: AI Gateway에서 기능 플래그를 정리하면 GitLab.com, GitLab Self-Managed, GitLab Dedicated를 포함한 모든 GitLab 인스턴스에 변경이 즉시 반영됩니다.
기술적 세부 사항:
-
활성화된 기능 플래그에
push_feature_flag가 실행되면 플래그 이름이 현재 컨텍스트에 캐시되고, 이후GitLab-Sidekiq/Rails가 AI Gateway로 요청을 보낼 때x-gitlab-enabled-feature-flagsHTTP 헤더에 첨부됩니다. -
프론트엔드 클라이언트(예: VS Code Extension 또는 LSP)가 AI Gateway와 직접 통신하기 위해 User JWT(UJWT)를 요청하면 GitLab은 다음을 반환합니다.
- 공개 헤더(
x-gitlab-enabled-feature-flags포함). - 생성된 UJWT(만료 시간 1시간).
- 공개 헤더(
프론트엔드 클라이언트는 만료 시 UJWT를 다시 생성해야 합니다. ChatOps를 통한 기능 플래그 업데이트 같은 백엔드 변경은 헤더 값을 오래된 상태로 만듭니다. 이 헤더 값은 다음 UJWT 생성 시 갱신됩니다.
마찬가지로 프론트엔드로 기능 플래그를 푸시하는 push_frontend_feature_flag도 있습니다.
GraphQL API#
추상화 레이어를 사용해 AI 공급자 API에 연결하려면 확장 가능한
aiAction GraphQL API를 사용합니다.
input은 키/값 쌍을 받으며 key는 수행할 액션입니다. 하나의 뮤테이션 요청에는
하나의 AI 액션만 허용됩니다.
뮤테이션 예시입니다.
mutation {
aiAction(input: {summarizeComments: {resourceId: "gid://gitlab/Issue/52"}}) {
clientMutationId
}
}
예를 들어 "explain code" 액션을 만든다고 가정합니다. 이를 위해 input에 새 키
explainCode를 추가합니다. 뮤테이션은 다음과 같습니다.
mutation {
aiAction(
input: {
explainCode: { resourceId: "gid://gitlab/MergeRequest/52", code: "foo() { console.log() }" }
}
) {
clientMutationId
}
}
그러면 GraphQL API는 Anthropic Client를 사용해 응답을 보냅니다.
응답을 받는 방법#
AI 공급자로 보내는 API 요청은 백그라운드 job에서 처리됩니다. 따라서 요청을 계속 유지하지 않으며, 프론트엔드가 요청과 구독의 응답을 매칭해야 합니다.
userId와 resourceId만 사용하면 요청에 맞는 응답을 판별하는 과정에서 문제가 생길 수 있습니다. 예를 들어 두 AI 기능이 같은 userId와 resourceId를 사용하면 두 구독이 서로의 응답을 받게 됩니다. 이런 간섭을 막기 위해 clientSubscriptionId를 도입했습니다.
aiCompletionResponse 구독에서 응답을 매칭하려면 aiAction 뮤테이션에 clientSubscriptionId를 전달할 수 있습니다.
clientSubscriptionId는 다른 AI 기능과 간섭하지 않도록 기능별로, 그리고 페이지 안에서 고유해야 합니다.UUID사용을 권장합니다.clientSubscriptionId는aiAction뮤테이션의 일부로 전달된 경우에만aiCompletionResponse브로드캐스트에 사용됩니다.clientSubscriptionId를 전달하지 않으면aiCompletionResponse에는userId와resourceId만 사용됩니다.
댓글 요약 뮤테이션 예시에서는 뮤테이션의 일부로 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
}
}
Chat 구독은 동작 방식이 다릅니다.
동시 구독이 많아지지 않도록 skip()을 사용해 뮤테이션이 전송된 다음에만 구독하도록 합니다.
다양한 ID 파라미터 설명#
aiAction 뮤테이션을 사용할 때 요청과 응답을 올바르게 라우팅하기 위해 여러 ID 파라미터가 쓰입니다. 각 파라미터의 역할은 다음과 같습니다.
user_id(필수)- 목적: 요청한 사용자를 식별하고 인증합니다
- 용도: 권한 확인, 요청 귀속, 응답 라우팅
- 예시:
gid://gitlab/User/123 - 참고: 이 ID는 GraphQL API 프레임워크가 자동으로 포함합니다
client_subscription_id(스트리밍이나 다중 기능에 권장)- 특정 요청/응답 쌍을 추적하기 위해 클라이언트가 생성하는 UUID
- 스트리밍 응답을 사용하거나 여러 AI 기능이 같은 페이지를 공유할 때 필요합니다
- 예시:
"9f5dedb3-c58d-46e3-8197-73d653c71e69" - 스트리밍이 없는 단순하고 독립적인 요청에서는 생략할 수 있습니다
resource_id(상황에 따름 - 일부 기능에서 필수)- 목적: AI 작업에 컨텍스트를 제공하는 특정 GitLab 엔터티(프로젝트, 이슈, MR)를 참조합니다
- 용도: 권한 검증과 컨텍스트 정보 수집
- 실제 예시:
"gid://gitlab/Issue/164723626" - 참고: 일부 기능은 특정 리소스를 요구하지 않습니다
project_id(상황에 따름 - 일부 기능에서 필수)- 목적: AI 작업의 프로젝트 컨텍스트를 식별합니다
- 용도: 프로젝트별 권한 확인과 컨텍스트
- 실제 예시:
"gid://gitlab/Project/278964" - 참고: 일부 기능은 특정 프로젝트를 요구하지 않습니다
현재 추상화 레이어 흐름#
다음 그래프는 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[#96;::Gitlab::Llm::VertexAi::Completions::...#96; class using #96;::Gitlab::Llm::Templates::...#96; 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]다중 모델을 위한 기존 AI 구성 요소 재사용#
GitLab은 프롬프트, 입력/출력 파서, 도구·함수 호출 같은 AI 구성 요소를 각 LLM에 맞게 최적화하려 합니다. 다만 모델마다 구성 요소를 분기하면 유지 보수 부담이 커집니다. 따라서 기능 품질이 떨어지지 않는 한 여러 모델에서 기존 구성 요소를 재사용하는 편이 좋습니다. 대략적인 기준은 다음과 같습니다.
- 여러 모델에 대해 기존 프롬프트 템플릿을 개선해 나갑니다. 특정 모델에서 품질 저하가 발생하지 않는 한 새 템플릿을 도입하지 않습니다.
- 여러 모델에 대해 기존 입력/출력 파서와 도구·함수 호출을 개선해 나갑니다. 특정 모델에서 품질 저하가 발생하지 않는 한 새로 도입하지 않습니다.
- 특정 모델에서 품질 저하가 확인되면 해당 모델에 한해 공유 구성 요소를 분기합니다.
이러한 사례의 예시로, 품질 저하가 없는 한 Claude 전용 CoT 최적화를 Mixtral 같은 다른 모델에도 적용할 수 있습니다.
모니터링#
- 각 AI 액션의 오류 비율과 응답 지연 apdex는 Sidekiq Service 대시보드의 **SLI Detail:
llm_completion**에서 확인할 수 있습니다. - 소비된 토큰, 각 AI 기능의 사용량과 기타 통계는 periscope 대시보드에서 확인할 수 있습니다.
- AI Gateway 로그.
- AI Gateway 메트릭.
- 프록시를 통한 기능 사용량 대시보드.
보안#
인공지능(AI) 기능 보안 코딩 가이드라인을 참고합니다.
도움말#
- 연락 방법은 여기에서 확인할 수 있습니다
- GitLab Duo Chat 작업에 대한 가이드라인을 확인합니다.
- GitLab Duo에 기초 챗 에이전트를 추가하는 방법을 알아봅니다.
- GitLab Duo Agent Platform에 기초 플로를 추가하는 방법을 알아봅니다.