본문으로 건너뛰기

AI로 문의 분류하기 — 판정 API로 답과 확률만 받는 법

원포트 API 키로 https://oneport.kr/v1/decisions 를 부르면 질문마다 답과 확률만 와요. 값은 입력에만 붙어, 질문 4개와 한국어 한 줄(입력 약 620토큰)이면 한 번에 약 0.06 크레딧이에요.

출처 4곳 · 확인약 8분 읽기
판정 질문 세 가지
판정 질문 세 가지
predicate묻는 것문장이 참일 확률돌아오는 답probability이렇게 써요환불 요청인가 · 오늘 답해야 하나
choice묻는 것보기 2~255개 중 하나돌아오는 답choice · confidence · 보기마다 probability이렇게 써요어느 팀에 넘길까
score묻는 것낮은 단계부터 적은 단계 위의 점수돌아오는 답score · confidence · 단계마다 probability이렇게 써요얼마나 급한가(낮음 · 보통 · 높음)

이 표의 설명 보기

읽는 분
문의 분류 · 처리 갈래 나누기를 자동으로 만드는 개발자와 자동화 담당자
끝나면
원포트 키로 판정 API 를 불러 답과 확률을 받고, 문의 수만큼 드는 값을 어림해요.
이 글의 목차 (9개 절)
01

글 대신 답과 확률만 받아요

어느 팀에 넘길지, 환불 요청인지, 급한지처럼 답이 정해 둔 보기 안에 있는 일은 채팅 모델의 긴 답을 다시 읽을 필요가 없어요. 원포트 API 키로 https://oneport.kr/v1/decisions 를 부르면 질문마다 답과 확률만 와요. OpenAI Decisions API 와 같은 모양이라 openai SDK 의 decisions.create 를 주소만 바꿔 그대로 써요.

글을 만들지 않아 값은 입력에만 붙어요. 원포트가 재 보니 질문 4개와 한국어 한 줄이 입력 약 620토큰이었고, 그만큼이면 한 번에 약 0.06 크레딧이에요.

1 크레딧 = 부가세 포함 2원어치예요.

판정 질문 세 가지
판정 질문 세 가지
predicate묻는 것문장이 참일 확률돌아오는 답probability이렇게 써요환불 요청인가 · 오늘 답해야 하나
choice묻는 것보기 2~255개 중 하나돌아오는 답choice · confidence · 보기마다 probability이렇게 써요어느 팀에 넘길까
score묻는 것낮은 단계부터 적은 단계 위의 점수돌아오는 답score · confidence · 단계마다 probability이렇게 써요얼마나 급한가(낮음 · 보통 · 높음)

어떤 질문은 답 대신 type 이 refusal 로 올 수 있어요. 같은 요청의 다른 질문은 그대로 답해요.

02

Python 으로 문의 한 줄 판정하기

openai 파이썬 패키지 3.50.0 에는 client.decisions.create 가 있어요(Node.js 는 openai 7.56.0). pip install -U openai 로 올리고 환경 변수 ONEPORT_API_KEY 에 키를 넣어 실행해요. 코드에 키 원문을 적지 않아요. 키가 없으면 구매할 때 받을 메일로 「키 받기」 링크가 와요.

CLI · 설정

문의 한 줄 판정 (Python)

import os

from openai import OpenAI

client = OpenAI(base_url="https://oneport.kr/v1", api_key=os.environ["ONEPORT_API_KEY"], timeout=120)

r = client.decisions.create(
    model="gpt-6-luna",
    input="지난주에 산 좌석 두 개 중 하나를 환불하고 싶어요. 오늘 안에 답 주세요.",
    questions=[
        {"name": "refund", "type": "predicate", "instructions": "환불을 요청하는 글인가?"},
        {"name": "team", "type": "choice", "instructions": "어느 팀이 받을 글인가?",
         "choices": [{"value": "billing"}, {"value": "account"}, {"value": "tech"}]},
        {"name": "urgency", "type": "score", "instructions": "얼마나 급한가?",
         "levels": [{"label": "낮음"}, {"label": "보통"}, {"label": "높음"}]},
    ],
)

for a in r.answers:  # 보낸 질문 순서대로 와요
    if a.type == "refusal":
        print(a.name, "답하지 않음 → 사람에게")
    elif a.type == "predicate":
        print(a.name, round(a.probability, 2))
    elif a.type == "choice":
        print(a.name, a.choice, round(a.confidence, 2))
    else:  # score
        print(a.name, round(a.score, 2), round(a.confidence, 2))

print("입력 토큰", r.usage.input_tokens)
03

답을 읽는 순서와 문턱

위 코드와 같은 글 · 같은 질문 셋을 공식 Node.js SDK 로 원포트 시험 서버에 보냈을 땐 refund 1.0 · team billing · urgency 1.98(단계 셋이라 0~2) 이 왔고 입력은 399토큰이었어요.

원포트가 한국어 글 세 개(통계 질문 · 가정통신문 부탁 · 수학 풀이 부탁)에 판정 네 개씩을 물었을 땐 열두 답이 모두 미리 정해 둔 답과 같았어요. 세 개는 적은 수라 문턱은 내 문의 글로 다시 재요.

  1. type 이 refusal 인 답을 먼저 걸러 사람에게 넘겨요.
  2. predicate 는 probability, choice 는 choice 와 confidence, score 는 score 를 읽어요. 답은 보낸 질문 순서대로 오고, name 을 주면 같은 name 이 붙어요.
  3. 어디서 끊을지(예: 0.8)는 실제 문의 글에 답을 달아 두고 판정과 견줘서 정해요.
  4. 모델을 바꾸면 문턱을 다시 재요. 모델마다 확률이 퍼지는 모양이 달라요.
04

보낼 값 — n8n · Dify 공통

HTTP 요청에 넣을 값
HTTP 요청에 넣을 값
주소넣을 값POST https://oneport.kr/v1/decisions
머리글넣을 값Authorization: Bearer 받은 키 · Content-Type: application/json
보낼 글(JSON)넣을 값아래 상자 — input 자리에 앞 단계의 문의 글
답넣을 값answers 배열(보낸 질문 순서) · 쓴 입력은 usage.input_tokens
CLI · 설정

판정 요청 본문(JSON)

{
  "model": "gpt-6-luna",
  "input": "여기에 문의 글",
  "questions": [
    { "name": "refund", "type": "predicate", "instructions": "환불을 요청하는 글인가?" },
    { "name": "team", "type": "choice", "instructions": "어느 팀이 받을 글인가?",
      "choices": [{ "value": "billing" }, { "value": "account" }, { "value": "tech" }] },
    { "name": "urgency", "type": "score", "instructions": "얼마나 급한가?",
      "levels": [{ "label": "낮음" }, { "label": "보통" }, { "label": "높음" }] }
  ]
}
05

n8n — HTTP Request 노드로 부르기

  1. HTTP Request 노드를 더하고 Method 는 POST, URL 은 https://oneport.kr/v1/decisions 로 넣어요.
  2. Authentication 은 Generic Credential Type, Generic Auth Type 은 Header Auth 를 고르고, 새 credential 의 Name 에 Authorization, Value 에 「Bearer 받은 키」를 넣어요. 키를 JSON 이나 Headers 칸에 적지 않아요.
  3. Send Body 를 켜고 Body Content Type 은 JSON, Specify Body 는 Using JSON 으로 둔 뒤 위 JSON 을 붙여 넣어요. input 자리엔 앞 단계의 문의 글을 끼우는데, 글에 따옴표나 줄바꿈이 있으면 JSON.stringify 로 감싸요.
  4. Options 의 Timeout 은 120000(밀리초) 이상으로 두고, 노드 Settings 의 Retry On Fail 은 꺼요. 실패 갈래를 가리지 않고 다시 보내서 이미 처리됐을 수 있는 요청도 다시 나가요.
  5. 다음 노드에서 {{ $json.answers[0].probability }} 처럼 답을 읽고, If 노드로 문턱 위와 아래를 갈라요.
  6. 실패도 갈라 받으려면 Options 의 Response 에서 Include Response Headers and Status 와 Never Error 를 켜요. statusCode · headers · body 가 따로 와서 statusCode 로 갈래를 나눌 수 있어요.
06

Dify — HTTP Request 노드와 코드 노드

  1. 워크플로에 HTTP Request 노드를 더하고 POST 와 https://oneport.kr/v1/decisions 를 넣어요.
  2. API Key 방식에서 Bearer 를 고르고 키를 넣어요. 키는 Secret 환경 변수로 만들어 그 변수를 넣어요.
  3. Body 는 JSON 으로 두고 위 JSON 을 넣은 뒤 input 자리에 앞 노드의 글 변수를 끼워요. 글에 따옴표나 줄바꿈이 섞이면 앞에 코드 노드를 두고 json.dumps 로 본문을 만들어 통째로 넣어요.
  4. Read timeout 은 120초 이상으로 두고 Retry Settings 는 꺼요.
  5. 다음에 코드 노드를 두고 HTTP Request 의 status_code 와 body 를 입력 변수로 받아 아래 코드를 넣어요. 출력 변수 team · error 는 문자열, refund 는 숫자로 정해요. refund 가 -1 이면 답이 없거나 실패한 글이라 사람에게 넘겨요.
복사용 문안

Dify 코드 노드 — 판정 답 꺼내기 (Python)

import json


def main(status_code, body):
    try:
        data = json.loads(body)
    except ValueError:
        return {"team": "", "refund": -1, "error": "응답을 읽지 못했어요"}
    if status_code != 200:
        err = data.get("error") or {}
        return {"team": "", "refund": -1, "error": err.get("reason") or err.get("type") or str(status_code)}
    found = {a.get("name"): a for a in data.get("answers", [])}
    team = found.get("team", {})
    refund = found.get("refund", {})
    return {
        "team": team.get("choice", "") if team.get("type") == "choice" else "",
        "refund": refund.get("probability", -1) if refund.get("type") == "predicate" else -1,
        "error": "",
    }
07

값은 입력에만 붙어요

부르기 전에 (본문 바이트 ÷ 2 + 질문 수 × 200) 토큰어치, 최소 1,000토큰을 잡아 두고, 답을 보낸 직후 실제 usage 로 정산해요. 잔액이 잡아 두는 몫보다 적으면 실제 사용이 더 작아도 402 가 와요.

이 문 응답에는 글 문의 usage.cost_credits 칸이 없어요. 사용을 직접 세려면 usage.input_tokens 를 모아 위 단가를 곱해요.

판정 한 번과 1,000번 어림
판정 한 번과 1,000번 어림
질문 4개 + 한국어 한 줄 · 한 번입력 토큰(약)620사용(크레딧)약 0.06
같은 판정 1,000번입력 토큰(약)62만사용(크레딧)약 57

입력 100만 토큰당 91.98 크레딧(GET /v1/models 의 판정 줄) 기준 셈이에요. 앞부분이 캐시된 입력은 그 10분의 1 단가로 세고, 출력은 0 이에요. 2026년 11월 기준이고 바뀔 수 있어요.

08

실패하면 받은 것마다

상태 코드가 온 실패는 사용이 0 이에요. 모델 회사 답은 60초까지 기다리고, 넘으면 504 에 x-should-retry: false 를 붙여요. openai 패키지는 이 머리글을 보고 다시 보내지 않아요. 이 문은 90초 안에 끝나니 내 쪽 시간 제한은 120초쯤으로 둬요.

openai 패키지는 연결 오류 · 시간 초과도 기본 2번 더 보내요(max_retries). 이 문은 Idempotency-Key 를 읽지 않아 그때 두 번 사용될 수 있어요. 정확히 세야 하면 max_retries=0 으로 두고 직접 가르세요.

판정 요청이 실패했을 때 할 일
판정 요청이 실패했을 때 할 일
400 · 401 · 403 · 404할 일멈추고 문장대로 고쳐요. error.param 이 고칠 칸이에요.
400 vendor_param_rejected할 일error.param 칸 값을 고쳐 보내요.
400 vendor_rejected · 504할 일질문이나 입력을 나눠 보내요.
402 · 429 held_by_others할 일Retry-After(5초) 뒤 그대로 보내요.
402 hold_exceeds_balance · 429 key_month_limit할 일질문 수나 입력을 줄여요. 작게 보내도 막히면 멈춰요.
402 below_minimum_balance · 429 key_day_limit · group_closed할 일멈춰요 — 충전하거나, 한국 시간 다음 날 0시를 기다리거나, 스페이스 관리자에게 말해요.
429 rate_limit_error · 503 api_error할 일Retry-After 만큼 쉬고 그대로 보내요.
502 upstream_error할 일몇 초 쉬고 그대로 보내요.
상태 코드 없음(연결 끊김 · 내 쪽 시간 초과)할 일이미 사용됐을 수 있어요. 다시 보낼지 직접 정해요.
09

팀과 회사에서 쓸 때

판정을 돌리는 서비스마다 키를 따로 만들고 키마다 한 달 한도를 걸어 둬요. 한 서비스가 한도에 닿아도 다른 키는 그대로 써요. 지갑 잔액은 키들이 같이 써요.

원포트는 판정으로 보낸 글을 사용 기록에 남기지 않고 모델 · 토큰 수 · 성공 여부 · 요청 ID 만 남겨요. 글은 판정하러 OpenAI 로 가고, 그쪽 처리는 OpenAI 정책을 따라요.

여러 개발자의 키 · 한도, 견적 · 세금계산서, 보안 검토 질문까지 한 번에 정하려면 도입 문의로 인원과 시기를 알려 주세요. 늦어도 다음 영업일 안에 연락드립니다.

자주 묻는 질문

한 번에 질문을 몇 개까지 넣을 수 있나요?

한 요청에 1~400개예요. 401개면 원포트가 보내기 전에 400 으로 막고 사용은 0 이에요. 질문을 늘려도 판정할 글은 한 번만 세고, 질문마다 지시문과 보기 글만큼 입력이 늘어요.

채팅 모델에게 JSON 으로 답하라고 하는 것과 무엇이 다른가요?

판정 문은 글을 만들지 않아 출력 몫이 없고, choice 의 답은 보낸 보기 중 하나이거나 refusal 이에요. 보기마다 확률이 같이 와서 어디서 끊을지를 숫자로 정할 수 있어요.

출처와 확인일

원포트 AI 운영사 스피커블이 위 출처를 그날 열어 확인하고 썼어요. 확인하는 방법

함께 보면 좋은 글과 도움말

← 블로그 전체 목록 보기