당신은 풀 리퀘스트에서 다음과 같은 댓글을 본 적이 있을 것입니다. "기본 URL만 무료 모델로 지정하면 된다. API가 같지 않나?"
듣기에는 그럴듯합니다. 대부분의 제공업체들은 현재 채팅 완료(chat-completions) 방언을 사용합니다. 그렇다면 실제로 무엇이 고장 날 수 있을까요?
생각하는 것보다 더 많은 것이요. 요청 형태는 공유되지만, 응답 계약(response contract)은 그렇지 않습니다. 그리고 당신의 파서는 오직 응답만을 볼 뿐입니다.
저는 모델 교체에 대해 하나의 규칙을 지키고 있습니다. 디프(diff)할 수 없는 교체는 절대 신뢰하지 않는 것입니다. 그래서 여기 검사기(probe)가 있습니다. 이 검사기가 깨뜨리는 네 가지 믿음과, 그 뒤에 숨겨진 수정된 모델입니다.
"같은 API"는 잘못된 것을 비교한다
'같은 API'라는 것은 보통 같은 경로(route)와 같은 필드 이름을 의미합니다. 이것은 쉬운 부분입니다. 하지만 가장 크고 일찍 실패하는 부분이기도 합니다. 30초 안에 404 오류를 보게 됩니다.
조용한 실패는 한 단계 아래에 있습니다. 필드의 존재 여부, 필드의 형태, 그리고 에러 본문(error bodies)입니다. 이것들은 새벽 3시에 재시도 로직을 깨뜨리며, 당신의 curl 명령어로는 절대 알 수 없습니다.
그러니 엔드포인트가 아닌 계약(contract)을 비교하세요.
믿음 1: 같은 경로는 같은 응답 계약을 의미한다
경로란 경로에 대한 약속입니다. 이는 본문(body)에 대해서는 아무것도 말해주지 않습니다. 제공업체 문서와 이슈 스레드를 판단했을 때, 다음 사항들이 변동하는 경향이 있습니다:
finish_reason 값과 그것이 나타나는 시점.
usage가 아예 존재하는지 여부, 그리고 어떤 카운터를 가지고 있는지.
- 도구 호출(tool calls)이 리스트로 돌아오는지, 문자열로 돌아오는지, 아니면 아무것도 오지 않는지.
- 에러 본문의 키(
error.message 대 detail 대 단순 문자열).
- 스트리밍 청크 경계와 마지막 청크가 도착하는 위치.
이 중 어느 것도 이국적인 것은 아닙니다. 전부 계약(contract)입니다.
수정된 모델: 계약은 당신의 파서가 수용하는 것입니다. 무언가를 교체하기 전에 그 목록을 작성해 두세요.
믿음 2: JSON으로 파싱되면, 교체가 성공한 것이다
이것 하나가 세 가지 다른 검사를 하나의 단어로 축소합니다. 이것들을 분리하세요:
- 파싱(Parse): 본문이 유효한 JSON인가?
- 스키마(Schema): 코드가 인덱싱하는 필드를 가지고 있는가?
- 의미(Meaning): 내용이 작업을 만족시키는가?
무료 엔드포인트는 레벨 1을 통과하고 레벨 2에서 실패할 수 있습니다. 많은 응답들이 None으로 읽히는 본문과 함께 200을 반환합니다. 그러다가 당신은 세 프레임 깊이에서 AttributeError를 받게 됩니다.
레벨 3은 아무도 테스트하지 않는 부분입니다. 파싱(Parsing)만으로는 답변이 올바른지 여부를 알려주지 못합니다.
개선된 모델: 파싱 비율(parse rate), 스키마 비율(schema rate), 태스크 비율(task rate)을 개별적으로 추적하세요. 하나의 숫자는 버그를 숨깁니다.
믿음 3: 사용량 수치는 청구할 수 있는 사실입니다
usage 블록은 대부분의 방언에서 선택 사항입니다. 일부 엔드포인트(endpoints)는 이를 반환합니다. 어떤 것은 가끔만 반환하고, 또 어떤 것은 다르게 계산합니다.
스스로에게 직설적인 질문을 던져보세요. 만약 내일 usage가 사라진다면 예산 관리 시스템이 멈출까요?
그렇다면, 그것은 제공업체의 문제가 아니라 당신의 버그입니다. 로컬 토크나이저(local tokenizer)를 사용해 자체적으로 토큰을 계산하거나, 문자를 세세요. 둘 다 저장하세요.
개선된 모델: usage는 힌트로 취급하고, 자신만의 카운터를 원장(ledger)으로 취급하세요.
믿음 4: 내가 작성한 프롬프트 5개가 평가가 될 수 있을까
모두가 이렇게 합니다. 통합을 작성한 사람이 만든 행복 경로(happy-path) 프롬프트 5개입니다. 모두 통과합니다. 배포합니다.
그것은 스모크 테스트(smoke test)이며, 약한 테스트입니다. 와이어가 작동한다는 것만 증명할 뿐입니다. 당신의 페이지를 방문하는 케이스에 대해서는 아무것도 증명하지 못합니다.
상상력이 아닌 실패로부터 골든 세트(golden set)를 구축하세요. 로그에서 실제 프롬프트 5개를 가져오세요. 이미 파서를 고장 낸 것들도 포함해야 합니다.
개선된 모델: 케이스가 적대적이라면 작은 N도 괜찮습니다. 친화적인 케이스의 작은 N은 연극에 불과합니다.
프로브(The probe)
여기에 아티팩트가 있습니다. 이것은 stdlib Python이며, 품질이 아닌 형태(shape)를 기록합니다. build_payload와 인증 헤더(auth header)는 제공업체가 문서화한 요청 형태에 맞게 조정하세요.
# probe_contract.py - stdlib만 사용. build_payload와 auth header를 조정하세요.
import json, os, time, urllib.request, urllib.error
...
각 후보군(candidate)에 대해 두 번 실행하세요. 그런 다음 두 영수증을 비교하세요.
PROBE_BASE_URL=https://a.example/v1 PROBE_API_KEY=$KEY_A python probe_contract.py > a.md
PROBE_BASE_URL=https://b.example/v1 PROBE_API_KEY=$KEY_B python probe_contract.py > b.md
diff -u a.md b.md
두 영수증을 모두 커밋하세요. 이제 스왑에 증거가 첨부됩니다.
영수증 읽는 법
단지 예시적인 형태일 뿐입니다. 이들은 실제 실행에서 얻은 측정값이 아닙니다.
| case | run | status | json | finish | usage | tools | ms |
|---|
| json_only | 1 | 200 | yes | stop | present | absent | - |
| ... | | | | | | | |
| 점수처럼 읽지 말고 체크리스트처럼 읽으세요: | | | | | | | |
- JSON을 반환해야 하는 케이스에서
json=no인 경우. 중단하세요. 파서가 여기서 죽습니다.
- 도구 호출이 필요한데
tools=absent인 경우. 중단하거나, 해결책을 받아 재테스트를 진행하세요.
- 요청 시 종료하도록 요청한 지점에서
finish=length인 경우. 사용자의 종료 처리 방식이 다릅니다. 테스트하세요.
usage=absent. 존재한다고 가정하는 모든 로직을 제거하세요.
- 익숙하지 않은
err_keys가 포함된 status=400의 경우. 오류 분류기(error classifier)에 분기가 필요합니다.
ms 열을 벤치마크로 읽지 마세요. 그것은 요청 하나를 두 번 수행한 결과입니다. 이는 지연 시간 주장(latency claim)이 아니라 연기 신호일 뿐입니다.
의사 결정 테이블 (Decision table)
| 수신 신호 (Receipt signal) | 현행 유지 교체 (Swap as-is) | 어댑터 추가 (Add adapter) | 거부 (Reject) |
|---|
| 모든 케이스: json=yes, 예상 필드 존재 | 예 | - | - |
| ... | | | |
중간 열은 대부분의 교체가 실제로 발생하는 곳입니다. 괜찮습니다. 다만 어댑터를 우발적인 것이 아니라 명시적으로 만들어주세요.
무료 엔드포인트 활용처 (Where a free endpoint fits)
이 프로브는 제공업체에 구애받지 않습니다(provider-agnostic). 도달할 수 있는 모든 엔드포인트가 작동합니다. MonkeyCode의 무료 모델 접근은 실행을 위한 엔드포인트를 얻을 수 있는 한 곳입니다. 공개 고지: 본 문서는 MonkeyCode의 제품 아웃리치(product outreach)의 일환으로 준비되었습니다.
만약 그 경로를 선택한다면 실용적인 참고 사항 두 가지가 있습니다. 키는 환경 변수(env var)에 보관하고, 절대로 스크립트에 넣지 마세요. 그리고 앱과 동일한 네트워크 위치에서 프로브를 실행하세요. 무료 서버 옵션으로 배포하는 경우, 그곳에서 실행하세요. 경로(path)가 ms에 영향을 미치며, 경로는 비교 대상(diffing)의 일부입니다.
제한 사항 및 건너뛰어도 되는 경우 (Limitations, and who should skip this)
프로브가 무엇이 아닌지 솔직하게 인지하세요:
- 답변 품질을 평가하지 않습니다. 루브릭도, 심사위원도 없습니다.
- 긴 컨텍스트(long context), 스트리밍 엣지 케이스(streaming edge cases), 또는 동시성(concurrency)은 테스트하지 않습니다.
- 부하 테스트가 아닙니다. 네 가지 케이스를 두 번 실행한다고 해서 포화 지점(saturation point)을 찾을 수는 없습니다.
- 한 번도 실행하지 않은 프롬프트에 대한 의미론적 표류(semantic drift)는 잡아내지 못합니다.
인간 검토가 필요한 경우 등급별 평가(graded evals)는 건너뛰세요. 또한 고정 출력 스키마(fixed output schema)가 없다면 이 접근 방식도 건너뛰어야 합니다. 계약(contract)이 없으면 비교할 것(diff) 자체가 없습니다.
만약 귀하의 제품이 토큰 수량으로 비용을 청구한다면, 이 프로브는 단지 시작점일 뿐입니다. 어떤 카운터도 신뢰하기 전에 실제 인보이스와 대조(reconcile)해야 합니다.
가장 먼저 물어봐야 할 질문
다음