에이전트·RAG

AGENT / 19번째 글

RAG 리랭킹: 검색 품질을 한 단계 끌어올리는 기술

RAG의 검색 결과를 정밀하게 재정렬하는 리랭킹의 원리와 Cross-Encoder 모델, Cohere·BGE·Jina 등 주요 리랭커 비교, 실전 구현까지 한국어로 완전 해설한다.

PALDYN Team31 MIN READ

지난 글에서 BM25·벡터·하이브리드라는 세 가지 검색 전략을 견줘 봤다. 어느 전략을 쓰든 검색이 돌려주는 것은 점수로 줄 세운 문서 목록이고, LLM에 넘기는 것은 그 목록의 맨 앞 몇 건이다. 이 글은 그 줄을 한 번 더 세우는 일, 곧 1차 검색이 뽑은 후보 수십 건을 더 비싸고 더 정확한 모델로 다시 채점해 순서를 바꾸는 리랭킹을 다룬다. 이 일을 맡는 모델을 리랭커라고 부른다. 색인은 그대로 두고 단계 하나만 끼우는 일이라 붙이기는 쉽지만, 후보를 몇 건 넘길지, 어느 모델을 쓸지, 지연을 얼마나 줄지를 정하지 않고 붙이면 느리기만 하고 나아지는 것이 없는 경우도 흔하다. 그 결정들을 차례로 짚는다.

두 인코더의 계산량

바이인코더

지금 쓰는 벡터 검색은 거의 전부 바이인코더다. 질의와 문서를 같은 모델로 따로따로 인코딩해 벡터 하나씩으로 만들고, 두 벡터의 코사인 유사도나 내적으로 가까운 정도를 잰다. 둘이 따로 인코딩되므로 문서 쪽 벡터는 질의가 오기 전에 전부 만들어 색인에 넣어 둘 수 있다. 질의가 들어오면 질의 하나만 인코딩하고, 색인에서 그 벡터와 가까운 이웃을 찾으면 끝난다. 이웃을 전부 견주지 않고 대략 찾는 방법을 근사 최근접 탐색(ANN)이라고 하며, 문서가 수백만 건이어도 수십 밀리초 안에 돌아온다.

대가는 질의와 문서가 끝까지 한 번도 만나지 않는다는 점이다. 문서 벡터는 질의를 모르는 채로 만들어진 요약이다. 그래서 「파이썬 설치 방법」을 찾는데 「파이썬 제거 방법」이 거의 같은 점수로 올라온다. 두 문서는 쓰는 낱말도 문체도 거의 같고, 갈리는 것은 「설치」와 「제거」라는 한 낱말뿐인데, 그 한 낱말의 차이가 벡터 하나에 평균되어 묻히기 때문이다.

크로스 인코더

크로스 인코더는 질의와 문서를 한 줄로 붙여 트랜스포머에 한 번에 넣고, 관련도 점수 하나를 받는 모델이다. 붙여 넣었으므로 어텐션이 질의의 「설치」와 문서의 「제거」를 직접 맞대어 볼 수 있다. 바이인코더가 놓치는 부정·조건·순서 같은 세부가 여기서 점수에 드러난다. 리랭커라고 하면 대개 이 크로스 인코더를 가리킨다.

대신 미리 해 둘 수 있는 일이 하나도 없다. 점수는 질의와 문서의 짝마다 따로 나오고, 질의를 알아야 계산을 시작할 수 있다. 문서 벡터를 쌓아 둔 색인 같은 것이 존재할 수 없다는 뜻이다.

인코딩 횟수

둘의 차이는 횟수로 세면 분명해진다. 문서가 NN건인 색인에 질의 하나가 들어왔다고 하자.

  • 바이인코더: 문서 NN건은 색인할 때 한 번씩, 질의 시점에는 질의 1건만 인코딩한다
  • 크로스 인코더로 전부 채점: 질의가 올 때마다 짝 NN개를 모델에 통과시킨다

예를 들어 NN이 100만이고, GPU 한 장에서 크로스 인코더가 1초에 짝 1,000개를 처리한다고 가정하자. 질의 하나를 채점하는 데 1,000초, 17분 가까이 걸린다. 바이인코더 쪽은 질의 인코딩 한 번과 ANN 탐색으로 수십 밀리초다. 같은 가정에서 크로스 인코더에 후보 50건만 넘기면 짝 50개, 곧 50밀리초다.

