임베딩
임베딩은 데이터를 벡터화된 형식으로 표현하는 방법으로, 유사한 문서를 쉽고 효율적으로 찾을 수 있도록 합니다.
현재 임베딩은 이슈에만 생성되며 다음과 같은 기능을 제공합니다.
아키텍처
임베딩은 Elasticsearch에 저장되며 고급 검색에도 사용됩니다.
이 프로세스는 Search::Elastic::ProcessEmbeddingBookkeepingService
에 의해 주도되며 Redis 큐에 추가하고 가져옵니다.
임베딩 큐에 추가
다음은 이슈를 예시로 한 임베딩 큐에 추가하는 과정 설명입니다.
이슈 임베딩은 "이슈 제목 '#{issue.title}' 및 설명 '#{issue.description}'"
의 내용에서 생성됩니다.
Search::Elastic::IssuesSearch
에서 정의된 ActiveRecord 콜백을 사용하여 이슈에 대한 임베딩 참조물이 생성되고, 이슈가 생성되거나 제목 또는 설명이 업데이트되었고 임베딩이 생성 가능한 경우에 임베딩 큐에 추가됩니다.
임베딩 큐에서 가져오기
Search::ElasticIndexEmbeddingBulkCronWorker
cron 작업이 매분 실행되며 다음을 수행합니다.
그러므로 16개의 동시 프로세스가 동시에 임베딩을 생성하더라도 450개 임베딩/분의 속도 제한 설정을 초과하지 않도록 항상 확인합니다.
백필링
고급 검색 마이그레이션은 백필링을 수행하는 데 사용됩니다. 이는 큐에 참조물을 일괄로 추가한 뒤 앞에서 설명한 cron 작업에 의해 처리됩니다.
새로운 임베딩 유형 추가
다음은 임베딩을 생성하고 Elasticsearch에 저장하기 위한 단계 개요입니다.
- Elasticsearch 클러스터가 임베딩 생성을 처리할 수 있는지 또는 추가 리소스가 필요한지 비용 및 리소스 계산을 수행합니다.
- 임베딩을 저장할 위치를 결정합니다. 기존 Elasticsearch 인덱스를 확인하고 적합한 기존 인덱스가 없는 경우 새 인덱스를 만듭니다.
- 인덱스에 임베딩 필드를 추가합니다: 예시.
- 내용을 생성할 수 있도록 방식을 업데이트하여 새로운 유형을 수용합니다.
- 새 단위 원시를 추가합니다: 여기 및 여기.
- 임베딩을 생성할 시기에 필요한 검사를 추가하기 위해
Elastic::ApplicationVersionedSearch
를 사용합니다. 예시는Search::Elastic::IssuesSearch
를 참조하세요. - 임베딩을 백필링합니다: 예시.
로컬에 이슈 임베딩 추가
전제 조건
- Elasticsearch가 실행 중인지 확인합니다.
-
기존 Elasticsearch 설정이 있는 경우 다음을 실행하여
AddEmbeddingToIssues
마이그레이션이 완료되었는지 확인합니다.Elastic::MigrationWorker.new.perform
- 로컬 환경에서 GitLab Duo 기능을 실행할 수 있는지 확인합니다.
-
레일즈 콘솔에서 다음을 실행하여 임베딩(768 차원의 벡터)이 출력되는지 확인합니다. 그렇지 않은 경우 AI 설정에 문제가 있는 것입니다.
Gitlab::Llm::VertexAi::Embeddings::Text.new('text', user: nil, tracking_context: {}, unit_primitive: 'semantic_search_issue').execute
백필링 실행
프로젝트의 이슈에 대한 임베딩을 백필링하려면 레일즈 콘솔에서 다음을 실행합니다.
Gitlab::Duo::Developments::BackfillIssueEmbeddings.execute(project_id: project_id)
이 작업은 이슈를 큐에 추가하고 일괄로 처리하여 Elasticsearch에 임베딩을 색인화합니다. 분당 450개의 임베딩 속도 제한을 준수합니다. 문제가 있는 경우 Slack의 @maddievn
또는 #g_global_search
로 문의하십시오.
확인
만약 다음 내용이 0을 반환한다면, 프로젝트의 모든 이슈에는 임베딩(embedding)이 있습니다:
curl "http://localhost:9200/gitlab-development-issues/_count" \
--header "Content-Type: application/json" \
--data '{"query": {"bool": {"filter": [{"term": {"project_id": PROJECT_ID}}], "must_not": [{"exists": {"field": "embedding"}}]}}}' | jq '.count'
PROJECT_ID
를 귀하의 프로젝트 ID로 대체하세요.