OpenAI Cookbook은 같은 플러그인 테스트를 도구 단위, 독립형 모델 호출 루프, Codex 제품 실행 환경에서 각각 평가하는 방법을 소개했다. BLS(미국 노동통계국) 데이터를 다루는 예제에서 독립형 루프는 5개 사례를 모두 통과했지만 Codex는 3개만 통과했고, MCP 서버에 지침을 추가한 뒤에는 Codex도 5개를 통과했다.

모델을 평가할 때는 모델뿐 아니라 실행 환경인 하니스(harness)도 결과에 영향을 준다. 하니스는 모델이 받는 프롬프트와 사용할 수 있는 도구를 비롯해 에이전트 루프, 도구 실행, 턴 제한, 샌드박스 정책 등을 포함한다. 따라서 한 환경에서 얻은 점수만으로 실제 제품에서의 성능을 판단하기 어렵다.

  • 도구 직접 테스트는 빠르고 무료지만 자연어 해석이나 도구 선택은 평가하지 않는다.
  • 독립형 함수 호출 루프는 모델의 도구 선택을 살펴보는 데 유용하지만 제품 하니스의 동작을 재현하지는 않는다.
  • 제품 하니스 평가는 실제 배포 환경에 더 가깝지만 설정과 실행 비용이 더 크다.

세 단계로 나눠 평가하기

예제는 같은 테스트 사례를 세 방식에 적용한다. 도구 직접 테스트는 구조화된 입력을 resolve 도구에 바로 전달해 도구 로직을 확인한다. 독립형 루프는 자연어 질문을 모델에 주고, 모델이 MCP 도구를 선택해 호출한 뒤 답을 내도록 한다. Codex 평가는 플러그인을 설치한 제품 하니스에서 같은 질문을 실행한다.

이 예제의 다섯 사례는 합성 데이터로 구성했다. 실제 BLS 영역의 일부 특성을 축소해 모호한 기본값, 서로 다른 두 후보, 데이터 공백이 드러나도록 했다. CPI(소비자물가지수)는 예제 카탈로그에 없으며, ‘employment’는 동률인 두 측정 후보가 있어 사용자에게 확인해야 하는 사례다. 테스트 데이터와 기대 결과는 promptfooconfig.yaml에 모아 세 접근법이 공유한다.

직접 테스트는 API 키나 네트워크 호출 없이 약 1초 만에 다섯 사례를 실행하며, 결과가 결정적이다. 반면 자연어 질문을 해석하는 모델의 능력은 검사하지 않는다. 독립형 루프와 Codex는 모델 API 호출이 필요하고, 기본 설정에서 실행 비용은 API 가격 기준 약 0.01달러다. 동봉된 노트북은 기록된 실행 결과를 재생하므로 비용이 들지 않는다. 라이브 실행에는 유효한 OpenAI API 키와 실행 중인 MCP 서버가 필요하다. 설치 요건과 절차는 README에, 실행 명령은 Makefile에 정리돼 있다.

평가 방식확인하는 내용주요 한계비용·충실도
도구 직접 테스트구조화된 입력에 대한 도구 로직자연어 해석과 도구 선택은 확인하지 않음무료·가장 낮은 충실도
독립형 함수 호출 루프통제된 환경에서의 자연어 해석과 도구 선택제품 하니스 동작은 확인하지 않음중간 비용·중간 충실도
제품 하니스플러그인을 설치한 Codex에서의 실제 실행대상 제품과 평가 설정 사이에 차이가 남을 수 있음가장 높은 비용·ChatGPT 데스크톱 앱 자체보다는 낮은 충실도

하니스가 결과를 바꾼 사례

기록된 다섯 사례에서 독립형 루프는 5개를 통과했지만, Codex는 3개만 통과했다. Codex는 CPI 사례에서 도구가 반환하지 않은 실제 BLS 계열 ID CUUR0000SA0을 자체적으로 제시해 데이터를 조회했다. 최종 답변은 데이터를 이용할 수 없다고 맞게 말했지만, 기대하지 않은 계열을 조회했기 때문에 평가에서 실패했다. ‘employment’ 사례에서도 동률인 후보 중 하나 이상을 조회해, 사용자에게 먼저 선택을 묻지 않았다. 새 라이브 실행에서는 모델의 경로에 따라 결과가 달라질 수 있다.

독립형 루프에는 계열 ID를 지어내지 말고 동률 후보를 모두 밝히라는 시스템 지침이 있었다. Codex에는 같은 지침이 없었다. MCP 서버가 초기화 과정에서 보내는 instructions 필드에 카탈로그에 없는 ID를 쓰지 말 것, 후보가 없으면 데이터가 없다고 답할 것, 최고 신뢰도가 동률이면 조회하지 말고 사용자에게 확인할 것을 담아 Codex 평가를 다시 실행하자, 기록된 결과에서 5개 사례가 모두 통과했다. 도구와 resolver는 바뀌지 않았다. 다만 이 지침을 받은 Codex 결과도 기록된 실행 결과이며, 새로운 실행에서 같은 점수가 보장되는 것은 아니다.

평가의 판정 기준에도 한계가 있다. 다섯 사례 평가기는 도구 호출, 반환된 계열, 불필요한 조회 여부, 비어 있지 않은 최종 답변을 검사하지만 답변 자체가 정확한지, 실제로 사용자에게 필요한 확인 질문을 했는지는 판정하지 않는다. 따라서 실제 제품 평가에는 답변 수준의 검사도 필요하다. 이 예제의 다섯 사례 결과와 별도로, 제작진은 실제 BLS 플러그인의 질문 108개와 BLS 조사 56개를 대상으로 평가했다. 이 평가는 최종 답변을 LLM 평가 기준으로 판정했으며, 다섯 사례에 사용한 도구 호출 검사와는 별개다.

