[DB 선택 대화형 프롬프트] - setup/lib/db_select.sh: 설치 시 SQLite/PostgreSQL/PostgreSQL+pgvector 선택 - DB_TYPE 환경변수로 무인 설치 지원 - pgvector 자동 빌드/설치 (소스 빌드 폴백 포함) - .env DATABASE_URL 자동 기록 [Vector DB] - docker-compose.yml: postgres를 pgvector/pgvector:pg15 이미지로 교체 - Qdrant: docker profile=vector 로 선택적 활성화 - docs/vector_db_guide.md: pgvector/Qdrant 사용법 + 시나리오 [Gitea 온프레미스 Git 서버] - docker-compose.yml: gitea/gitea:1.21-rootless 서비스 추가 - setup/lib/gitea_setup.sh: 공통 설치/초기화 함수 - setup/gitea_init.sh: 독립 실행형 초기화 스크립트 - 관리자 계정 생성 - guardia 조직 + GUARDiA 저장소 생성 - main 브랜치 보호 (PR + 리뷰 1명 필수) - develop 브랜치 생성 - 개발자 계정 (engineer1/2, pm1, admin) + feature/이름/init 브랜치 자동 생성 - 현재 소스 자동 push [브랜치 전략] main : 보호 브랜치, PR 필수, 리뷰 1명 필수 develop : 통합 브랜치, force-push 금지 feature/이름/기능: 개인 개발 브랜치 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.9 KiB
3.9 KiB
GUARDiA Vector DB 가이드
지원 방식
| 방식 | 설치 | 성능 | 용도 |
|---|---|---|---|
| pgvector | PostgreSQL 확장 | 중간 | SR 유사도, KB 검색 |
| Qdrant | Docker 컨테이너 | 높음 | 대규모 시맨틱 검색 |
1. pgvector (기본 권장)
설치
# setup.sh 실행 시 "3) PostgreSQL + pgvector" 선택
bash setup/setup_ubuntu.sh
# 또는 수동:
CREATE EXTENSION IF NOT EXISTS vector;
GUARDiA에서 벡터 컬럼 사용
from sqlalchemy import Column
from pgvector.sqlalchemy import Vector
class SRRequest(Base):
__tablename__ = "tb_sr_request"
# ...
embedding = Column(Vector(768)) # Ollama 임베딩 차원
# 유사 SR 검색
from sqlalchemy import text
similar = await db.execute(
text("SELECT sr_id, title, 1 - (embedding <=> :vec) AS similarity "
"FROM tb_sr_request ORDER BY embedding <=> :vec LIMIT 5"),
{"vec": query_embedding}
)
임베딩 생성 (Ollama)
import httpx
async def get_embedding(text: str) -> list[float]:
async with httpx.AsyncClient() as client:
r = await client.post("http://localhost:11434/api/embeddings", json={
"model": "nomic-embed-text", # 경량 임베딩 모델
"prompt": text
})
return r.json()["embedding"]
환경변수
ENABLE_VECTOR=true
DATABASE_URL=postgresql+asyncpg://guardia:guardia@localhost:5432/guardia
2. Qdrant (고성능 벡터 검색)
Docker 시작
# vector 프로파일로 Qdrant 포함 실행
docker compose --profile vector up -d qdrant
# 또는 docker compose.yml에서 profiles 제거 후 항상 실행
GUARDiA에서 Qdrant 사용
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
client = QdrantClient(url=os.getenv("QDRANT_URL", "http://localhost:6333"))
# 컬렉션 생성
client.create_collection(
collection_name="sr_embeddings",
vectors_config=VectorParams(size=768, distance=Distance.COSINE),
)
# SR 인덱싱
client.upsert("sr_embeddings", points=[
PointStruct(id=sr.id, vector=embedding, payload={"sr_id": sr.sr_id, "title": sr.title})
])
# 유사 SR 검색
results = client.search("sr_embeddings", query_vector=query_embedding, limit=5)
환경변수
QDRANT_URL=http://localhost:6333
ENABLE_QDRANT=true
3. 사용 시나리오
KB 시맨틱 검색
# KB 문서 검색 — 키워드가 아닌 의미 기반
async def search_kb_semantic(query: str, db) -> list:
embedding = await get_embedding(query)
results = await db.execute(
text("SELECT id, title, content, 1-(embedding<=>:v) score "
"FROM tb_kb WHERE embedding IS NOT NULL "
"ORDER BY embedding <=> :v LIMIT 10"),
{"v": str(embedding)}
)
return results.mappings().all()
유사 SR 재발 탐지
# 새 SR과 유사한 과거 SR 찾기 (학습 루프 연동)
async def find_similar_sr(new_sr: SRRequest, db) -> list:
embedding = await get_embedding(f"{new_sr.title} {new_sr.description}")
results = await db.execute(
text("SELECT sr_id, title, status, "
"1-(embedding<=>:v) AS similarity "
"FROM tb_sr_request "
"WHERE embedding IS NOT NULL AND sr_id != :sid "
" AND 1-(embedding<=>:v) > 0.85 " # 85% 이상 유사도
"ORDER BY similarity DESC LIMIT 5"),
{"v": str(embedding), "sid": new_sr.sr_id}
)
return results.mappings().all()
Ollama 임베딩 모델 설치
# nomic-embed-text: 경량 임베딩 모델 (274MB)
ollama pull nomic-embed-text
# 또는 한국어 특화
ollama pull bge-m3
4. Docker Compose 프로파일
# 기본 (pgvector만)
docker compose up -d
# Qdrant 포함
docker compose --profile vector up -d
# Gitea 포함
docker compose up -d gitea
# 모두 실행
docker compose --profile vector up -d