시맨틱 검색
GitLab v19.2시맨틱 검색은 키워드 매칭이 아닌 의미를 기반으로 의미적으로 유사한 콘텐츠를 찾기 위해 벡터 임베딩을 사용하며, 이를 통해 Duo Chat과 같은 AI 기능이 사용자 쿼리에 대한 관련 컨텍스트를 검색할 수 있습니다.
시맨틱 검색은 키워드 매칭이 아닌 의미를 기반으로 의미적으로 유사한 콘텐츠를 찾기 위해 벡터 임베딩을 사용하며, 이를 통해 Duo Chat과 같은 AI 기능이 사용자 쿼리에 대한 관련 컨텍스트를 검색할 수 있습니다.
개요#
시맨틱 검색은 텍스트를 벡터 임베딩으로 변환하고 벡터 저장소에 저장합니다. 사용자가 쿼리를 만들면 쿼리도 임베딩으로 변환되어 저장된 벡터와 비교하여 가장 유사한 결과를 찾습니다. 이 접근 방식은 의미적 의미를 포착하여 정확한 키워드가 일치하지 않아도 관련 콘텐츠를 찾을 수 있습니다.
시맨틱 검색 기능은 Active Context 프레임워크를 사용하여 구현됩니다.
시맨틱 코드 검색은 이 프레임워크로 구현된 첫 번째 기능입니다. 다른 시맨틱 검색 컬렉션 유형에 대한 지원을 추가할 수 있습니다.
아키텍처#
시맨틱 검색은 gitlab-active-context 젬을 통해 구현된 Active Context 프레임워크로 구동됩니다. 이 프레임워크는 다양한 벡터 저장소(Elasticsearch, OpenSearch, pgvector를 사용한 PostgreSQL)에 대한 변환 레이어를 제공하여 벡터 저장소별 구현 없이도 동일한 코드가 지원되는 모든 벡터 저장소와 작동할 수 있게 합니다.
이 프레임워크는 확장 가능하며 다양한 유형의 시맨틱 검색 컬렉션을 지원하도록 설계되었습니다. 각 시맨틱 검색 컬렉션은 다음을 사용하여 구현됩니다:
-
컬렉션 (
Ai::ActiveContext::Collections::): 인덱싱되는 콘텐츠와 저장 방법을 정의합니다 -
참조 (
Ai::ActiveContext::References::): 콘텐츠 업데이트를 위한 임베딩을 추적하고 관리합니다 -
쿼리 (
Ai::ActiveContext::Queries::): 벡터 저장소에서 유사한 콘텐츠를 검색합니다 -
큐 (
Ai::ActiveContext::Queues::): 임베딩 생성의 비동기 처리를 관리합니다 -
마이그레이션: 벡터 저장소의 스키마 변경 및 데이터 변환을 실행합니다
다른 콘텐츠 유형(예: 머지 리퀘스트 또는 문서)에 이러한 컴포넌트를 구현하면 새 컬렉션 유형을 추가할 수 있습니다.
임베딩 모델#
자세한 아키텍처 내용은 [임베딩 모델 설계 문서](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/ai_context_abstraction_layer/embedding_models/)를 참조하세요.
모델 메타데이터#
시맨틱 검색은 임베딩 모델을 사용하여 인덱싱과 검색에 사용되는 임베딩을 생성합니다.
임베딩 모델은 Ai::ActiveContext::Collection 레코드의 metadata에 current_indexing_embedding_model, next_indexing_embedding_model, search_embedding_model로 저장됩니다.
각 임베딩 모델 메타데이터에는 다음 정보가 있습니다:
-
model_type:gitlab_managed또는self_hosted중 하나 -
model_ref: 모델 식별자(예:text_embedding_005_vertex또는Ai::SelfHostedModelID) -
field: 임베딩이 저장되는 벡터 저장소 필드 -
dimensions: 임베딩 벡터 차원으로, 벡터 저장소 필드를 생성하고 임베딩을 생성할 때 사용됩니다
ActiveContext::EmbeddingModel 객체 및 임베딩 생성#
컬렉션 클래스(예: Ai::ActiveContext::Collections::Code)에서 임베딩 모델은 Ai::ActiveContext::Embeddings::ModelFactory를 통해 ActiveContext::EmbeddingModel 객체로 노출됩니다.
임베딩은 생성된 ActiveContext::EmbeddingModel 객체에서 generate_embeddings를 호출하여 생성됩니다. 예를 들면:
ac_embedding_model = Ai::ActiveContext::Collections::Code.current_indexing_embedding_model # this returns an ActiveContext::EmbeddingModel
ac_embedding_model.generate_embeddings(<array_of_content>, user: <optional_user>)
내부적으로 ActiveContext::EmbeddingModel#generate_embeddings는 AI Gateway에 임베딩 요청을 보내는 Gitlab::Llm::Embeddings::* 클래스를 실행합니다.
모델 전환#
모델 전환은 Ai::ActiveContext::EmbeddingModelActivationService를 통해 구현되며, 이는 임베딩 모델을 설정하거나 변경하기 위한 일련의 백그라운드 Active Context 태스크를 시작합니다.
비동기 임베딩 생성#
인덱싱된 콘텐츠의 임베딩은 Ai::ActiveContext::References::Code와 같은 참조 클래스를 사용하여 큐 시스템을 통해 비동기적으로 생성됩니다:
-
참조 추적: 콘텐츠가 생성되거나 업데이트되면 적절한 참조 클래스에서 임베딩 참조가 추적됩니다
-
배치 처리: 참조는
Ai::ActiveContext::BulkProcessWorker에 의해 배치로 처리됩니다 -
벡터 저장: 생성된 임베딩은 구성된 벡터 저장소에 저장됩니다
Ai::ActiveContext::BulkProcessWorker는 매 분마다 실행되고 큐에서 임베딩 참조를 처리하는 크론 작업입니다. 참조를 가져와서 임베딩을 생성하고 큐에서 제거합니다. 처리 후 큐가 비어있지 않으면 워커는 처리를 계속하기 위해 자신을 다시 큐에 넣습니다. 임베딩 생성이 실패하면 한 번 재시도하고 그 후 데드 큐에 배치됩니다.
쿼리 실행#
쿼리가 실행될 때:
-
임베딩 생성: 사용자의 쿼리는 인덱싱된 콘텐츠와 동일한 모델을 사용하여 임베딩으로 변환됩니다
-
벡터 검색: k-최근접 이웃(KNN) 검색을 사용하여 임베딩을 저장된 벡터와 비교합니다
-
필터링: 결과는 관련 기준(예: 프로젝트, 파일 경로)으로 필터링됩니다
-
인가: 결과는 사용자가 접근 권한이 있는 콘텐츠만 포함하도록 필터링됩니다
-
결과 제한: 기본적으로 10개의 가장 유사한 결과가 반환됩니다
마이그레이션#
Active Context 프레임워크는 연결된 벡터 저장소에 대한 스키마 변경 및 데이터 변환을 관리하기 위한 마이그레이션 시스템을 사용합니다. 마이그레이션은 데이터베이스에서 추적되고 워커 프로세스에 의해 비동기적으로 실행됩니다.
Ai::ActiveContext::MigrationWorker는 5분마다 크론 작업으로 실행하여 완료되지 않은 마이그레이션을 실행합니다.
태스크#
자세한 아키텍처 내용은 [Active Context 태스크](https://handbook.gitlab.com/handbook/engineering/architecture/design-documents/ai_context_abstraction_layer/active_context_tasks/) 설계 문서를 참조하세요.
Active Context 프레임워크는 장기 실행 비동기 작업을 관리하기 위한 태스크 실행 시스템을 사용합니다. Active Context 태스크 시스템은 임베딩 모델 활성화, 증분 인덱싱, 데이터 마이그레이션과 같은 복잡한 워크플로를 처리합니다. 재시도, 오류 처리, 상태 지속성에 대한 기본 지원이 포함되어 있어 중요한 작업의 안정적인 실행을 보장합니다.
벡터 저장소#
인스턴스는 다음 벡터 저장소 중 하나를 사용할 수 있습니다:
-
Elasticsearch
-
OpenSearch
-
pgvector를 사용한 PostgreSQL
시맨틱 검색을 사용하려면 벡터 저장소 연결을 생성해야 합니다. 연결을 구성하는 두 가지 방법이 있습니다:
옵션 1: GitLab UI 사용
Advanced Search에서 사용하는 Elasticsearch 또는 OpenSearch 클러스터의 경우:
-
Admin > Settings > Search로 이동합니다
-
Connect to the advanced search cluster를 선택합니다
-
연결이 자동으로 생성되고 구성됩니다
옵션 2: Rails 콘솔 사용
다음 방법 중 하나를 사용합니다. name 필드는 사용자가 정의하는 레이블입니다.
명시적 URL로 연결하려면(예: OpenSearch):
connection = Ai::ActiveContext::Connection.create!(
name: "opensearch",
options: { url: ["http://localhost:9202"] },
adapter_class: "ActiveContext::Databases::Opensearch::Adapter"
)
connection.activate!
기존 Advanced Search 클러스터의 자격 증명을 재사용하려면:
connection = Ai::ActiveContext::Connection.create!(
name: "elasticsearch",
adapter_class: "ActiveContext::Databases::Elasticsearch::Adapter",
options: { use_advanced_search_config: true }
)
connection.activate!
PostgreSQL의 경우 pgvector 확장을 사용합니다:
PostgreSQL 데이터베이스에서 확장을 생성합니다:
CREATE EXTENSION vector;
Rails 콘솔에서 연결을 생성합니다:
connection = Ai::ActiveContext::Connection.create!(
name: "postgres",
options: { host: 'localhost', port: 5432, user: 'postgres', password: '<password>', database: 'postgres' },
adapter_class: "ActiveContext::Databases::Postgresql::Adapter"
)
connection.activate!
자세한 내용은 pgvector 문서를 참조하세요.
지원되는 어댑터 클래스:
-
ActiveContext::Databases::Elasticsearch::Adapter -
ActiveContext::Databases::Opensearch::Adapter -
ActiveContext::Databases::Postgresql::Adapter
options 해시에는 벡터 저장소에 특정한 연결 세부 정보(URL, 자격 증명 및 기타 어댑터별 설정)가 포함되어야 합니다.
개발자 가이드#
큐에 있는 항목 관리#
처리를 기다리는 모든 큐 항목 보기:
ActiveContext::Queues.all_queued_items
크론 워커를 기다리지 않고 모든 큐 항목을 즉시 처리합니다:
ActiveContext.execute_all_queues!
벡터 저장소 검색#
벡터 저장소의 모든 항목 찾기:
ActiveContext::adapter.search(
user: current_user,
collection: ::Ai::ActiveContext::Collections::Code,
query: ActiveContext::Query.all
)
연결 초기화#
새 연결로 새로 시작하려면 모든 기존 데이터를 삭제하고 재생성합니다:
active_connection = ::Ai::ActiveContext::Connection.active
active_connection.migrations.destroy_all
active_connection.repositories.destroy_all
active_connection.enabled_namespaces.destroy_all
active_connection.collections.destroy_all
active_connection.destroy
연결을 활성화해야 합니다:
connection.activate!
Duo Self-hosted를 위한 시맨틱 검색#
-
Self-hosted 임베딩 모델 설정
SaaS용 메타데이터를 사용하지 않도록 지속된 임베딩 모델 메타데이터를 지워야 합니다
::Ai::ActiveContext::Collections::Code.collection_record.update_metadata!(
current_indexing_embedding_model: nil,
search_embedding_model: nil,
next_indexing_embedding_model: nil
)
관리자 페이지에서 임베딩 모델을 설정하거나, 또는 Rails 콘솔에서 EmbeddingModelActivationService를 통해 설정할 수 있습니다:
::Ai::ActiveContext::EmbeddingModelActivationService.new(
collection_class: ::Ai::ActiveContext::Collections::Code,
model_type: 'gitlab_managed',
model_ref: 'text_embedding_005_vertex',
dimensions: 768,
chunk_strategy: 'code_bytes',
chunk_strategy_size: 1000,
user: User.first
).execute
GitLab 오퍼링에 새 임베딩 모델 추가#
새 GitLab 관리형 임베딩 모델을 지원하려면 AI Gateway의 Model Selection 카탈로그에 추가합니다.
1. models.yml에 추가#
ai_gateway/model_selection/models.yml에서 모델에 대한 새 항목을 추가하고 다음 필드를 설정합니다:
-
gitlab_identifier: 모든 GitLab 앱에서 사용되는 전역 모델 식별자.<model_name>_<provider>형식을 따릅니다 -
model_class_provider: 항상litellm_embedding -
family: 항목 중 하나로embedding을 설정합니다
전체 항목은 다음 예시를 참조하세요:
models:
- name: "text-embedding-005"
provider: "Gemini Enterprise Agent Platform"
gitlab_identifier: "text_embedding_005_vertex"
description: "Natural language processing technique that converts textual data into numerical vectors."
cost_indicator: "1"
max_context_tokens: 20000 # https://docs.cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings#api_limits
model_class_provider: litellm_embedding
family:
- vertex
- embedding
params:
model: "text-embedding-005"
custom_llm_provider: vertex_ai
prompt_params:
vertex_location: global
2. unit_primitives.yml에 추가#
ai_gateway/model_selection/unit_primitives.yml에서 관련 기능 설정 아래에 새 모델을 선택 가능한 모델로 추가합니다.
시맨틱 코드 검색의 경우 embeddings_code 기능 설정 아래에 새 모델을 추가합니다.
새 시맨틱 검색 컬렉션의 경우 새 기능 설정 항목을 추가해야 합니다.
트러블슈팅#
시맨틱 검색에서 결과가 반환되지 않음#
가능한 원인:
- 저장소가 아직 인덱싱되지 않음(상태가
embedding_indexing_in_progress)
확인: Ai::ActiveContext::Code::Repository.find_by(project_id: project.id).state
-
해결: 인덱싱이 완료될 때까지 기다리거나
ActiveContext.execute_all_queues!를 실행하여 수동으로 처리를 트리거합니다 -
네임스페이스가 적합하지 않음
확인: Ai::ActiveContext::Code::EnabledNamespace.exists?(namespace_id: project.root_namespace.id)
-
해결: 네임스페이스가 적격성 기준을 충족하는지 확인합니다
-
벡터 저장소 연결이 구성되지 않음
확인: Ai::ActiveContext::Connection.active.present?
- 해결: 벡터 저장소 연결을 구성합니다
데드 큐 항목 관리#
임베딩 생성이 반복적으로 실패하면 항목이 데드 큐에 배치됩니다. Rails 콘솔 없이 Admin API를 사용하여 관리합니다.
데드 큐 크기 확인
데드 큐 크기는 Rake 작업 출력의 Embedding Queues 섹션에서 확인할 수 있습니다:
sudo gitlab-rake gitlab:semantic_search:code:info
모든 데드 큐 항목 지우기
모든 데드 큐 항목을 삭제하려면:
curl --request DELETE \
--header "PRIVATE-TOKEN: <your_token>" \
"https://gitlab.example.com/api/v4/admin/active_context/dead_queue"
또는 chatops를 통해:
/chatops gitlab run active_context dead_queue clear
데드 큐 항목을 처리 큐로 재생
데드 큐 항목을 다시 처리 큐로 이동하여 재시도하려면:
curl --request POST \
--header "PRIVATE-TOKEN: <your_token>" \
--data "queue=retry_queue" \
"https://gitlab.example.com/api/v4/admin/active_context/dead_queue/replay"
또는 chatops를 통해(권장):
/chatops gitlab run active_context dead_queue replay --queue=retry_queue
유효한 큐 값은 retry_queue, code, code_backfill입니다. retry_queue를 사용하면 데드 큐로 다시 실패하기 전에 한 번 더 처리를 시도합니다. code를 사용하면 임베딩 파이프라인을 처음부터 다시 시작합니다.