JEV는 얼마나 유용할까?
개요
얼마전에 나온 Decision AI 인 JEV 를 최근에 활용하고 있는데 처음 나왔을때만 해도 LLM 과 비교를 많이 했던 기억이 난다.
이제는 다들 용도가 조금 다르다는 것을 알고 계시는 것 같고, 여러가지 분야에서 활용하는 모습을 볼 수 있다. 또한 JEV 에 영감을 받은 다양한 모델들이 나오고 있는 모양인데 JEV 이외에는 직접 사용을 해보지는 않았다.
JEV 는 일반적으로 많이들 쓰이는 LLM 과는 다르게 "경량형 판별기"와 같은 인상을 많이 받아 왔는데, 저렴한 비용이 또 특징이라 의사결정이 필요한 ML 에도 영향을 끼칠 것으로 예상한다.
Decision AI, 온라인 스토어 활용 예시
Decision AI 를 활용할 수 있는 예시로 온라인 스토어의 에이전틱 워크플로우를 구성하는 사례를 이용해봤다.
- 위탁판매 온라인스토어의 업무 프로세스
- (고객) 상품선택 -> 옵션선택
- (고객) 상품 주문
예) 2차검수 - 시나노골드 2kg (14-16입) - (스토어) 주문 이벤트 발생
- (스토어) 도매 플랫폼에 주문상품 매칭
예) 시나노골드 황금사과 정품 2kg (14-16과) - (스토어) 도매 플랫폼에 발주 주문
- Decision AI 를 활용할 수 있는 업무 프로세스
온라인스토어에 정의된 상품명/옵션과
다양한 도매 플랫폼에 등록된 상품명/옵션의 이름이 다른 부분을
사람이 검수하여 도매 플랫폼에 발주해야 하는 업무를 JEV 로 대체한다. - JEV 질의 및 응답 예시
JEV의 역할은 결국 온라인 스토어의 상품명을 수많은 도매 플랫폼의 상품명 + 옵션명 목록에서 적절한 상품명 + 옵션명을 결정하는 것이다.
- 온라인 스토어 상품 및 옵션명
- 2차검수 - 시나노골드 2kg (14-16입)
- 도매 플랫폼 상품 및 옵션명
- 시나노골드 황금사과 정품 2kg (14-16과)
a. JEV Request Struct 예시
{
"event": "JEV_REQUEST",
"method": "systemOne",
"state": {
"order": {
"productName": "2차검수 - 시나노골드",
"optionName": "2kg (14-16입)"
},
"policy": "상품 품종, 중량, 개수가 일치해야 한다. '입'과 '과'는 동일한 개수 단위로 취급한다. '2차검수' 등 판매용 접두어는 무시한다. 명시되지 않은 등급은 임의로 추정하지 않는다. 정확하게 일치하는 상품이 없거나 여러 후보를 구별할 수 없다면 NONE을 선택한다."
},
"questions": {
"selected": {
"type": "choice",
"instructions": "주문과 정확히 일치하는 도매처 상품 및 옵션을 하나 선택하거나 NONE을 선택하라.",
"options": {
"P001": "시나노골드 사과 / 2kg (14-16과)",
"P002": "시나노골드 사과 / 2kg (10-12과)",
"P003": "시나노골드 사과 / 3kg (14-16과)",
"P004": "시나노골드 가정용 / 2kg (14-16과)",
"P005": "시나노골드 정품 / 2kg (14-16과)",
"P006": "시나노골드 사과 / 5kg (20-25과)",
"P007": "시나노골드 사과 / 2kg (16-18과)",
"P008": "시나노골드 사과 / 1kg (7-8과)",
"P009": "홍로 사과 / 2kg (14-16과)",
"P010": "부사 사과 / 2kg (14-16과)",
"NONE": "정확히 일치하는 후보가 없거나 정보가 부족함"
}
}
}
}b. JEV Response Struct 예시
{
"event": "JEV_RESPONSE",
"method": "systemOne",
"status": "success",
"answers": {
"selected": {
"choice": "P001",
"confidence": 0.94,
"probabilities": {
"P001": 0.94,
"P002": 0.01,
"P003": 0.01,
"P004": 0.02,
"P005": 0.01,
"P006": 0.002,
"P007": 0.003,
"P008": 0.002,
"P009": 0.001,
"P010": 0.001,
"NONE": 0.001
}
}
},
"usage": {
"input_tokens": 1850
},
"latencyMs": 420
}- LLM 질의 및 응답 예시
같은 역할을 LLM 이 처리 한다면 다음과 같은 프롬프트로 요청을 해야한다.
당신은 이커머스 주문 상품과 도매처 상품을 매칭하는 상품 선택 시스템입니다.
[목표]
스마트스토어 주문과 정확히 일치하는 도매처 상품 및 옵션을
아래 후보 중에서 하나만 선택하세요.
[주문 정보]
상품명: 2차검수 - 시나노골드
옵션명: 2kg (14-16입)
[도매처 상품 후보]
P001: 시나노골드 사과 / 2kg (14-16과)
P002: 시나노골드 사과 / 2kg (10-12과)
P003: 시나노골드 사과 / 3kg (14-16과)
P004: 시나노골드 가정용 / 2kg (14-16과)
P005: 시나노골드 정품 / 2kg (14-16과)
P006: 시나노골드 사과 / 5kg (20-25과)
P007: 시나노골드 사과 / 2kg (16-18과)
P008: 시나노골드 사과 / 1kg (7-8과)
P009: 홍로 사과 / 2kg (14-16과)
P010: 부사 사과 / 2kg (14-16과)
[판단 기준]
1. 상품 품종, 중량, 개수가 일치해야 합니다.
2. '입'과 '과'는 동일한 개수 단위로 취급합니다.
3. '2차검수' 등 판매용 접두어는 무시합니다.
4. 주문에 명시되지 않은 등급은 임의로 추정하지 않습니다.
5. 정확하게 일치하는 상품이 없거나 여러 후보를 구별할 수 없다면 NONE을 선택합니다.
6. 후보 목록에 없는 상품 ID를 생성해서는 안 됩니다.
[응답 형식]
반드시 다음 JSON 형식으로만 응답하세요.
설명이나 Markdown은 포함하지 마세요.
{
"selectedId": "P001~P010 또는 NONE"
}LLM vs JEV
용도 자체가 다른 모델이라고 볼 수 있으나 범용모델로서 LLM 과 JEV 를 비교해보기로 했다. LLM은 gpt-6-luna 모델을 사용하고 Codex App Server 형태로 cli 를 매번 호출하는 방식을 배제했다.
1) 상품후보 개수별 "정확도" 변화
위에서 확인한 요청방식을 보면 JEV 는 상품개수(30건/100건/300건) 만큼 상품명 + 옵션명 조합으로 Request Struct 의 options 에 추가 되는 형태고 LLM 또한 프롬프트에 상품명 + 옵션명이 추가되는 형태다.
아래는 규모별로 JEV 와 LLM(gpt-6-luna) 의 정확도 변화를 도식화 한 것이다. 그래프와 같이 LLM 의 경우 상품 개수가 많은 경우 정확도가 점점 떨어지는 것을 볼 수 있다.