실제 BLS 플러그인 평가 결과

실제 플러그인 벤치마크는 56개 BLS 조사에서 뽑은 단일 턴 질문 108개로 구성된 홀드아웃 테스트 분할을 사용했다. 평가자는 gpt-5.6-sol 기반 LLM 루브릭이며, 표 1은 모델별 1회 실행, 표 2와 3은 응답 캐시를 끄고 세 차례 실행한 결과다. Codex는 0.159.2, promptfoo는 0.123.1 버전이었다.

모델통과율질문당 도구 호출질문당 추론 토큰
GPT-6.1 Sol0.944.0219
GPT-6 Astra0.943.7414
GPT-6 Luna0.885.541,229

GPT-6.1 Sol과 GPT-6 Astra는 이 실행에서 108개 중 한 문제만 차이가 나, 두 모델의 우열을 안정적으로 가릴 근거가 부족하다고 자료는 설명한다. GPT-6 Luna는 통과율이 더 낮았고, GPT-6.1 Sol보다 도구 호출은 약 40% 많았으며 질문당 추론 토큰은 60배 넘게 사용했다.

모델 간 격차도 하니스에 따라 달라졌다. Codex에서는 GPT-6 Luna의 통과율이 0.88, GPT-5-mini가 0.43이었지만, 독립형 루프에서는 각각 0.74와 0.64였다. GPT-5-mini의 Codex 실패 중 약 절반은 아무 작업도 하지 않는 셸 명령 호출과 관련됐으며, 전체 질문 중 도구를 호출한 비율은 Codex에서 약 85%, 독립형 루프에서 약 95%였다. 독립형 루프에는 셸이 없다. GPT-6 Luna는 독립형 루프에서 데이터가 없다고 답하거나 루프의 단계 제한에 도달하는 경우가 실패의 대부분이었다. Codex에서는 해당 턴이 이어졌지만, 평가 결과만으로 그 차이의 작동 원인을 확정할 수는 없다.

같은 Codex 설정에서 GPT-6 Luna로 세 차례 실행한 통과율은 0.88, 0.89, 0.86이었다. 전체 점수의 범위는 3%포인트였지만, 질문별로 보면 108개 중 23개(21%)가 세 실행 중 적어도 한 번 통과와 실패 사이에서 바뀌었다. 한 질문의 도구 호출 수도 한 실행에서는 5회, 다른 실행에서는 19회였다. 자료는 모델의 다른 해결 경로 선택, LLM 평가자의 판정 차이, 모델이나 하니스의 외부 업데이트가 실행 간 차이를 만들 수 있다고 설명한다.

평가를 적용할 때

조사하려는 문제를 드러낼 수 있는 가장 저렴한 평가부터 시작하는 것이 실용적이다. resolver 로직이나 테스트 데이터를 바꿨다면 직접 테스트를 실행하고, 도구 설명·프롬프트·채점 기준·모델을 조정하는 동안에는 독립형 루프를 사용할 수 있다. 새 모델을 도입할 때는 제품 하니스에서도 확인해야 한다. 두 평가가 일치한다면 반복 작업은 독립형 루프에서 하고, 제품 하니스는 출시 점검과 결과 공유에 활용할 수 있다.

그럴듯하지만 틀린 답이 나올 수 있는 사례도 테스트에 넣어야 한다. 예를 들어 답이 짧은 계열 목록이어야 하는 경우, 모호한 질문을 되물어야 하는 경우, 데이터가 전혀 없는 경우를 포함한다. 사례마다 무엇을 시험하는지와 정답 기준을 표시하면 특정 유형만 골라 평가할 수 있다. 평가 기록과 실제 제품 실행 기록을 비교하면 지침, 도구 접근성, 런타임 버전처럼 설정에서 빠진 차이도 찾을 수 있다.

같은 사례를 캐시 없이 반복 실행해 결과의 안정성도 측정해야 한다. 통과율만 볼 것이 아니라 질문당 도구 호출과 추론 토큰을 함께 살피고, 답변 표본은 사람이 검토하는 것이 좋다. 저렴한 하니스와 작은 모델은 빠른 개발에 도움이 되지만 실제 배포 환경을 완전히 대신하지는 못한다. 제품 동작은 배포된 하니스와 모델의 조합으로 결정된다.

다른 플러그인에 이 구조를 적용할 때는 테스트 사례, 평가 로직, 지침, 플러그인 설정을 각 환경에 맞게 바꿔야 한다. 반면 도구 직접 테스트, 독립형 루프, 제품 하니스를 구분하는 세 단계 구조는 재사용할 수 있다. 에이전트 평가와 모델 평가의 차이는 AI Agents That Matter, 반복 시도 모두가 성공할 확률을 다루는 pass^k는 τ-bench, Codex 실행 환경은 Codex 샌드박스 안내에서 더 살펴볼 수 있다.

부록: 원문 예시

text
from server import IndicatorQuery, resolve resolve(indicators=[     IndicatorQuery(indicator="unemployment rate"),     IndicatorQuery(indicator="employment"),     IndicatorQuery(indicator="consumer price index"), ])
text
for step in range(max_steps + 1):     response = await openai.responses.create(input=conversation, **request)     function_calls = [item for item in response.output if item.type == "function_call"]     if not function_calls:         return {             "answer": response.output_text,             "tool_calls": recorded_calls,             "completed": True,         }     if step == max_steps:         break     # The API rejects round-tripped items that still carry null-valued fields.     conversation += [item.model_dump(exclude_none=True) for item in response.output]     for call in function_calls:         arguments = json.loads(call.arguments or "{}")         result = await mcp.call_tool(call.name, arguments)         recorded_calls.append({"name": call.name, "arguments": arguments, "result": result.structured_content})