페르소나 소스팩 동기화 정리
This commit is contained in:
parent
6a81ec596c
commit
e8e08935ed
10 changed files with 1126 additions and 283 deletions
|
|
@ -22,7 +22,7 @@ from pydantic import BaseModel, Field
|
|||
|
||||
from ..db import acquire, get_pool
|
||||
from ..deps import AIView, Principal, Role, require_role
|
||||
from ..services import live_coach, rag
|
||||
from ..services import rag, source_pack_sync
|
||||
|
||||
router = APIRouter(prefix="/kb", tags=["kb"])
|
||||
|
||||
|
|
@ -326,6 +326,8 @@ async def index_document(
|
|||
# 관리자 인덱싱은 RLS 미적용(쓰기 — kb 스키마 직접). role 주입 없이 acquire.
|
||||
async with acquire() as conn:
|
||||
result = await rag.index_document(conn, req)
|
||||
except rag.IndexPolicyViolation as e:
|
||||
raise HTTPException(status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e)) from e
|
||||
except rag.NotConfigured as e:
|
||||
raise HTTPException(status.HTTP_503_SERVICE_UNAVAILABLE, detail=f"RAG not configured: {e}")
|
||||
except RuntimeError as e:
|
||||
|
|
@ -354,64 +356,36 @@ async def sync_live_coach_source_packs(
|
|||
evaluator RAG 검색에도 올린다. source row를 먼저 upsert한 뒤 content_hash 기반 증분 색인을
|
||||
수행한다. 임베딩 모델 미가용 시 BM25-only degraded 색인으로 이어진다.
|
||||
"""
|
||||
source_rows = live_coach.build_rag_source_rows()
|
||||
index_payloads = live_coach.build_rag_index_payloads()
|
||||
source_rows, index_payloads = source_pack_sync.build_repo_source_pack_manifest()
|
||||
if not source_rows or not index_payloads:
|
||||
raise HTTPException(
|
||||
status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
detail="live coach source packs are empty",
|
||||
)
|
||||
|
||||
items: list[LiveCoachSourcePackSyncItem] = []
|
||||
source_row_by_id = {row["source_id"]: row for row in source_rows}
|
||||
try:
|
||||
async with acquire() as conn:
|
||||
for row in source_rows:
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO kb.source
|
||||
(source_id, title, kb_kind, license_class, origin_path, citation, external_llm_ok)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
ON CONFLICT (source_id) DO UPDATE SET
|
||||
title = EXCLUDED.title,
|
||||
kb_kind = EXCLUDED.kb_kind,
|
||||
license_class = EXCLUDED.license_class,
|
||||
origin_path = EXCLUDED.origin_path,
|
||||
citation = EXCLUDED.citation,
|
||||
external_llm_ok = EXCLUDED.external_llm_ok
|
||||
""",
|
||||
row["source_id"],
|
||||
row["title"],
|
||||
row["kb_kind"],
|
||||
row["license_class"],
|
||||
row["origin_path"],
|
||||
row["citation"],
|
||||
row["external_llm_ok"],
|
||||
)
|
||||
for payload in index_payloads:
|
||||
if payload["source_id"] not in source_row_by_id:
|
||||
continue
|
||||
result = await rag.index_document(conn, rag.IndexRequest(**payload))
|
||||
items.append(
|
||||
LiveCoachSourcePackSyncItem(
|
||||
source_id=payload["source_id"],
|
||||
doc_id=result.doc_id,
|
||||
chunks_indexed=result.chunks_indexed,
|
||||
skipped_unchanged=result.skipped_unchanged,
|
||||
embedded=result.embedded,
|
||||
degraded=result.degraded,
|
||||
)
|
||||
)
|
||||
result = await source_pack_sync.sync_repo_source_packs(conn, apply=True)
|
||||
except rag.NotConfigured as exc:
|
||||
raise HTTPException(status.HTTP_503_SERVICE_UNAVAILABLE, detail=f"RAG not configured: {exc}") from exc
|
||||
except RuntimeError as exc:
|
||||
raise HTTPException(status.HTTP_503_SERVICE_UNAVAILABLE, detail=f"DB not ready: {exc}") from exc
|
||||
|
||||
return LiveCoachSourcePackSyncResponse(
|
||||
sources_upserted=len(source_rows),
|
||||
chunks_indexed=sum(item.chunks_indexed for item in items),
|
||||
skipped_unchanged=sum(1 for item in items if item.skipped_unchanged),
|
||||
embedded=all(item.embedded for item in items) if items else False,
|
||||
degraded=any(item.degraded for item in items),
|
||||
items=items,
|
||||
sources_upserted=result.sources_upserted,
|
||||
chunks_indexed=result.chunks_indexed,
|
||||
skipped_unchanged=result.skipped_unchanged,
|
||||
embedded=result.embedded,
|
||||
degraded=result.degraded,
|
||||
items=[
|
||||
LiveCoachSourcePackSyncItem(
|
||||
source_id=item.source_id,
|
||||
doc_id=item.doc_id,
|
||||
chunks_indexed=item.chunks_indexed,
|
||||
skipped_unchanged=item.skipped_unchanged,
|
||||
embedded=item.embedded,
|
||||
degraded=item.degraded,
|
||||
)
|
||||
for item in result.items
|
||||
],
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue