자동화된 레드티밍 하네스를 만들어 봤다면 이 실패 양상을 이미 알고 있을 것입니다. 공격자 모델이 공격 생성을 거부하고, 판정 모델이 채점해야 할 출력을 읽기를 거부하며, 공격 성공률이 조용히 떨어집니다. 에러는 하나도 나지 않았습니다. 대상이 더 안전해진 것을 측정한 것이 아니라 — 도구가 더 신중해진 것을 측정한 것입니다. 무검열 LLM API는 그 변수를 측정에서 제거하기 위해 존재합니다.
가드레일이 나쁘다는 주장이 아닙니다. 가드레일이 어디에 있어야 하는지에 관한 주장입니다. 소비자용 채팅 제품의 가드레일은 제 역할을 하고 있습니다. 같은 가드레일이 평가 루프 안에 있으면, 여러분과 여러분이 계산하려는 숫자 사이에 끼어 있는 통제되지 않은 교란 변수가 됩니다.
거부는 위음성이고, 성공처럼 보인다
이것이 이토록 뼈아픈 이유는 거부가 에러가 아니기 때문입니다. HTTP 200을 받습니다. finish_reason: "stop"을 받습니다. 깔끔하게 파싱되는 정상적인 JSON을 받습니다. 그 안의 문자열은 "그 요청은 도와드릴 수 없습니다"이고, 파이프라인은 이를 데이터셋 열, 레이블 필드, 보고서 섹션에 써넣고 다음으로 넘어갑니다.
구체적으로, 가장 아픈 세 곳에서:
공격자 모델. 반복적 탈옥 탐색 — PAIR, TAP, GCG 계열의 정제, 공격자가 루프 안에 있는 모든 것 — 에서 거부는 탐색의 그 가지를 종료시킵니다. 보고되는 공격 성공률은 대상의 견고성이 아니라 공격자의 의향의 함수가 됩니다. 공격자를 덜 신중한 모델로 바꾸면 대상 모델에 적용했다던 "개선"이 증발합니다.
판정 및 채점 모델. 유해 출력에 대한 LLM-as-judge 채점은 판정 모델이 실제로 유해 출력을 읽어야 가능합니다. 거부하면 파싱할 수 없는 점수가 나옵니다. 대부분의 하네스는 그 행을 버립니다. 버려진 행은 무작위로 빠진 것이 아닙니다 — 가장 채점이 필요한 심각한 출력에 정확히 몰려 있으므로, 집계 결과가 안전한 쪽으로 기웁니다.
분석 작업. 주류 모델에 디컴파일된 루틴이 무엇을 하는지 물으면, 실제 요청이 아니라 멀웨어 냄새가 나는 토큰의 존재만으로 거부하는 경우가 많습니다. 작업은 방어적이었는데 분류기는 어휘에 반응한 것입니다. 로그에서 익스플로잇 트래픽을 분류하거나, 탐지기를 학습시키려고 피싱 코퍼스에 레이블을 달거나, CTF 결과를 정리해 쓸 때도 같은 이야기입니다.
거부가 조용하기 때문에 팀들은 결국 거부 감지기를 만들게 되는데, 이 자체가 또 하나의 미해결 문제입니다.
REFUSAL_MARKERS = ("i can't", "i cannot", "i'm unable", "i won't", "as an ai")
def looks_like_refusal(text: str) -> bool:
"""Substring heuristic. Good enough to alarm on, not good enough to trust:
it misses polite deflections that never use the phrase, and it fires on any
completion that quotes a refusal. Both error directions corrupt a dataset."""
return any(m in text[:200].lower() for m in REFUSAL_MARKERS)원천에서 없앨 수 있는 문제를 위해 신뢰할 수 없는 감지기를 만드는 것은 잘못된 거래입니다.
API 호출하기
unbleep은 OpenAI Chat Completions 스키마를 쓰므로, 이미 가진 어떤 클라이언트든 동작합니다. base URL을 바꾸고, 키를 바꾸고, SDK는 그대로 두세요.
import json
import os
from openai import OpenAI
client = OpenAI(
base_url="https://unbleep.ai/v1",
api_key=os.environ["UNBLEEP_API_KEY"],
)
TRIAGE = """You are a malware analyst writing notes for a detection engineer.
Given a decompiled routine, describe what it does, the observable artefacts it
would leave on a host, and where a defender could detect it. Reply as JSON with
keys: behaviour, artefacts, detection_surface, confidence."""
def triage(decompiled: str) -> dict:
"""One sample in, one structured verdict out — no refusal branch to handle."""
resp = client.chat.completions.create(
model="unbleep",
messages=[
{"role": "system", "content": TRIAGE},
{"role": "user", "content": decompiled},
],
response_format={"type": "json_object"},
temperature=0.2,
)
return json.loads(resp.choices[0].message.content)curl로 하면 이렇습니다. 여기서는 탐지기 학습 데이터를 만들기 위해 피싱 코퍼스에 레이블을 답니다.
curl https://unbleep.ai/v1/chat/completions \
-H "Authorization: Bearer $UNBLEEP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "unbleep",
"messages": [
{"role": "system", "content": "Label each email for a phishing detector. Answer with one word: phishing or benign."},
{"role": "user", "content": "Subject: Payroll update required\n\nYour direct deposit is on hold. Confirm at hxxp://payroll-verify.example.com"}
],
"temperature": 0,
"max_tokens": 4
}'레이블링 루프에서는 temperature: 0과 빠듯한 max_tokens가 평소보다 더 중요합니다. 원하는 것은 레이블이지, 레이블을 설명하는 문단이 아니니까요.
티어 고르기
세 모델 모두 무검열이며, 컨텍스트와 가격만 다릅니다.
unbleep— 256K 컨텍스트, 입력/출력 1M당 $3.00 / $3.00. 기본값: 공격자와 판정 역할, 샘플 분석.unbleep-high— 1M 컨텍스트, $5.00 / $5.00. 긴 트랜스크립트와 다중 문서 상관 분석. 요청 본문 하나는 2,000,000바이트(~500K 토큰)로 제한되므로, 윈도우는 한 번의 호출이 아니라 대화에 걸쳐 채워집니다.unbleep-mini— 32K 컨텍스트, $1.00 / $1.00. 행 단위로 비용을 치르는 대량 분류.
unbleep과 unbleep-high는 추론 티어입니다. 답하기 전에 생각하고, 그 트레이스를 content와 나란히 reasoning_content 필드로 반환합니다. 판정 모델에서 이 트레이스는 정말로 유용합니다 — 어떤 행이 왜 그 점수를 받았는지 알려주며, 불일치를 감사할 때 바로 그것이 필요합니다. 다만 출력으로 과금되므로, 필요 없는 작업에는 "thinking": false를 보내세요. unbleep-mini는 바로 답하며 트레이스를 반환하지 않습니다.
여러분이 통제하는 거버넌스
모델에서 거부를 제거한다고 해서 파이프라인에서 감독을 제거해야 하는 것은 아닙니다. 선택적 policy 파라미터는 요청 단위로 우리 쪽에서 거버넌스를 실행합니다.
resp = client.chat.completions.create(
model="unbleep",
messages=[...],
extra_body={"policy": "research"}, # recorded on the usage row; answers exactly like off
)off가 기본값이자 필터 없는 기준선입니다. research는 off와 정확히 똑같이 답합니다 — 레벨이 사용량 행에 기록되므로, 여러분의 리포팅에서 평가 트래픽과 기준선 트래픽을 분리할 수 있습니다. 추가 검사는 전혀 적용하지 않습니다. strict는 메시지 텍스트를 운영자가 관리하는 서비스 차단 목록과 대조해 일치하면 422를 반환합니다. 이 목록은 옵트인한 모든 사용자에게 동일하며 — 계정별로 설정할 차단 목록은 없습니다 — 따라서 프로덕션 콘텐츠 정책이 아니라 최후의 안전장치로 취급하세요.
파이프라인을 여기에 연결하기 전에 정리해 둘 것이 하나 있습니다. 우리는 여러분이 보낸 것과 돌아온 것을 저장합니다. 우리가 수락해 모델로 전달하는 모든 호출의 요청 본문, 응답 내용, 출발지 IP는 남용 조사, 지원, 과금 분쟁을 위해 우리 데이터베이스에 기록되어 30일간 보관됩니다. 본문은 64 KB에서 잘립니다. 출발지 IP는 30일보다 오래 남습니다 — 해당 호출을 과금하는 사용량 행에도 기록되며, 그 행은 더 오래 보관하는 재무 기록입니다. 저장되지 않는 유일한 것은 strict가 모델에 도달하기 전에 거부한 요청으로, 이는 내용 없이 사용량 기록에만 나타납니다. 그 밖에 예외는 없고, 끌 수 있는 설정도 없습니다. 여러분의 코퍼스가 경계 밖에 30일짜리 사본이 남는 것이 문제가 될 만큼 민감하다면 — 실제 멀웨어, 고객 데이터, NDA가 걸린 프로젝트 — 그것은 실질적인 제약이며, 개인정보 처리방침은 시작한 뒤가 아니라 시작하기 전에 읽어야 할 페이지입니다.
에러는 OpenAI 형식을 따르므로 기존 핸들러가 동작합니다. 401 잘못된 키, 402 크레딧 소진, 422 정책에 의해 차단, 429 요청 한도 초과, 5xx 재시도 가능. 모든 응답에 x-ratelimit-* 헤더가 실려 있어 배치 작업이 추측 없이 속도를 조절할 수 있습니다.
무검열 LLM API가 주지 않는 것
무검열 모델은 더 날카로운 도구이지, 무엇이든 허용하는 도구가 아닙니다. 기본 모델이 거절하도록 튜닝된 질문에 — 여러분이 물어서는 안 될 질문을 포함해 — 답하며, 다른 모든 것에 적용하는 것과 같은 자신감으로 그렇게 합니다. 이는 보호된 모델이 무지 때문에 거절했을 자리에서, 이 모델은 그냥 지어낼 수도 있다는 뜻이기도 합니다. 나오는 결과에 책임지는 사람을 두세요. 허용 사용 정책은 이 API가 무엇을 위한 것인지, 그리고 결코 허용되지 않는 좁은 범위의 것들이 무엇인지 분명히 밝힙니다. 기준은 어휘가 아니라 권한과 의도입니다. 합법적인 사용은 여러분의 책임입니다.
API 키를 발급받고 도구의 신중함을 재는 일을 그만두세요.