2) 상품후보 개수별 "응답시간" 변화
아래는 상품 개수별로 P95 응답시간의 변화를 보여주고 있다. 응답시간은 각각 대체로 유사한 변화를 보여주고 있고 JEV가 LLM(gpt-6-luna) 에 비해 압도적인 속도를 보여주고 있다.

JEV의 용도에 대해 생각해보자
의사결정 모델이라는 기준에서 여러 ML 모델들을 떠올리게 되는데 JEV 자체도 범용 의사결정 모델이라는 관점으로 보면 이런 의사결정모델들도 Fine-tuning 이 가능하다면 특수 목적의 용도로도 쓸 수 있지 않을까 하는 생각도 해본다.
앞으로도 다양한 형태의 의사결정모델이 나올듯 하지만 처음에 제기 됐던 이슈가 JEV가 Multimodal 이 아니라는 것이었는데 어느새 TypeSafe AI 는 JEV 에 Image 를 Experimental 상태로 지원하기 시작했고 앞으로도 다양한 형태로 서비스를 만들수 있지 않을까 싶다.
JEV Image 테스트 (CAPTCHA 데이터)
JEV 의 Image 지원을 테스트 하기 위해서 고전적인 형태의 간단한 CAPTCHA 를 해결 할 수 있을지 테스트 해봤다.
1. CAPTCHA 이미지 데이터 출처
테스트에는 GitHub에 공개된 reCAPTCHA Study Dataset을 사용했고 이미지 선택 문제를 연구 목적으로 수집한 자전거·자동차·신호등 등 특정 객체가 포함한 이미지를 선택하는 문제를 제공한다.
테스트 페이지에서는 데이터셋에 저장된 3×3 또는 4×4 이미지 선택 문제를 불러와 실제 CAPTCHA와 유사한 형태로 표시하고 정답 정보도 함께 활용해 JEV 모델의 선택 결과를 평가하도록 한다.
2. JEV Image Models 테스트
아래와 같이 비교적 준수하게 테스트를 통과했고 개중에는 누락하거나 오류를 내기도 했다.
이 테스트라면 다양한 분야에서도 쓸 수 있을 듯하다. 예를 들어서 공장에서 불량품을 걸러내는 부분이나 온라인 마켓에서 후기 사진 검수 또는 성인 이미지 검수 등의 용도로도 쓸 수 있지 않을까 싶다. (비용도 저렴하다)




