اگر یک هارنس ردتیمینگ (red-teaming) خودکار ساختهاید، این حالت خرابی را از قبل میشناسید: مدل مهاجمتان از تولید حمله سر باز میزند، مدل داورتان از خواندن خروجیای که قرار است نمره بدهد امتناع میکند، و نرخ موفقیت حملهتان بیسروصدا پایین میآید. هیچ خطایی رخ نداده. شما ایمنتر شدن هدف را اندازه نگرفتید — محتاطتر شدن ابزارتان را اندازه گرفتید. یک API مدل زبانی بدون سانسور برای همین وجود دارد که این متغیر را از اندازهگیری حذف کند.
این استدلالی علیه گاردریلها نیست. استدلالی است دربارهٔ اینکه جای گاردریل کجاست. گاردریل روی یک محصول چت مصرفی دارد کارش را میکند. همان گاردریل داخل یک حلقهٔ ارزیابی، یک عامل مخدوشکنندهٔ کنترلنشده است که بین شما و عددی که میخواهید محاسبه کنید نشسته است.
امتناع یک منفی کاذب است، و شبیه موفقیت به نظر میرسد
دلیل اینکه این موضوع اینقدر گزنده است این است که امتناعها خطا نیستند. HTTP 200 میگیرید. finish_reason: "stop" میگیرید. JSON خوشساختی میگیرید که تمیز parse میشود. رشتهٔ داخلش «نمیتوانم در این مورد کمک کنم» است، و پایپلاین شما آن را در یک ستون دیتاست، یک فیلد برچسب یا یک بخش گزارش مینویسد و رد میشود.
بهطور مشخص، در سه جایی که بیشترین ضربه را میزند:
مدلهای مهاجم. در یک جستوجوی تکرارشوندهٔ جیلبریک — PAIR، TAP، پالایش به سبک GCG، هر چیزی که یک مهاجم در حلقه دارد — یک امتناع آن شاخه از جستوجو را خاتمه میدهد. نرخ موفقیت حملهای که گزارش میکنید تابعی از میل مهاجمتان میشود، نه استحکام هدفتان. مهاجم را با یک مهاجم کماحتیاطتر عوض کنید و «بهبودی» که برای مدل هدفتان منتشر کردید دود میشود و هوا میرود.
مدلهای داور و نمرهدهنده. نمرهدهی به خروجیهای مضر با روش LLM-as-judge ایجاب میکند که داور واقعاً خروجی مضر را بخواند. وقتی امتناع میکند، نمرهای میگیرید که قابل parse نیست. بیشتر هارنسها آن سطر را دور میاندازند. سطرهای دورانداختهشده بهطور تصادفی گم نشدهاند — دقیقاً روی همان خروجیهای شدیدی جمع میشوند که بیش از همه به نمرهشان نیاز دارید، پس عدد تجمیعیتان به سمت «ایمن» کج میشود.
کارهای تحلیلی. از یک مدل رایج بپرسید یک روتین دیکامپایلشده چه کار میکند، و اغلب بر اساس حضور توکنهای بدافزارنما امتناع میکند، نه بر اساس درخواست واقعی شما. کار دفاعی بود؛ دستهبند روی واژگان فعال شد. همین داستان برای تریاژ ترافیک اکسپلویت در لاگها، برچسبگذاری یک پیکرهٔ فیشینگ برای آموزش یک آشکارساز، یا نوشتن گزارش یک یافتهٔ 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، $3.00 / $3.00 بهازای هر 1M ورودی/خروجی. پیشفرض: نقشهای مهاجم و داور، تحلیل نمونه.unbleep-high— کانتکست 1M، $5.00 / $5.00. رونوشتهای طولانی و همبستگی چندسندی. بدنهٔ یک درخواست به 2,000,000 بایت (~500K توکن) محدود است، پس پنجره در طول یک مکالمه پر میشود، نه در یک فراخوانی.unbleep-mini— کانتکست 32K، $1.00 / $1.00. دستهبندی پرحجم، جایی که بهازای هر سطر پول میدهید.
unbleep و unbleep-high سطحهای استدلالیاند: پیش از پاسخ فکر میکنند و رد استدلال را در فیلد reasoning_content کنار 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 متن پیام را با فهرست مسدودسازی (blocklist) سرویس که اپراتور نگهداریاش میکند مقایسه میکند و در صورت تطابق 422 برمیگرداند. آن فهرست برای همهٔ کسانی که آن را فعال میکنند یکسان است — فهرست مسدودسازی بهازای هر حساب برای پیکربندی وجود ندارد — پس آن را یک لایهٔ پشتیبان بدانید، نه سیاست محتوایی پروداکشن خودتان.
یک چیز را پیش از اینکه پایپلاینی را به این وصل کنید باید روشن کنید: ما آنچه میفرستید و آنچه برمیگردد را ذخیره میکنیم. بدنهٔ درخواست، محتوای پاسخ و IP مبدأ هر فراخوانیای که میپذیریم و به یک مدل میفرستیم در پایگاهدادهٔ ما نوشته میشود و 30 روز نگه داشته میشود، برای بررسی سوءاستفاده، پشتیبانی و اختلافهای صورتحساب. بدنهها در 64 KB بریده میشوند. IP مبدأ بیش از آن 30 روز میماند — روی سطر مصرفی که فراخوانی را صورتحساب میکند هم نوشته میشود، و آن سطر یک سند مالی است که مدت بیشتری نگه میداریم. تنها چیزی که ذخیره نمیشود درخواستی است که strict پیش از رسیدن به مدل رد میکند: آن درخواست بدون محتوایش در تاریخچهٔ مصرف شما ظاهر میشود. هیچچیز دیگری مستثنا نیست و تنظیمی برای خاموش کردنش وجود ندارد. اگر پیکرهٔ شما آنقدر حساس است که یک نسخهٔ 30 روزه بیرون از محدودهٔ امن شما مشکلساز باشد — بدافزار زنده، دادهٔ مشتریان، پروژهای تحت NDA — این یک محدودیت واقعی است، و سیاست حریم خصوصی صفحهای است که باید پیش از شروع بخوانید، نه بعدش.
خطاها از همان ساختار (envelope) OpenAI پیروی میکنند، پس هندلرهای موجود کار میکنند: 401 کلید نامعتبر، 402 اتمام اعتبار، 422 مسدودشده توسط policy، 429 محدودیت نرخ، 5xx قابل تلاش مجدد. هر پاسخ هدرهای x-ratelimit-* را حمل میکند تا یک کار دستهای بتواند بدون حدس زدن سرعت خودش را تنظیم کند.
چیزی که یک API مدل زبانی بدون سانسور به شما نمیدهد
مدل بدون سانسور ابزار تیزتری است، نه ابزاری سهلگیر. به پرسشهایی پاسخ میدهد که مدل پایه برای رد کردنشان تنظیم شده بود، از جمله پرسشهایی که نباید بپرسید، و این کار را با همان اطمینانی میکند که به همهچیز دیگر اعمال میکند — که یعنی جایی که یک مدل محافظتشده از سر ناآگاهی امتناع میکرد، این یکی ممکن است بهسادگی پاسخ بسازد. یک انسان را پاسخگوی آنچه بیرون میآید نگه دارید. سیاست استفادهٔ مجاز بهروشنی میگوید این API برای چیست و مجموعهٔ محدودی از چیزها که هرگز برایشان نیست کداماند؛ معیار، مجوز و نیت است، نه واژگان. مسئولیت استفادهٔ قانونی با شماست.
یک کلید API بگیرید و اندازهگیریِ احتیاط ابزارتان را متوقف کنید.