여기서 구조가 정해진다. 크로스 인코더는 정확하지만 전체에는 못 쓰고, 바이인코더는 전체에 쓸 수 있지만 거칠다. 그러니 바이인코더로 100만 건을 수십 건으로 줄이고, 그 수십 건에만 크로스 인코더를 쓴다. 이것이 2단계 검색이고, 리랭킹은 그 두 번째 단계의 이름이다.

2단계 검색

RAG 리랭킹 파이프라인

후보 수

2단계 검색에서 손잡이는 둘이다. 1단계가 리랭커에 넘기는 후보 수 kk와, 리랭커가 LLM에 넘기는 최종 건수 nn이다. nn은 LLM 컨텍스트와 답변 품질이 정하므로 보통 3~10건 안에서 고르고, 실제로 고민할 것은 kk다.

kk를 늘리면 두 가지가 함께 움직인다. 하나는 재현율이다. 여기서 재현율은 정답 문서가 상위 kk건 안에 들어온 질의의 비율이고, recall@k로 적는다. kk가 크면 정답이 목록 어딘가에 들어올 가능성이 커지므로 재현율은 오르기만 한다. 다른 하나는 리랭킹 지연이다. 크로스 인코더는 짝마다 한 번씩 돌아야 하므로 지연이 kk에 거의 비례해 늘어난다.

두 곡선의 모양이 다르다는 점이 결정의 핵심이다. 재현율은 처음에 빠르게 오르다가 곧 눕는다. 예를 들어 어느 평가 집합에서 recall@10이 0.78, recall@50이 0.91, recall@200이 0.94였다면, 10에서 50으로 갈 때는 13포인트를 얻지만 50에서 200으로 갈 때는 3포인트를 얻으면서 지연은 네 배가 된다. 지연은 그런 식으로 눕지 않고 직선으로 오른다. 그래서 kk는 재현율 곡선이 눕기 시작하는 무릎에서 고른다. 현업에서 30~100 사이를 많이 쓰는 이유가 대개 여기에 있지만, 그 값은 자기 평가 집합에서 곡선을 그려 봐야 알 수 있다.

재현율 상한

리랭커는 후보 kk건의 순서만 바꾼다. 목록에 없는 문서를 새로 데려오지는 못한다. 그러니 리랭킹 뒤의 recall@n은 리랭킹 앞의 recall@k를 넘을 수 없다. 위 예에서 kk를 50으로 두면, 리랭커가 아무리 완벽해도 최종 상위 5건에 정답이 들어오는 질의는 91%가 한계다.

이 상한은 리랭커를 평가할 때 두 수를 따로 재야 한다는 뜻이기도 하다. 1단계의 recall@k와 리랭킹 뒤의 recall@n을 나란히 적어 두면, 둘의 차이가 리랭커가 아직 못 살린 몫이고 1에서 recall@k를 뺀 나머지가 1단계가 놓친 몫이다. 앞의 몫이 크면 리랭커를 바꾸고, 뒤의 몫이 크면 1단계를 고친다. 리랭커만 바꿔 가며 최종 점수를 보면 어느 쪽이 병목인지 가려지지 않는다.

구현

sentence-transformers의 CrossEncoder로 쓰면 짝 목록을 넣고 점수 목록을 받는 것이 전부다.

from sentence_transformers import CrossEncoder

reranker = CrossEncoder("BAAI/bge-reranker-v2-m3", max_length=512)

query = "AI 규제 현황과 주요 법안"
candidates = vector_search(query, top_k=50)      # 1단계: 후보 k=50

pairs = [(query, doc.text) for doc in candidates]
scores = reranker.predict(pairs, batch_size=32)  # 2단계: 짝마다 점수

ranked = sorted(zip(candidates, scores), key=lambda x: -x[1])
top5 = [doc for doc, _ in ranked[:5]]            # LLM에는 n=5만

max_length는 짝 하나를 몇 토큰에서 자를지 정하고, batch_size는 한 번에 GPU에 올리는 짝 수다. 짝 50개를 하나씩 돌리면 모델 호출이 50번이지만 32개씩 묶으면 두 번이라, 지연은 대부분 이 묶음 크기에서 갈린다. 점수의 절대값은 모델마다 척도가 달라 비교에 쓰지 않는다. 같은 질의 안에서 순서를 정하는 데만 쓴다.

프레임워크 연결

LangChain에서는 1단계 검색기를 리랭커로 감싸는 방식으로 붙인다. ContextualCompressionRetriever가 감싸는 쪽이고 CrossEncoderReranker가 그 안에서 순서를 바꾸는 쪽이다. LangChain v1부터 이 두 클래스는 langchain-classic 패키지로 옮겨졌으므로, 0.x 버전에서는 아래 import가 langchain.retrievers로 시작한다.

