음성 재생과 운영 배포 정리
This commit is contained in:
parent
8ed185ce6c
commit
ac7db95542
1020 changed files with 46863 additions and 2175 deletions
|
|
@ -252,6 +252,7 @@ def _vector_literal(vec: Sequence[float]) -> str:
|
|||
# $7 = w_sparse(real)
|
||||
# $8 = pre_k (int — dense/sparse 각 후보 수, 보통 50)
|
||||
# $9 = k (int — 융합 후 반환 수)
|
||||
# $10 = source_ids(text[] — 빈 배열이면 전체 허용)
|
||||
#
|
||||
# 정보비대칭 강제: 두 CTE 모두 `$4 = ANY(visible_to) AND sensitivity <= $5` 사전필터.
|
||||
# kinds 빈 배열 처리: cardinality($3)=0 이면 kb_kind 조건을 통과(전체).
|
||||
|
|
@ -267,6 +268,7 @@ dense AS (
|
|||
FROM kb.chunk c, params p
|
||||
WHERE c.embedding IS NOT NULL
|
||||
AND (cardinality($3::text[]) = 0 OR c.kb_kind = ANY($3::text[]))
|
||||
AND (cardinality($10::text[]) = 0 OR c.source_id = ANY($10::text[]))
|
||||
AND $4 = ANY(c.visible_to)
|
||||
AND c.sensitivity <= $5
|
||||
ORDER BY c.embedding <=> p.q_dense
|
||||
|
|
@ -279,6 +281,7 @@ sparse AS (
|
|||
WHERE p.q_ts IS NOT NULL
|
||||
AND to_tsvector('simple', c.chunk_text) @@ p.q_ts
|
||||
AND (cardinality($3::text[]) = 0 OR c.kb_kind = ANY($3::text[]))
|
||||
AND (cardinality($10::text[]) = 0 OR c.source_id = ANY($10::text[]))
|
||||
AND $4 = ANY(c.visible_to)
|
||||
AND c.sensitivity <= $5
|
||||
ORDER BY s_sparse DESC
|
||||
|
|
@ -473,6 +476,7 @@ async def search_kb(
|
|||
fs = filters.get("sensitivity_max")
|
||||
if isinstance(fs, int):
|
||||
sens_max = min(sens_max, fs) # 더 엄격하게만
|
||||
source_filter = [str(item) for item in (filters.get("source_id", []) if filters else [])]
|
||||
|
||||
# (2) 질의 임베딩(dense+sparse). 모델 미가용 → NotConfigured 전파.
|
||||
eq = await asyncio.to_thread(embed_query, query) # CPU 인코딩 → 스레드풀(이벤트루프 비차단)
|
||||
|
|
@ -491,17 +495,13 @@ async def search_kb(
|
|||
policy.w_sparse, # $7
|
||||
pre_k, # $8 pre_k
|
||||
max(k * 4, k), # $9 융합 후 1차 컷(리랭킹 입력 여유분)
|
||||
source_filter, # $10 source_id 좁힘
|
||||
)
|
||||
except Exception as e: # UndefinedFunction(vector 미설치) / UndefinedColumn 등
|
||||
raise NotConfigured(f"KB hybrid query failed (DB/pgvector not ready): {e}") from e
|
||||
|
||||
# source_id 추가 좁힘(SQL 후처리 — 화이트리스트 보존, 코드 단순화)
|
||||
src_filter = set(filters.get("source_id", [])) if filters else set()
|
||||
|
||||
chunks: list[RetrievedChunk] = []
|
||||
for r in rows:
|
||||
if src_filter and r["source_id"] not in src_filter:
|
||||
continue
|
||||
# asyncpg는 jsonb를 str(JSON text)로 반환 → 파싱. 코덱 등록 시 dict 그대로도 수용.
|
||||
_meta_raw = r["meta"]
|
||||
meta = json.loads(_meta_raw) if isinstance(_meta_raw, str) else dict(_meta_raw or {})
|
||||
|
|
@ -635,6 +635,7 @@ async def retrieve_eval_grounding(
|
|||
query: str,
|
||||
k: int = 5,
|
||||
kinds: Optional[Sequence[str]] = None,
|
||||
source_ids: Optional[Sequence[str]] = None,
|
||||
rerank: bool = True,
|
||||
) -> RetrievalResult:
|
||||
"""평가 AI 채점 근거 회수 — DSM/이론/taxonomy 정답라벨 + 논평.
|
||||
|
|
@ -644,13 +645,17 @@ async def retrieve_eval_grounding(
|
|||
|
||||
kinds: 평가 차원에 따라 좁히기(예: 기법 채점 → ['technique','supervisor_pattern']).
|
||||
"""
|
||||
filters = {"kb_kind": list(kinds)} if kinds else None
|
||||
filters: dict[str, Any] = {}
|
||||
if kinds:
|
||||
filters["kb_kind"] = list(kinds)
|
||||
if source_ids:
|
||||
filters["source_id"] = list(source_ids)
|
||||
return await search_kb(
|
||||
conn,
|
||||
query=query,
|
||||
role=AIRole.EVALUATOR,
|
||||
k=k,
|
||||
filters=filters,
|
||||
filters=filters or None,
|
||||
rerank=rerank,
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue