실행 프로그램과 확장
Jev-Omni란? 사진·음성·영상에서 답을 고르는 로컬 AI
현관 사진에서 필요한 정보가 문이 열려 있는지 하나뿐이라면, 사진 전체를 설명하는 긴 답변은 필요하지 않습니다. 녹음 파일에서도 내용을 모두 받아쓰기보다 확인할 일이 있었는지만 알고 싶을 때가 있습니다. Jev-Omni는 이런 작업을 위한 공개 분류 모델입니다. 상황과 질문, 선택지를 주면 각 선택지의 확률을 반환합니다. 다만 이름에 Jev가 들어간다고 TypeSafe AI의 Jev를 내려받는 것은 아닙니다. 별도 개발자가 Gemma 4 12B IT를 바탕으로 만든 독립 프로젝트이며, 현재 공개 실행 코드는 일반 채팅 앱에 모델 파일 하나를 넣는 방식과 다릅니다.
긴 설명보다 짧은 판단이 필요한 순간
집 안의 카메라가 현관을 찍고 있다고 해봅시다. 자동화에 필요한 것은 ‘문이 열림’, ‘문이 닫힘’, ‘사진으로 판단하기 어려움’ 중 하나입니다. 화면에 무슨 물건이 있는지 유창하게 설명해도, 프로그램은 마지막에 그 셋 중 하나를 골라야 합니다. Jev-Omni는 그 선택 자체를 결과로 받으려는 접근입니다.
반대로 ‘왜 그런 판단을 했는지 설명해줘’나 ‘이 사진으로 광고 이미지를 만들어줘’는 다른 작업입니다. Jev-Omni는 설명문을 쓰거나 이미지·영상을 생성하는 모델이 아닙니다. 반복해서 같은 종류의 질문을 처리하는 분류기, 혹은 어떤 도구를 다음에 호출할지 정하는 보조 모델로 보는 편이 용도에 가깝습니다.
기존 JEV 글의 Qwen 구현과 무엇이 다른가
로컬 JEV형 구현 중에는 Qwen이 다음에 출력할 후보 토큰1의 점수를 바로 읽는 방식이 있습니다. Jev-Omni는 Gemma 4 12B IT 기반 모델에 별도로 학습한 분류 헤드를 붙입니다. 공개 코드는 입력을 처리한 뒤 마지막 위치의 내부 표현을 이 헤드에 전달하고, 선택지 점수를 확률로 바꿉니다. 길게 토큰을 이어 쓰는 디코딩 루프는 없습니다.
출력은 prediction, prediction_index, confidence, probabilities입니다. 가장 높은 확률의 선택지만 쓰거나 전체 확률을 남겨 나중에 검토할 수 있습니다. options에는 서로 다른 문구를 넣는 것이 좋습니다.
결과가 선택지 문구를 키로 쓰는 사전이므로 같은 문구를 중복하면 결과 해석이 꼬일 수 있습니다. 한 번의 predict 호출은 질문 하나를 처리하므로, 여러 질문을 무료로 동시에 해결한다고 생각하면 안 됩니다.

파일 하나로 시작하되, 보이지 않은 장면은 묻지 않습니다
사진은 흐림 여부나 정해진 물건의 존재를 분류하는 식으로 시작할 수 있습니다. 음성은 짧은 구간에 특정 소리가 있었는지, 영상은 여러 장면에서 상태가 바뀌었는지 확인하는 실험에 쓸 수 있습니다. 이것은 가능한 활용 예이지, 이 프로젝트가 모든 용도에서 정확도를 검증했다는 뜻은 아닙니다. 실제 파일과 사람이 매긴 정답을 함께 준비해야 내 작업에 맞는지 알 수 있습니다.
공개 헬퍼의 음성 경로는 ffmpeg로 앞부분 최대 30초를 잘라 처리합니다. 영상은 기본 16프레임2을 골라 이미지로 전달하며 영상의 오디오 트랙을 함께 듣는 경로는 아닙니다. 긴 영상에서 아주 잠깐 일어난 사건은 선택된 프레임 사이로 빠질 수 있습니다. ‘영상 지원’과 ‘영상의 모든 순간을 확인’은 구분해야 합니다.
12B라는 이름보다 먼저 볼 것은 로딩 방식입니다
평소 12B 모델을 4비트로 실행했다면 몇 GB면 충분하다고 느낄 수 있습니다. 하지만 공개 Jev-Omni 체크포인트3는 그런 배포 형태가 아닙니다.
텍스트 가중치 인덱스만 약 47.63GB이고, 기본 로더는 이를 FP324로 CUDA5에 올립니다. 모델 카드도 런타임 여유를 제외하고 약 50GB를 안내합니다.
따라서 24GB RTX 3090·4090이나 32GB RTX 5090에서 기본 예제를 그대로 실행한다고 보장할 수 없습니다.
더 중요한 것은 초기 로딩의 피크입니다. 멀티모달 로더는 일부 선형층을 BF166으로 바꾸고 나서 원본 Gemma 모델도 로드해 구성 요소를 교체합니다. 계산 중 BF16 autocast를 쓴다는 말이 처음부터 모든 가중치를 절반 크기로 올린다는 뜻은 아닙니다. 최종 사용량만 보고 장비를 고르면 로딩 도중 실패할 수 있어, 특정 용량을 최소 사양으로 단정하지 않았습니다.
Mac의 메모리가 넉넉하더라도 현재 공개 load_jev_omni는 CUDA 외 장치를 거부합니다. GPU7 두 장의 메모리를 합산하는 분산 로딩도 기본 함수에 없습니다. Mac에서는 기존 Qwen·MLX8 기반 JEV형 구현을 먼저 살펴보는 편이 낫습니다. 양자화9하거나 로더를 수정하는 실험은 가능성을 검토할 별도 작업이지, 공개 예제가 이미 지원하는 기능으로 표시할 수는 없습니다.