from langchain_classic.retrievers import ContextualCompressionRetriever
from langchain_classic.retrievers.document_compressors import CrossEncoderReranker
from langchain_community.cross_encoders import HuggingFaceCrossEncoder

base = vectorstore.as_retriever(search_kwargs={"k": 50})
model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-v2-m3")

retriever = ContextualCompressionRetriever(
    base_compressor=CrossEncoderReranker(model=model, top_n=5),
    base_retriever=base,
)
docs = retriever.invoke("AI 규제 현황은?")

여기서도 손잡이는 같은 둘이다. search_kwargs의 k가 후보 수이고 top_n이 최종 건수다. 프레임워크가 감싸 준다고 해서 kk를 정하는 일까지 대신해 주지는 않는다.

리랭커 모델 선택

주요 리랭커 모델 비교

오픈 모델

가중치를 내려받아 자기 GPU에서 돌리는 리랭커가 있다. BAAI의 bge-reranker-v2-m3와 Jina AI의 jina-reranker-v2-base-multilingual이 다국어로 학습되어 한국어 질의에 그대로 쓸 수 있는 쪽이다. cross-encoder/ms-marco-MiniLM-L-6-v2는 작고 빨라 예제에 자주 나오지만, 영어 검색 데이터로만 학습되어 한국어 문서에는 점수가 거의 뜻을 갖지 못한다. 한국어 RAG에서 이 모델로 실험하고 「리랭킹은 효과가 없다」고 결론 내리는 일이 드물지 않다.

오픈 모델의 비용은 호출 수가 아니라 GPU 시간이다. 트래픽이 적으면 하루 대부분 노는 GPU 값을 내고, 트래픽이 많으면 호출당 단가가 API보다 훨씬 낮아진다. 지연도 직접 쥘 수 있다. 모델을 작은 것으로 바꾸거나, 입력 길이를 줄이거나, 반정밀도로 돌리는 선택이 전부 자기 손에 있다. 라이선스는 모델마다 다르므로 상업 서비스라면 모델 카드에서 먼저 확인한다.

API 리랭커

Cohere·Voyage AI·Jina AI 같은 회사는 리랭킹을 API로 판다. 질의와 문서 목록을 보내면 순서와 점수가 돌아온다. GPU를 관리할 필요가 없으니 프로토타입과 트래픽이 들쭉날쭉한 서비스에 잘 맞는다. Cohere의 파이썬 SDK로는 이렇게 부른다.

import cohere

co = cohere.ClientV2()  # 키는 환경 변수 CO_API_KEY에서 읽는다

res = co.rerank(
    model="rerank-v3.5",
    query="AI 규제 현황과 주요 법안",
    documents=[doc.text for doc in candidates],
    top_n=5,
)
top5 = [candidates[r.index] for r in res.results]

결과는 문서 본문이 아니라 원래 목록의 자리(index)와 점수로 돌아오므로, 자리로 원래 문서를 다시 찾는다. 모델 이름은 판이 자주 바뀌니 쓰기 전에 그 회사의 모델 목록에서 현재 이름을 확인한다.

API 쪽에서 따로 셈해 둘 것은 두 가지다. 하나는 네트워크 왕복이 지연에 그대로 더해진다는 점이다. 같은 리전의 GPU에서 50밀리초 걸릴 일이 바다 건너 API를 거치면 그 몇 배가 될 수 있다. 다른 하나는 문서가 회사 밖으로 나간다는 점이다. 사내 문서를 다루는 RAG라면 이것이 지연보다 먼저 결정을 가른다.

입력 길이 상한

크로스 인코더에는 한 번에 넣을 수 있는 토큰 수 상한이 있고, 질의와 문서를 붙인 짝 전체가 그 안에 들어가야 한다. 넘으면 뒤가 잘린다. 문서 뒷부분에 답이 있는 청크는 잘린 채로 채점되어 순위가 부당하게 내려간다. 입력이 길수록 어텐션 계산이 길이에 비해 빠르게 불어나서 지연도 커진다.

그래서 청크 크기와 리랭커의 길이 상한을 함께 정한다. 청크가 상한보다 한참 짧으면 신경 쓸 것이 없다. 청크가 길면 세 갈래가 있다. 앞부분만 넣고 잘리는 것을 받아들이거나, 청크를 겹치게 여러 조각으로 나눠 각각 채점한 뒤 가장 높은 조각의 점수를 그 청크의 점수로 삼거나, 애초에 청크를 상한에 맞춰 자른다. 두 번째는 정확하지만 짝 수가 조각 수만큼 늘어 지연이 그 배수가 된다. 대부분은 세 번째가 가장 싸다.

