feat(ai): 내부 어시스턴트 수집 파이프라인과 Elasticsearch 검색 기반 - #352
Merged
Conversation
corpus 스캔부터 청크 저장까지의 수집 경로와 검색 원시 계층을 추가한다. - ingestion: scanner(allowlist·원문 hash), parsers, chunker, embeddings, pipeline - retrieval: bm25 artifact store, pgvector 조회 - persistence: SQLAlchemy 모델·repository, alembic initial_corpus - cli: ingest 명령 - .gitignore: AI 로컬 산출물(.data, mypy/ruff 캐시) 제외 미검증: 아직 실행한 적 없음. ingest 실행·검색 경로·평가 러너는 후속 작업. Claude-Session: https://claude.ai/code/session_01GDm6wJvLcheakBeELYsLMk
ai 프로필로 분리해 기존 로컬 스택과 포트·수명주기를 겹치지 않게 한다. - ai-postgres: pgvector 0.8.1-pg17, 127.0.0.1:5433 루프백 바인딩 - ai-api: ai-assistant 이미지 빌드 - profiles ai 로 기본 기동에서 제외 Claude-Session: https://claude.ai/code/session_01GDm6wJvLcheakBeELYsLMk
검색 저장소를 BM25S·pgvector에서 Elasticsearch 단일 노드로 교체하기로 한 결정과 그 세부 구현 계획을 남긴다. 적용 우선순위는 DECISION > V1 > MVP 설계. - AI-ELASTICSEARCH-DECISION.md: 결정 근거, 검색 계약, 인덱스 발행 절차 - AI-ELASTICSEARCH-IMPLEMENTATION-PLAN.md: 모듈 책임, 문서 계약, 이슈 분리 - AI-INTERNAL-ASSISTANT-V1.md: 내부 어시스턴트 v1 범위 - AI-OPERATIONS-ASSISTANT-MVP-DESIGN.md: 상위 문서와의 우선순위 반영 미측정: 현재 검색 품질·지연 비교값 없음. 교체 전 baseline 확보가 선행 과제. Claude-Session: https://claude.ai/code/session_01GDm6wJvLcheakBeELYsLMk
tree-sitter-java 0.23.5(ABI 14)와 tree-sitter 0.26.0 조합에서 Node.start_point 필드 접근 시 프로세스가 SIGSEGV/SIGBUS로 종료된다. 상한이 없어 0.26.0이 설치되고 있었다. 실측 (PaddleWebhookService.java, 노드 3856개 순회): - tree-sitter 0.26.0 + java 0.23.5 → 크래시 (exit 138/139) - tree-sitter 0.25.2 + java 0.23.5 → 정상 (rows read 3856) - tree-sitter 0.25.0 + java 0.23.5 → 정상 수정 후 ingest 실행 결과 (exit 0): - 문서 16 / 청크 317 / 임베딩 317, 누락 0 - 크래시 대상이던 PaddleWebhookService.java 도 청크 17개로 정상 처리 임베딩은 AI_EMBEDDING_PROVIDER=fake(결정적 해시) 기준. 실제 모델 검증은 미수행. 검색 품질은 측정하지 않았다. Claude-Session: https://claude.ai/code/session_01GDm6wJvLcheakBeELYsLMk
구현 계획 1단계(Nori 이미지·client·mapping·실제 서버 smoke)를 구성한다. - docker/elasticsearch/Dockerfile: ES 9.5.3 + analysis-nori 이미지 빌드 시 설치 - docker-compose.ai.yml: ai-elasticsearch 서비스, 127.0.0.1:9208 루프백 전용, 보안 활성, ES_JAVA_OPTS 512m, mem_limit 2g - config/settings.py: endpoint·자격증명·CA·alias·timeout - persistence/elasticsearch_store.py: 문서 계약 매핑(dynamic strict), 결정적 build_id, 물리 인덱스 생성·bulk·개수 검증·alias 발행 - retrieval/fusion.py: chunk_id 중복 제거 RRF(k=60), 동점은 chunk_id 정렬 실측 (Nori 대 BM25S 토크나이징): - 문서 "결제를 검증하였습니다" / 질의 "결제 검증" - BM25S: ['결제를','검증하였습니다'] 대 ['결제','검증'] -> 공통 토큰 0 - Nori: ['결제','검증'] 대 ['결제','검증'] -> 일치 실측 (색인·검색, exit 0): - 청크 317 / 차원 1024 색인, bulk 실패 0, 개수 검증 통과, alias 전환 완료 - match 질의 "결제 검증" -> toss-billing-review-readiness.md:64-70 (score 7.01) - match 질의 "구독 갱신" -> API.md:688-692 (score 7.00) 미검증: 임베딩은 fake 해시(1024차원)라 벡터 검색 품질은 의미 없음. 벡터 검색·하이브리드 CLI 경로·평가셋은 후속. 검색 품질 비교값 없음. Claude-Session: https://claude.ai/code/session_01GDm6wJvLcheakBeELYsLMk
계획서 "이전 pgvector/BM25S 구현은 활성 경로 교체 검증 후 정리"를 따른다. 추가: - retrieval/elasticsearch.py: keyword(multi_match) / vector(script_score) 질의, 요청당 물리 인덱스 고정, source_type 필터, timeout·shard 실패 시 명시적 실패 - cli/main.py: search 명령을 ES 경로로 재배선(--retriever hybrid|keyword|vector, --source-type 반복 지정), 출력에 physical_index 포함 제거: - retrieval/bm25.py, retrieval/vector.py - bm25s 의존성, bm25_index_dir 설정, .data/bm25 산출물 - IngestionSummary.bm25_fingerprint 및 파이프라인의 BM25 빌드 단계 유지: persistence/* 와 ai-postgres. ingest 가 아직 문서·청크 원본을 저장하며 Postgres 제거는 snapshot 색인(계획 2단계) 범위다. 실측 (교체 후, exit 0): - ingest: scanned 16 / unchanged 16 / chunk 0 변경 없음 - ruff·mypy: 신규·수정 파일 통과 (기존 parsers.py SIM102 1건은 미접촉) - search "결제 검증" keyword -> payment-load-test.md:79-93 (12.2224) - search "결제를 검증하였습니다" keyword -> 동일 문서 상위 (9.0762) BM25S 에서는 공통 토큰 0으로 불가능했던 매칭이다 - search hybrid -> rrf(es_keyword)/rrf(es_vector_exact) 결합 동작 미검증: 임베딩이 fake 해시라 vector·hybrid 순위는 품질 근거가 없다. 평가셋·리랭커·LLM 답변 생성은 후속. Claude-Session: https://claude.ai/code/session_01GDm6wJvLcheakBeELYsLMk
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
배경
내부 개발·운영 어시스턴트(#350)의 첫 실행 가능 단위다. 문서·코드 corpus 수집부터
Elasticsearch 한국어 검색까지를 실제로 동작하는 상태로 만든다.
검색 저장소는 AI-ELASTICSEARCH-DECISION.md 결정에 따라
BM25S·pgvector 대신 Elasticsearch 단일 노드를 사용한다.
변경 범위
수집 파이프라인 (
ai-assistant/)ingestElasticsearch 검색
127.0.0.1:9208루프백 전용dynamic: strict), 결정적 build_id, bulk·개수 검증·alias 발행search --retriever hybrid|keyword|vector --source-type제거
retrieval/bm25.py,retrieval/vector.py,bm25s의존성,.data/bm25persistence/*와ai-postgres는 유지. ingest 가 아직 원본을 저장하며Postgres 제거는 snapshot 색인(계획 2단계) 범위다
실측 결과
ingest(exit 0)Elasticsearch 색인 (exit 0)
한국어 분석 비교 — 이번 저장소 교체의 근거
결제를 검증하였습니다결제 검증['결제를','검증하였습니다']['결제','검증']['결제','검증']['결제','검증']검색 (exit 0)
결제 검증keyword ->docs/operations/payment-load-test.md:79-93(12.2224)결제를 검증하였습니다keyword -> 동일 문서 상위 (9.0762)rrf(es_keyword)/rrf(es_vector_exact)결합 동작품질 게이트
parsers.pySIM102 1건은 이번 범위 밖이라 미접촉수정한 결함
tree-sitter 0.26.0+tree-sitter-java 0.23.5조합에서Node.start_point접근 시프로세스가 SIGSEGV/SIGBUS 로 종료된다. 상한이 없어 0.26.0 이 설치되고 있었다.
tree-sitter>=0.25.0,<0.26으로 고정했다.미검증 / 범위 밖
fake결정적 해시(1024차원)라 vector·hybrid 순위는 품질 근거가 없다bge-m3)·리랭커 미적용확인 요청
127.0.0.1:9208)이며profiles: ["ai"]로 기본 기동에서 제외된다https://claude.ai/code/session_01GDm6wJvLcheakBeELYsLMk