diff --git a/app/ai/client.py b/app/ai/client.py index 3684b76..6ff06b5 100644 --- a/app/ai/client.py +++ b/app/ai/client.py @@ -264,7 +264,7 @@ class AIClient: """벡터 임베딩 — GPU 서버 전용""" response = await self._http.post( self.ai.embedding.endpoint, - json={"model": self.ai.embedding.model, "prompt": text}, + json={"model": self.ai.embedding.model, "prompt": text, "keep_alive": -1}, # bge-m3 GPU 상주(홈랩 sparse 검색 cold reload ~6s 방지) ) response.raise_for_status() return response.json()["embedding"] diff --git a/app/services/search/retrieval_service.py b/app/services/search/retrieval_service.py index c14a2eb..f1539ef 100644 --- a/app/services/search/retrieval_service.py +++ b/app/services/search/retrieval_service.py @@ -361,7 +361,7 @@ async def search_text( + similarity(coalesce(d.ai_tags::text, ''), :q) * 2.5 + similarity(coalesce(d.user_note, ''), :q) * 2.0 + similarity(coalesce(d.ai_summary, ''), :q) * 1.5 - + similarity(coalesce(d.extracted_text, ''), :q) * 1.0 + + similarity(left(coalesce(d.extracted_text, ''), 2000), :q) * 1.0 -- FTS 보너스 (idx_documents_fts_full 활용) + coalesce(ts_rank( to_tsvector('simple', @@ -369,7 +369,7 @@ async def search_text( coalesce(d.ai_tags::text, '') || ' ' || coalesce(d.ai_summary, '') || ' ' || coalesce(d.user_note, '') || ' ' || - coalesce(d.extracted_text, '') + left(coalesce(d.extracted_text, ''), 2000) ), plainto_tsquery('simple', :q) ), 0) * 2.0 @@ -380,7 +380,7 @@ async def search_text( WHEN similarity(coalesce(d.ai_tags::text, ''), :q) >= 0.3 THEN 'tags' WHEN similarity(coalesce(d.user_note, ''), :q) >= 0.3 THEN 'note' WHEN similarity(coalesce(d.ai_summary, ''), :q) >= 0.3 THEN 'summary' - WHEN similarity(coalesce(d.extracted_text, ''), :q) >= 0.3 THEN 'content' + WHEN similarity(left(coalesce(d.extracted_text, ''), 2000), :q) >= 0.3 THEN 'content' ELSE 'fts' END AS match_reason, d.material_type, d.jurisdiction, d.published_date