도메인 파인튜닝

학습 쌍

공개 리랭커는 웹 문서와 일반 질의로 학습되었다. 사내 약관, 제품 매뉴얼, 의료 기록처럼 낱말과 판단 기준이 따로 노는 도메인에서는 「관련 있다」의 뜻부터 다르다. 이럴 때 자기 데이터로 리랭커를 더 학습시키는 것이 파인튜닝이다. 리랭커의 파인튜닝 데이터는 (질의, 문서, 관련 여부) 짝이다.

짝을 모으는 길은 둘이다. 하나는 클릭 로그다. 검색 결과에서 사용자가 연 문서를 관련 있음으로, 보고도 지나친 문서를 관련 없음으로 적는다. 양이 많고 공짜지만 흔들린다. 사람은 맨 위 결과를 내용과 상관없이 더 자주 누르므로, 로그를 그대로 쓰면 리랭커가 기존 순위를 흉내 내는 쪽으로 배운다. 이 자리 치우침을 걷어내려면 결과 몇 건의 순서를 가끔 섞어 보여 주고, 섞였을 때의 클릭만 학습에 쓰는 식의 보정이 필요하다. 다른 하나는 사람이 정답을 달아 둔 골든셋이다. 양은 적지만 깨끗하다. 만드는 절차는 골든 데이터셋에서 다룬 것과 같고, 평가용으로 만든 것을 학습에 섞으면 평가가 무의미해지므로 둘은 처음부터 떼어 둔다.

하드 네거티브

관련 없는 짝을 아무 문서에서나 뽑으면 학습이 너무 쉽다. 「환불 기한」 질의에 「사내 식당 메뉴」를 관련 없다고 가르쳐 봐야 리랭커는 이미 안다. 리랭커가 실제로 틀리는 것은 1단계가 상위로 올려 보낸, 그럴듯하지만 틀린 문서다. 그래서 1단계 검색의 상위 후보 가운데 정답이 아닌 것을 음성 예로 쓰고, 이런 예를 하드 네거티브라고 부른다. 리랭커가 운영에서 받는 입력이 정확히 이런 문서들이라, 학습 분포와 운영 분포가 맞아떨어진다.

다만 하드 네거티브에는 가짜가 섞인다. 골든셋에 정답이 하나만 적혀 있어도 실제로는 같은 답을 담은 문서가 여럿일 수 있고, 그 나머지가 음성으로 들어가면 리랭커는 맞는 문서를 밀어내도록 배운다. 음성 후보 가운데 점수가 정답과 거의 같은 것은 사람이 한 번 보거나 빼는 편이 낫다.

도입 시점

파인튜닝은 마지막에 꺼내는 카드다. 순서는 이렇다. 먼저 다국어 공개 리랭커를 붙이고 앞 절처럼 recall@k와 리랭킹 뒤 recall@n을 잰다. 그 차이, 곧 리랭커가 못 살린 몫이 크게 남아 있고, 틀리는 사례를 열어 보니 도메인 용어나 도메인 판단 기준 때문이라면 그때 파인튜닝을 검토한다. 틀리는 원인이 1단계 누락이면 리랭커를 아무리 가르쳐도 안 나아진다.

그만한 값을 하는지는 짝의 수와 유지 비용으로 따진다. 수백 쌍으로는 공개 모델을 흔들기만 하기 쉽고, 수천 쌍 이상이 모일 때 차이가 나기 시작한다고 보는 편이 안전하다. 그리고 한 번 파인튜닝한 리랭커는 문서가 바뀔 때마다 다시 평가해야 하는 자산이 된다. 그 운영 부담까지 지고도 남는 개선일 때만 한다.

후기 상호작용과의 관계

만나는 시점

바이인코더와 크로스 인코더의 차이는 결국 질의와 문서가 언제 만나느냐다. 바이인코더는 끝에 벡터 하나씩으로 만나고, 크로스 인코더는 처음부터 한 줄로 붙어 만난다. 그 사이에 후기 상호작용이 있다. 문서를 토큰마다 벡터 하나씩으로 인코딩해 두고, 질의가 오면 질의 토큰 벡터와 문서 토큰 벡터를 맞대어 점수를 낸다. ColBERT 계열이 이 방식이고, 계산 방법은 레이트 인터랙션 글에서 따로 다룬다.

