Skip to content

[Feat] 벡터 검색 인프라 구축 - OpenSQL+pgvector 및 bge-m3 임베딩 서버 - #38

Merged
kangcheolung merged 5 commits into
developfrom
feature/35
Jul 20, 2026
Merged

[Feat] 벡터 검색 인프라 구축 - OpenSQL+pgvector 및 bge-m3 임베딩 서버#38
kangcheolung merged 5 commits into
developfrom
feature/35

Conversation

@kangcheolung

@kangcheolung kangcheolung commented Jul 20, 2026

Copy link
Copy Markdown
Member

🔍️ 작업 내용

Closes #35

✨ 상세 설명

OpenSQL + pgvector 구성

  • tmaxopensql/postgres:14.6 이미지에 pgvector 0.8.0을 소스 컴파일로 설치하는 커스텀 Dockerfile 추가
  • 대회 요구사항(OpenSQL 기반)을 유지하면서 벡터 검색 확장을 설치하는 방법으로 채택
  • init-and-start.sh: Ansible 완료 후 docgrid DB 자동 생성, vector 확장 활성화, pg_hba.conf TCP 접속 허용 설정

임베딩 서버

  • POST /embed: 텍스트 입력 → 1024차원 dense vector 반환
  • GET /health: 서버 및 모델 로드 상태 확인
  • HuggingFace 모델은 첫 실행 시 다운로드 후 Docker 볼륨에 캐시 (약 3GB, 이후 재시작은 빠름)

🛠 추후 리팩토링 및 고도화 계획

  • pg_hba.conf 규칙을 0.0.0.0/0 trust에서 Docker 브리지 대역으로 좁히기 (시연 환경 보안)
  • 임베딩 서버 배치 처리 지원 (POST /embed/batch)

📸 스크린샷 (선택)

image image

💬 리뷰 요구사항

  • docker/opensql/vars.yml 변경으로 pg 유저가 app → docgrid로 바뀌었습니다. 기존 볼륨이 있는 경우 docker compose down -v 후 재시작 필요합니다.
  • docker compose up 시 bge-m3 모델 다운로드로 약 10~15분 소요됩니다.

Summary by CodeRabbit

  • 새 기능

    • 텍스트를 벡터로 변환하는 임베딩 서버를 추가했습니다.
    • 상태 확인 및 임베딩 생성을 위한 API를 제공합니다.
    • Hugging Face 모델 캐시를 지원해 재시작 시 로딩 시간을 줄였습니다.
    • PostgreSQL에 pgvector 확장을 포함한 로컬 빌드 구성을 제공합니다.
    • 데이터베이스와 임베딩 서버를 Docker Compose로 함께 실행할 수 있습니다.
  • 문서

    • 임베딩 서버 구성, API 사용법, 실행 방법과 초기 모델 다운로드 과정을 문서화했습니다.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

OpenSQL PostgreSQL에 pgvector 0.8.0 설치와 docgrid 초기화를 추가하고, bge-m3 기반 FastAPI 임베딩 서버를 구현했습니다. Docker Compose에 두 서비스를 연결하고 HuggingFace 모델 캐시, 헬스체크 및 관련 실행 문서를 추가했습니다.

Changes

데이터베이스 및 임베딩 인프라

Layer / File(s) Summary
OpenSQL pgvector 초기화
docker/opensql/*, docs/kangcheolung-#35-embedding-server.md
OpenSQL PostgreSQL 이미지를 로컬 빌드하고 pgvector 0.8.0을 설치합니다. 시작 시 docgrid 데이터베이스와 vector 확장을 준비하며 접속 설정과 인증 정보를 변경했습니다.
bge-m3 임베딩 API
embedding-server/*, docs/kangcheolung-#35-embedding-server.md
FastAPI 수명주기에서 BAAI/bge-m3를 로드하고 GET /health, POST /embed 및 요청·응답 스키마를 제공합니다.
Compose 서비스 통합
docker-compose.yml, docs/kangcheolung-#35-embedding-server.md
PostgreSQL을 로컬 빌드로 전환하고 embedding-server, 포트 매핑, 네트워크, HuggingFace 캐시 볼륨 및 healthcheck를 추가했습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DockerCompose
  participant PostgreSQL
  participant EmbeddingServer
  DockerCompose->>PostgreSQL: 로컬 OpenSQL 이미지 빌드 및 시작
  PostgreSQL->>PostgreSQL: docgrid DB와 vector 확장 초기화
  DockerCompose->>EmbeddingServer: embedding-server 빌드 및 시작
  EmbeddingServer-->>DockerCompose: GET /health 상태 반환
Loading

Possibly related PRs

  • DocGrid/backend#4: postgres Compose 설정과 OpenSQL 변수 구성을 함께 변경한 PR입니다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning FastAPI와 bge-m3 임베딩 서버와 Compose 등록은 맞지만, dimension 반환과 normalize_embeddings=True 요구가 보이지 않습니다. POST /embed 응답에 dimension을 추가하고, 임베딩 생성 시 normalize_embeddings=True를 적용하며 필요하면 sentence-transformers 기준도 맞추세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed 문서 추가와 OpenSQL/임베딩 서버 관련 설정 변경만 있으며, 목적과 무관한 별도 변경은 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed 제목이 OpenSQL+pgvector와 bge-m3 임베딩 서버라는 핵심 변경을 간결하게 잘 요약합니다.
Description check ✅ Passed 템플릿의 필수 섹션인 작업 내용, 상세 설명, 추후 계획, 리뷰 요구사항이 모두 포함되어 있습니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/35

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docker-compose.yml (1)

17-22: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

PostgreSQL의 Healthcheck가 실패하지 않도록 계정과 데이터베이스명을 업데이트하세요.

vars.yml 파일 변경에 따라 기존 app 데이터베이스 및 사용자가 삭제되었습니다. 하지만 Healthcheck 명령은 여전히 -U app -d app을 참조하고 있어 컨테이너가 unhealthy 상태에 빠지게 됩니다.

경로 지시문(Path instructions)에 따른 환경 설정 검증 결과이며, 새롭게 생성된 DB 설정과 동기화가 필요합니다.

⚙️ Healthcheck 수정 제안
     healthcheck:
-      test: ["CMD-SHELL", "/usr/pgsql-14/bin/pg_isready -U app -d app"]
+      test: ["CMD-SHELL", "/usr/pgsql-14/bin/pg_isready -U docgrid -d postgres"]
       interval: 10s
       timeout: 5s
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docker-compose.yml` around lines 17 - 22, Update the PostgreSQL healthcheck
command in the healthcheck configuration to use the database name and user
defined by the updated vars.yml settings instead of the removed app account and
database, keeping the existing readiness-check behavior unchanged.

Source: Path instructions

🧹 Nitpick comments (1)
embedding-server/Dockerfile (1)

10-10: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

비특권(non-root) 사용자로 서버를 실행하도록 구성하는 것을 권장합니다.

운영 환경에서는 탈취된 컨테이너의 권한 남용을 방지하기 위해 컨테이너 내부 프로세스를 root가 아닌 일반 사용자로 실행하는 것이 보안 모범 사례입니다.

🛡️ Non-root 사용자 추가 제안
 COPY main.py .
 
+RUN useradd -m appuser
+USER appuser
+
 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@embedding-server/Dockerfile` at line 10, Update the embedding server
Dockerfile to create and select a non-root user before the existing CMD
entrypoint, ensuring uvicorn runs as that user while preserving the current
host, port, and application settings.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docker-compose.yml`:
- Around line 55-60: Update the healthcheck configuration’s start_period from
120s to at least 900s, allowing sufficient time for the embedding server’s
initial model download while leaving the existing test, interval, timeout, and
retries unchanged.

In `@docker/opensql/init-and-start.sh`:
- Around line 17-18: Update the pg_hba.conf entry appended by the initialization
script to use scram-sha-256 instead of trust, while preserving the existing
idempotent grep-and-append behavior. Ensure the configured database password is
used for remote authentication.

In `@embedding-server/main.py`:
- Line 44: Update the model.encode call in the embedding request flow to pass
normalize_embeddings=True, preserving the existing batch_size and max_length
options.
- Around line 12-19: Update lifespan so BGEM3FlagModel initialization runs in a
background thread or task instead of blocking startup, while preserving the
existing global model state. Allow the FastAPI server to begin accepting
requests immediately, keep model unset during loading so endpoints return the
existing 503 response, and retain cleanup by resetting model on shutdown.

---

Outside diff comments:
In `@docker-compose.yml`:
- Around line 17-22: Update the PostgreSQL healthcheck command in the
healthcheck configuration to use the database name and user defined by the
updated vars.yml settings instead of the removed app account and database,
keeping the existing readiness-check behavior unchanged.

---

Nitpick comments:
In `@embedding-server/Dockerfile`:
- Line 10: Update the embedding server Dockerfile to create and select a
non-root user before the existing CMD entrypoint, ensuring uvicorn runs as that
user while preserving the current host, port, and application settings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9203303b-866b-46a7-820d-6824f6311b3b

📥 Commits

Reviewing files that changed from the base of the PR and between 3087fe0 and 676b376.

📒 Files selected for processing (8)
  • docker-compose.yml
  • docker/opensql/Dockerfile
  • docker/opensql/init-and-start.sh
  • docker/opensql/vars.yml
  • docs/kangcheolung-#35-embedding-server.md
  • embedding-server/Dockerfile
  • embedding-server/main.py
  • embedding-server/requirements.txt

Comment thread docker-compose.yml Outdated
Comment thread docker/opensql/init-and-start.sh Outdated
Comment thread embedding-server/main.py Outdated
Comment thread embedding-server/main.py
def embed(req: EmbedRequest):
if model is None:
raise HTTPException(status_code=503, detail="Model not loaded")
result = model.encode([req.text], batch_size=1, max_length=8192)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

PR 목표에 명시된 normalize_embeddings=True 적용이 누락되었습니다.

PR 요약 및 목표(PR objectives)에는 normalize_embeddings=True를 적용한다고 기재되어 있으나, model.encode() 호출에는 해당 옵션이 반영되어 있지 않습니다. 의도적으로 제외하신 것인지, 아니면 추가해야 하는지 확인 부탁드립니다.

💡 옵션 추가 제안

만약 라이브러리에서 해당 인자를 지원한다면 다음과 같이 추가할 수 있습니다:

-    result = model.encode([req.text], batch_size=1, max_length=8192)
+    result = model.encode([req.text], batch_size=1, max_length=8192, normalize_embeddings=True)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
result = model.encode([req.text], batch_size=1, max_length=8192)
result = model.encode([req.text], batch_size=1, max_length=8192, normalize_embeddings=True)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@embedding-server/main.py` at line 44, Update the model.encode call in the
embedding request flow to pass normalize_embeddings=True, preserving the
existing batch_size and max_length options.

…m-sha-256 적용, 모델 백그라운드 로드

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] Python 임베딩 서버 구축 (FastAPI + bge-m3)

1 participant