2편에서 만든 멀티턴 검색을 실제 질문으로 재봤더니 기존 검색보다 느리고 정확도도 낮았습니다. 구조를 되돌리기 직전에 실행 기록을 열어봤고, 평가가 비어 있는 그래프를 조회한 뒤 사실상 벡터 검색만으로 답하고 있었다는 것을 찾았습니다. 그래프를 제대로 연결하고 다시 잰 결과와, 그 결과가 검색 구조를 어떻게 바꿨는지 정리합니다.
구조를 되돌리기 직전에 실행 기록을 열어봤습니다
멀티턴 검색의 목표는 도구를 여러 번 부르는 데 있지 않았습니다. 관계와 목록, 집계 질문에서 벡터 검색보다 넓은 근거를 찾되 단순 사실 질문까지 느리게 만들지 않는 것이었습니다.
첫 A/B 결과는 분명했습니다. 멀티턴이 더 느리고 정확도도 낮았습니다.
숫자가 명확하니 되돌리면 되는 상황이었습니다. 그 전에 실행 기록을 따라가 봤습니다.
평가 하네스가 표시 이름을 그래프 식별자로 사용하고 있었습니다. 요청은 정상적으로 나갔고, 존재하지만 비어 있는 그래프를 조회했고, 답변은 벡터 검색만으로 만들어졌습니다.
평가가 측정한 것 그래프 조회 실패 후 벡터 검색으로 답한 실행
평가가 붙인 이름 "그래프 검색"
두 구성의 차이를 잰 것이 아니라, 같은 벡터 검색에 그래프 조회 왕복을 얹은 비용을 잰 것이었습니다. 느린 것도 당연했고 정확도가 같은 수준인 것도 당연했습니다.
이 결과는 폐기했습니다. 4편에서 옵션이 켜진 것을 사용 증거로 보지 않기로 했는데, 평가 하네스는 여전히 그렇게 하고 있었습니다.
그래서 그래프 검색으로 인정할 조건을 네 가지로 못 박았습니다.
평가 대상 컬렉션이 실제 그래프 식별자와 연결돼 있는가
그래프에 트리플이 존재하는가
그래프 도구가 호출됐는가
반환된 관계가 합성 입력에 포함됐는가
측정 결과가 기대와 반대로 나왔을 때 구조를 되돌리기 전에 계측을 먼저 의심해볼 만합니다. 특히 결과가 너무 깔끔하게 한쪽 손을 들어줄 때 그렇습니다. 잘못 연결된 실험은 대체로 아주 선명한 답을 냅니다.
라벨 검색도 전체 문자열 스캔에서 색인 기반 조회로 바꿨습니다. 아래 수치는 그 색인과 데이터셋 구성을 별도로 준비한 격리 환경의 결과입니다. 배포 환경에 같은 구성이 없으면 재현되지 않습니다. 그래프 기능을 켠 상태와 운영 가능한 검색 경로는 같은 말이 아닙니다.
다시 재보니 그래프의 기여가 질문 유형마다 달랐습니다
그래프가 실제로 연결된 상태에서 고정 질문 100개를 비교했습니다. 같은 질문, 답변 모델, 벡터 근거, 시간 예산과 판정 기준을 쓰고 그래프 근거의 사용 여부만 바꿨습니다.
새 검색 구성의 정답성은 0.465, 기존 구성은 0.230이었고 완전 정답은 각각 34개와 13개였습니다. 해당 평가 조건의 결과이지 일반적인 제품 성능 보장은 아닙니다.
더 중요한 것은 유형별로 나눈 결과였습니다.
| 질문 유형 | 벡터만 | 벡터 + 그래프 | 해석 |
|---|---|---|---|
| 집계·전체 나열 | 0.033 | 0.683 | 클래스의 전체 개체 집합이 필요함 |
| 관계형 조회 | 0.292 | 0.521 | 주어와 술어를 함께 제한한 탐색이 유효함 |
| 단일 사실 | 약 0.46 | 약 0.47 | 의미가 가까운 원문 검색만으로 충분함 |
그래프는 모든 질문에서 벡터 검색을 대체하지 않았습니다. 답이 연결 구조나 집합 자체인 질문에서만 차이를 만들었습니다.
단일 사실 질문에서는 그래프 탐색을 더해도 이득이 사실상 없었습니다. 2편에서 단일 사실 질문까지 여러 턴을 쓰는 것이 문제였다고 적었는데, 그것이 숫자로 확인된 셈입니다.
전체 평균 하나만 봤다면 "그래프를 붙이니 0.230에서 0.465가 됐다"로 끝났을 것입니다. 그 문장은 맞지만 다음에 무엇을 할지는 알려주지 않습니다. 유형별로 나누고 나서야 어디에 루프가 필요 없는지가 보였습니다.
질문을 분류하는 대신 네 경로를 함께 돌렸습니다
질문 유형마다 필요한 것이 다르다면 질문을 먼저 분류하면 될 것 같습니다.
그 앞에 LLM 분류기를 두면 오분류가 새로운 실패 지점이 됩니다. 집계 질문을 단일 사실로 잘못 분류하면 그 질문은 그래프를 아예 못 봅니다.
그래서 분류하지 않기로 했습니다. 비용이 제한된 검색 경로를 병렬로 실행하고, 구조 신호가 없는 경로는 빈 결과를 반환하게 했습니다.
벡터 원문 검색 ─────────────┐
라벨·이웃 연결성 검색 ──────┤
클래스 전체 집합 조회 ──────┼─→ 근거 정렬 ─→ 답변 합성 1회
주어·술어 정밀 관계 조회 ───┘
클래스 조회는 질문 용어가 실제 클래스 라벨로 해소될 때만 실행합니다. 관계 조회는 질문의 관계어가 그래프의 술어 라벨과 맞을 때 주어 후보와 술어를 함께 제한합니다.
단어 목록을 프롬프트에 적어두지 않았습니다. 현재 그래프의 클래스와 술어가 그대로 게이트 역할을 합니다. 그래프가 바뀌면 게이트도 따라 바뀝니다.
합성은 한 번만 합니다. 루프가 "근거가 충분한가"를 반복 판단하게 두지 않고, 각 검색기가 맡은 연산을 결정적으로 수행한 뒤 합성기가 모인 근거로 답을 만듭니다.
클래스 전체 목록은 합성 입력의 앞쪽에 두고 출력 예산도 따로 확보했습니다. "모두"라는 요구가 요약 과정에서 잘리지 않게 하기 위해서입니다. 2편에서 절단이 근거를 지웠던 문제에 대한 대응이기도 합니다.
분기가 필요해 보일 때 분류기를 앞에 두는 것이 자연스럽습니다. 분류가 틀렸을 때의 비용이 크다면, 분류하지 않고 여러 경로를 싸게 돌린 뒤 신호가 있는 것만 쓰는 편이 나을 수 있습니다.
정확한 질의가 느린 질의는 아니었습니다
정밀 관계 조회의 첫 구현은 술어 전체를 훑었습니다. 정확했고 모든 질문에서 느렸습니다.
정확도와 속도를 맞바꿔야 하는 상황처럼 보였습니다. 실제로는 질의 계획의 순서 문제였습니다.
엔티티를 먼저 색인으로 바인딩하고, 그 주변에서 매칭된 술어만 검사하도록 순서를 바꿨습니다. 식별자 문자열을 직접 조합하지 않아 괄호와 공백이 있는 식별자도 안전하게 처리됩니다.
관계형 점수가 0.292에서 0.521로 올라갔고 단일 사실 질문의 속도도 유지됐습니다. 최종 구성은 모든 질문을 한 턴에 처리했고, 해당 평가에서 중앙값 약 2.4초, 요청의 95%가 4.1초 안에 끝났습니다.
정확도와 속도가 함께 좋아졌다는 것은 대체로 앞의 구현이 트레이드오프가 아니었다는 뜻입니다. 둘 중 하나를 포기하기 전에 계획의 순서를 먼저 볼 만합니다.
멀티턴이 틀렸던 것이 아니라 역할이 끝난 것이었습니다
측정 결과로 저희가 한 일은 2편의 구조를 걷어낸 것입니다. 검증한 기능 경로에서 멀티턴 루프를 제거하고 병렬 검색과 단일 합성을 남겼습니다.
그렇다고 멀티턴이 잘못된 아이디어였던 것은 아닙니다.
관계 검색의 도구와 탐색 경로를 빠르게 확장하는 데 필요했습니다. 어떤 도구가 필요한지, 어떤 순서로 부르면 답이 나오는지를 모델이 매 질문마다 탐색하면서 알려줬습니다.
색인과 클래스 집합, 정밀 관계 질의가 갖춰지자 모델이 매번 도구 순서를 다시 발견할 이유가 줄었습니다. 발견해야 할 것이 이미 코드에 들어왔기 때문입니다.
그러니까 멀티턴은 최종 구조가 아니라 최종 구조를 찾기 위한 도구였습니다. 탐색적인 구조를 먼저 만들고 거기서 배운 것을 결정적인 경로로 굳히는 순서였고, 되돌아보면 그 순서를 바꿀 수는 없었을 것 같습니다.
이 시점의 결과는 기능 브랜치와 격리 환경 검증이며 운영 배포 완료를 뜻하지 않습니다.
검색 구조를 정리한 다음에는 화면 쪽이 남았습니다. 답이 어디서 왔는지 보여주는 강조 기능인데, 다음 편에서는 그 강조가 실제 근거보다 훨씬 많은 노드를 칠하고 있었다는 이야기를 다룹니다.

