멀티벤더 AI 검증에서 모델 ID를 표시명으로 믿으면 안 되는 이유

여러 AI 모델을 교차 검증에 쓸 때 나는 검증 결과 파일을 열어 이름부터 확인했다. 파일 이름에 검증사 이름이 들어 있으면 "아, 이건 그 벤더가 봤구나" 하고 넘어갔다. 그런데 실제로 그 요청을 받은 모델은 설정에 적힌 것과 다른 모델이었다. 화면에는 맞는 이름이 떠 있었는데, 그 이름으로 일한 건 다른 존재였다.
발견한 계기는 사소했다. 검증 결과가 이상하게 관대하다는 느낌이 들어 로그를 열어봤을 뿐이다. 그런데 그 안에 "요청한 모델을 인식하지 못해 다른 모델로 대체한다"는 문구가 반복해서 찍혀 있었다. 세어 보니 수십 번이었다. 그동안 특정 벤더가 꼼꼼히 검증했다고 믿었던 결과들이, 실은 훨씬 가벼운 모델이 조용히 대신 처리한 결과였다.
설정 파일엔 분명 그 이름이 적혀 있었다
사건은 설정 파일에 모델 이름을 적어 넣는 아주 평범한 순간에서 시작됐다. 특정 벤더의 상위 모델을 쓰겠다고 슬러그(모델을 호출할 때 쓰는 정확한 내부 이름, Slug)를 하나 지정했다. 이름 뒤에 "-preview"라는 흔한 접미사가 하나 붙어 있었는데, 그 슬러그는 실제로는 존재하지 않는 이름이었다. 정식 출시되며 접미사가 빠졌는데 설정에는 예전 이름이 남아 있던 것이다.
문제는 이 잘못된 이름을 호출기가 그냥 튕겨내지 않았다는 데 있다. 존재하지 않는 슬러그를 요청받은 시스템은 에러를 내는 대신 알아서 더 가벼운 대체 모델로 넘어갔다. 화면과 결과 파일에는 여전히 원래 요청한 이름이 표시됐다. 실제로 일한 건 다른 모델인데, 기록에는 내가 지정한 이름이 그대로 남았다. 겉모습과 실체가 갈라지는 순간이었다.
더 나쁜 건 이 잘못된 이름이 한 곳에만 있지 않았다는 점이다. 설정은 보통 여러 곳에 복사된다. 로컬 설정 파일, 팀 공유 설정, 연동 도구의 기본값까지. 오타 하나가 원본에서 복제될 때마다 같이 퍼졌다. 나중에 세어 보니 여러 파일, 여러 곳에 같은 잘못된 이름이 박혀 있었다. 뿌리 하나를 못 뽑으면 가지 전부에서 같은 문제가 반복된다.
이름이 맞다는 것과 그 이름으로 실행됐다는 것은 다른 말이다
이 사고를 겪고 나서야 두 문장을 구분하게 됐다. "설정에 그 이름이 적혀 있다"와 "그 이름의 모델이 실제로 그 일을 했다"는 완전히 다른 주장이다. 앞 문장은 파일을 열어 보면 바로 확인된다. 뒤 문장은 호출이 실제로 어떻게 처리됐는지를 봐야만 안다. 나는 오랫동안 앞 문장이 참이면 뒤 문장도 저절로 참이라고 믿었다. 아니었다.
비유하면 이렇다. 식당에 예약할 때 "김 셰프님으로 부탁드립니다"라고 이름을 남겼다고 해서, 그 이름이 영수증에 찍혀 나온다고 해서, 실제로 김 셰프가 주방에서 그 요리를 만들었다는 보장은 없다. 주방이 바쁘면 다른 요리사가 대신 만들고 영수증 양식은 그대로 두는 식당도 있을 수 있다. 손님은 영수증만 보고 "역시 김 셰프 솜씨네"라고 믿는다. 맛이 평소와 다르다는 걸 눈치채지 못하면 그 믿음은 계속 유지된다.
교차 검증의 전제는 서로 다른 벤더가 서로 다른 관점으로 같은 결과물을 본다는 데 있다. 이 전제가 성립하려면 "내가 요청한 벤더가 실제로 그 검증을 수행했다"는 사실이 확실해야 한다. 그런데 표시명은 요청 시점의 의도만 보여줄 뿐, 실행 시점의 사실을 보증하지 않는다. 요청과 실행 사이에 조용한 대체가 끼어들면, 검증 결과에는 여전히 원하던 벤더의 이름이 붙어 있지만 실제로는 그 벤더가 검증하지 않은 것이 된다. 겉으로는 두 벤더가 교차 확인한 것처럼 보이는데 실제로는 한 벤더 안에서 끝난 셈이다.
표시명이 배신하는 세 가지 길목
같은 상황을 몇 번 더 겪으며 표시명과 실체가 갈라지는 지점이 대체로 세 군데로 반복된다는 걸 알았다.
첫 번째는 이름이 비슷한 슬러그다. 정식 이름과 미리보기(프리뷰) 이름처럼 철자 몇 글자만 다른 슬러그가 흔하다. 정식판이 나온 뒤에도 예전 미리보기 이름이 문서나 설정에 남아 있는 경우가 많다. 둘 다 그럴듯해 보이니 사람 눈으로는 구분이 잘 안 된다.
두 번째는 설정이 여러 곳에 흩어져 있는 구조다. 같은 값이 로컬 설정·공유 설정·연동 도구 기본값처럼 여러 파일에 중복 저장되면, 하나를 고쳐도 나머지가 안 고쳐진 채 남는다. 겉으로는 "고쳤다"고 생각하지만 실제 호출은 여전히 안 고쳐진 사본을 타고 나간다.
세 번째가 제일 조용하다. 알 수 없는 이름을 만났을 때 시스템이 에러 대신 알아서 대체 모델로 넘어가는 동작이다. 이게 편의 기능처럼 보이지만 검증 맥락에서는 함정이다. 에러가 났다면 바로 알아챘을 텐데, 대체가 조용히 일어나면 화면상 아무 이상 신호가 없다. 결과가 나오고, 이름표도 맞고, 다 정상으로 보인다. 실은 그 결과를 만든 게 내가 생각한 모델이 아니었을 뿐이다.
수십 번, 로그에만 남아 있던 증거
이 문제를 잡아낸 방법은 특별하지 않았다. 검증 결과가 지나치게 후하다는 감이 먼저 왔고, 그다음 호출 로그를 처음부터 끝까지 훑었다. 검증 도구가 남기는 실행 로그 안에 "요청한 모델 이름을 인식하지 못해 기본 모델로 대체한다"는 문구가 반복돼 있었다. 하나둘이 아니라 수십 번이었다.
이 숫자가 의미하는 바는 이렇다. 그 잘못된 설정이 살아 있던 기간 동안 그 벤더로 보낸 요청 상당수가 실제로는 더 가벼운 대체 모델의 응답이었다는 뜻이다. 그런데 결과 파일이나 화면에는 원래 지정했던 벤더·모델 이름이 그대로 찍혀 있었다. 검증 통과 기록만 보면 "상위 모델이 확인했다"고 읽히지만, 로그를 보면 "대체 모델이 확인했다"가 진실이었다.
고친 방법은 간단했다. 잘못된 슬러그를 정확한 이름으로 전부 바꾸고, 실제로 그 이름이 응답하는지 살아있는 호출로 한 번 더 확인했다. 파일을 몇 개 고쳤다고 끝내지 않고, 진짜 그 모델이 응답 코드를 정상으로 돌려주는지까지 실측했다. 표시명을 고치는 것과 그 표시명이 실제로 작동하는지 확인하는 것, 이 둘도 서로 다른 일이었다.
표시명 대신 무엇을 봐야 하나
이 사건 이후로 표시명을 완전히 안 믿지는 않되, 표시명만으로 끝내지 않는 습관을 들였다. 표시명이 참인지 확인할 수 있는 실제 호출 근거는 몇 가지로 정리된다.
| 확인 대상 | 믿으면 안 되는 것 | 대신 봐야 하는 것 |
|---|---|---|
| 어떤 모델이 검증했나 | 결과 파일·화면에 표시된 이름 | 실행 로그에 남은 실제 호출 모델 값 |
| 요청이 성공했나 | 에러가 안 났다는 사실 | 대체·폴백 발생 여부를 알리는 로그 문구 |
| 설정이 다 고쳐졌나 | 원본 설정 파일 하나만 확인 | 실제로 쓰이는 모든 사본·미러 파일 전수 확인 |
| 지금도 맞게 동작하나 | 과거에 한 번 확인했다는 기록 | 지금 시점에 다시 실행해 본 결과(재현 가능한 호출) |
| 두 벤더가 정말 다른가 | 결과 파일 이름에 벤더명이 들어 있다는 것 | 각 결과가 서로 다른 실행 로그·응답 근거에서 나왔는지 |
핵심은 한 문장으로 줄일 수 있다. 판정은 자기 보고가 아니라 실행 증거로 내린다. 모델 스스로 "저는 A입니다"라고 말하는 것도, 설정 파일에 A라고 적혀 있는 것도 자기 보고에 가깝다. 진짜 증거는 그 요청이 실제로 어떤 응답 경로를 탔는지 보여주는 로그, 혹은 지금 다시 호출해서 확인한 결과다.
이건 작성자와 다른 벤더가 검증해야 한다는 원칙과 맞닿아 있다. 그 원칙이 성립하려면 "정말 다른 벤더가 봤다"는 사실 자체가 참이어야 하는데, 표시명만 믿으면 그 전제가 조용히 무너질 수 있다. 벤더를 나누는 규칙을 아무리 잘 세워도, 그 규칙이 가리키는 이름이 실제 호출과 일치하는지 별도로 확인하지 않으면 규칙은 종이 위에서만 유효하다.
재발 방지 체크리스트
- 모델 슬러그를 설정에 적을 때, 자동완성이나 기억이 아니라 공식 목록에서 정확한 철자를 복사했는가.
- 같은 설정값이 저장된 모든 사본·미러 파일을 한 번에 나열하고 전부 확인했는가(원본 하나만 고치고 끝내지 않았는가).
- 모델 이름을 인식 못 했을 때 조용히 다른 모델로 넘어가는지, 아니면 명확한 에러를 내는지 알고 있는가.
- 검증 결과를 신뢰하기 전에 실행 로그에서 "대체·폴백·인식 실패" 같은 문구를 검색해 봤는가.
- 결과 파일 이름에 벤더명이 들어 있다는 것과 실제로 그 벤더가 호출됐다는 것을 같은 것으로 취급하지 않았는가.
- 중요한 설정 변경 뒤에는 문서 수정에서 끝내지 않고, 실제로 살아있는 호출 한 번으로 재확인했는가.
표시명은 의도를 보여줄 뿐 사실을 증명하지 않는다. 설정 파일에 원하는 이름을 적어 넣는 일과 그 이름의 모델이 실제로 응답하는 일 사이에는, 조용히 대체가 끼어들 틈이 늘 있다. 다음에 검증 결과를 볼 때는 파일 이름부터 안심하지 말고 로그부터 열어 보길 권한다.
설정 수정부터 실행 증거까지 재현하는 순서
문제를 다시 확인할 때는 먼저 잘못된 슬러그가 어디에 남았는지 검색하고, 그다음 새 호출의 로그를 본다. 두 단계를 거꾸로 하면 새 설정이 아니라 고치지 않은 다른 사본을 호출해 놓고도 원인을 놓칠 수 있다. 아래 명령의 OLD_MODEL_SLUG와 NEW_MODEL_SLUG는 실제 설정에 있던 문자열로 바꾸고, 검색 결과를 하나씩 설정 원본·공유 사본·문서 예시·생성된 캐시로 분류한다.
rg -n --hidden 'OLD_MODEL_SLUG' .
rg -n --hidden 'NEW_MODEL_SLUG' .
rg -n -i 'fallback|substitut|unknown model|unrecognized|not found' LOG_DIRECTORY
첫 명령의 결과가 비어 있어야 이전 이름이 저장소 안에 남지 않았다고 말할 수 있다. 다만 숨김 파일과 저장소 밖의 사용자 설정, 연동 도구가 별도로 관리하는 기본값은 현재 디렉터리 검색에 잡히지 않을 수 있다. 그러므로 검색 범위가 실제 호출기가 읽는 모든 위치를 포함하는지 먼저 확인한다. 두 번째 명령은 새 이름의 위치를 보여 줄 뿐 그 이름이 유효하다는 증거는 아니다. 세 번째 명령의 단어도 제품마다 다르므로, 실제로 관찰했던 대체·인식 실패 문구가 있다면 그 문구를 그대로 추가해 검색한다.
- 기존 실패 로그에서 요청한 슬러그, 실제 처리 모델, 대체를 알린 문구를 한 요청 단위로 묶는다. 서로 다른 실행의 줄을 합쳐 하나의 증거처럼 만들지 않는다.
- 잘못된 슬러그를 참조하는 위치를 전부 나열하고, 실제 호출 설정과 설명용 문서 또는 오래된 로그를 구분한다. 과거 로그의 문자열까지 고쳐 쓰면 사고 기록이 사라지므로 실행 설정만 수정한다.
- 수정 뒤 이전 슬러그를 다시 검색한다. 남은 결과가 의도적으로 보존한 과거 기록이라면 왜 남겼는지 구분할 수 있게 한다.
- 같은 검증 입력으로 살아 있는 호출을 한 번 실행한다. 이 호출에서 요청이 성공했다는 사실과 실제 모델 값, 대체 경고가 없다는 사실을 함께 확인한다.
- 결과 파일과 호출 로그를 같은 실행 식별 기준으로 연결한다. 시간만 비슷한 두 파일을 짝짓지 말고 한 요청에서 나온 것인지 확인한다.
| 관찰 결과 | 판정 | 다음 확인 |
|---|---|---|
| 새 슬러그 호출이 명확한 오류로 끝남 | 이름 또는 접근 조건이 아직 맞지 않음 | 결과 파일을 검증 증거로 쓰지 않고 설정 출처 재확인 |
| 응답은 성공했지만 대체 문구가 있음 | 요청 성공, 모델 일치 실패 | 실제 처리 모델과 대체 원인을 확인 |
| 대체 문구는 없지만 실제 모델 값도 없음 | 증거 부족 | 로그 수준과 응답 메타데이터에서 식별 근거 확보 |
| 실제 모델 값이 요청과 일치하고 대체 문구 없음 | 해당 호출의 일치 근거 확보 | 결과 파일이 바로 그 호출에서 나왔는지 연결 확인 |
여기서 가장 흔한 오해는 오류가 없으면 검증도 끝났다고 보는 것이다. 원래 사고도 오류 대신 조용한 대체가 일어났기 때문에 오래 숨었다. 반대로 로그에서 실제 모델 값을 찾지 못했다고 곧바로 다른 모델이 실행됐다고 단정해서도 안 된다. 그 경우의 판정은 불일치가 아니라 증거 부족이다. 확인할 수 없는 결과를 특정 벤더의 독립 검증으로 세지 않는 것이 안전한 처리다.
살아 있는 호출 한 번의 성공도 영구 보증은 아니다. 설정 사본이 다시 덮어쓰이거나 호출 경로가 바뀌면 같은 문제가 돌아올 수 있다. 그래서 수정 증거는 "새 이름이 파일에 있음"에서 끝나지 않고, "이전 이름 전수 검색", "실제 호출", "대체 경고 확인", "결과와 로그 연결"의 네 조각으로 남겨야 한다. 이 네 조각 중 빠진 것이 있으면 무엇을 확인했고 무엇은 아직 추정인지 구분해 적는다.
자주 묻는 질문
결과 파일에 벤더명이 있으면 교차 검증이 성립한 것 아닌가요?
아니다. 파일명과 표시명은 요청할 때의 의도만 보여 준다. 알 수 없는 슬러그가 조용히 대체 모델로 넘어갈 수 있으므로, 각 결과가 서로 다른 실행 로그와 실제 응답 근거에서 나왔는지 확인해야 한다.
모델 슬러그 하나를 고쳤는데도 문제가 계속될 수 있나요?
그럴 수 있다. 같은 값이 로컬 설정, 팀 공유 설정, 연동 도구 기본값처럼 여러 사본에 퍼져 있으면 고치지 않은 사본으로 호출이 나간다. 실제로 쓰이는 모든 설정과 미러 파일을 전수 확인해야 한다.
요청이 에러 없이 끝났다면 원하는 모델이 실행됐다고 봐도 되나요?
그렇게 볼 수 없다. 존재하지 않는 슬러그를 시스템이 거부하지 않고 더 가벼운 모델로 대체할 수 있다. 성공 여부만 보지 말고 실행 로그에서 대체·폴백·인식 실패 문구와 실제 호출 모델 값을 확인해야 한다.
설정을 수정한 뒤 어떤 증거로 재확인해야 하나요?
정확한 슬러그로 모든 사본을 고친 뒤, 문서와 표시명만 확인하지 말고 살아 있는 호출을 다시 실행한다. 정상 응답과 실행 로그의 실제 모델 값을 함께 봐야 수정이 호출 경로까지 반영됐는지 알 수 있다.
아직 댓글이 없습니다.