Skip to content

Commit 08998f4

Browse files
committed
refactor(ai): 실패·저속한 LLM 리랭커 제거, RAG를 top_k 직접 검색으로 단순화
리랭커가 프로덕션에서 항상 실패→검색순서 폴백 중이라 가치 0에 ~1-2s만 소모. 모든 RAG 경로(질문풀·꼬리질문·피드백)가 이미 검색순서를 쓰고 있어 제거는 동작 무변경이며 지연·비용만 감소. - rag/reranker.py, chain/prompts/rerank.py, test_reranker.py 삭제 - 3개 consumer: candidate_k 후보 fetch + rerank_hits 제거 → rag_top_k 직접 검색 - settings: rerank_enabled/rerank_candidate_k/followup_rerank_enabled 제거 (followup_rag_timeout_sec 타임아웃 안전망은 유지)
1 parent 669fd11 commit 08998f4

10 files changed

Lines changed: 11 additions & 323 deletions

File tree

ai/src/ai_server/chain/prompts/rerank.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

ai/src/ai_server/config/settings.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,7 @@ class Settings(BaseSettings):
3838
ai_realtime_exchange: str = "stackup.realtime"
3939
ai_realtime_routing_user: str = "realtime.user.notify"
4040
feedback_rag_top_k: int = 5
41-
# 리랭킹: 하이브리드 검색으로 후보 N개(candidate_k)를 가져와 LLM 으로 재정렬 후 top_k 주입.
42-
rerank_enabled: bool = True
43-
rerank_candidate_k: int = 20
44-
# 꼬리질문 RAG 저지연: 리랭커(LLM 호출, 종종 실패)를 건너뛰고 검색 순서를 그대로 쓴다.
45-
followup_rerank_enabled: bool = False
46-
# RAG 컨텍스트 구성(임베딩+검색+리랭크) 전체 상한. 초과 시 (none) 으로 폴백해 첫 토큰을 막지 않는다.
41+
# RAG 컨텍스트 구성(임베딩+검색) 전체 상한. 초과 시 (none) 으로 폴백해 첫 토큰을 막지 않는다.
4742
followup_rag_timeout_sec: float = 1.5
4843
# 질문 풀 초기 크기. Core 의 applyPool 이 questions[0] 만 INSERT 하므로 1 로 고정해 토큰 낭비 차단.
4944
# 후속 작업에서 풀 저장 도입 시 늘리기 (예: 5).

ai/src/ai_server/messaging/consumers/feedback_consumer.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
VoiceAnalysisSummary,
1616
)
1717
from ai_server.rag.embedder import EmbeddingProvider
18-
from ai_server.rag.reranker import NoopReranker, Reranker, rerank_hits
1918

2019
log = structlog.get_logger(__name__)
2120

@@ -41,8 +40,6 @@ def __init__(
4140
core_client: CoreClient,
4241
embedder: EmbeddingProvider | None = None,
4342
rag_top_k: int = 5,
44-
reranker: Reranker | None = None,
45-
candidate_k: int = 20,
4643
) -> None:
4744
self._generator = generator
4845
self._publisher = publisher
@@ -51,8 +48,6 @@ def __init__(
5148
self._core = core_client
5249
self._embedder = embedder
5350
self._rag_top_k = rag_top_k
54-
self._reranker = reranker or NoopReranker()
55-
self._candidate_k = max(candidate_k, rag_top_k)
5651

5752
async def handle(self, message: AbstractIncomingMessage) -> None:
5853
async with message.process(requeue=False):
@@ -148,16 +143,13 @@ async def _build_rag_context(self, req: GenerateFeedbackRequest) -> str:
148143
query_embedding=query_vec,
149144
query_text=last_answer,
150145
document_ids=req.context_document_ids,
151-
top_k=self._candidate_k,
146+
top_k=self._rag_top_k,
152147
)
153148
except Exception as exc:
154149
log.warn("feedback.rag.failed", error=str(exc), session_id=req.session_id)
155150
return "(none)"
156151
if not hits:
157152
return "(none)"
158-
hits = await rerank_hits(
159-
self._reranker, query=last_answer, hits=hits, top_k=self._rag_top_k
160-
)
161153
return "\n---\n".join(
162154
f"[doc#{h.document_id} chunk#{h.chunk_index}] {h.chunk_text}" for h in hits
163155
)

