System One 계열의 새로운 추출 모델, Clairic 소개
TMT오늘 저희는 새로운 System One 방식 모델 계열인 추출 모델(extraction model)의 프리뷰를 발표합니다. 그 첫 모델인 Clairic은 지금 Workers AI에서 @cf/cloudflare/clairic으로 바로 쓸 수 있습니다. 이 모델은 곧 오픈 웨이트로 공개할 계획입니다. Clairic은 비정형 입력에서 값을 추출하고, 계산하고, 추정하고, 예측할 수 있는 추출 모델이며, 이 모든 일을 기존 LLM보다 훨씬 높은 정확도와 빠른 응답 속도, 저렴한 비용으로 해냅니다.
배경
한 달 전 TypeSafe가 System One 모델을 발표하자 업계가 크게 들썩였습니다. TypeSafe가 블로그에서 언급했듯이, 그리고 대니얼 카너먼의 책 생각에 관한 생각(Thinking, Fast and Slow)이 정의한 대로, System One 모델은 빠르고 정확해야 합니다. 이 점에서 (LLM처럼) 신중하게 추론할 수 있는 System Two 모델과 대비됩니다. 이와 함께 TypeSafe는 Jev를 선보였습니다. Jev는 특정 용도에 딱 맞게 만든 모델로, 좁은 분야에 특화된 만큼 가격도 부담 없게 매겨졌습니다. Jev는 LLM이 실패하던 곳에서 뛰어난 성능을 보였고, 사용자가 확률과 타입이 잘 정해진 출력을 바탕으로 결정을 내리도록 도왔습니다. Jev가 등장하자 사람들은 LLM이 아닌 새로운 계열의 모델과, 그 모델을 자신의 워크플로에 통합하는 방법을 고민하기 시작했습니다.
저희는 System One 모델이라는 개념에서 영감을 받아, LLM이 비효율적인 다른 작업은 없을지 생각해 보기 시작했습니다. 오늘날 프런티어 LLM으로 가는 구조화된 출력 호출 중에는 같은 모양이 계속 반복되는 것이 많습니다. 송장 합계는 얼마인가? 언제 배송됐나? 며칠이나 늦었나? 이 수리에는 얼마가 들까? 앞으로 24시간 동안 트래픽은 어떻게 될까? 이 중 어느 것도 답을 미리 나열해 둘 수 없는데, 결정 모델이 확률을 매기려면 바로 그런 목록이 필요합니다. 그래서 저희는 오늘 소개하는 모델 계열, 즉 System One 추출 모델에 이르렀습니다.
System One 추출 모델 소개
지금까지 System One 모델은 모두 결정 모델이었습니다. Jev와 Clef는 입력 상태와 질문 목록을 받아, 입력과 나열된 질문에 대한 확률을 돌려줍니다. Clairic은 새로운 계열인 System One 추출 모델의 첫 모델입니다. 여전히 빠르고, 타입이 있고, 저렴하지만, Clairic은 입력에서 직접 추출하거나, 입력으로 계산하거나, 입력 너머를 예측한 값으로 답합니다.
대부분의 모델 작업은 세 가지 출력 중 하나를 요구합니다. 숫자, 정해진 집합 안의 선택지, 아니면 자유 형식의 텍스트입니다. Clairic은 첫 번째를 맡아 80% 범위와 함께 숫자를 돌려주고, 이름이나 날짜, 목록처럼 타입이 있는 값도 입력에서 뽑아냅니다. Clef는 두 번째를 맡아 선택지 중에서 고르고 선택지마다 확률을 돌려줍니다. 세 번째는 LLM이 맡습니다. Clairic과 Clef는 추론하거나 토큰을 생성하지 않고 한 번의 패스로 답하기 때문에, 저희는 두 모델을 System One 모델이라고 부릅니다. 두 모델은 입력에 대해서만 요금을 받고 보통 1초 안에 응답하지만, 같은 단계를 추론으로 풀어내는 LLM은 몇 초가 걸립니다.
추출 모델이 돌려줄 수 있는 값은 다음과 같습니다.
- 추출된 값: 이름, 주문 번호, 설명처럼 입력에서 그대로 가져온 텍스트입니다. 각 값은 문자 오프셋과 신뢰도 점수가 붙은 스팬(span)으로 돌아옵니다.
- 그리고 계산된 값: 입력에서 읽어 내거나 입력을 바탕으로 계산한 숫자, 날짜, 시각, 날짜와 시각, 기간, 목록입니다. 각 타입의 규칙(예를 들어 센트 단위라면 소수점 둘째 자리)을 따르며, 신뢰도 점수가 함께 붙습니다.
- 추정된 값: 입력에 적혀 있지는 않지만 입력이 근거를 제공하는 값입니다. 각 값은 지정한 범위 안에서 지정한 간격으로 나뉜 분포로 돌아오며, 중앙값과 80% 구간이 함께 붙습니다.
- 예측된 값: 시계열의 미래 값입니다. 앞으로의 단계마다 추정값이 하나씩 나오고, 각각 고유한 80% 구간이 붙습니다.
또한 토큰을 생성하지 않기 때문에, LLM과 같은 방식으로 타입이 틀린 답을 내놓거나 '환각'을 일으킬 수 없습니다(물론 실수는 할 수 있습니다). 출력은 요청한 타입의 값이거나, 모델이 입력에서 답을 찾지 못했을 때는 null입니다. 출력마다 신뢰도 점수도 함께 나오므로, 모델을 믿어도 될지 아니면 다시 확인해야 할지 판단하는 데 도움이 됩니다.
추출 모델이 System One 모델과 System Two 모델 전체 구도에서 어디에 자리하는지는 다음과 같습니다.
| System One: 추출 | System One: 결정 | System Two | |
|---|---|---|---|
| 예시 모델 | Clairic | Jev, Clef | GPT, Claude, Gemini, DeepSeek |
| 샘플링 | 한 번의 병렬 패스 | 한 번의 병렬 패스 | 한 번에 토큰 하나씩 |
| 목적 | 값 예측 | 결정 | 글쓰기와 추론 |
| ML 관점 | 회귀와 추출 | 분류 | 생성 |
| 사고 방식 | 시스템 1: 빠름, 한 번에 처리 | 시스템 1: 빠름, 한 번에 처리 | 시스템 2: 느림, 신중함 |
| 출력 | 타입이 있는 값: 스팬, 숫자, 날짜, 시각, 목록, 분포와 보정된 확률 | 타입이 있는 결정: 선택지와 보정된 확률 | 자유 형식 문자열 |
| 출력 공간 | 연속적이지만, 스키마에 따라 타입과 범위가 정해짐 | 직접 나열한 유한한 선택지 집합 | 무엇이든 |
| 답하는 질문 | 금액은 얼마인가? 언제 일어나는가? 얼마나 될까? | 어느 범주인가? 정당한가? 어떤 조치를 취해야 할까? | 왜 일어났을까? 어떻게 접근해야 할까? 고칠 수 있을까? |
| 출력이 항상 유효한 응답인가? | 예: 모든 답은 선언한 타입의 값(또는 null)이며 지정한 범위 안에 있음 | 예: 답은 항상 나열한 선택지 중 하나 | 아니요: 문자열을 파싱하고 검사해야 함 |
이 모델들은 함께 맞물려 동작하면서, 실제 데이터를 파싱하고, 입력을 바탕으로 결정을 내리고, 행동으로 옮기는 데까지 한 걸음 더 다가가도록 돕습니다. 추출 모델은 날것의 입력을 타입이 있는 값으로 바꾸고, 결정 모델은 값을 결정으로 바꾸며, LLM은 결정을 말로 바꿉니다.
요청이 동작하는 방식
Clairic은 LLM과 다르게 설계되었습니다. 결정 모델과 마찬가지로 한 번의 포워드 패스로 입력 토큰만 처리하므로, 출력 토큰에는 요금이 붙지 않습니다. 특정 용도에서는 LLM보다 훨씬 빠르고, 저렴하고, 정확합니다.
요청은 state(읽을 텍스트와, 선택 사항인 이미지 최대 4장)와 타입이 있는 fields 맵으로 이루어집니다. 필드마다 이름을 붙이고, 타입과 함께 평이한 문장으로 쓴 instructions(선택 사항)를 지정하면, 필드마다 타입이 있는 답을 하나씩 받습니다. 이 답은 모두 한 번의 병렬 패스에서 나옵니다. 추론도 출력 토큰도 없고 모든 계산이 한 번의 포워드 패스로 끝나기 때문에, 빠르면서도 저렴합니다.
| 타입 | 반환값 |
|---|---|
text | 입력의 특정 스팬과 그 오프셋 |
number | 읽어 내거나 계산한 숫자로, integer와 decimals 설정을 따름 |
date, time, datetime | ISO 형식의 달력 날짜와 유효한 시각 |
duration | 선택한 단위로 나타낸 시간의 길이 |
list | 조건에 맞는 텍스트·숫자·날짜를 입력에 나온 순서대로 나열한 목록 |
estimate | [min, max] 범위 안에서 step 간격으로 나뉜 분포(선형 또는 로그 스케일) |
forecast | 시계열의 미래 단계마다 하나씩 나오는 추정값 |
모든 스칼라 답에는 p_null(값이 입력에 없을 확률)과 confidence가 붙습니다. 모든 estimate 답에는 중앙값과 80% 구간(p10부터 p90까지)이 붙고, 요청하면 99개 백분위수 전체도 받을 수 있습니다. 필드 수에는 제한이 없습니다. 필드가 너무 많아 한 번의 패스에 입력과 함께 담기지 않으면, 서버가 필드를 여러 병렬 패스로 나눠 각 패스가 입력 전체를 보게 한 다음 답을 합칩니다.
다음은 모델의 기능을 보여 주는 몇 가지 예시입니다. 물론 이런 기능을 워크플로에서 쓰려면 알맞은 입력이 필요합니다.
예시: 값 추출하기
추출은 아마 오늘날 LLM에게 가장 흔하게 맡기는 일일 것입니다. "송장 번호, 공급업체, 지급 기한을 JSON으로 돌려줘" 같은 식입니다. 대부분은 잘 되지만, 실패하는 경우를 잡아내기가 어렵습니다. 출력이 올바른 JSON이 아닐 수도 있고, 생성 과정에서 숫자 하나를 잘못 읽을 수도 있으며, 텍스트 발췌가 일단 돌아오면 그 내용이 원문 어디에 있었는지 추적할 방법이 없습니다. 그래서 대부분은 이를 막으려고 여러 겹의 파싱, 스키마 검증, 재시도, 표본 검사를 갖춘 추출 파이프라인을 만듭니다. 게다가 모든 문서의 모든 필드마다 추론 토큰과 출력 토큰 비용을 냅니다.
Clairic은 다르게 동작합니다. 텍스트로 답을 생성하지 않습니다. 대신 다음과 같은 결과를 얻습니다.
- 입력에서 추출한 값을 돌려주므로, 답이 입력에 근거를 둡니다.
- 계산된 값을 돌려주므로, 비정형 데이터를 미리 정리하지 않고도 파싱할 수 있습니다.
- 문자 오프셋 스팬을 돌려주므로, 데이터가 입력의 어디에 있었는지 짚을 수 있습니다.
- 신뢰도 라벨이 붙으므로, 어떤 값을 다시 확인해야 할지 판단할 수 있습니다.
- 강한 타입의 출력을 내므로, 숫자와 날짜가 각 타입의 규칙에 맞게 만들어집니다(예: 센트 필드는 소수점 둘째 자리까지).
- null 값을 처리합니다. 필드 값이 없으면 답으로
null이 돌아옵니다(null일 확률 추정치와 추측값도 함께 옵니다). - 더 저렴하고 빠르게 답합니다. 모든 필드가 같은 병렬 패스에서 답을 얻기 때문입니다. 그래서 필드 30개를 요청해도 3개를 요청할 때와 비용이 거의 같습니다.
예시를 하나 따라가면서 Clairic이 비정형 데이터에서 값을 추출하고 추정하는 방식을 살펴보겠습니다. 고객 지원 이메일을 예로 들어 보겠습니다.
Hi, order A-88412 arrived on Sept 28, 2026 with a cracked screen and a dented corner. I paid $649.00 plus $52.10 tax. It's now Oct 9, 2026 and I'd like this fixed or refunded. Thanks, Dana
Worker에서는 이 데이터를 처리하도록 Clairic에 다음과 같이 요청합니다.
const { answers } = await env.AI.run("@cf/cloudflare/clairic", {
state: email,
fields: {
order_id: { type: "text", instructions: "Order number" },
delivered_on: { type: "date", instructions: "Delivery date" },
amount_paid: { type: "number", decimals: 2, unit: "USD", instructions: "Total paid including tax" },
days_since_delivery: { type: "duration", unit: "days", integer: true,
instructions: "Days from delivery to the date the customer wrote" },
damage: { type: "list", items: "text", instructions: "Each kind of damage described" },
tracking_number: { type: "text" },
},
});Clairic은 추출한 값, 입력에서의 스팬, null일 확률(p_null), 신뢰도 점수를 돌려줍니다.
{
"order_id": {
"type": "text",
"p_null": 3.4e-6,
"span": [10, 17],
"guess": "A-88412",
"confidence": 0.999957,
"value": "A-88412"
},
"delivered_on": {
"type": "date",
"p_null": 6.5e-8,
"guess": "2026-09-28",
"confidence": 0.999999,
"value": "2026-09-28"
},
"amount_paid": {
"type": "number",
"p_null": 1.6e-5,
"guess": 701.1,
"confidence": 0.999944,
"value": 701.1
},
"days_since_delivery": {
"type": "duration",
"p_null": 6.1e-9,
"unit": "days",
"guess": 11,
"confidence": 0.999999,
"value": 11
},
"damage": {
"type": "list",
"value": ["cracked screen", "dented corner"],
"spans": [[50, 64], [71, 84]]
},
"tracking_number": {
"type": "text",
"p_null": 1,
"span": [106, 112],
"guess": "$52.10",
"confidence": 0.416016,
"value": null
}
}눈여겨볼 점이 몇 가지 있습니다.
amount_paid는 이메일 어디에도 적혀 있지 않습니다. 이 예시에서 Clairic은 같은 패스 안에서 가격과 세금을 더해 그 합을 돌려줍니다.days_since_delivery역시 입력에 직접 나와 있지 않고, 텍스트에 있는 두 날짜로 계산한 값입니다.damage는 두 가지 손상을 정확한 스팬으로 나열하므로, 원문에서 해당 부분을 강조 표시할 수 있습니다.tracking_number는 이메일에 없으므로, 그럴듯해 보이는 추측 대신null로 돌아옵니다.guess는 그렇지 않았다면 모델이 골랐을 값을 보여 줍니다.
Clairic은 이미지도 처리합니다
실제로 찍은 영수증 사진입니다. 글자가 선명하지 않고, 사진 각도 때문에 알아보기가 더 어렵습니다. 저희는 이 이미지를 Clairic에 넘겨 무엇을 추출할 수 있는지 확인해 봤습니다.
{
"model": "clairic",
"answers": {
"order_number": {
"type": "number",
"p_null": 0.0040206750854849815,
"guess": 77245,
"confidence": 0.776249383996532,
"value": 77245
},
"purchased_at": {
"type": "datetime",
"p_null": 4.136094133855295e-08,
"guess": "2026-07-01T13:34:00",
"confidence": 0.831464227002992,
"value": "2026-07-01T13:34:00"
},
"quantity": {
"type": "number",
"p_null": 5.2313655629632194e-08,
"guess": 2,
"confidence": 0.9997007500403496,
"value": 2
},
"unit_price": {
"type": "number",
"p_null": 0.001599092734977603,
"guess": 7.99,
"confidence": 0.9991279019989127,
"value": 7.99
},
"subtotal": {
"type": "number",
"p_null": 9.69956488461321e-08,
"guess": 15.98,
"confidence": 0.9999881983893096,
"value": 15.98
},
"sales_tax": {
"type": "number",
"p_null": 2.5511653802823275e-06,
"guess": 0,
"confidence": 0.9999800924450729,
"value": 0
},
"tip": {
"type": "number",
"p_null": 5.953857908025384e-05,
"guess": 2.39,
"confidence": 0.9335768781214697,
"value": 2.39
},
"discount": {
"type": "number",
"p_null": 0.9994148015975952,
"guess": 0,
"confidence": 0.91852733929319,
"value": null
}
}
}보시다시피 Clairic은 이미지에서 모든 값을 신뢰도 점수와 함께 추출했습니다. 영수증에 할인이 표시되어 있지 않다는 점도 정확히 판단해, 값을 null로 돌려줬습니다.
예시: 값 추정하기
어떤 값은 입력에 아예 없지만, 입력에 그 값을 뒷받침하는 근거가 담겨 있습니다. 예를 들어 값이 텍스트에 그대로 적혀 있지 않아도 주변 값으로 알아낼 수 있는 경우가 있습니다. LLM에게 추정을 요청하면 보통 모델이 얼마나 확신하는지 전혀 알 수 없는 숫자 하나를 받습니다. LLM은 무난한 추측을 하거나, 환각을 일으키거나, 추론을 거듭하며 답 주변을 맴돕니다. 추정값을 하나 얻더라도, 그 뒤의 처리 단계에서는 확신 있는 180달러와 확신 없는 180달러를 구분할 수 없습니다. 그래서 주어진 상황에서 무엇을 자동화해도 될지 판단하는 데 도움이 되지 않습니다. 게다가 LLM으로 추론하는 방식은 훨씬 느리고 비쌉니다.
결정 모델은 구간("100달러 미만", "100~500달러", …) 중 하나를 고르는 방식으로 추정을 흉내 낼 수 있습니다. 하지만 구간은 거칠고, 구간마다 입력 토큰이 늘어나며, 범주가 새로 생길 때마다 모델이 결정을 내리는 과정에서 헷갈릴 요인도 늘어납니다.
Clairic은 지정한 범위에 걸친 분포를 돌려줍니다. 점 추정값, 중앙값, 80% 구간, 그리고 요청하면 모든 백분위수를 받을 수 있습니다. 추정값은 지정한 범위 안에 들어가도록 설계되어 있어서, 나중에 값을 잘라 내거나 반올림할 필요가 없습니다. 구간의 폭은 데이터에 대한 확신을 반영합니다. 범위가 좁으면 확신이 높다는 뜻이고 넓으면 확신이 낮다는 뜻이며, 이 정보를 바탕으로 추가 검사를 할지 정할 수 있습니다.
이번에는 Clairic이 과거 주택 가격과 비교 대상 매물의 거래 내역을 보고 추정값을 내는 예시입니다.
const { answers } = await env.AI.run("@cf/cloudflare/clairic", {
state: \`Comparable sales:
sqft,beds,year_built,neighborhood,sale_price
1450,3,1998,Elm Park,412000
2100,4,2006,Elm Park,585000
980,2,1975,Riverside,265000
1600,3,2003,Elm Park,449000
1300,3,1990,Riverside,318000
Subject property:
sqft,beds,year_built,neighborhood
1620,3,2001,Elm Park\`,
fields: {
sale_price: { type: "estimate", unit: "USD", min: 50000, max: 5000000, scale: "log", step: 1000 }
});Clairic은 다음과 같은 추정값을 돌려줍니다.
{
"sale_price": { "type": "estimate", "value": 418000, "median": 415000, "p10": 370000, "p90": 470000, "p_below": 0.0, "p_above": 0.0 }
}값은 항상 지정한 범위 안에 들어가고, 구간의 폭은 입력이 예측에 얼마나 많은 정보를 주는지 보여 줍니다. 가격은 구간이 좁고(37만~47만 달러), 매물이 시장에 나와 있던 기간은 구간이 넓습니다(24~148). 필드 수에 제한이 없고 병렬로 답을 얻기 때문에, 한 번의 호출로 여러 항목에 점수를 매기고(후보, 잠재 고객, 매물마다 추정값 하나씩) 코드에서 정렬할 수 있습니다.
예시: 값 예측하기
범용 모델에게 시계열 값을 예측하는 일은 꽤 어렵습니다. 보통은 지표마다 전용 파이프라인을 만들거나(데이터를 파싱하고, 모델을 학습시키고, 튜닝하고, 배포하는 과정), 36개월 치 숫자를 LLM에 붙여 넣고 다음 3개월 치를 물어봐야 합니다. 첫 번째 방법은 정확하지만, 새 시계열마다 구축하려면 비용과 시간이 정말 많이 듭니다. 두 번째 방법은 쉽지만, 구간 없이 점 예측값만 나오고, 프롬프트 문구에 따라 예측이 달라지며, 답의 신뢰도도 제한적입니다.
Clairic은 그 둘 사이에 있습니다. 전용 시계열 모델을 대체한다고 주장하는 것은 아니지만, 일반 LLM보다는 조금 더 빠르고 저렴합니다. forecast 필드는 state에 평문으로 넣은 과거 데이터를 받아, 앞으로의 단계마다 값 하나와 80% 구간을 지정한 범위 안에서 돌려줍니다. 과거 데이터가 CSV로 내보낸 파일이든, 대시보드에서 복사해 붙여 넣은 내용이든, 메모가 섞인 행이든, 이미 가지고 있는 형태 그대로 읽으므로 데이터를 미리 정리하지 않아도 되는 경우가 많습니다.
실제 데이터에서도 잘 통하는지 보려고 저희는 공개된 시계열을 사용했습니다. 미국 교통보안청(TSA)이 매일 미국 공항 검색대에서 검색하는 사람 수입니다. 저희는 21일 연속으로 매일 아침 그때까지의 실제 인원수를 주고, Clairic에게 다음 날 인원수를 물었습니다.
const { answers } = await env.AI.run("@cf/cloudflare/clairic", {
state: \`Daily number of people screened at TSA checkpoints at US airports.
date,weekday,travelers
2026-07-16,Thu,2850229
...
2026-10-13,Tue,2353356
Forecast date: 2026-10-14 (Wed)\`,
fields: {
travelers: { type: "forecast", horizon: 1, interval: "day",
min: 500000, max: 4000000, scale: "log",
instructions: "Number of people screened tomorrow" },
},
});결과는 다음과 같습니다.
{
"travelers": { "type": "forecast", "value": [2416117], "median": [2419283], "p10": [2270774], "p90": [2556769] }
}실제로 그날 TSA가 검색한 인원은 241만 9,474명으로, Clairic이 예측한 중앙값 241만 9,283명과 거의 같았습니다.
데이터: TSA 검색대 통과 여행객 수, 2026년 10월 15일 확인.
21일 동안 Clairic의 예측은 평균 3.3% 빗나갔고, 실제 인원수 21개 중 17개가 80% 구간 안에 들어왔습니다. 80% 구간이라면 마땅히 보여야 할 결과입니다. Clairic은 숫자만 보고 주간 리듬을 잡아냈습니다. 화요일과 토요일은 한산하고, 목요일, 금요일, 일요일은 붐볐습니다.
빗나간 날들도 흥미롭습니다. 구간을 벗어난 4일 중 3일이 콜럼버스 데이 연휴 주말이었는데, 이때는 이전 몇 주의 흐름으로 예상한 것보다 더 많은 사람이 비행기를 탔습니다. Clairic은 시계열의 패턴을 바탕으로 예측하지만, 공휴일처럼 시계열에 드러나지 않는 사건은 반영하지 않습니다.
빠른 생각과 느린 생각
이 모델들은 기존의 에이전트 워크플로와 나란히 쓰도록 설계되었습니다. 추출 모델은 값을 예측하고, 결정 모델은 그 값으로 무엇을 할지 정하며, LLM은 그 값을 가지고 행동합니다. System One 모델과 System Two 모델의 완벽한 조합입니다. 지금까지는 LLM을 위해 데이터를 손으로 추출하거나, LLM에게 지저분한 데이터를 파싱하게 해야 했습니다(이 방식은 비용과 시간이 많이 들고 환각으로 이어질 수 있습니다). 이 조합은 그 사이의 빈틈을 메워 줍니다. System One 추출 모델을 쓰면 실제 데이터를 더 빠르고, 효율적이고, 정확하게 다룰 수 있습니다.
앞에서 본 제품 파손 청구를 예로 들어, 모든 모델이 어떻게 함께 동작하는지 보여 드리겠습니다. 이 예시는 여기서 직접 써 볼 수 있는 라이브 데모로도 만들어 두었습니다.
// 1. Clairic이 이메일을 값으로 바꿉니다
const facts = (await env.AI.run("@cf/cloudflare/clairic", {
state: email,
fields: {
customer_name: { type: "text", instructions: "Customer's first name" },
order_id: { type: "text", instructions: "Order number" },
amount_paid: { type: "number", decimals: 2, unit: "USD", instructions: "Total paid including tax" },
days_since_delivery: { type: "duration", unit: "days", integer: true,
instructions: "Days from delivery to the date the customer wrote" },
damage: { type: "list", items: "text", instructions: "Each kind of damage described" },
repair_cost: { type: "estimate", unit: "USD", min: 10, max: 5000, scale: "log", step: 1,
instructions: "Cost to repair the damage described" },
},
})).answers;
const { customer_name, order_id, amount_paid, days_since_delivery, damage, repair_cost } = facts;
// 2. Clef는 원본 이메일이 아니라 Clairic의 값과 정책을 바탕으로 결정합니다
const options = {
refund: "Full refund of the amount paid",
repair: "Free repair, with a prepaid shipping label",
};
const { choice } = (await env.AI.run("@cf/cloudflare/clef", {
state: \`Damage claim for order ${order_id.value}.
Paid: $${amount_paid.value.toFixed(2)}. Delivered ${days_since_delivery.value} days ago.
Damage reported: ${damage.value.join(", ")}.
Estimated repair cost: $${repair_cost.median} (80% range $${repair_cost.p10}-$${repair_cost.p90}).
Policy: refunds within 30 days of delivery. Prefer repair when it costs less than 60% of the price and the damage doesn't stop the product from working.\`,
questions: {
resolution: { type: "choice", instructions: "What should we offer?", criteria: options },
},
})).answers.resolution;
// 3. LLM이 결정과 필요한 사실만 가지고 답장을 씁니다
const { response } = await env.AI.run("@cf/zai-org/glm-5.3", {
messages: [{
role: "user",
content: \`Write a short, warm reply to ${customer_name.value}. Use only these facts: order ${order_id.value}; \` +
\`damage: ${damage.value.join(", ")}; what happens next: ${options[choice]}. Under 60 words.\`,
}],
});단계마다 이전 단계보다 깔끔한 입력을 받습니다. Clef는 자유 형식의 이메일 대신, 타입이 있는 값을 다섯 줄로 요약한 내용을 보고 결정합니다. 자유 형식의 이메일은 프롬프트 인젝션에 취약할 수도 있습니다. LLM은 이메일을 전혀 보지 않고 결정과 필요한 예측값만 보므로, 잘못 쓸 수 있는 숫자가 그만큼 줄어듭니다. 모든 단계에 타입이 있어 나중에 검증할 수 있고, 텍스트를 생성하는 단계는 하나뿐입니다. 이 파이프라인을 LLM만으로 만들면 세 단계 모두 생성 호출이 되고, 답장에 들어간 값을 모두 손으로 확인해야 합니다.
저희는 이 파이프라인을 LLM만 쓰는 버전과 비교해 돌려 봤고, 두 버전 모두 답장은 GLM-5.3이 썼습니다. LLM만 쓰는 버전에서는 같은 이메일, 정책, 프롬프트를 바탕으로 추출과 결정도 GLM-5.3이 맡습니다.
| Clairic → Clef → GLM-5.3 | 모든 단계에 GLM-5.3 | |
|---|---|---|
| 전체 지연 시간 | 19.3초 | 61.7초 |
| 1. 추출 | Clairic: 0.46초 | GLM-5.3: 16.1초 |
| 2. 결정 | Clef: 0.22초 | GLM-5.3: 21.9초 |
| 3. 답장 | GLM-5.3: 18.6초 | GLM-5.3: 16.4초 |
| 입력 토큰 | 701(청구 100만 건당 184달러) | 390(청구 100만 건당 546달러) |
| 출력 토큰 | 1,329(청구 100만 건당 5,848달러) | 2,544(청구 100만 건당 1만 1,194달러) |
| 청구 100만 건당 비용 | 6,032달러 | 1만 1,740달러 |
연쇄 파이프라인(cascade)은 19.3초 만에 끝나, 61.7초가 걸린 쪽보다 시간이 69% 줄었습니다. 약 3.2배 빠른 셈입니다. Clairic과 Clef는 추출과 결정을 합쳐 1초도 안 되는 시간에 처리했지만, GLM-5.3은 같은 두 단계에 38초가 걸렸습니다. 연쇄 파이프라인은 LLM 전용 파이프라인보다 비용도 49% 적게 듭니다. GLM을 쓴 두 파이프라인 모두 매번 사실과 결정을 정확히 맞혔지만, Clairic의 수리비 추정값은 매번 같았던 반면 GLM-5.3의 추정값은 실행할 때마다 바뀌었습니다(250달러, 250달러, 220달러였고 범위도 매번 달랐습니다).
특히 LLM 전용 파이프라인에서는 Gemma 4와 Qwen이 모두 이 작업에 실패했습니다. 입력에서 repair_cost 같은 값을 추론해 내지 못했기 때문인데, 이 결과는 LLM이 데이터 추출 작업에 그다지 뛰어나지 않다는 것을 보여 줍니다.
프리뷰 릴리스
오늘 저희는 Workers AI에서 Clairic의 호스팅 엔드포인트를 공개합니다. 이 모델은 곧 오픈 웨이트로도 공개할 계획입니다. 저희는 먼저 System One 추출 모델이라는 개념을 소개하는 시간을 갖고 싶었습니다. 그래야 이 계열의 모델이 어떤 워크플로에 알맞게 들어갈지 고민해 보실 수 있기 때문입니다.
현재 엔드포인트는 초기 체크포인트이며, 앞으로 더 좋아질 것으로 예상합니다. 지금까지의 초기 인상은 다음과 같습니다.
- 읽기는 강하지만, 여러 단계의 산술은 아직 약합니다. 한두 단계짜리 계산(합계, 차이, 단위 변환, 날짜 계산)은 믿을 만해 보입니다. 서로 의존하는 단계가 길게 이어지면, 스크래치패드 없이 한 번에 처리하는 모델은 무엇이든 어려워합니다. 표의 여러 행에 걸쳐 값을 집계하는 일도 마찬가지입니다. 적어도 지금은 Clairic에게 값을 예측하게 하고, 계산은 코드에 맡기세요.
- 추정에는 근거가 필요합니다. Clairic은 입력에 비교 대상, 과거 데이터, 설명 텍스트가 있을 때 가장 잘 추정합니다. 근거가 없는 값을 요청하면 구체적인 답을 얻기 어려울 수 있습니다.
- 보정 수준은 측정해서 확인한 것이며, 보장되지는 않습니다. 구간은 보정되도록 학습되었고 대부분의 홀드아웃 세트에서 실제로 보정되어 있지만, 낯선 데이터에서는 구간이 좁게 나올 수 있습니다.
- 예측 기능은 기본적인 수준입니다. 이 모델은 특정 데이터로 학습한 시계열 모델을 정확하게 대체하거나 그만큼 정확하게 예측하도록 설계되지 않았습니다. 세밀한 장기 예측이 아니라, 중요도가 낮은 일반적인 패턴 맞추기처럼 알맞은 곳에 쓰세요.
- 신뢰도를 활용하세요. 이 아키텍처는 모든 답이 형식에 맞게 나오도록 보장할 뿐, 반드시 정확하도록 보장하지는 않습니다.
confidence,p_null, 구간을 활용해 (알맞은 워크플로 맥락에서) 무엇을 자동화하고 무엇을 추가 검토로 넘길지 정하세요.
저희는 체크포인트마다 모델의 산술, 추정, 예측 능력을 계속 개선해 나가겠습니다. 작업을 좀 더 진행한 뒤에는 누구나 자유롭게 다뤄 볼 수 있도록 모델을 오픈 웨이트로 공개할 계획입니다.
직접 써 보기
Clairic은 Workers AI에서 @cf/cloudflare/clairic으로 프리뷰를 제공합니다. Worker에서는 env.AI.run()으로, 그 밖의 어디에서든 REST API로 호출할 수 있습니다. 전체 모델 문서는 여기에 있고, 추출 모델 API가 어떻게 생겼는지 설명하는 새 개념 문서도 있습니다.
추신. Clef라는 이름의 어원을 좋아해 주셔서, 이번에는 Clairic이라는 이름을 어떻게 정했는지 말씀드리겠습니다. 저희는 먼저 모델 이름을 주제와 소리 면에서 Clef와 비슷하게 짓고 싶었습니다. 그래서 떠오른 것이 Clair였습니다. 같은 'cl' 소리로 시작하고, 음악에도 뿌리가 있습니다('Clair de Lune', 달빛). 더 중요하게는, 이름이 모델의 성격을 잘 드러내기를 바랐습니다. Clairic 모델은 입력 자료 묶음에서 데이터를 명확하게(clearly) 추출하고, 장부 정리 같은 작업에서 정확성을 지키는 사무(clerical) 작업을 도울 수 있어야 합니다. 모델의 예측 기능은 'Clair'라는 어근에 기댑니다. 투시력(clairvoyance)처럼 미래 값을 추정하고 예측할 수 있게 해 준다는 뜻입니다. 마지막으로, 이 이름을 [Cl]oudflare의 [AI R]egression 모델로 읽을 수 있다는 점도 마음에 들었습니다. 그렇게 Clairic이 세상에 태어났습니다. 즐겁게 써 주시길 바랍니다.