64 lines
3.2 KiB
Bash
Executable file
64 lines
3.2 KiB
Bash
Executable file
#!/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"
|