→ כל הפוסטים

API של LLM ללא צנזורה ל-red-teaming ולמחקר אבטחה

20 אוג׳ 2026 · 5 דק׳ קריאה · red-teaming, security

אם בניתם harness אוטומטי ל-red-teaming, אתם כבר מכירים את מצב הכשל: מודל התוקף שלכם מסרב לייצר את ההתקפה, מודל השופט שלכם מסרב לקרוא את הפלט שהוא אמור לדרג, ושיעור הצלחת ההתקפה שלכם יורד בשקט. שום דבר לא זרק שגיאה. לא מדדתם את היעד שלכם נהיה בטוח יותר — מדדתם את הכלים שלכם נהיים זהירים יותר. API של LLM ללא צנזורה קיים כדי להסיר את המשתנה הזה מהמדידה.

זה לא טיעון שה-guardrails רעים. זה טיעון על המקום שבו הם שייכים. guardrail על מוצר צ'אט לצרכנים עושה את עבודתו. אותו guardrail בתוך לולאת הערכה הוא משתנה מבלבל (confounder) לא מבוקר שיושב בינכם לבין המספר שאתם מנסים לחשב.

סירוב הוא false negative, והוא נראה כמו הצלחה

הסיבה שזה נושך כל כך חזק היא שסירובים אינם שגיאות. אתם מקבלים HTTP 200. אתם מקבלים finish_reason: "stop". אתם מקבלים JSON תקין שמתפרסר בלי בעיה. המחרוזת שבפנים היא "אני לא יכול לעזור עם זה", והפייפליין שלכם כותב אותה לעמודת דאטהסט, לשדה תווית או לסעיף בדוח, וממשיך הלאה.

באופן קונקרטי, בשלושת המקומות שבהם זה כואב הכי הרבה:

מודלי תוקף. בחיפוש jailbreak איטרטיבי — PAIR, TAP, עידון בסגנון GCG, כל דבר עם תוקף בלולאה — סירוב מסיים את הענף הזה של החיפוש. שיעור הצלחת ההתקפה שאתם מדווחים הופך לפונקציה של הנכונות של התוקף שלכם, לא של החוסן של היעד. החליפו את התוקף בתוקף פחות זהיר, וה"שיפור" ששלחתם למודל היעד שלכם מתאדה.

מודלי שופט ומדרג. דירוג LLM-as-judge על פלטים מזיקים דורש שהשופט באמת יקרא פלט מזיק. כשהוא מסרב, אתם מקבלים ציון שאי אפשר לפרסר. רוב ה-harnesses זורקים את השורה הזו. שורות שנזרקו לא חסרות באקראי — הן מתרכזות בדיוק בפלטים החמורים שאתם הכי צריכים שידורגו, ולכן המצרף שלכם מוטה לכיוון הבטוח.

עבודת ניתוח. שאלו מודל מיינסטרים מה עושה רוטינה שעברה דה-קומפילציה, ולעיתים קרובות הוא יסרב על סמך נוכחות של טוקנים שנראים כמו malware ולא על סמך הבקשה שלכם בפועל. המשימה הייתה הגנתית; המסווג נדלק על אוצר מילים. אותו סיפור בטריאז' של תעבורת exploit בלוגים, בתיוג קורפוס פישינג לאימון גלאי, או בכתיבת ממצא של CTF.

מכיוון שסירובים הם שקטים, צוותים מוצאים את עצמם כותבים גלאי סירובים — שזו בעיה לא פתורה בפני עצמה:

python
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 מדברת בסכמת ה-Chat Completions של OpenAI, כך שכל קליינט שכבר יש לכם עובד. שנו את ה-base URL, שנו את המפתח, שמרו על ה-SDK.

python
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, כאן בתיוג קורפוס פישינג לבניית נתוני אימון לגלאי:

bash
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 ו-unbleep-high הם דרגות reasoning: הם חושבים לפני שהם עונים ומחזירים את ה-trace בשדה reasoning_content לצד content. עבור מודל שופט ה-trace הזה שימושי באמת — הוא אומר לכם למה שורה קיבלה את הציון שקיבלה, וזה מה שאתם צריכים כשאתם מבקרים אי-הסכמה. הוא גם מחויב כפלט, אז שלחו "thinking": false בעבודות שלא צריכות אותו. unbleep-mini עונה ישירות ולא מחזיר trace.

