Jev 파이썬 사용법 — Vercel AI SDK(ai 0.8) evaluate()로 분류기 붙이고 Vercel에 배포하기
Vercel이 10월 2일 블로그 글 「Jev for Python engineers」에서 파이썬용 AI SDK의 새 실험 기능 evaluate()를 소개했다. 파이썬 코드에서 TypeSafe AI의 판단 모델 Jev를 Vercel AI Gateway를 거쳐 바로 부르는 함수다. 패키지 이름은 PyPI의 ai, 10월 9일 기준 최신 버전은 0.8.0(9월 29일 UTC 업로드)이고 라이선스는 Apache-2.0, 파이썬 3.12 이상이 필요하다. SDK 자체는 아직 공개 베타다.
Jev가 무엇인지는 이전에 정리한 TypeSafe AI Jev 소개 글에, API 키 없이 로컬에서 돌리는 방법은 NanoJev-MLX 테스트 글에, 개인정보 탐지에 붙인 실험은 JevK5 하이브리드 글에 있다. 이번 글은 그 이야기를 되풀이하지 않는다. 파이썬 개발자가 ai 패키지로 Jev를 부르는 법, 그리고 Vercel에 배포했을 때 인증이 어떻게 바뀌는지에만 집중한다.
원문을 쓴 Vercel의 Yury Selivanov는 Jev를 "범용 분류기(universal classifier)"라고 부른다. 분류기는 원래 작업마다 데이터를 모으고 라벨을 붙여 새로 학습시켜야 했다. 스팸 필터라면 스팸인지 아닌지 라벨을 붙인 메일이 잔뜩 필요했다. Jev는 이미 넓게 학습된 LLM을 분류기처럼 쓰도록 만든 모델이라 이 학습 단계가 없다. 대신 문장을 생성하지 않는다. 질문에서 정한 선택지와 타입에 맞춘 JSON만 돌려준다.
파이썬에서 Jev 첫 호출까지
원문이 안내하는 순서는 짧다.
- 프로젝트에
uv add ai로 SDK를 추가한다(파이썬 3.12 이상). - Vercel 대시보드의 AI Gateway API Keys 화면에서 키를 만든다.
- 그 키를
AI_GATEWAY_API_KEY환경변수에 넣는다. - 아래 코드를 실행한다.
import asyncio
import ai
from ai.ops import experimental as jev
async def main():
result = await jev.evaluate(
ai.get_model("typesafe-ai/jev"),
"You're Neil deGrasse Tyson",
{"bigger": jev.ChoiceQuestion(
instructions="Which is bigger, the Sun or the Earth?",
criteria={"Sun": None, "Earth": None},
)},
)
print(result.value["bigger"])
if __name__ == "__main__":
asyncio.run(main())
evaluate()에 넘기는 건 세 가지다. 모델, 상태(state, 판단 대상 — 문자열이어도 되고 JSON 객체·배열이어도 된다), 그리고 질문 묶음. 질문은 ChoiceQuestion(하나 고르기), ScoreQuestion(정해 둔 단계로 점수 매기기), NoulQuestion(문장이 참일 확률 추정) 셋 중 하나다. 원문은 Jev 공식 API를 "거의 그대로" SDK에 옮겼다고 설명한다.
버전은 꼭 보고 쓰자. GitHub 릴리스 노트를 보면 이 기능은 9월 18일(UTC) 0.7.0에서 ai.ops.experimental_evaluate라는 이름으로 처음 들어왔고, 9월 29일 0.8.0에서 ai.ops.experimental.evaluate로 경로가 바뀌었다. 같은 릴리스에서 Boolean 질문은 Noul로 이름이 바뀌고 confidence 값이 새로 노출됐다. 들어온 지 열하루 만에 경로가 바뀐 셈이다. 9월에 나온 예제를 그대로 붙여 넣으면 import 단계에서 깨질 수 있다.
딕셔너리로 물을까, Pydantic 모델로 물을까
질문을 넘기는 방식은 두 가지다. 위 예제처럼 딕셔너리로 넘기면 결과도 딕셔너리(result.value["bigger"])로 온다. 질문 개수가 실행 중에 바뀌는 경우에 맞다. 반대로 질문을 Pydantic 모델로 정의하면 output_type에 같은 필드 이름을 가진 답변 모델을 반드시 함께 넘겨야 하고, 그 대가로 result.value.queue.choice처럼 타입이 붙은 결과를 받는다. 저장소의 evaluation.py 예제는 고객 문의 하나를 놓고 담당 큐(Choice), 긴급도(Score), 환불 타당성(Noul)을 한 요청에 묻는다 — 같은 원본 정보로 여러 판단을 내려야 할 때 쓰는 패턴이다.
답변 쪽에서 헷갈리기 쉬운 부분이 두 개 있다. ChoiceAnswer와 ScoreAnswer의 confidence는 공급자가 값을 줄 때만 0~1 사이 숫자이고 아니면 None이다. 그리고 NoulAnswer.noul은 "참일 확률"이지 확신도가 아니다. Noul 답변에는 따로 confidence 필드가 없다.
Vercel에 배포하면 키 대신 OIDC — 단 extra 하나가 필요하다
로컬에서는 API 키가 가장 편하다. Vercel 문서에 따르면 API 키는 로컬·외부 서버·CI 어디서나 동작하고, 직접 폐기하지 않는 한 만료되지 않는다. 다만 키를 만든 팀원이 팀을 떠나면 Vercel이 그 사람이 만든 키를 비활성화한다. 특정 사람에게 묶이지 않는 인증이 필요하면 Vercel 배포 환경의 OIDC 토큰을 쓰라는 게 문서의 안내다. Vercel 배포에는 VERCEL_OIDC_TOKEN이 자동으로 들어오므로 키를 따로 만들 필요가 없다.
여기서 놓치기 쉬운 설정이 하나 있다. ai 0.8.0 패키지(wheel)를 내려받아 AI Gateway 공급자 코드를 직접 읽어 보니 인증 순서는 이렇다.
AI_GATEWAY_API_KEY가 있으면 그 키를 쓴다.- 키가 없고
VERCEL=1이거나VERCEL_OIDC_TOKEN이 있으면 OIDC로 넘어간다. - 그런데 OIDC 토큰은 선택 패키지
vercel-oidc로 가져온다. 이 패키지가 없으면uv add "ai[vercel]"을 설치하거나 API 키를 쓰라는InstallationError가 난다.
원문의 설치 안내는 uv add ai뿐이다. 키 없이 Vercel에 올릴 생각이면 의존성을 ai[vercel]로 적어야 한다. 아래는 FastAPI로 감싼 최소 예시다. 저장소 예제의 질문을 그대로 빌려 문의 하나를 담당 큐로 보낸다. 실제 Gateway 키로 호출하지는 않았다. 파이썬 3.14로 문법 검사만 통과시킨 코드다.
# app.py
import ai
from ai.ops import experimental as jev
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
model = ai.get_model("typesafe-ai/jev")
class Ticket(BaseModel):
message: str
@app.post("/api/route")
async def route(ticket: Ticket):
result = await jev.evaluate(
model,
ticket.message,
{"queue": jev.ChoiceQuestion(
instructions="Which support queue should handle this ticket?",
criteria={
"billing": "Charges, duplicate payments, and refunds",
"technical": "Bugs, outages, and performance problems",
"other": None,
},
)},
)
answer = result.value["queue"]
return {"queue": answer.choice, "confidence": answer.confidence,
"probabilities": answer.probabilities}
# pyproject.toml
[project]
name = "jev-router"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"ai[vercel]==0.8.0",
"fastapi>=0.117.1",
]
Vercel 파이썬 런타임은 app.py·main.py 같은 파일에서 최상위 app 변수를 찾아 함수로 실행하고, 의존성은 pyproject.toml(uv.lock 유무 무관)이나 requirements.txt에서 읽는다. 지원 버전은 3.12(기본)·3.13·3.14라서 SDK의 3.12 하한과도 맞는다. 로컬에서 OIDC로 시험하려면 vercel link 뒤 vercel env pull로 토큰을 받는데, 이 토큰은 12시간만 유효하다. 12시간이 지나 인증이 막히면 vercel env pull을 다시 돌리는 게 순서다.
비용 감도 잡아 두자. Gateway의 공개 모델 목록 API(/v1/models, 키 없이 조회됨)를 10월 9일 직접 호출해 보니 typesafe-ai/jev 항목의 단가는 입력 토큰당 0.000000042달러, 출력 0달러였다. 100만 입력 토큰에 0.042달러다. 요청 한도는 전체 64,000토큰, 그중 상태와 가장 긴 질문을 합쳐 32,000토큰이고 스트리밍도 출력 토큰 한도도 없다고 같은 항목에 적혀 있다.
원문의 두 실험이 보여 주는 한계
글쓴이는 1년 전 직접 만들다 실패한 기능부터 Jev에 맡겨 봤다. 파이썬 REPL에서 지금 입력 중인 게 영어인지 파이썬 코드인지 자동으로 구분하는 분류기다. 이틀 걸려 손수 학습시킨 분류기는 if i를 쳤을 때 파이썬, if i i에서 영어, if i is에서 다시 파이썬으로 오락가락했다. Jev는 그보다 훨씬 나아 보였지만 빈틈이 있었다. 반쯤 친 파이썬 식 "what's" + " up을 영어로 판정한 사례를 원문이 직접 든다.
두 번째 실험은 일부러 "멍청한" 쪽이다. 글을 못 쓰는 Jev에게 파이썬 코드를 쓰게 하려고, GPT-5.6이 먼저 구체적인 계획을 세우고 Jev는 AST 노드를 하나씩 고르게 했다. 결과는 문법상 유효하지만 대부분 틀린 코드였다. 처음 시도한 글자·키워드 단위 방식으로는 if 문 하나 치기도 버거웠다고 한다. 분류기에게 LLM 일을 시키면 어디서 무너지는지 보여 주는 예시라 오히려 쓸모가 있다.
우리 서비스에 붙인다면
개인적으로는 이 SDK의 장점이 "Jev 전용 클라이언트를 따로 두지 않아도 된다"는 데 있다고 본다. 같은 ai.get_model()로 LLM도 부르고 Jev도 부르니, 문의 분류처럼 좁은 판단은 Jev에 넘기고 답장 작성만 LLM에 맡기는 식의 분업을 한 코드베이스 안에서 짤 수 있다. 원문도 Jev를 "좁은 결정"용으로 만든 모델이라고 못 박는다. 우리 용도에 충분히 정확한지는 직접 시험해 봐야 한다는 단서도 함께다.
붙이기 전에 챙길 것을 체크리스트로 묶으면 이렇다.
- 버전 고정: 공개 베타이고 9월에만 경로가 한 번 바뀌었다.
==0.8.0처럼 정확히 고정하고, 올릴 때는 릴리스 노트의 이름 변경부터 본다. - 배포 의존성은
ai[vercel]: 키 없이 OIDC로 쓰려면 필수다. -
confidence가None일 때의 분기: 값이 없을 수 있다고 SDK 문서가 명시한다. 임계값 비교 코드가None에서 터지지 않게 둔다. - 데이터 보존 옵션: 저장소 예제는
EvaluationParams(provider_options={"gateway": {"zeroDataRetention": True, "disallowPromptTraining": True}})로 요청 단위 옵션을 건다. 고객 문의처럼 민감한 상태를 넘긴다면 이 줄부터 검토한다. - 정확도 기준 세트: 우리 데이터 수십 건에 정답을 달아 두고, 원문의
"what's" + " up같은 경계 사례를 꼭 넣는다.
보안 이력도 찾아봤다. OSV 취약점 DB에 PyPI ai 패키지를 조회한 결과는 10월 9일 기준 0건이었고, GitHub 저장소의 보안 권고도 비어 있었다. 이름이 같은 npm ai(자바스크립트 AI SDK)에는 파일 업로드 형식 검사 우회 권고(GHSA-rwvc-j5jr-mgvh)가 있지만 별개 패키지다. 다만 Vercel 플랫폼에는 2026년 4월 보안 사고가 있었다. 직원이 쓰던 외부 AI 도구 Context.ai가 뚫리면서, 일부 고객의 '민감(sensitive)' 표시가 없는 환경변수가 복호화돼 유출됐다. Vercel은 그런 변수를 노출됐을 수 있는 값으로 보고 우선 교체하라고, 앞으로는 민감 환경변수 기능을 쓰라고 권했다. Vercel이 npm 패키지는 변조되지 않았다고 확인한 사건이지만, AI_GATEWAY_API_KEY를 Vercel 환경변수에 넣을 거라면 교훈은 분명하다. 민감 표시를 켜거나, 아예 키 없이 OIDC로 가는 쪽이 낫다.