실행 프로그램과 확장

Jev-Omni란? 사진·음성·영상에서 답을 고르는 로컬 AI

현관 사진에서 필요한 정보가 문이 열려 있는지 하나뿐이라면, 사진 전체를 설명하는 긴 답변은 필요하지 않습니다. 녹음 파일에서도 내용을 모두 받아쓰기보다 확인할 일이 있었는지만 알고 싶을 때가 있습니다. Jev-Omni는 이런 작업을 위한 공개 분류 모델입니다. 상황과 질문, 선택지를 주면 각 선택지의 확률을 반환합니다. 다만 이름에 Jev가 들어간다고 TypeSafe AI의 Jev를 내려받는 것은 아닙니다. 별도 개발자가 Gemma 4 12B IT를 바탕으로 만든 독립 프로젝트이며, 현재 공개 실행 코드는 일반 채팅 앱에 모델 파일 하나를 넣는 방식과 다릅니다.

실행 조건과 핵심 내용
  • 문장을 생성하지 않고 선택지별 확률을 반환하며, 텍스트·이미지·음성·영상을 입력으로 받습니다.
  • 공개 기본 로더는 CUDA 전용입니다. FP32 가중치 약 50GB와 초기 로딩·멀티모달 구성의 추가 메모리를 고려해야 합니다.
  • H200 공개 수치는 최적화된 실행의 지연시간입니다. RTX·Mac 성능이나 다운로드부터 결과까지 걸리는 시간으로 읽으면 안 됩니다.

긴 설명보다 짧은 판단이 필요한 순간

집 안의 카메라가 현관을 찍고 있다고 해봅시다. 자동화에 필요한 것은 ‘문이 열림’, ‘문이 닫힘’, ‘사진으로 판단하기 어려움’ 중 하나입니다. 화면에 무슨 물건이 있는지 유창하게 설명해도, 프로그램은 마지막에 그 셋 중 하나를 골라야 합니다. 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이고, 기본 로더는 이를 FP324CUDA5에 올립니다. 모델 카드도 런타임 여유를 제외하고 약 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())"
Linux 셸 기준입니다. 마지막 값이 True여야 기본 CUDA 경로를 진행할 수 있습니다. 이 단계에서는 모델 가중치를 받지 않습니다.

텍스트 한 건이 된 다음 사진을 넣어봅니다

다음 코드를 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)
공개 로더를 사용하는 예제이며 이 사이트에서 GPU 실행을 검증한 결과는 아닙니다. 음성·영상은 modality와 media를 해당 파일에 맞게 바꿉니다.

공개 성능은 빠르지만, 어디까지 잰 숫자인가

모델 카드의 H200 결과는 웜 상태의 최적화된 백엔드에서 요청 20회의 중앙값입니다. 약 2천 토큰 텍스트는 83ms, 이미지는 26ms, 13초 음성은 31ms, 16프레임 영상은 504ms로 안내합니다. 전처리와 네트워크 시간은 별도입니다. 큰 영상 파일을 열고 프레임을 읽는 시간이나 처음 가중치를 올리는 시간까지 이 숫자에 포함되어 있지는 않습니다.

채팅 모델의 tok/s와 나란히 놓기도 어렵습니다. Jev-Omni는 긴 답변을 생성하지 않으므로 입력 처리와 분류 완료까지의 지연시간, 동시에 처리할 수 있는 요청 수가 더 적절한 지표입니다.

이 글의 H200 수치를 사이트의 RTX·Mac 속도 체감으로 변환하지 않은 이유입니다. 내 장비에서는 같은 파일·같은 질문으로 로딩을 끝낸 뒤 여러 번 재고, 전처리를 포함한 시간도 별도로 남기는 것이 좋습니다.

개발자가 공개한 병합 모델의 평가 결과
평가공개 점수읽을 때 볼 조건
DecisionBench Medium87.57%80개 시나리오·293문항, 시나리오 동일 가중 평균
JevBench86.15%매칭된 195개 그룹·231개 판단, 그룹 동일 가중 평균
MMAU63.10%1,000문항의 micro accuracy
MVBench53.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 구현으로 질문과 선택지를 먼저 다듬어도 됩니다.

그 과정에서 답이 좋아졌을 때, 더 큰 멀티모달 모델을 올릴 이유도 분명해집니다.

용어 각주

  1. 토큰모델이 입력이나 출력을 나누어 처리하는 단위입니다. 토큰 하나가 글자 하나나 일정한 시간 길이에 해당하지는 않습니다.

    본문으로 돌아가기
  2. 프레임영상의 한 장면을 이루는 단일 이미지입니다. 초당 프레임 수와 프레임 해상도는 서로 다른 속성입니다.

    본문으로 돌아가기
  3. 체크포인트학습된 모델의 가중치 등을 저장한 파일입니다. 같은 모델 계열도 버전이나 용도에 따라 다른 체크포인트를 쓸 수 있습니다.

    본문으로 돌아가기
  4. FP3232비트 부동소수점 수치 형식입니다. BF16보다 값 하나에 더 많은 메모리를 쓰며 수치를 더 세밀하게 표현할 수 있습니다.

    본문으로 돌아가기
  5. CUDANVIDIA GPU에서 범용 계산을 실행하기 위한 소프트웨어 플랫폼입니다. CUDA용으로 만든 프로그램은 다른 GPU에서 그대로 동작한다고 보장되지 않습니다.

    본문으로 돌아가기
  6. BF16모델의 수를 저장하고 계산하는 16비트 부동소수점 형식입니다. 사용 가능 여부는 하드웨어와 실행 프로그램에 달려 있습니다.

    본문으로 돌아가기
  7. GPU많은 계산을 병렬로 처리하는 프로세서입니다. AI 모델 실행에서는 모델 계산을 맡습니다.

    본문으로 돌아가기
  8. MLXApple silicon용 머신러닝 프레임워크입니다. Apple silicon의 통합 메모리 구조를 활용하며, 지원 모델과 기능은 MLX 도구별로 다릅니다.

    본문으로 돌아가기
  9. 양자화모델의 수치를 더 적은 비트로 표현하는 방법입니다. 메모리 사용량과 함께 정확도나 실행 속도도 달라질 수 있으며, 영향은 형식과 구현에 따릅니다.

    본문으로 돌아가기
  10. PyTorchAI 모델을 만들고 실행하는 소프트웨어 프레임워크입니다. 모델과 함께 호환되는 PyTorch 버전 및 하드웨어 지원도 확인해야 합니다.

    본문으로 돌아가기
  11. Python 가상환경프로젝트별로 Python 패키지를 분리해 설치하는 공간입니다. 패키지 버전 충돌을 줄이며 가상 머신과는 다릅니다.

    본문으로 돌아가기