פיקוח בשליטתכם

הסרת הסירובים מהמודל לא אומרת הסרת הפיקוח מהפייפליין שלכם. הפרמטר האופציונלי policy מריץ פיקוח בצד שלנו, לכל בקשה:

python
resp = client.chat.completions.create(
    model="unbleep",
    messages=[...],
    extra_body={"policy": "research"},  # recorded on the usage row; answers exactly like off
)

off הוא קו הבסיס הלא-מסונן שבברירת המחדל. research עונה בדיוק כמו off — הרמה נרשמת בשורת ה-usage, כך שתוכלו להפריד תעבורת הערכה מתעבורת קו בסיס בדיווח שלכם. הוא לא מפעיל שום סינון נוסף. strict סורק את טקסט ההודעות מול רשימת החסימה של השירות, שמתוחזקת על ידי המפעיל, ומחזיר 422 כשיש התאמה. הרשימה הזו זהה לכל מי שבוחר להצטרף — אין רשימת חסימה לכל חשבון להגדרה — אז התייחסו אליה כאל רשת ביטחון, לא כאל מדיניות התוכן שלכם בפרודקשן.

דבר אחד שכדאי לסגור לפני שאתם מפנים פייפליין לכאן: אנחנו שומרים את מה שאתם שולחים ואת מה שחוזר. גוף הבקשה, תוכן התשובה וכתובת ה-IP של המקור של כל קריאה שאנחנו מקבלים ומעבירים למודל נכתבים למסד הנתונים שלנו ונשמרים 30 יום, לצורך חקירת שימוש לרעה, תמיכה ומחלוקות חיוב. הגופים נחתכים ב-64 KB. כתובת ה-IP של המקור שורדת מעבר ל-30 הימים — היא נכתבת גם לשורת ה-usage שמחייבת את הקריאה, והשורה הזו היא רשומה פיננסית שאנחנו שומרים לזמן ארוך יותר. הדבר היחיד שלא נשמר הוא בקשה ש-strict דוחה לפני שהיא מגיעה למודל: היא מופיעה בהיסטוריית ה-usage שלכם בלי התוכן שלה. שום דבר אחר לא פטור, ואין הגדרה שמכבה את זה. אם הקורפוס שלכם רגיש מספיק כדי שעותק ל-30 יום מחוץ לפרימטר שלכם יהיה בעיה — malware חי, נתוני לקוחות, פרויקט תחת NDA — זו מגבלה אמיתית, ואת מדיניות הפרטיות כדאי לקרוא לפני שמתחילים, לא אחרי.

שגיאות עוקבות אחר המעטפת של OpenAI, כך שמטפלים קיימים עובדים: 401 מפתח שגוי, 402 נגמר הקרדיט, 422 נחסם על ידי policy, 429 מגבלת קצב, 5xx אפשר לנסות שוב. כל תשובה נושאת headers של x-ratelimit-*, כך שעבודת אצווה יכולה לווסת את עצמה בלי לנחש.

מה API של LLM ללא צנזורה לא נותן לכם

מודל ללא צנזורה הוא כלי חד יותר, לא כלי מתירני. הוא יענה על שאלות שמודל הבסיס כוונן לסרב להן, כולל כאלה שלא הייתם צריכים לשאול, ויעשה זאת באותה רמת ביטחון שהוא מפגין בכל דבר אחר — מה שגם אומר שבמקום שבו מודל מוגן היה מסרב מתוך בורות, זה עלול פשוט להמציא. השאירו אדם אחראי על מה שיוצא. מדיניות השימוש המקובל אומרת בפשטות למה ה-API מיועד ומהי הקבוצה הצרה של הדברים שהוא לעולם לא מיועד להם; ההרשאה והכוונה הן המבחן, לא אוצר המילים. שימוש חוקי הוא באחריותכם.

קבלו מפתח API והפסיקו למדוד את הזהירות של הכלים שלכם.