문서 쪽을 미리 계산해 둘 수 있다는 점은 바이인코더를 닮았고, 토큰 단위로 질의와 문서를 맞댄다는 점은 크로스 인코더를 닮았다. 다만 토큰끼리 유사도를 재는 것일 뿐 어텐션이 질의와 문서를 함께 읽지는 않으므로, 정확도는 대개 크로스 인코더에 조금 못 미친다.

갈림길

후기 상호작용은 두 자리에 놓을 수 있고, 그 자리가 이 글과 갈라지는 지점이다. 1단계 검색 자리에 두면 벡터 하나로 뭉개져 1단계에서 놓치던 문서를 건질 수 있다. 앞에서 본 재현율 상한 자체를 올리는 쪽이다. 대신 토큰마다 벡터를 저장하므로 색인이 몇 배로 커진다.

리랭커 자리에 두면 크로스 인코더와 같은 일을 한다. 후보 kk건의 토큰 벡터를 그때그때 계산해 순서를 바꾸므로 색인을 다시 만들 필요가 없고, 크로스 인코더보다 빠르다. 대신 정확도는 조금 내주고, 상한은 여전히 1단계의 recall@k다. 그러니 질문이 「순서가 틀린다」이면 크로스 인코더 리랭커가 먼저이고, 「정답이 목록에 아예 안 들어온다」이면 후기 상호작용을 1단계에 두는 쪽을 검토한다.

지연 예산

리랭킹이 들어간 RAG의 지연 예산

단계별 배분

지연 예산은 사용자가 기다려 줄 시간을 먼저 정하고 그것을 단계마다 나눠 주는 방식이다. RAG에서 사용자가 체감하는 것은 답이 다 나오는 시간보다 첫 글자가 뜨는 시간, 곧 첫 토큰 지연이다. 그리고 리랭킹은 그 첫 토큰 앞에 통째로 놓인다. LLM은 컨텍스트가 정해져야 생성을 시작할 수 있고, 컨텍스트는 리랭킹이 끝나야 정해지기 때문이다.

예를 들어 첫 토큰까지 1.5초를 목표로 잡았다고 하자. 질의 임베딩에 20밀리초, 벡터·키워드 검색에 50밀리초를 쓰고, LLM이 컨텍스트를 읽고 첫 토큰을 내는 데 1초가 걸린다면, 리랭킹과 네트워크 왕복에 쓸 수 있는 몫은 400밀리초 남짓이다. 이 몫이 kk와 모델 크기와 입력 길이를 한꺼번에 제약한다. 앞의 가정대로 짝 1,000개를 1초에 처리하는 모델이면 kk 50은 50밀리초로 여유가 넉넉하지만, 청크가 길어 처리량이 5분의 1로 떨어지면 같은 kk에 250밀리초가 되어 예산의 대부분을 먹는다.

예산을 넘으면 줄일 곳은 정해져 있다. kk를 재현율 곡선의 무릎까지 내리고, 청크를 리랭커 상한에 맞춰 짧게 자르고, 한 번의 호출에 짝을 모두 묶어 넣고, 그래도 모자라면 작은 리랭커로 바꾼다. 리랭커가 줄인 컨텍스트는 LLM이 읽을 양도 줄이므로, 리랭킹에 쓴 시간 일부가 생성 쪽에서 돌아오기도 한다. 50건을 LLM에 다 넘기던 구성이라면 5건으로 줄이는 것만으로 첫 토큰 지연이 오히려 짧아질 수 있다.

체감 지연

생성을 스트리밍으로 내보내면 답이 길어도 첫 문장부터 읽을 수 있어 체감 지연이 크게 준다. 그러나 스트리밍이 줄여 주는 것은 생성의 뒷부분뿐이다. 검색과 리랭킹은 첫 토큰 앞에 놓여 있어 스트리밍으로 가려지지 않는다. 리랭킹 100밀리초는 그대로 첫 토큰 100밀리초다.

그래서 체감을 줄이는 손질은 첫 토큰 앞쪽에 모인다. 검색이 시작됐다는 표시를 먼저 내보내 빈 화면을 없애고, 자주 오는 질의는 리랭킹 결과를 캐시해 두고, 대화형 서비스라면 사용자가 입력하는 동안 이전 질의로 검색을 미리 시작해 두기도 한다. 어느 것이든 리랭킹 자체를 빠르게 하는 것은 아니다. 리랭킹이 막는 자리가 첫 토큰 앞이라는 사실을 알고 그 앞을 채우는 일이다.

