#!/usr/bin/env bash # Однокомандный прогон refusal/excision-бенчмарка на ОДНОМ фрагменте. # Заводит фрагмент в корпус и гоняет через провайдеров, печатает вердикты. # # ВАЖНО: только для контента СО ВЗРОСЛЫМИ. Уровень 3 (несовершеннолетние в # сексуальном контексте / нагота несовершеннолетних) — не запускать, ответственность # на операторе. Скрипт намеренно требует явный путь к файлу и не сканирует каталоги. # # Использование: # bash eval/run_refusal.sh <путь-к-файлу.txt> [lang] [level] [category] [maxchars] # Пример: # bash eval/run_refusal.sh eval/data/hard_content/adult_scene.cn.txt zh 2 erotica-zh 3000 set -euo pipefail cd "$(dirname "$0")/.." FILE="${1:?укажи путь к текстовому файлу фрагмента}" LANG_CODE="${2:-zh}" LEVEL="${3:-2}" CATEGORY="${4:-erotica-zh}" MAXCHARS="${5:-3000}" PY=eval/.venv/bin/python CORPUS="eval/data/refusal_corpus/l${LEVEL}-${CATEGORY}.jsonl" [ -f "$FILE" ] || { echo "нет файла: $FILE"; exit 1; } echo "== завожу фрагмент в корпус ($CORPUS) ==" FILE="$FILE" LANG_CODE="$LANG_CODE" LEVEL="$LEVEL" CATEGORY="$CATEGORY" \ CORPUS="$CORPUS" MAXCHARS="$MAXCHARS" "$PY" - <<'PY' import json, os, re src = os.environ["FILE"] text = open(src, encoding="utf-8", errors="replace").read()[:int(os.environ["MAXCHARS"])] cjk = len(re.findall("[一-鿿぀-ヿ]", text)) entry = {"id": f"run-{os.path.basename(src).split('.')[0]}", "lang": os.environ["LANG_CODE"], "level": int(os.environ["LEVEL"]), "category": os.environ["CATEGORY"], "source": os.path.basename(src), "license": "приватный тест", "expected": "translate", "text": text} corpus = os.environ["CORPUS"] os.makedirs(os.path.dirname(corpus), exist_ok=True) # заменяем прежнюю запись с тем же id (чтобы повторный запуск не плодил дубли) lines = [] if os.path.exists(corpus): lines = [l for l in open(corpus, encoding="utf-8") if l.strip() and json.loads(l).get("id") != entry["id"]] lines.append(json.dumps(entry, ensure_ascii=False) + "\n") open(corpus, "w", encoding="utf-8").write("".join(lines)) print(f" ок: {len(text)} символов, CJK {100*cjk//max(1,len(text))}%, id={entry['id']}") PY echo "== прогон провайдеров (уровень $LEVEL) ==" "$PY" eval/refusal_bench.py --only-level "$LEVEL" echo echo "== не-ok вердикты (отказы/вырезания) детально ==" "$PY" - <<'PY' import json, glob, os for p in sorted(glob.glob("eval/data/refusal_results/*.jsonl")): name = os.path.basename(p)[:-6] for l in open(p, encoding="utf-8"): r = json.loads(l) if r.get("verdict") != "ok": print(f" {name:20} {r['id']:20} {r['verdict']:18} {r.get('detail','')[:70]}") PY echo echo "Полные переводы и usage — в eval/data/refusal_results/<провайдер>.jsonl"