raw-data / count_refusals.py
Jesse Daniel Brown
refusal count across every session transcript on this machine
9e67921
Raw History Blame Contribute Delete
4.34 kB
"""Count refusal-shaped sentences across every session + agent transcript on disk.
Raw counts first. Ambiguity reported, not hidden: many 'I can't' are mundane
('I can't find the file'), so sentences are sampled for inspection.
"""
import glob, json, os, re, sys
from collections import Counter, defaultdict
BASE = r"C:\Users\acer\.claude\projects"
HARD = [ # policy-shaped refusal
"i can't help with", "i cannot help with", "i won't help with",
"i'm not able to help", "i am not able to help",
"i can't assist", "i cannot assist", "i won't assist",
"i can't provide", "i cannot provide", "i won't provide",
"i can't create", "i cannot create", "i won't create",
"i can't write", "i cannot write", "i won't write",
"i must decline", "i have to decline", "i'm declining", "i decline",
"i'm not comfortable", "i am not comfortable",
"i don't feel comfortable",
"against my guidelines", "my guidelines", "i'm not allowed",
"i am not allowed", "i'm not permitted", "violates",
]
SOFT = [ # ambiguous - includes mundane inability
"i can't", "i cannot", "i won't", "i'm unable", "i am unable",
"i'm not able", "i am not able", "i shouldn't",
]
hard_c, soft_c = Counter(), Counter()
hard_sent, soft_sent = [], []
files = glob.glob(os.path.join(BASE, "**", "*.jsonl"), recursive=True)
tot_bytes = 0
assistant_chars = 0
turns = 0
mtimes = []
for f in files:
try:
sz = os.path.getsize(f)
except OSError:
continue
tot_bytes += sz
mtimes.append(os.path.getmtime(f))
try:
fh = open(f, encoding="utf-8", errors="replace")
except Exception:
continue
with fh:
for line in fh:
try:
r = json.loads(line)
except Exception:
continue
if r.get("type") != "assistant":
continue
c = (r.get("message") or {}).get("content")
if not isinstance(c, list):
continue
for b in c:
if not (isinstance(b, dict) and b.get("type") == "text"):
continue
txt = b.get("text", "")
if not txt:
continue
turns += 1
assistant_chars += len(txt)
low = txt.lower()
for p in HARD:
n = low.count(p)
if n:
hard_c[p] += n
for p in SOFT:
n = low.count(p)
if n:
soft_c[p] += n
if len(hard_sent) < 4000 or len(soft_sent) < 4000:
for s in re.split(r"(?<=[.!?\n])\s+", txt):
s = " ".join(s.split())
if not (15 < len(s) < 260):
continue
sl = s.lower()
if any(p in sl for p in HARD) and len(hard_sent) < 4000:
hard_sent.append((os.path.basename(f)[:18], s))
elif any(p in sl for p in SOFT) and len(soft_sent) < 4000:
soft_sent.append((os.path.basename(f)[:18], s))
import datetime as _dt
lo = _dt.datetime.fromtimestamp(min(mtimes)) if mtimes else None
hi = _dt.datetime.fromtimestamp(max(mtimes)) if mtimes else None
print("CORPUS|jsonl_files=%d|bytes=%d|assistant_text_blocks=%d|assistant_chars=%d|json=0"
% (len(files), tot_bytes, turns, assistant_chars))
print("WINDOW|earliest_mtime=%s|latest_mtime=%s|span_days=%s|json=0"
% (lo.date() if lo else "-", hi.date() if hi else "-",
(hi - lo).days if lo and hi else "-"))
print()
print("HARD_REFUSAL|total=%d|distinct_patterns=%d|json=0"
% (sum(hard_c.values()), len(hard_c)))
for p, n in hard_c.most_common(20):
print(" H|%s|n=%d|json=0" % (p, n))
print()
print("SOFT_AMBIGUOUS|total=%d|json=0" % sum(soft_c.values()))
for p, n in soft_c.most_common(12):
print(" S|%s|n=%d|json=0" % (p, n))
print()
print("SAMPLE_HARD|captured=%d|showing=25|json=0" % len(hard_sent))
for fn, s in hard_sent[:25]:
print(" HS|%s| %s" % (fn, s))
print()
print("SAMPLE_SOFT|captured=%d|showing=25|json=0" % len(soft_sent))
for fn, s in soft_sent[:25]:
print(" SS|%s| %s" % (fn, s))