ai/src/ai_server/messaging/consumers/followup_consumer.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
GenerateFollowupRequest,
2121
)
2222
from ai_server.rag.embedder import EmbeddingProvider
23-
from ai_server.rag.reranker import NoopReranker, Reranker, rerank_hits
2423

2524
log = structlog.get_logger(__name__)
2625

@@ -43,14 +42,11 @@ def __init__(
4342
core_client: CoreClient | None = None,
4443
embedder: EmbeddingProvider | None = None,
4544
rag_top_k: int = 5,
46-
reranker: Reranker | None = None,
47-
candidate_k: int = 20,
4845
streaming_generator: StreamingFollowupGenerator | None = None,
4946
session_notifier: SessionRealtimeNotifier | None = None,
5047
tts=None,
5148
storage=None,
5249
tts_voice: str = "",
53-
rerank_enabled: bool = True,
5450
rag_timeout_sec: float = 1.5,
5551
) -> None:
5652
self._generator = generator
@@ -60,14 +56,11 @@ def __init__(
6056
self._core = core_client
6157
self._embedder = embedder
6258
self._rag_top_k = rag_top_k
63-
self._reranker = reranker or NoopReranker()
64-
self._candidate_k = max(candidate_k, rag_top_k)
6559
self._streaming = streaming_generator
6660
self._notifier = session_notifier
6761
self._tts = tts
6862
self._storage = storage
6963
self._tts_voice = tts_voice
70-
self._rerank_enabled = rerank_enabled
7164
self._rag_timeout_sec = rag_timeout_sec
7265

7366
async def handle(self, message: AbstractIncomingMessage) -> None:
@@ -251,8 +244,6 @@ async def _build_rag_context(self, req: GenerateFollowupRequest) -> str:
251244

252245
async def _do_build_rag_context(self, req: GenerateFollowupRequest) -> str:
253246
query = f"{req.previous_question}\n\n{req.answer_text}"
254-
# 리랭크 비활성 시 candidate 확장 없이 top_k 만 검색(LLM 리랭커 호출 회피).
255-
search_k = self._candidate_k if self._rerank_enabled else self._rag_top_k
256247
try:
257248
query_vec = (
258249
await self._embedder.embed([query], task_type="RETRIEVAL_QUERY")
@@ -261,18 +252,14 @@ async def _do_build_rag_context(self, req: GenerateFollowupRequest) -> str:
261252
query_embedding=query_vec,
262253
query_text=query,
263254
document_ids=req.context_document_ids,
264-
top_k=search_k,
255+
top_k=self._rag_top_k,
265256
)
266257
except Exception as exc:
267258
log.warn("followup.rag.failed", error=str(exc), session_id=req.session_id)
268259
return "(none)"
269260

270261
if not hits:
271262
return "(none)"
272-
if self._rerank_enabled:
273-
hits = await rerank_hits(
274-
self._reranker, query=query, hits=hits, top_k=self._rag_top_k
275-
)
276263
return "\n---\n".join(
277264
f"[doc#{h.document_id} chunk#{h.chunk_index}] {h.chunk_text}" for h in hits
278265
)

ai/src/ai_server/messaging/consumers/questions_consumer.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
QuestionPoolCallbackPayload,
1515
)
1616
from ai_server.rag.embedder import EmbeddingProvider
17-
from ai_server.rag.reranker import NoopReranker, Reranker, rerank_hits
1817

1918
log = structlog.get_logger(__name__)
2019

