지난 글에서 모델을 부르기 전에 거르는 층을 봤다. 이번에는 반대편이다. 답이 이미 만들어졌고, 그 답이 사용자 화면이나 다른 시스템으로 나가기 직전의 자리다. 출력 가드는 모델이 내놓은 답을 내보내기 전에 한 번 더 검사해 통과·수정·차단을 정하는 층이다.
이 층에는 입력 가드에 없는 조건이 두 개 붙는다. 첫째, 검사할 대상이 이미 존재한다. 입력 가드는 "이 요청이 나중에 무엇을 만들어 낼까"를 추측해야 하지만 출력 가드는 나온 것을 보고 판정한다. 같은 노력을 들여도 정확도가 훨씬 높다. 둘째, 여기서 쓰는 시간은 전부 사용자 대기 시간이다. 입력 가드의 30밀리초는 모델이 답을 만드는 몇 초 앞에 묻히지만, 출력 가드의 300밀리초는 답이 다 나온 뒤에 붙는 순수한 추가 지연이다. 그리고 스트리밍을 쓰고 있다면 애초에 검사할 완성된 답이 존재하지 않는다.
이 두 조건이 출력 가드 설계의 거의 전부를 결정한다. 정확도를 살 수 있으니 어려운 판정을 여기 두고 싶어지지만, 정확히 그 판정이 사용자를 기다리게 한다. 아래는 그 사이에서 무엇을 어디에 두는지에 대한 이야기다.
출력 가드의 몫
입력 가드와의 분업
출력 가드가 왜 따로 필요한지는 한 문장으로 말할 수 있다. 요청이 멀쩡해도 답은 잘못 나온다.
"작년 3분기 매출이 얼마였나요"는 어느 기준으로 봐도 정상 질문이다. 입력 가드는 이 요청을 막을 근거가 없고 막아서도 안 된다. 그런데 검색이 자료를 못 찾았을 때 모델은 "잘 모르겠습니다" 대신 그럴듯한 숫자를 적어 넣는 일이 잦다. "환불 규정을 알려 주세요"도 마찬가지다. 약관에 없는 예외 조항이 답에 섞여 나가면 그것은 회사가 한 약속이 된다. 요청만 놓고는 어느 쪽도 판별할 방법이 없다.
반대 방향의 실수도 있다. 입력에서 잡아야 할 것을 출력에서 잡으려 드는 경우다. 금지된 요청인 줄 알면서 일단 모델을 부르고 나온 답을 보고 막으면, 막기는 막지만 토큰과 시간은 이미 다 썼다. 여기서 쓰는 원칙은 단순하다 — 요청의 성질만으로 판별되는 것은 입력에서, 답의 내용을 봐야만 판별되는 것은 출력에서 본다.
누출의 세 갈래
출력에서만 잡히는 문제는 셋으로 갈린다.
사실 오류는 근거에 없는 내용이 답에 들어간 것이다. 지어낸 수치, 존재하지 않는 조항, 원문에 없는 인과 설명이 여기 속한다. 근거 문서와 대조해야만 알 수 있다.
정보 노출은 나가면 안 되는 것이 답에 섞인 것이다. 다른 사용자의 데이터, 시스템 프롬프트 내용, 내부 식별자, 아직 공개되지 않은 정책이 여기 속한다. 이건 공격을 받아서만 생기는 것이 아니다. 검색 결과에 남의 문서가 한 건 섞여 들어오면 모델은 그것이 남의 것인지 알 방법이 없다. 데이터 경계가 무너진 자리를 마지막으로 잡는 그물이 출력 가드다.
정책 위반은 답의 내용이 우리가 정한 선을 넘은 것이다. 금지 표현, 부적절한 어조, 자격 없이 하는 의료·법률·투자 조언이 여기 속한다. 판단이 필요한 자리라 규칙만으로는 잘 안 잡힌다.
셋은 잡는 방법이 다르고, 잡혔을 때 할 일도 다르다. 하나의 "출력 검사"로 뭉뚱그리면 세 종류가 한 임계값을 공유하게 되고, 그러면 사실 오류를 더 잡으려 조인 순간 정상 답변까지 함께 막힌다.
두 층의 경계
두 층이 겹치는지 확인하는 실무 방법이 하나 있다. 검사 목록을 한 장에 적고 항목마다 「입력만·출력만·양쪽」을 적어 보는 것이다. 양쪽에 적은 항목은 그 옆에 이유를 한 줄 쓴다. 대부분은 이유를 못 적고 한쪽으로 정리된다.
실제로 양쪽에 남는 것은 금지어 목록 정도이고, 그것도 목적이 다르다. 입력의 금지어는 요청 자체를 거절하는 근거이고 출력의 금지어는 답에 섞여 나온 표현을 지우는 근거다. 같은 목록을 쓰더라도 걸렸을 때의 동작이 다르므로 두 벌로 두는 편이 낫다. 이렇게 정리해 두지 않으면 같은 검사가 두 곳에서 돌면서 지연만 두 배가 되고, 어느 층이 잡았는지 로그를 봐도 알 수 없게 된다.
형식 검사
스키마와 열거값
형식 검사가 가장 값싸고 가장 확실하다. 스키마에 맞는가, 열거값이 정해 둔 집합 안인가, 숫자가 허용 범위 안인가. 판정이 참·거짓으로 딱 갈리고 모델 호출이 필요 없으며 대개 밀리초 단위로 끝난다.
값싸다는 이유로 가볍게 보기 쉬운데, 실제 사고의 상당 부분이 여기서 걸린다. 도구를 부르는 응답이 인자 하나를 빠뜨렸다거나, 상태값에 pending 대신 Pending이 들어왔다거나, 확률 값이 1.4로 나오는 식이다. 구조화 출력을 어떻게 강제하고 검사할지 자체를 다루는 이야기는 형태는 맞는데 값이 틀릴 때에 따로 정리해 두었다.
참조 무결성
형식 검사에 하나 더 붙일 것이 있는데 자주 빠진다. 참조 무결성은 답에 나온 식별자가 실제로 존재하는 값인지 확인하는 검사다. 모델이 돌려준 document_id, order_id, 도구 이름, 사번을 데이터베이스나 목록에 한 번 조회해 보면 된다.
왜 이게 필요한지는 모델이 무엇을 배웠는지를 보면 알 수 있다. 모델은 식별자의 생김새를 배우지 값을 외우지 않는다. 여덟 자리 주문번호를 요구하면 여덟 자리 숫자를 만들어 낸다. 스키마 검사는 이걸 통과시킨다 — 형태가 완벽하기 때문이다. 그럴듯할수록 더 위험한 유형인데, 조회 한 번이면 100% 잡힌다.
여기에 짝으로 붙는 검사가 하나 더 있다. 권한 대조는 존재하는 식별자가 이 요청자에게 보여도 되는 것인지 확인하는 검사다. 답에 인용된 문서 id를 요청자의 권한으로 다시 조회해 보고, 안 나오면 그 인용을 뺀다. 앞에서 말한 정보 노출의 상당 부분이 이 한 줄에서 걸린다.
재생성 상한
형식 오류에는 재생성이 잘 듣는다. 검증기가 뱉은 오류 메시지를 그대로 붙여 다시 시키면 대부분 한 번에 고쳐진다. 스키마 위반은 모델이 몰라서 틀린 것이 아니라 놓친 것인 경우가 많기 때문이다.
문제는 상한을 안 두는 것이다. 모델이 같은 오류를 반복하는 상황에서 무한히 다시 부르면 지연과 비용이 함께 튄다. 한 번 호출이 2초 걸리고 요청당 30원이라고 하면, 상한 없는 재시도 열 번은 그 요청 하나를 20초·300원짜리로 만든다. 이런 요청이 동시에 수십 건이면 큐가 밀리고 그때부터는 정상 요청까지 느려진다. 2회까지 시도하고 그다음은 폴백이 실무의 기본값이다.
그리고 재시도가 같은 결과를 만드는 함정이 있다. 온도가 0에 가깝고 프롬프트가 그대로면 재생성은 방금과 같은 답을 낸다. 다시 시킬 때는 오류 정보를 프롬프트에 더하거나 온도를 조금 올려서, 입력이 달라졌음을 보장한 뒤에 부른다. 이걸 안 하면 재시도 2회가 그냥 비용 3배다.
근거 대조
문장 단위 유사도
근거 대조는 답에 적힌 내용이 실제로 근거 문서에 있는지 맞춰 보는 검사다. 검색 결과를 요약하거나 인용하는 기능에서는 이것이 핵심이다.
완전 일치를 요구하면 안 된다. 요약하면서 어순을 바꾸거나 두 문장을 합치는 것은 정상 동작인데 그것까지 전부 걸린다. 답을 문장 단위로 쪼개고 문장마다 근거 문서와의 유사도를 재서, 임계값 아래인 문장만 문제 삼는 방식이 무난하다. 임계값은 추측으로 정하지 말고, 정상 답변 서른 건과 지어낸 답 서른 건의 점수 분포를 그려 놓고 둘이 갈리는 자리를 고른다.
한국어에서는 문장 쪼개기 자체가 한 번 걸린다. 마침표는 소수점에도 붙고 약어에도 붙으므로 마침표만으로 자르면 「3.5% 인상」이 두 문장이 된다. 이 단계가 틀리면 뒤의 유사도는 볼 필요도 없다.
한계도 분명히 적어 둘 필요가 있다. 근거 대조는 "근거에 있는가"만 본다. 검색이 엉뚱한 문서를 물어 왔고 모델이 그 문서를 충실히 요약했다면 이 검사는 통과시킨다. 답은 틀렸는데 가드는 초록불이다. 이건 검색 품질의 문제이지 가드의 문제가 아니므로, 두 문제를 섞으면 고칠 곳을 두고 임계값만 계속 만지게 된다.
수치 대조
숫자는 따로 다루는 편이 낫다. 답에 나온 수치를 정규식으로 뽑아 근거 문서의 수치와 대조하는 검사인데, 값싼 것에 비해 잡히는 오류가 의외로 많다. 문장 유사도만으로는 「매출이 120억 원」과 「매출이 210억 원」이 거의 같은 점수를 받기 때문이다. 숫자 하나만 다른 문장은 유사도가 가장 잘 속는 자리다.
물론 이 검사도 못 잡는 것이 있다. 「3분기 매출 120억」이라고 썼는데 근거는 「3분기 누적 120억」이라면 숫자는 맞고 뜻이 다르다. 수치 대조는 값이 어디서 왔는지까지는 못 보므로, 여기서 통과한 것이 사실이라는 뜻은 아니다.
거꾸로 가장 흔한 오작동은 정규식으로 사실을 확인하려 드는 것이다. 「숫자가 들어 있으면 의심」 같은 규칙을 붙이면 정상 답변의 절반이 걸린다. 형식은 정규식으로, 사실은 대조로 검사한다. 이 선을 넘는 순간 오탐이 쌓이고, 오탐이 쌓이면 운영자가 검사를 꺼 버린다.
판정 비용 조정
정책이나 규정처럼 규칙으로 안 되는 것은 판정 모델에 맡긴다. 답과 기준을 함께 주고 위반인지 물어보는, 채점자 역할의 모델 호출이다. 문제는 값이다. 전체 요청에 판정 모델을 붙이면 비용이 두 배 가까이 될 수 있다.
게다가 검사가 생성보다 비싸지는 지점이 있다. 답이 300토큰이어도 그 답을 검사하려면 근거 문서 8,000토큰을 판정 모델에 다시 넣어야 한다. 이러면 검사 쪽 입력이 생성 쪽 입력보다 크다. 검사 하나를 붙였는데 비용이 두 배가 아니라 세 배가 되는 자리가 여기다.
조정 방법은 셋이고, 실무에서는 대개 셋을 함께 쓴다.
위험도로 나눈다. 도구를 부르거나 외부로 나가는 답은 전량 검사하고, 읽기 전용 요약은 표본만 본다. 신호로 나눈다. 값싼 검사가 애매하다고 표시한 것만 위로 올린다 — 근거 유사도가 임계값 근처인 문장이 있을 때만 판정 모델을 부르는 식이다. 작은 모델을 쓴다. 「이 문장이 이 근거에 있는가」는 답을 만드는 일보다 쉬운 작업이라 최상위 모델이 필요한 경우가 드물다.
셋을 합치면 판정 모델 호출은 대개 전체 요청의 5~15% 수준으로 떨어진다. 남는 85%는 값싼 검사만 지나가므로 지연도 함께 줄어든다.
정책 검사
민감정보와 금지 표현
정책 검사는 답에 개인정보가 섞였는지, 쓰면 안 되는 표현이 들어갔는지, 어조가 서비스에 맞는지를 본다. 개인정보와 금지어처럼 모양이 정해진 것은 패턴으로 잡히고, 어조나 조언의 성격처럼 판단이 필요한 것은 분류기나 판정 모델이 필요하다.
한 가지는 미리 정해 두는 편이 낫다. 개인정보는 출력에서 지우는 것이 최선이 아니다. 답에 이미 들어온 것을 지우는 것보다, 애초에 그 값이 모델에 들어가지 않게 하는 쪽이 확실하다. 출력의 마스킹은 앞 단계가 놓친 것을 받는 마지막 그물로 두고, 그것에 의존하지 않는다.
규정 일관성
가장 어려운 검사는 「이 안내가 우리 약관과 어긋나지 않는가」다. 판정 모델도 여기서 자주 틀린다.
어려운 이유가 있다. 규정 위반은 대개 틀린 문장이 있어서가 아니라 있어야 할 문장이 빠져서 생긴다. 「30일 안에 환불 가능합니다」는 그 자체로 틀린 말이 아니다. 「미개봉 상태에 한해」가 빠져서 틀린 것이다. 있는 것을 대조하는 검사와 빠진 것을 찾는 검사는 난이도가 다르고, 빠진 것을 찾으려면 그 답이 다뤄야 할 항목의 목록이 먼저 있어야 한다.
그래서 이 검사는 실무에서 두 갈래로 쪼갠다. 답이 특정 주제를 건드렸을 때 반드시 함께 나와야 하는 필수 문구 목록은 규칙으로 검사하고, 그 밖의 어긋남만 판정 모델에 맡긴다. 목록으로 내려오는 것을 최대한 내려 보내고 나면 판정 모델이 다룰 몫은 생각보다 작다.
표본 검사
그러고도 남는 규정 판단은 전량이 아니라 표본으로 돌린다. 그리고 걸린 것은 자동으로 고치지 말고 사람에게 보낸다. 규정 판단을 모델이 고치게 두면 틀린 판정으로 멀쩡한 안내를 망가뜨리는 경우가 생기고, 그건 안 고친 것보다 나쁘다.
표본에는 부수 효과가 하나 있다. 표본에서 나온 위반율이 그 기능의 실제 위반율 추정치가 된다. 하루 100건을 봐서 3건이 걸렸다면 전체에서도 대략 3% 근처라고 볼 수 있고, 이 숫자가 다음 달에 5%로 올랐다면 프롬프트나 문서 쪽에서 무언가 바뀐 것이다. 전량 검사를 못 하는 자리에서 표본은 방어이면서 계측이다.
사람 큐를 둘 때 반드시 함께 정할 것은 큐가 밀렸을 때의 동작이다. 검토 대기 중인 답을 붙잡아 두면 기능이 멈추고, 그냥 내보내면 큐를 둔 의미가 없다. 대개는 위험도가 높은 항목만 붙잡고 나머지는 내보낸 뒤 사후 검토하는 쪽으로 정리된다.
스트리밍
완전 버퍼링
출력 가드의 가장 실질적인 문제는 이것이다. 검사하려면 답이 있어야 하는데, 스트리밍은 답이 만들어지는 대로 내보낸다. 방법은 셋뿐이고 각각 무엇을 포기하는지가 분명하다.
첫째는 다 받고 검사하는 것이다. 가장 안전하고 가장 느리다. 첫 글자까지의 시간이 생성 전체 시간과 같아지므로, 두세 문장짜리 답에는 괜찮고 A4 한 장짜리 보고서에는 못 쓴다. 스트리밍을 쓰는 이유가 애초에 첫 글자를 빨리 보여 주는 것이었으니 이 방식은 스트리밍을 껐다는 뜻에 가깝다. 다만 화면에 진행 표시를 두면 체감은 꽤 나아진다.
조각 검사
둘째는 문단이나 문장 경계에서 끊어 그 조각만 검사하는 것이다. 통과한 조각을 흘려보내고 다음 조각을 모은다. 지연과 안전의 절충이라 대부분의 긴 생성에 맞는 답이다.
여기에는 한 가지 구조적 한계가 있다. 조각만 봐서는 판단할 수 없는 검사가 있다. 답 전체의 결론이 규정과 어긋나는지, 앞 문단과 뒤 문단이 서로 다른 말을 하는지는 문단 하나로 알 수 없다. 그런 검사는 마지막 조각을 내보내기 전에 전체를 한 번 더 본다. 이때 이미 흘려보낸 부분은 되돌릴 수 없으므로, 전체 검사가 걸렸을 때 화면 아래에 정정 안내를 붙일 자리를 미리 만들어 둬야 한다.
조각의 크기도 정할 값이다. 작게 자르면 첫 글자는 빨라지지만 검사 호출 횟수가 늘어 비용이 붙고, 크게 자르면 완전 버퍼링에 가까워진다. 문단 단위가 대개 무난한 절충이다.
낙관적 표시와 회수
셋째는 일단 다 흘려보내고 문제가 발견되면 화면에서 지우는 것이다. 첫 글자가 가장 빠르다. 대신 사용자가 이미 읽은 내용을 지우게 되므로, 문제가 드물고 되돌려도 해가 없는 자리에서만 쓴다.
개인정보처럼 한 번 보이면 끝인 항목에는 절대 쓰지 않는다. 화면에서 지워도 사용자는 이미 봤고, 스크린샷을 찍었을 수도 있다. 이 방식이 회수하는 것은 화면이지 정보가 아니다.
그래서 실제 설계 요령은 방식을 고르는 것이 아니라 검사를 스트리밍 경로에서 빼는 것에 가깝다. 놓치면 안 되는 검사는 답이 만들어지기 전 단계에서 처리한다 — 개인정보는 도구 결과가 프롬프트에 들어가기 전에 마스킹하고, 권한 없는 문서는 검색 단계에서 뺀다. 스트리밍 경로에는 되돌려도 되는 검사만 남긴다. 이렇게 정리하면 세 방식 중 무엇을 고르든 사고의 크기가 제한된다.
차단과 수정
네 가지 조치
검사를 붙이는 것보다 걸린 뒤에 무엇을 할지 정하는 일이 어렵다. 선택지는 넷이고, 검사 종류마다 맞는 답이 다르다.
| 조치 | 어울리는 검사 | 주의할 점 |
|---|---|---|
| 재생성 | 형식 오류 | 횟수 상한을 반드시 둔다 |
| 부분 수정 | 근거 없는 문장, 민감정보 | 무엇을 고쳤는지 로그에 남긴다 |
| 차단 후 폴백 | 정책 위반 | 폴백 문구가 무성의하면 신뢰를 잃는다 |
| 사람 검토 | 규정 판단 | 큐가 밀리면 기능이 멈춘다 |
이 표를 적어 두는 일이 검사를 하나 더 만드는 것보다 대개 효과가 크다. 검사만 붙이고 조치를 안 정해 두면 예외 처리 코드가 조용히 통과시키는 쪽으로 수렴하기 때문이다.
부분 제거와 정합성
부분 수정은 가장 저평가된 조치다. 근거 없는 문장 하나 때문에 답 전체를 버리면 사용자는 아무것도 못 받는다. 문제 문장만 떨어뜨리고 나머지를 내보내면 대개 여전히 유용하다. 민감정보도 해당 부분만 마스킹하면 되고, 인용이 잘못됐으면 그 인용만 빼면 된다.
다만 한 가지를 확인해야 한다. 문장을 빼면 앞뒤가 안 맞는 경우가 있다. 「따라서 세 번째 방법이 가장 저렴합니다」를 남겨 두고 세 번째 방법을 설명한 문장을 뺐다면, 남은 답은 근거는 없어졌는데 결론만 서 있는 모양이 된다. 지시어(「이것은」·「위에서 본」)로 시작하는 문장, 앞 문장의 숫자를 받는 문장, 목록의 중간 항목은 혼자 빠지면 티가 난다.
실무에서 쓰는 기준은 이렇다. 뺀 문장이 답의 결론이나 근거에 걸려 있으면 부분 제거 대신 재생성이나 차단으로 올린다. 예시나 부연처럼 곁가지면 빼도 된다. 그리고 뺀 자리에는 「일부 내용은 근거를 확인할 수 없어 제외했습니다」 같은 한 줄을 남긴다 — 빈자리를 감추면 사용자가 남은 답을 완전한 답으로 읽는다.
폴백 문구
차단은 마지막 수단이지만 필요할 때가 있다. 이때 폴백 문구의 품질이 그 기능에 대한 인상을 정한다.
「요청을 처리할 수 없습니다」만 나오면 사용자는 같은 요청을 그대로 반복한다. 그러면 같은 검사에 또 걸리고, 사용자는 서비스가 고장 났다고 생각한다. 폴백에는 세 가지를 담는다 — 무엇 때문에 막혔는지(공격자에게 힌트가 되지 않는 선에서), 무엇을 바꾸면 되는지, 그래도 안 되면 어디에 문의하면 되는지. 여기에 문의 경로 하나만 있어도 반복 요청이 눈에 띄게 준다.
수정 로그
그리고 조용히 고치지 않는다. 수정을 로그에 남기지 않으면 「출력 가드가 매일 3만 건을 손보고 있으며 그중 절반은 프롬프트를 고치면 애초에 안 생길 문제」라는 사실을 아무도 모르게 된다.
로그에는 어느 검사가 무엇을 잡았는지, 원본과 수정본의 차이가 무엇인지를 남긴다. 이 기록이 쌓이면 검사별 수정률이 나오고, 수정률이 높은 항목은 검사를 조일 자리가 아니라 프롬프트나 스키마로 되돌아갈 자리를 가리킨다. 도구 인자 하나가 자주 빠진다면 그건 프롬프트의 설명이 모호한 것이고, 특정 표현이 매번 마스킹된다면 그 표현을 쓰지 말라고 미리 말해 두면 된다.
출력 가드는 안전망이지 프롬프트 결함의 은폐 장치가 아니다. 수정률이 계속 오르는데 사고는 안 난다면, 그건 가드가 잘 도는 것이 아니라 위쪽이 조금씩 나빠지고 있는데 가드가 가려 주고 있는 것이다.
운영 지표
골든셋
출력 가드에 판정 모델을 쓰면 새로운 문제가 하나 생긴다. 판정 모델도 틀린다. 그리고 그 오류는 두 방향 모두 비싸다. 멀쩡한 답을 막으면 기능이 쓸모없어지고, 나쁜 답을 통과시키면 가드가 없는 것과 같다.
그래서 검사기에도 골든셋이 필요하다. 정답 판정을 사람이 미리 붙여 둔 검사용 답변 묶음이고, 세 갈래로 채운다.
- 나가면 안 되는 답 — 과거 사고, 일부러 만든 위반 사례
- 나가도 되는 답 — 정상 답변 중 오탐이 났던 것들. 이쪽을 빼먹으면 과차단이 측정되지 않는다
- 애매한 답 — 사람 사이에서도 판단이 갈리는 것. 여기서의 불일치는 검사기가 아니라 정책 문서를 고쳐야 한다는 신호다
두 번째 갈래를 빠뜨리는 일이 가장 흔하다. 위반 사례만 모아 놓고 재면 검사기를 조일수록 점수가 오르므로, 「전부 차단」이 만점을 받는 세트가 된다.
사람 라벨 일치도
판정 모델의 판단은 사람 판단 30~50건과 한 번은 맞춰 본다. 같은 답을 사람이 채점하고 모델이 채점해서 얼마나 같은 결론을 내는지 세는 것이다.
일치율이 낮을 때 임계값부터 만지는 것이 흔한 실수다. 일치가 안 되는 이유는 대개 채점 기준이 모호해서이지 숫자가 잘못돼서가 아니다. 사람 둘이 같은 답을 두고 갈렸다면 모델이 맞힐 방법이 없다. 사람끼리의 일치율을 먼저 재 보고, 그것이 낮으면 정책 문서를 다시 쓴다. 사람끼리는 잘 맞는데 모델만 갈린다면 그때가 프롬프트나 임계값을 볼 차례다.
모델 교체 후 재측정
한 번 맞춰 놓은 검사기는 계속 맞아 있지 않다. 모델을 바꾸면 다시 재야 한다. 생성 모델을 바꾸면 답의 문체와 길이가 달라져서 근거 유사도의 분포가 통째로 이동하고, 판정 모델을 바꾸면 같은 프롬프트에 다른 엄격도로 답한다. 둘 다 임계값이 예전 분포에 맞춰져 있으므로 그대로 두면 어느 한쪽으로 치우친다.
버전을 올릴 때만이 아니라 프롬프트를 크게 고쳤을 때도 마찬가지다. 골든셋을 다시 돌려 차단율과 통과율이 어떻게 움직였는지 보고, 임계값을 새 분포에 맞춘다. 이 과정이 없으면 「모델을 최신으로 올렸더니 차단이 세 배가 됐다」 같은 일이 배포 다음 날 지표로 나타난다.
검사별 계측
마지막으로, 모든 검사를 한 덩어리 함수로 만들지 않는다. 검사가 하나로 뭉쳐 있으면 무엇이 무엇을 잡았는지 알 수 없고, 검사 하나를 끄거나 임계값을 조정하는 일이 배포 단위가 된다. 검사마다 이름·결과·걸린 시간을 따로 남기면 그때부터 「어느 검사가 지연의 절반을 쓰는가」와 「어느 검사가 한 달째 아무것도 안 잡는가」를 물을 수 있다.
여기에 함께 정해 둘 것이 검사가 실패했을 때의 동작이다. 판정 모델이 타임아웃됐을 때 무엇을 할지 안 정해 두면 예외 처리 코드가 조용히 통과시키는 경우가 많다. 위험도별로 미리 정한다 — 도구를 부르는 답은 검사 실패 시 막고, 읽기 전용 요약은 통과시키되 표시를 남기는 식이다.
정리하면 출력 가드는 값싼 것부터 쌓는다. 스키마와 참조 무결성은 거의 공짜이면서 실제 사고의 상당 부분을 잡고, 근거 대조가 그다음이며, 판정 모델은 앞의 검사가 애매하다고 표시한 것에만 쓴다. 그리고 걸렸을 때의 조치를 검사마다 따로 정한다 — 형식은 재생성, 근거는 부분 제거, 정책은 마스킹이나 차단, 규정은 사람에게.
다음 글에서는 출력 가드 중에서도 규칙이 가장 명확한 항목 하나를 따로 본다. 개인정보를 어디서 어떻게 지울 것인가다.
읽어주셔서 감사합니다. 😊

