NPCvector/debug_writer.py
type-two 07a0db6b61 NPCvector v1: pgvector corpus → original NPC voice lines (GABGOD)
Distill pattern: embedded forum corpus (style reference only, never shipped
verbatim) → persona line banks with human review gate → SFT export for LoRA.
First deployment: PROCITY shopkeepers from Soulstrut/VGplus on ultra.
Includes the abliterated writer toggle and the earned-gotchas writeup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 21:19:31 +10:00

37 lines
1.8 KiB
Python

#!/opt/homebrew/bin/python3
"""One-shot debug: send the exact production prompt, dump response stats."""
import json, sys
import requests, psycopg2
import distill as D
persona = sys.argv[1] if len(sys.argv) > 1 else "milkbar_kid"
conn = psycopg2.connect(D.CFG["db"]); cur = conn.cursor()
topic = D.PERSONAS[persona]["topics"][0]
refs = D.retrieve(cur, D.embed(topic), 12, 40, 800)
w = D.writer_cfg()
ref_block = "\n---\n".join(r[2].strip()[:400] for r in refs[:6])
n = D.CFG["lines_per_topic"]
sys_p = ("You write dialogue for NPCs in a 90s Australian shopping-town video game. "
"You are given real forum posts as a VOICE AND ATTITUDE reference. "
"Never copy, quote, or lightly rephrase the reference text; never use usernames, "
"real names, URLs, or identifiable stories from it. Write ORIGINAL lines only.")
voice = D.PERSONAS[persona]["voice"]
user_p = (f"CHARACTER: {voice}\n\nSITUATION: {topic}\n\n"
f"VOICE REFERENCE (do not copy from this):\n{ref_block}\n\n"
f"Write {n} distinct things this character might SAY OUT LOUD in this situation. "
f"One or two sentences each, spoken register, no stage directions, no numbering baggage. "
f"Answer as a JSON array of {n} strings and nothing else.")
r = requests.post(w["url"] + "/v1/chat/completions", timeout=900, json={
"model": w["model"], "temperature": 0.85, "max_tokens": 4096,
"messages": [{"role": "system", "content": sys_p},
{"role": "user", "content": user_p}]})
d = r.json()
ch = d["choices"][0]
msg = ch["message"]
print("finish:", ch.get("finish_reason"),
"| content:", len(msg.get("content") or ""),
"| reasoning:", len(msg.get("reasoning") or ""))
print("usage:", d.get("usage"))
print("content head:", (msg.get("content") or "")[:300])
print("reasoning tail:", (msg.get("reasoning") or "")[-400:])