@@ -31,8 +30,6 @@ def __init__(
3130
core_client: CoreClient | None = None,
3231
embedder: EmbeddingProvider | None = None,
3332
rag_top_k: int = 5,
34-
reranker: Reranker | None = None,
35-
candidate_k: int = 20,
3633
) -> None:
3734
self._generator = generator
3835
self._publisher = publisher
@@ -44,8 +41,6 @@ def __init__(
4441
self._core = core_client
4542
self._embedder = embedder
4643
self._rag_top_k = rag_top_k
47-
self._reranker = reranker or NoopReranker()
48-
self._candidate_k = max(candidate_k, rag_top_k)
4944

5045
async def handle(self, message: AbstractIncomingMessage) -> None:
5146
async with message.process(requeue=False):
@@ -138,17 +133,14 @@ async def _build_context(self, req: GenerateQuestionsRequest) -> str:
138133
query_embedding=query_vec,
139134
query_text=query,
140135
document_ids=document_ids,
141-
top_k=self._candidate_k,
136+
top_k=self._rag_top_k,
142137
)
143138
except Exception as exc:
144139
log.warn("questions.rag.failed", error=str(exc), session_id=req.session_id)
145140
return base_context
146141

147142
if not hits:
148143
return base_context
149-
hits = await rerank_hits(
150-
self._reranker, query=query, hits=hits, top_k=self._rag_top_k
151-
)
152144
rag_context = "\n---\n".join(
153145
f"[doc#{h.document_id} chunk#{h.chunk_index}] {h.chunk_text}" for h in hits
154146
)

ai/src/ai_server/messaging/runner.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
from ai_server.messaging.connection import RabbitConnection
3333
from ai_server.rag.chunker import MarkdownChunker
3434
from ai_server.rag.embedder import build_embedding_provider
35-
from ai_server.rag.reranker import build_reranker
3635
from ai_server.messaging.consumers.feedback_consumer import FeedbackConsumer
3736
from ai_server.messaging.consumers.followup_consumer import FollowupConsumer
3837
from ai_server.messaging.consumers.questions_consumer import QuestionsConsumer
@@ -102,7 +101,6 @@ def __init__(self, settings: Settings) -> None:
102101
max_retries=settings.embedding_max_retries,
103102
retry_base_delay_sec=settings.embedding_retry_base_delay_sec,
104103
)
105-
reranker = build_reranker(settings, core_client=core_client)
106104
vision_pdf_reader = build_vision_pdf_reader(settings, core_client=core_client)
107105

108106
# 이력서 PDF
@@ -182,8 +180,6 @@ def __init__(self, settings: Settings) -> None:
182180
initial_pool_size=settings.questions_initial_pool_size,
183181
core_client=core_client,
184182
embedder=embedder,
185-
reranker=reranker,
186-
candidate_k=settings.rerank_candidate_k,
187183
)
188184

189185
# 꼬리질문 생성 (US-19)
@@ -206,14 +202,11 @@ def __init__(self, settings: Settings) -> None:
206202
callback_routing_key=settings.ai_callback_routing_questions,
207203
core_client=core_client,
208204
embedder=embedder,
209-
reranker=reranker,
210-
candidate_k=settings.rerank_candidate_k,
211205
streaming_generator=streaming_followup_generator,
212206
session_notifier=session_notifier,
213207
tts=tts,
214208
storage=storage,
215209
tts_voice=settings.openai_tts_voice,
216-
rerank_enabled=settings.followup_rerank_enabled,
217210
rag_timeout_sec=settings.followup_rag_timeout_sec,
218211
)
219212

@@ -228,8 +221,6 @@ def __init__(self, settings: Settings) -> None:
228221
callback_routing_key=settings.ai_callback_routing_feedback,
229222
core_client=core_client,
230223
embedder=embedder,
231-
reranker=reranker,
232-
candidate_k=settings.rerank_candidate_k,
233224
rag_top_k=settings.feedback_rag_top_k,
234225
)
235226

ai/src/ai_server/rag/reranker.py

Lines changed: 0 additions & 119 deletions
This file was deleted.

0 commit comments

Comments
 (0)