Promptfoo 첫 평가 파일 만들기: 해커톤 제출 전에 로컬에서 확인할 것 | DAKER 커뮤니티

한 줄 답: 좋아 보이는 답을 몇 번 확인하는 일과, 같은 입력에 같은 기준으로 다시 돌려 통과 여부를 확인하는 일은 다릅니다 관련 일정 예: ; 2026년 3월 9일, 2026년 3월 9일.

데이콘·DAKER 커뮤니티 기준으로 정리한 안내입니다.

좋아 보이는 답을 몇 번 확인하는 일과, 같은 입력에 같은 기준으로 다시 돌려 통과 여부를 확인하는 일은 다릅니다. 해커톤처럼 제출 링크가 곧 결과물이 되는 상황에서는 특히 그렇습니다. 채팅창의 인상보다 파일에 적힌 평가 기준이 더 중요해집니다.

이 글은 Promptfoo로 첫 평가 파일을 만드는 최소 범위를 정리한 메모입니다. 설치부터 예제 실행, 어서션 추가, 실패 줄 확인까지를 다루되, 범위는 로컬에서 평가 파일 한 장을 만드는 데 맞춥니다.

프롬프트를 시험으로 돌립니다

좋아 보이는 답을 세 번 본 것은 시험이 아닙니다. Promptfoo 설정 파일에 입력과 어서션을 적고, 실패하는 줄을 고친 뒤에 링크를 올립니다.

참고 영상은 Jason의 Start with PromptFoo in under 10 min.입니다. 설치, promptfoo init, 설정 파일, promptfoo eval, HTML 결과까지를 한 번에 보여 줍니다. 다만 명령의 기준은 영상이 아니라 공식 문서 Getting started입니다. 영상은 그 순서를 화면으로 재현한 기록에 가깝습니다.

OpenAI는 2026년 3월 9일 Promptfoo 인수를 발표했습니다. 공식문은 OpenAI to acquire Promptfoo입니다. 거래 금액은 그 글에 없습니다. 이 글도 금액을 덧붙이지 않습니다. 저장소는 promptfoo/promptfoo이며, 이 글을 쓰는 시점에 GitHub 페이지가 보여 준 별 표시는 24,499개입니다.

영상이 실제로 보여 준 흐름

영상에서 Jason은 일본어 학습 앱 폴더에 Promptfoo를 넣습니다. 설치는 Homebrew로 진행하지만, 이 글에서는 공식 문서의 기준인 npx promptfoo@latest를 따릅니다. 녹화 시점 화면에 나온 버전은 0.108.0이지만, 그 숫자를 오늘 최신 버전처럼 옮기지는 않습니다.

첫 단계는 promptfoo init입니다. 대화형 마법사가 열리고, 처음이면 Not sure yet를 고릅니다. 로컬 모델을 시험하려고 Ollama를 고릅니다. 이미 README가 있으면 덮어쓰지 않고, 폴더에는 promptfooconfig.yaml이 생깁니다. 여기에는 예제 프롬프트, 공급자, 테스트가 들어 있습니다.

그 상태로 promptfoo eval을 실행하면 API 키가 없어 실패할 수 있습니다. 영상에서는 공급자를 Ollama로 바꾸고, 모델 이름 앞에 ollama:를 붙인 뒤에야 평가가 돌아갑니다. 예제 설정 결과는 성공 4건, 실패 2건입니다. 다만 이 숫자는 그 영상의 설정과 그 시점의 로컬 모델 결과일 뿐, Promptfoo 전체의 평균이나 기준점은 아닙니다.

결과를 HTML로 보려면 출력 파일을 지정하거나, 공식 문서처럼 npx promptfoo@latest view를 쓰면 됩니다. 터미널 표보다 브라우저 화면이 모델별 비교를 읽기 쉽습니다.

영상 후반부에서 Jason은 예제를 번역 시험으로 바꿉니다. 언어 변수는 Japanese이고, 입력은 Hello world, 가까운 화장실, My name is Jason입니다. 처음에는 어서션 없이 돌리기 때문에 출력만 있으면 통과합니다. 이후 contains를 넣어 이름 번역에 가타카나가 포함되는지 확인합니다. 다만 본인도 이 기준이 약하다고 말합니다. 원어 화자가 정한 문자열이 있어야 시험이 단단해진다는 설명이 이어지는데, 제출 페이지 문구를 확인할 때도 같은 원칙이 적용됩니다.

공급자를 Mistral, Solar, Llama 3로 늘린 뒤 다시 돌리면 성공 5건, 실패 4건이 나옵니다. 이 역시 그 영상의 결과입니다. 로컬 모델을 쓰면 토큰 비용을 아낄 수 있고 API 키 없이 첫 평가를 돌릴 수 있다는 점은 분명하지만, 그 자체가 제출 품질을 보증하는 것은 아닙니다.

또 하나 분명한 점은 영상이 다루지 않은 범위입니다. RAG 평가, 에이전트 궤적, 레드팀은 다음 편으로 넘깁니다. 이 글도 그 주제를 확장하지 않습니다. 오늘 범위는 설정 파일 한 장, 평가 한 번, 실패 한 줄을 고치는 일입니다.

공식 문서 기준으로 시작하는 첫 명령

공식 Getting started는 예제로 시작하는 흐름을 제시합니다.

npx promptfoo@latest init --example getting-started
cd getting-started
npx promptfoo@latest eval
npx promptfoo@latest view

예제 폴더에는 promptfooconfig.yaml과 README가 생깁니다. 기본 예시는 번역 프롬프트를 여러 모델에 넣는 구조입니다. 클라우드 공급자를 쓰려면 인증이 필요하고, OpenAI라면 OPENAI_API_KEY를 환경 변수로 둡니다. 키 값은 글이나 채팅에 적지 않고 로컬 환경에만 두는 것이 좋습니다.

처음부터 직접 만들려면 npx promptfoo@latest init을 쓰면 됩니다. 화면으로 설정하려면 npx promptfoo@latest eval setup도 가능합니다. 다만 팀 기록을 남길 때는 같은 명령을 재현하기 쉬운 npx 기준이 편합니다.

설정 파일의 기본 구조

설정 파일은 크게 프롬프트, 공급자, 테스트로 나뉩니다. 프롬프트 자리 표시는 겹중괄호를 씁니다. 문서 예시는 영어 문장을 언어 변수로 번역하는 한 줄입니다. 공급자에는 OpenAI, Anthropic, Google, 파일로 연결한 커스텀 공급자, 로컬 Ollama 등이 들어갑니다. 테스트는 변수와 어서션으로 구성됩니다.

문서 예시에서는 French 입력 Hello world에 contains 값 Bonjour le monde, Spanish 입력에 icontains를 둡니다. 어서션은 선택 사항입니다. 없어도 평가는 돌아가지만, 그 경우에는 사람이 출력을 직접 읽어야 합니다. 어서션이 있으면 파일이 통과와 실패를 나눕니다.

어서션이 없으면 평가는 출력 모음입니다. 어서션이 있어야 파일이 통과와 실패를 나눕니다.

어떤 어서션부터 써야 하는가

Assertions and Metrics 문서에는 다양한 어서션이 정리돼 있습니다. 문자열 확인에는 equals, contains, icontains, regex가 있고, JSON 출력에는 is-json, contains-json가 있습니다. 모델의 거절 여부는 is-refusal로 볼 수 있고, 다른 모델이 채점하는 방식으로는 llm-rubric, similar가 있습니다. 앞에 not-를 붙이면 반대 조건이 됩니다.

RAG 관련 항목으로는 answer-relevance, context-faithfulness, context-recall, context-relevance가 있고, 에이전트 궤적에는 tool-used, tool-sequence, goal-success가 있습니다. 다만 첫 평가 파일에서는 범위를 넓히기보다 contains 하나로 시작하는 편이 낫습니다. 루브릭 기반 채점은 그다음 단계로 미루는 것이 좋습니다.

가중치와 임계값도 문서에 있습니다. 어서션마다 weight를 줄 수 있고 기본값은 1입니다. 테스트에 threshold를 두면 가중 평균이 그 값 이상일 때만 통과합니다. 문서의 산식 예시는 equals 가중 2, contains 가중 1일 때 출력이 Goodbye world이면 점수가 0.33이 되는 방식입니다. 이 숫자는 문서 설명용 예시일 뿐, 오늘의 실제 점수는 아닙니다.

오늘 범위에서 바로 쓸 수 있는 방식

해커톤 제출은 결국 올린 링크입니다. 따라서 제출 페이지의 문장이 어제와 같은지, 금지 문장이 다시 들어오지 않았는지를 채팅 기억에만 맡기지 않는 편이 좋습니다. 파일로 확인하는 쪽이 재현 가능하고, 팀원도 같은 기준을 볼 수 있습니다.

오늘 범위는 제출 페이지 카피 한 덩어리를 평가 파일 한 장에 고정하는 일입니다. 모델 전체를 바꾸는 작업이 아니라, 랜딩에 들어갈 한 줄을 기준 문자열로 확인하는 작업에 가깝습니다.

예제를 띄운 뒤에는 테스트를 우리 제출 문장으로 바꾸면 됩니다. 변수에는 랜딩에 들어갈 한 줄을 넣고, 어서션은 contains 하나로 시작합니다. 값은 제출입니다. 만약 페이지가 배포가 제출입니다라는 문장을 써야 한다면, 그 네 글자가 출력에 실제로 들어 있는지 확인하는 식입니다.

같은 테스트에 금지 문장도 추가할 수 있습니다. 예를 들어 not-contains에 데모 전용, 로그인 필요, coming soon 같은 문자열을 둘 수 있습니다. 심사위원이 링크를 열었을 때 보이면 안 되는 문장들입니다. 다만 금지 목록은 팀 상황에 맞게 직접 정하는 것이 좋고, 없는 목록을 그대로 복사해 쓰는 방식은 도움이 되지 않습니다.

중요한 단계는 일부러 실패를 만들어 보는 일입니다. 프롬프트를 약하게 바꿔 제출이라는 단어가 빠지게 만들고, 평가가 실제로 실패하는지 확인합니다. 실패하지 않는다면 어서션이 일을 하지 않는 것입니다. 그 경우에는 어서션을 먼저 고치고, 프롬프트를 원래대로 되돌린 뒤 다시 통과하는지 확인하면 됩니다.

이 글이 말하지 않는 것

Promptfoo가 모든 프롬프트 품질을 대신 보증하는 것은 아닙니다. 어서션이 약하면 통과는 통과가 아닙니다. contains에 너무 쉬운 단어만 넣으면 아무 문장이나 통과할 수 있고, llm-rubric의 채점 문장이 느슨하면 실패해야 할 답이 통과할 수 있습니다.

인수 발표도 곧바로 제품 완성의 신호로 읽지 않습니다. 공식문은 닫힌 뒤에 기술을 OpenAI Frontier에 넣는다고 적고 있을 뿐입니다. 오늘 로컬에서 만든 평가 파일이 곧바로 Frontier가 되는 것은 아닙니다. Fortune 500 사용 비율, 사용자 수, 거래 금액 같은 정보도 이 글에서는 덧붙이지 않습니다.

영상 속 성공 4, 실패 2 역시 벤치마크처럼 인용하지 않습니다. 그 숫자는 예제 설정과 그 순간의 Ollama 모델 결과입니다. 우리 랜딩 카피의 점수와는 무관합니다. 일본어 번역 예제를 그대로 올리면 평가는 돌아가도 제출은 나아지지 않습니다.

로컬에서 끝내고, 그다음에 CI로 옮기기

팀으로 내는 대회라면 이 평가 파일을 저장소에 함께 두는 편이 좋습니다. 프롬프트를 바꾸는 풀 리퀘스트에 GitHub Action을 붙이는 일은 그다음 단계입니다. 관련 문서는 Testing Prompts with GitHub Actions에 있습니다. 액션 이름은 promptfoo/promptfoo-action@v1이고, 러너 Node는 22.22.0 이상이며 문서는 Node 24 LTS를 권합니다.

다만 오늘 숙제는 로컬 한 번입니다. 로컬에서 실패하는 평가를 CI에 먼저 올리는 것은 순서가 맞지 않습니다. CI는 같은 시험을 반복하는 자리이고, 첫 시험은 로컬에서 끝내는 편이 좋습니다.

배포가 제출입니다. 올린 링크가 제출입니다. 그 링크의 문장이 파일과 같아야 합니다.

출처