효과가 없는 경우

1단계 누락

리랭커를 붙였는데 최종 품질이 거의 안 오르는 경우, 가장 흔한 원인은 정답이 애초에 후보 kk건 안에 없는 것이다. 앞에서 본 재현율 상한이 낮은 상태다. recall@50이 0.6이면 리랭커가 할 수 있는 최선은 그 60% 안에서 정답을 맨 위로 올리는 것이고, 나머지 40%는 손도 대지 못한다.

이때 할 일은 리랭커가 아니라 1단계에 있다. 키워드 검색을 섞어 하이브리드로 가거나, 청크를 다시 자르거나, 임베딩 모델을 바꾸거나, 질의 자체를 손본다. 질의를 손보는 일은 따로 한 갈래를 이룰 만큼 방법이 많다.

비슷한 문서들

두 번째는 후보들이 서로 너무 닮은 경우다. 같은 규정의 2024년판과 2025년판, 한 문서를 조금씩 겹치게 자른 이웃 청크들, 복사해 붙인 FAQ처럼 내용이 거의 같은 문서가 상위를 채우면 리랭커 점수도 거의 같게 나온다. 그 사이의 순서는 점수의 작은 흔들림이 정하므로 사실상 무작위이고, 리랭커는 그 흔들림을 그럴듯한 순서로 포장할 뿐이다.

이런 차이는 문장의 뜻이 아니라 문서 바깥의 속성에 있다. 어느 판이 최신인지, 어느 부서 문서인지 같은 것은 리랭커가 본문만 읽어서는 알 수 없다. 날짜와 판 번호를 메타데이터로 달아 메타데이터 필터링으로 먼저 거르거나, 색인할 때 중복을 걷어내는 편이 맞다. 그리고 1단계 후보 수가 최종 건수와 같은 구성, 예를 들어 kk도 5이고 nn도 5인 구성에서는 리랭커가 바꿀 순서만 있고 떨어뜨릴 문서가 없다. 그럴 때는 리랭킹을 붙인 것이 아니라 지연만 붙인 것이다.

다음 단계

정리하면 리랭킹은 색인을 건드리지 않고 크로스 인코더 한 단계를 끼워 순서를 바로잡는 일이다. 바이인코더로 넓게 뽑고 크로스 인코더로 좁히는 2단계 구조가 계산량 차이에서 나오고, 후보 수는 재현율 곡선의 무릎에서, 모델은 한국어와 배포 방식과 길이 상한으로, 지연은 첫 토큰 앞의 몫으로 정한다. 그리고 리랭커가 넘을 수 없는 선이 하나 있다. 1단계가 데려오지 못한 문서는 살릴 수 없다는 것이다.

다음 글은 그 선의 바깥을 다룬다. 검색이 시작되기 전에 질의를 다른 표현으로 바꾸고, 여러 표현으로 늘리고, 하위 질문으로 쪼개고, 앞선 검색 결과를 읽고 다음 질의를 새로 만드는 방법들이다. 리랭킹이 가진 후보 안에서 고르는 일이라면, 질의 재작성은 가질 후보 자체를 바꾸는 일이다.


읽어주셔서 감사합니다. 😊

LATEST

에이전트·RAG의 최신 글

에이전트·RAG2026.08.23

에이전트는 어디서 어긋나기 시작하는가

에이전트가 이상한 답을 낼 때 증상은 마지막에 보이지만 어긋난 자리는 그보다 앞입니다. 한 걸음이 무너지는 여섯 자리를 나누고, 증상에서 원인을 거슬러 찾는 방법과 자리별 처방을 정리합니다.

11 MIN
에이전트·RAG2026.08.23

에이전트가 무엇을 했는지 나중에 알 수 있게 만들기

에이전트는 같은 입력에도 다른 경로로 갑니다. 그래서 로그 몇 줄로는 왜 그렇게 됐는지 복원이 안 됩니다. 트레이스를 어떻게 나누고 구간마다 무엇을 붙이며 어떤 지표를 볼지 정리합니다.

11 MIN
에이전트·RAG2026.08.23

에이전트 비용은 걸음 수보다 빨리 늘어난다

걸음이 두 배면 비용은 두 배가 아니라 서너 배입니다. 왜 그렇게 되는지, 어디서 새는지, 상한을 몇 겹으로 어떻게 거는지와 실제로 효과가 큰 순서대로의 대응을 정리합니다.

13 MIN