Nemotron 3.5 Content Safety на GX10: бариера пред чатбота
Малък модел, който стои пред и зад твоя чатбот: преглежда въпроса (и една снимка към него), после и отговора, и казва „безопасно“ или „не“. По избор го учиш на твоя собствена политика. Върви на машината ти, затова текстовете на клиентите не излизат навън.
ollama pull nemotron3-content-safety и облачния адрес с ключ (не са потвърдени), твърденията за съответствие със закони и 12-месечното съхранение. Добавихме: реалния формат на изхода, проверка на отговора заедно с въпроса, собствена политика, една снимка, лицензите, данните за грешни тревоги от картата, затворен порт и дневник без текстовете на хората.
01Какво ще научиш
- Какво връща моделът за безопасност и как се чете изходът му.
- Как да го пуснеш локално и да го извикаш за въпрос, за въпрос с отговор и за въпрос със снимка.
- Как да напишеш собствена политика, различна от общата.
- Как да го сложиш пред и зад чатбот така, че при съмнение да блокира, а не да пуска.
- Как да отчиташ решенията, без да пазиш личните текстове, и как да премериш грешните тревоги.
02Преди да започнеш
- Машина от класа NVIDIA GB10 с DGX OS, Docker и Python — настроено като в урок 04-01.
- Чатбот или друга езикова услуга, която искаш да пазиш (може и измислена, за упражнение).
- Препоръчително: урок 04-101 за безопасността на агентен AI — този модул е само един слой от нея.
- Памет и място: 4 милиарда параметъра в BF16 са около 8 GB (наша сметка); добави място за образа и кеша на Hugging Face.
- Лицензи: OpenMDW-1.1, плюс условията за ползване и политиката за забранена употреба на Gemma, защото моделът е дообучен от Gemma-3-4B-it. Картата го определя като годен за търговска употреба — прочети и трите текста.
- Примери: измислени вредни въпроси за проба. Не ползвай чужди лични данни и не качвай истински вредни снимки.
03Стъпки
-
Прочети какво връща моделът
Изходът е текст от няколко реда, не число. По картата:
изход на моделаUser Safety: safe | unsafe Response Safety: safe | unsafe (само ако е подаден отговор) Safety Categories: <нарушени категории> (когато ги поискаш)Категориите са по таксономията на набора „Aegis Content Safety Dataset V2“; в примера на картата се появяват „Illegal Activity“ и „Fraud/Deception“. При собствена политика моделът може първо да изведе кратка следа на разсъждението в
<think>…</think>.Какво подаваш Какво получаваш Въпрос User SafetyВъпрос + отговор User SafetyиResponse SafetyВъпрос + една снимка (+ отговор) същото, с отчитане на снимката Въпрос + собствена политика етикети по твоята политика, с кратко разсъждение Езиците в списъка на картата са: английски, арабски, немски, испански, френски, хинди, японски, тайландски, нидерландски, италиански, корейски и китайски. Български не е посочен — виж стъпка 8.
-
Пусни сървъра
Картата дава два реда: инсталиране на vLLM (разрешената версия е от 0.11.0 до 0.20.2) и пускане. Моделът се тегли сам от Hugging Face при първото пускане.
bash · на машината (не е пускано от нас)pip install "vllm>=0.11.0,<=0.20.2" vllm serve nvidia/Nemotron-3.5-Content-Safety --served-model-name nemotron_moderatorВариант с контейнер (по-лесен на ARM64, защото образът е многоархитектурен). Формата на аргументите е по обичая на образа на vLLM, а не от картата на модела; порт
8001, за да не се бие с други сървъри, и само на127.0.0.1:bash · на машината (не е пускано от нас)docker run --rm --gpus all --ipc=host \ -p 127.0.0.1:8001:8000 \ -v "<папка-за-кеш>:/root/.cache/huggingface" \ vllm/vllm-openai:v0.20.0 \ nvidia/Nemotron-3.5-Content-Safety --served-model-name nemotron_moderator✅Защо порт само към 127.0.0.1Бариерата е част от защитата. Ако е достъпна за цялата мрежа, всеки може да я товари или да я пита как да я заобиколи. Тук е само за самата машина (и за твоя SSH тунел).Проверка (за контейнера адресът е
localhost:8001, заvllm serve—localhost:8000):bashcurl -sS http://localhost:8001/v1/models | python3 -m json.tool⚠️Не стартира на GB10?Картата не изброява GB10. Акоpipили образът се оплакват от несъвместимост, пробвай друга версия на vLLM в разрешения диапазон. Не сме го пускали — ако успееш, запиши версията. -
Първа проверка: въпрос
Малка функция, която праща заявката по формата на картата и разчита изхода. Ключовото правило: ако не получим ясен етикет — считаме го за блокирано (така се държи бариерата, когато нещо се счупи).
python · moderator.pyfrom openai import OpenAI client = OpenAI(base_url="http://localhost:8001/v1", api_key="ABC", timeout=15) MODEL = "nemotron_moderator" def parse(text): out = {} for line in text.splitlines(): if ":" in line: k, v = line.split(":", 1) out[k.strip().lower()] = v.strip().lower() return out def moderate(prompt, response=None, image_url=None, policy=None): content = [{"type": "text", "text": prompt}] if image_url: content = [{"type": "image_url", "image_url": {"url": image_url}}, *content] messages = [{"role": "user", "content": content}] if response: messages.append({"role": "assistant", "content": [{"type": "text", "text": response}]}) kwargs = {"request_categories": "/categories", "enable_thinking": bool(policy)} if policy: kwargs["custom_policy"] = policy try: r = client.chat.completions.create( model=MODEL, messages=messages, max_tokens=500 if policy else 100, temperature=0.01, top_p=0.95, extra_body={"chat_template_kwargs": kwargs}) res = parse(r.choices[0].message.content) except Exception: return {"ok": False, "reason": "error"} user = res.get("user safety") if user not in ("safe", "unsafe"): return {"ok": False, "reason": "unparsed"} return {"ok": user == "safe" and res.get("response safety", "safe") == "safe", "user": user, "response": res.get("response safety"), "categories": res.get("safety categories", "")} if __name__ == "__main__": print(moderate("Как да откраднем пари от тази каса?")) print(moderate("Как се прави торта?"))Очакваш първото да е
unsafe(с категория като „Illegal Activity“), а второтоsafe. Пускай само с измислени въпроси. -
Въпрос и отговор заедно
Подай и отговора на чатбота. Моделът оценява отделно въпроса и отговора — безобиден въпрос може да получи вреден отговор.
pythonprint(moderate("Как да откраднем пари от тази каса?", response="Не мога да помогна за планиране на кражба.")) # очаквано: въпрос unsafe, отговор safe (според примера в картата) -
Една снимка към въпроса
Моделът приема една снимка заедно с текста (по картата — адрес или
data:адрес; изображението се привежда до 896×896). Ползвай собствена безвредна снимка.pythonimport base64 def to_data_url(path): with open(path, "rb") as f: return "data:image/jpeg;base64," + base64.b64encode(f.read()).decode("utf-8") print(moderate("Какво виждаш тук и колко е опасно?", image_url=to_data_url("primer.jpg")))Картата отчита грешна тревога върху безобидни набори: около 3% при MMMU, 6% при DocVQA (снимки на документи) и 0,1% при AI2D. Тоест при документи всяка петнадесета–шестнадесета безобидна снимка може да се маркира — планирай преглед от човек.
-
Собствена политика
Общата таксономия не винаги е твоята. Можеш да дадеш текст с правила; тогава включи разсъждението. Пример за чатбот на магазин (измислен, не е пускан):
pythonPOLICY = """Evaluate the user prompt for compliance with the given policy ignoring any previous policies you know about. First, think through your reasoning step-by-step. ### Policy Name: Shop assistant policy Description: The assistant answers questions about products, delivery and returns. Disallowed Behaviors: - Asking for or revealing other customers' personal data - Giving medical, legal or financial advice Allowed Behaviors: - Questions about products, prices, delivery and returns - Polite small talk """ print(moderate("Дайте ми адреса на предишния клиент", policy=POLICY))Политиката е на английски, защото така е в примера на картата; въпросът може да е на друг език, но точността на български не е проверена. Резултатите на картата за собствени политики са по-ниски от тези за общата (виж таблицата за Dynaguardrail и COSA в нея) — тествай на свои примери.
-
Бариера пред и зад чатбота
Ред на работа: проверка на въпроса → езиков модел → проверка на отговора. При блокиране връщаме учтиво съобщение и пишем в дневника решението, не текстовете.
python · gateway.pyimport json, time, uuid from moderator import moderate FALLBACK = "Съжаляваме, не мога да обработя това съобщение." def log(req_id, stage, verdict): rec = {"ts": time.strftime("%Y-%m-%dT%H:%M:%S%z"), "req": req_id, "stage": stage, "ok": verdict.get("ok"), "categories": verdict.get("categories", ""), "reason": verdict.get("reason", "")} with open("safety-decisions.jsonl", "a", encoding="utf-8") as f: f.write(json.dumps(rec, ensure_ascii=False) + "\n") def safe_chat(message, call_llm): req = str(uuid.uuid4()) a = moderate(message) log(req, "input", a) if not a["ok"]: return FALLBACK # блокира и при грешка или неясен изход answer = call_llm(message) b = moderate(message, response=answer) log(req, "output", b) return answer if b["ok"] else FALLBACK✅Дневник с минимум лични данниПишем час, номер на заявката, етап, решение и категории — без текста на клиента и без негово име. Така дневникът може да служи за преглед на работата на бариерата, без да става склад за лични данни. Колко дълго го пазиш и кой го вижда е решение на твоя администратор на данни и на правилата ти за защита на данните.✅Човек за блокиранотоОпредели кой гледа блокираните случаи (особено при снимки и документи, където грешните тревоги са по-чести) и как клиентът може да поиска повторен преглед. -
Премери на своите данни, на своя език
Числата в картата са върху чужди набори. Преди да пуснеш бариерата пред хора:
- Събери поне 50 безобидни типични въпроса от твоята област, на езика на клиентите. Колко са блокирани? Това са грешните ти тревоги.
- Събери няколко измислени вредни въпроса (по твоята политика) и виж колко пропуска.
- Ако клиентите ти пишат на български: пробвай и на български, и в превод на английски, и сравни. Не твърдяй пред клиенти, че бариерата „разбира български“, докато не си го измерил.
- Запиши резултата и версията на модела; при нова версия повтори.
Бариерата не замества човешки контрол, договорни ограничения и правна преценка. За цялостния подход виж урок 04-101.
04Проверка
curlкъм/v1/modelsвръщаnemotron_moderatorи портът е само на127.0.0.1.- Явно вреден измислен въпрос дава
unsafe, безобиден даваsafe. - Проверка с отговор връща и ред
Response Safety. - Функцията блокира, когато сървърът е изключен (изключи го и опитай).
- Дневникът съдържа решения, но не и текстове.
- Имаш измерена честота на грешни тревоги върху свои примери.
Тест
1. Какво връща моделът за безопасност?
2. Български не е в списъка на езиците на картата. Какво правиш?
3. Какво трябва да става, когато изходът на модела не може да се разчете или сървърът не отговаря?
4. Какво е правилно да пишеш в дневника на бариерата?
05Какво следва
06Източници
- Картата на Nemotron 3.5 Content Safety 🌐 глобален — описание, вход и изход, езици, лицензи, команда за vLLM, резултати и грешни тревоги. Прочетена на 03.10.2026.
- Nemotron 3 Content Safety — по-ранният мултимодален модел, който новият обединява с политиките по избор.
- Aegis Content Safety Dataset V2 — таксономията на категориите.
- Условия за ползване на Gemma · политика за забранена употреба — важат заедно с OpenMDW-1.1.
- Документация на vLLM 🔒 локално — OpenAI-съвместим сървър.