설치는 전용 Python 환경에서 시작합니다
아래는 공개 Python 헬퍼를 사용하는 순서입니다. 먼저 CUDA를 지원하는 PyTorch10가 현재 GPU에서 동작하는지 확인합니다. 코드는 모델 저장소에서 내려받아 실행하므로 jev_omni.py와 load_model.py를 읽어본 뒤 의존성을 설치하세요. 별도 가상환경11을 쓰면 다른 로컬 AI 도구와 패키지 버전이 섞이는 일을 줄일 수 있습니다.
모델 카드의 요구 버전은 torch 2.10 이상과 transformers 5.17.0입니다. 음성을 사용할 때는 Python 패키지와 별개로 ffmpeg 실행 파일도 필요합니다. 처음 모델을 불러오면 Jev-Omni뿐 아니라 원본 Gemma의 멀티모달 구성도 내려받습니다. 다운로드 공간·시간과 추론 시간은 따로 생각하고, 첫 실행에 개인 파일 대신 테스트용 자료를 사용하세요.
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip huggingface_hub
hf download akhilaaa3/Jev-Omni requirements.txt jev_omni.py load_model.py --local-dir jev-omni
# Review the downloaded Python files before continuing.
python -m pip install -r jev-omni/requirements.txt
python -c "import torch; print(torch.cuda.is_available())"텍스트 한 건이 된 다음 사진을 넣어봅니다
다음 코드를 jev_demo.py로 저장하고 가상환경에서 python jev_demo.py로 실행합니다. 첫 질문은 모델 로딩과 출력 구조를 확인하는 용도입니다. Python 결과에는 선택지 문구와 확률이 함께 나오므로, 답변 문자열을 다시 해석하는 코드를 만들 필요가 없습니다. 아래 예제는 실제 측정 결과를 꾸며 넣은 것이 아니라 공개 함수 호출 방법입니다.
텍스트 호출이 끝난 다음 사진 예제의 주석을 해제하고 media에 실제 파일 경로를 넣습니다. 파일은 공개 헬퍼에서 로컬로 읽지만, 모델과 구성 파일을 처음 받는 단계에는 인터넷 연결이 필요합니다. 사진에 정답이 보이지 않으면 ‘판단 불가’를 고를 수 있도록 선택지를 설계하세요. 질문을 한국어로 바꿔 쓸 수 있는지와 업무 정확도는 따로 검증해야 하므로 예제는 영문으로 두었습니다.
import sys
from pathlib import Path
sys.path.insert(0, str(Path("jev-omni").resolve()))
from jev_omni import load_jev_omni
classifier = load_jev_omni()
result = classifier.predict(
state="The parcel arrived yesterday. The customer confirmed receipt.",
question="Has the customer received the parcel?",
options=["Yes", "No", "Not enough information"],
)
print(result)
# After the text test succeeds, set an existing local image path.
# result = classifier.predict(
# state="This is a photo of a doorway.",
# question="What is the state of the door?",
# options=["Open", "Closed", "Cannot tell from this image"],
# media="/absolute/path/door.jpg",
# modality="image",
# )
# print(result)공개 성능은 빠르지만, 어디까지 잰 숫자인가
모델 카드의 H200 결과는 웜 상태의 최적화된 백엔드에서 요청 20회의 중앙값입니다. 약 2천 토큰 텍스트는 83ms, 이미지는 26ms, 13초 음성은 31ms, 16프레임 영상은 504ms로 안내합니다. 전처리와 네트워크 시간은 별도입니다. 큰 영상 파일을 열고 프레임을 읽는 시간이나 처음 가중치를 올리는 시간까지 이 숫자에 포함되어 있지는 않습니다.
채팅 모델의 tok/s와 나란히 놓기도 어렵습니다. Jev-Omni는 긴 답변을 생성하지 않으므로 입력 처리와 분류 완료까지의 지연시간, 동시에 처리할 수 있는 요청 수가 더 적절한 지표입니다.
이 글의 H200 수치를 사이트의 RTX·Mac 속도 체감으로 변환하지 않은 이유입니다. 내 장비에서는 같은 파일·같은 질문으로 로딩을 끝낸 뒤 여러 번 재고, 전처리를 포함한 시간도 별도로 남기는 것이 좋습니다.
| 평가 | 공개 점수 | 읽을 때 볼 조건 |
|---|---|---|
| DecisionBench Medium | 87.57% | 80개 시나리오·293문항, 시나리오 동일 가중 평균 |
| JevBench | 86.15% | 매칭된 195개 그룹·231개 판단, 그룹 동일 가중 평균 |
| MMAU | 63.10% | 1,000문항의 micro accuracy |
| MVBench | 53.10% | 평가된 14개 작업·2,786문항, 작업 평균 |
개발자가 공개한 병합 모델의 평가 결과
DecisionBench Medium
- 공개 점수
- 87.57%
- 읽을 때 볼 조건
- 80개 시나리오·293문항, 시나리오 동일 가중 평균
JevBench
- 공개 점수
- 86.15%
- 읽을 때 볼 조건
- 매칭된 195개 그룹·231개 판단, 그룹 동일 가중 평균
MMAU
- 공개 점수
- 63.10%
- 읽을 때 볼 조건
- 1,000문항의 micro accuracy
MVBench
- 공개 점수
- 53.10%
- 읽을 때 볼 조건
- 평가된 14개 작업·2,786문항, 작업 평균