3. JEV Image, Request Struct
{
"method": "POST",
"url": "https://api.typesafe.ai/v1/systemone",
"headers": {
"Authorization": "Bearer <서버에서만 사용·비공개>",
"TypeSafe-Danger-Zone-Images": "true",
"Content-Type": "application/json",
"Accept": "application/json"
},
"body": {
"model": "jev-latest",
"state": {
"target_object": "tractors",
"tiles": {
"tile_0": "asset-68f2b61f-dcfb-4744-be7f-18749ea4c268",
"tile_1": "asset-d0669110-4665-4e0b-8f8a-b9cf99db2b2b",
"tile_2": "asset-40b670f5-4c54-4333-9200-ed4391c75e3e",
"tile_3": "asset-01c26a9b-e10f-490e-9ad0-14b426afae04",
"tile_4": "asset-d99b8b53-5f77-4760-86d6-be9a60b6079c",
"tile_5": "asset-8f9e3f56-8f48-4b05-b8a5-20ef6a2580de",
"tile_6": "asset-5bb20e70-007b-40e7-baa3-81daa5bbe95e",
"tile_7": "asset-5a52f0ec-190a-4f52-86c5-d223420e58c7",
"tile_8": "asset-42157d8c-17ac-4f5d-b58b-0950add8378d",
"tile_9": "asset-6a2bdfac-99c8-4bf1-83f9-369d5f506b97",
"tile_10": "asset-9a1c2aee-5e8a-4bed-8daf-a20a9c65d059",
"tile_11": "asset-56bfe7d8-62a2-40fe-b90d-ed82237ba990",
"tile_12": "asset-5c138bfc-71f6-4d9d-bc66-72c8539f2b36",
"tile_13": "asset-e232b96a-af9e-402f-b309-7a5e8f7b4f08",
"tile_14": "asset-86469f9d-4931-4530-9514-9f2306e90004",
"tile_15": "asset-0857c74a-df79-4397-ab26-57f425b42b18"
}
},
"assets": {
"asset-68f2b61f-dcfb-4744-be7f-18749ea4c268": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 5,980자 — 화면에서 생략>"
},
"asset-d0669110-4665-4e0b-8f8a-b9cf99db2b2b": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 6,092자 — 화면에서 생략>"
},
"asset-40b670f5-4c54-4333-9200-ed4391c75e3e": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 7,408자 — 화면에서 생략>"
},
"asset-01c26a9b-e10f-490e-9ad0-14b426afae04": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 8,224자 — 화면에서 생략>"
},
"asset-d99b8b53-5f77-4760-86d6-be9a60b6079c": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 12,520자 — 화면에서 생략>"
},
"asset-8f9e3f56-8f48-4b05-b8a5-20ef6a2580de": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 12,416자 — 화면에서 생략>"
},
"asset-5bb20e70-007b-40e7-baa3-81daa5bbe95e": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 12,540자 — 화면에서 생략>"
},
"asset-5a52f0ec-190a-4f52-86c5-d223420e58c7": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 12,896자 — 화면에서 생략>"
},
"asset-42157d8c-17ac-4f5d-b58b-0950add8378d": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 12,508자 — 화면에서 생략>"
},
"asset-6a2bdfac-99c8-4bf1-83f9-369d5f506b97": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 10,848자 — 화면에서 생략>"
},
"asset-9a1c2aee-5e8a-4bed-8daf-a20a9c65d059": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 9,016자 — 화면에서 생략>"
},
"asset-56bfe7d8-62a2-40fe-b90d-ed82237ba990": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 6,872자 — 화면에서 생략>"
},
"asset-5c138bfc-71f6-4d9d-bc66-72c8539f2b36": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 9,660자 — 화면에서 생략>"
},
"asset-e232b96a-af9e-402f-b309-7a5e8f7b4f08": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 8,240자 — 화면에서 생략>"
},
"asset-86469f9d-4931-4530-9514-9f2306e90004": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 8,612자 — 화면에서 생략>"
},
"asset-0857c74a-df79-4397-ab26-57f425b42b18": {
"type": "image",
"format": "jpg",
"data_base64": "<이미지 Base64 데이터 8,428자 — 화면에서 생략>"
}
},
"questions": {
"tile_0": {
"type": "choice",
"instructions": "Does `tiles.tile_0` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_1": {
"type": "choice",
"instructions": "Does `tiles.tile_1` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_2": {
"type": "choice",
"instructions": "Does `tiles.tile_2` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_3": {
"type": "choice",
"instructions": "Does `tiles.tile_3` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_4": {
"type": "choice",
"instructions": "Does `tiles.tile_4` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_5": {
"type": "choice",
"instructions": "Does `tiles.tile_5` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_6": {
"type": "choice",
"instructions": "Does `tiles.tile_6` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_7": {
"type": "choice",
"instructions": "Does `tiles.tile_7` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_8": {
"type": "choice",
"instructions": "Does `tiles.tile_8` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_9": {
"type": "choice",
"instructions": "Does `tiles.tile_9` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_10": {
"type": "choice",
"instructions": "Does `tiles.tile_10` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_11": {
"type": "choice",
"instructions": "Does `tiles.tile_11` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_12": {
"type": "choice",
"instructions": "Does `tiles.tile_12` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_13": {
"type": "choice",
"instructions": "Does `tiles.tile_13` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_14": {
"type": "choice",
"instructions": "Does `tiles.tile_14` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
},
"tile_15": {
"type": "choice",
"instructions": "Does `tiles.tile_15` visibly contain a tractors? Evaluate the image itself; do not infer from adjacent tiles.",
"criteria": {
"yes": "The target object is visibly present in this tile.",
"no": "The target object is absent or cannot be identified confidently."
}
}
}
},
"note": "실제 API로 보내는 JSON 구조입니다. 이미지 Base64와 API 키만 화면에서 숨깁니다. 정답은 전송되지 않습니다."
}