9d4aa201a8
문제 본문 + 보기 1~4 → bge-m3 1024차원. status 자체가 큐 역할 (별도 큐
테이블 없음 — ProcessingQueue 인프라 영향 0). APScheduler 1분 cron 이
status in {none, failed, stale} 행을 batch=10 처리. 새 문제는 default
'none' 으로 자동 backfill.
데이터 모델 (migrations 193~194):
- study_questions: embedding vector(1024), embedding_status VARCHAR(20)
DEFAULT 'none' (none/pending/ready/failed/stale), embedding_updated_at,
embedding_model
- HNSW partial index (vector_cosine_ops) WHERE deleted_at IS NULL AND
embedding IS NOT NULL — bge-m3 cosine 기준, documents.embedding (ivfflat)
과 ops 일관
재계산 트리거: question_text / choice_1~4 변경 시 ready→stale 자동.
correct_choice / explanation / subject / scope 변경은 재계산 안 함
(의미 검색에 영향 없음).
워커 (workers/study_question_embed_worker.py):
- race-safe pending 마킹 (조건부 UPDATE WHERE status IN none/failed/stale)
- AIClient.embed(text) bge-m3 호출, 15s timeout
- 실패 시 status='failed', 직전 embedding 보존, 다음 cron 틱에 재시도
- 본문 = "문제: ...\n보기:\n1. ...\n2. ...\n3. ...\n4. ..." (subject/scope
의도 제외 — 분류명이 의미 검색 노이즈)
후속 PR 예정: 비슷한 문제 검색 UI / 중복 입력 감지 / RAG 정확도 향상 /
오답 클러스터링. 본 PR 은 임베딩 저장·재계산·backfill 까지만.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
19 lines
1.1 KiB
SQL
19 lines
1.1 KiB
SQL
-- 193_study_questions_embedding.sql (1/2)
|
|
-- study_questions 자동 임베딩 (PR-4). 문제 본문 + 보기 1~4 → bge-m3 1024차원.
|
|
--
|
|
-- embedding_status 권장값 (강한 enum 미사용, status 자체가 큐 역할):
|
|
-- none — 신규 입력 (default, 한번도 임베딩 안 됨)
|
|
-- pending — 처리 진행 중 (race-safe 조건부 UPDATE 로 보호)
|
|
-- ready — 완료
|
|
-- failed — 실패 (재시도 가능). 직전 embedding 보존.
|
|
-- stale — question_text/choice_1~4 변경되어 outdated. cron 이 다음 틱에 재계산.
|
|
--
|
|
-- 재계산 트리거: question_text / choice_1~4 변경. correct_choice·explanation·subject·scope 변경은 재계산 안 함.
|
|
-- 별도 큐 테이블 미신설 — embedding_status 가 큐 역할 (cron polling). ProcessingQueue 인프라 영향 없음.
|
|
|
|
ALTER TABLE study_questions
|
|
ADD COLUMN IF NOT EXISTS embedding vector(1024),
|
|
ADD COLUMN IF NOT EXISTS embedding_status VARCHAR(20) NOT NULL DEFAULT 'none',
|
|
ADD COLUMN IF NOT EXISTS embedding_updated_at TIMESTAMPTZ,
|
|
ADD COLUMN IF NOT EXISTS embedding_model VARCHAR(120);
|