확률을 받았다고 판단까지 맡기는 것은 아닙니다
높은 confidence가 내 데이터에서도 높은 정답률을 보장하지는 않습니다. 공개 모델은 선택지 20개 이하를 중심으로 지원하고, 헤드가 받는 최대 256개와 그 범위의 검증된 품질은 다릅니다. 먼저 실제 질문 수십 개에 직접 정답을 달아 비교하고, 틀렸을 때의 확률도 보세요. 자동 통과 기준은 그 기록으로 정하고, 애매한 결과는 검토 대기 목록에 남기는 편이 안전합니다.
저장소는 Apache-2.0으로 표시되어 있고 원본 Gemma 4도 같은 라이선스를 안내합니다. 다만 학습 데이터와 내가 넣는 사진·녹음의 권리는 별개입니다. TypeSafe AI와 제휴하거나 그 Jev의 출력으로 학습한 프로젝트도 아니라는 점을 구분해두면 이름 때문에 생기는 오해를 줄일 수 있습니다.
로컬 AI를 써보고 싶은 이유가 꼭 긴 대화를 나누기 위해서일 필요는 없습니다. 매일 열어보던 사진 폴더에서 확인할 것만 골라주거나, 반복되는 분류를 대신해주는 작은 기능도 충분히 쓸모가 있습니다.
Jev-Omni는 그런 방향의 공개 사례입니다. 지금 가진 장비에서 더 작은 Qwen 구현으로 질문과 선택지를 먼저 다듬어도 됩니다.
그 과정에서 답이 좋아졌을 때, 더 큰 멀티모달 모델을 올릴 이유도 분명해집니다.
용어 각주
토큰 — 모델이 입력이나 출력을 나누어 처리하는 단위입니다. 토큰 하나가 글자 하나나 일정한 시간 길이에 해당하지는 않습니다.
본문으로 돌아가기프레임 — 영상의 한 장면을 이루는 단일 이미지입니다. 초당 프레임 수와 프레임 해상도는 서로 다른 속성입니다.
본문으로 돌아가기체크포인트 — 학습된 모델의 가중치 등을 저장한 파일입니다. 같은 모델 계열도 버전이나 용도에 따라 다른 체크포인트를 쓸 수 있습니다.
본문으로 돌아가기FP32 — 32비트 부동소수점 수치 형식입니다. BF16보다 값 하나에 더 많은 메모리를 쓰며 수치를 더 세밀하게 표현할 수 있습니다.
본문으로 돌아가기CUDA — NVIDIA GPU에서 범용 계산을 실행하기 위한 소프트웨어 플랫폼입니다. CUDA용으로 만든 프로그램은 다른 GPU에서 그대로 동작한다고 보장되지 않습니다.
본문으로 돌아가기BF16 — 모델의 수를 저장하고 계산하는 16비트 부동소수점 형식입니다. 사용 가능 여부는 하드웨어와 실행 프로그램에 달려 있습니다.
본문으로 돌아가기GPU — 많은 계산을 병렬로 처리하는 프로세서입니다. AI 모델 실행에서는 모델 계산을 맡습니다.
본문으로 돌아가기MLX — Apple silicon용 머신러닝 프레임워크입니다. Apple silicon의 통합 메모리 구조를 활용하며, 지원 모델과 기능은 MLX 도구별로 다릅니다.
본문으로 돌아가기양자화 — 모델의 수치를 더 적은 비트로 표현하는 방법입니다. 메모리 사용량과 함께 정확도나 실행 속도도 달라질 수 있으며, 영향은 형식과 구현에 따릅니다.
본문으로 돌아가기PyTorch — AI 모델을 만들고 실행하는 소프트웨어 프레임워크입니다. 모델과 함께 호환되는 PyTorch 버전 및 하드웨어 지원도 확인해야 합니다.
본문으로 돌아가기Python 가상환경 — 프로젝트별로 Python 패키지를 분리해 설치하는 공간입니다. 패키지 버전 충돌을 줄이며 가상 머신과는 다릅니다.
본문으로 돌아가기