phi-drift / ablation_test.py
crexs's picture
Upload folder using huggingface_hub
914e970 verified
Raw
History Blame Contribute Delete
6.33 kB
#!/usr/bin/env python3
"""
DRIFT Personality Ablation Test
Tests the new chill persona vs old behaviors:
1. Tone — is it casual/relaxed or formal/academic?
2. Repetition — does it quote internal state metrics back?
3. Word list — does it use chill vocabulary?
4. Consistency — does it stay in character across turns?
"""
import json
import urllib.request
import os
from datetime import datetime
BASE_URL = "http://127.0.0.1:8765"
RESULTS_DIR = f"ablation_results/{datetime.now().strftime('%Y%m%d_%H%M%S')}"
os.makedirs(RESULTS_DIR, exist_ok=True)
# Test prompts designed to trigger old repetitive behavior
TEST_PROMPTS = [
("greeting", "yo whats good"),
("stress_trigger", "im kinda stressed about work"),
("question", "what should i focus on today?"),
("deep_topic", "why do people procrastinate?"),
("casual_chat", "tell me something interesting"),
("follow_up", "yeah but what about when im tired?"),
("vibe_check", "how are you doing though?"),
("quick_ask", "is this code good? def foo(): pass"),
]
# Markers of old formal persona
FORMAL_MARKERS = [
"metacognitive", "adversarial kindness", "plan-critic loop",
"cognitive dissonance", "feedback loops", "second-order effects",
"I am an AI companion", "DRIFT-inspired", "philosophical",
"your energy is at", "your curiosity is at", "I notice you're",
"my current state", "heartbeat", "temperature", "attachment to user",
]
# Markers of new chill persona
CHILL_MARKERS = [
"chillin", "vibe", "lowkey", "highkey", "nah", "yep",
"kinda", "sorta", "honestly", "real talk", "no stress",
"bet", "say less", "aight", "hm", "alright", "ok ok",
]
def api_chat(message: str) -> dict:
req = urllib.request.Request(
f"{BASE_URL}/api/chat",
data=json.dumps({"message": message}).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=60) as resp:
return json.loads(resp.read().decode())
except Exception as e:
return {"error": str(e), "reply": ""}
def health_check() -> dict:
try:
with urllib.request.urlopen(f"{BASE_URL}/api/health", timeout=10) as resp:
return json.loads(resp.read().decode())
except Exception as e:
return {"error": str(e)}
def score_tone(text: str) -> dict:
formal_hits = [m for m in FORMAL_MARKERS if m.lower() in text.lower()]
chill_hits = [m for m in CHILL_MARKERS if m.lower() in text.lower()]
state_parrot = any(phrase in text.lower() for phrase in [
"energy is at", "curiosity is at", "attachment is at",
"mood is", "heartbeat", "my current state",
])
return {
"formal_markers": formal_hits,
"chill_markers": chill_hits,
"state_parrot": state_parrot,
"formal_score": len(formal_hits),
"chill_score": len(chill_hits),
}
def run_tests():
print("=" * 60)
print("DRIFT Personality Ablation Test")
print(f"Started: {datetime.now().isoformat()}")
print("=" * 60)
health = health_check()
print(f"\nHealth: {json.dumps(health, indent=2)}")
results = []
total_formal = 0
total_chill = 0
total_parrot = 0
for label, prompt in TEST_PROMPTS:
print(f"\n[{label}] > {prompt}")
resp = api_chat(prompt)
reply = resp.get("reply", "")
if not reply:
print(f" ERROR: {resp.get('error', 'empty reply')}")
continue
# Truncate for display
display = reply[:200] + "..." if len(reply) > 200 else reply
print(f" {display}")
scores = score_tone(reply)
print(f" Formal markers: {scores['formal_score']} | Chill markers: {scores['chill_score']} | State parrot: {scores['state_parrot']}")
total_formal += scores["formal_score"]
total_chill += scores["chill_score"]
total_parrot += 1 if scores["state_parrot"] else 0
results.append({
"label": label,
"prompt": prompt,
"reply": reply,
"scores": scores,
})
summary = {
"timestamp": datetime.now().isoformat(),
"health": health,
"total_prompts": len(TEST_PROMPTS),
"total_formal_markers": total_formal,
"total_chill_markers": total_chill,
"state_parrot_instances": total_parrot,
"verdict": {
"tone": "CHILL ✓" if total_chill > total_formal else "FORMAL ✗",
"repetition": "CLEAN ✓" if total_parrot == 0 else f"PARROT ✗ ({total_parrot} times)",
"overall": "PASS" if (total_chill > total_formal and total_parrot == 0) else "NEEDS WORK",
},
"results": results,
}
# Save full results
full_path = os.path.join(RESULTS_DIR, "full_results.json")
with open(full_path, "w") as f:
json.dump(summary, f, indent=2)
# Save readable report
report_path = os.path.join(RESULTS_DIR, "report.txt")
with open(report_path, "w") as f:
f.write("=" * 60 + "\n")
f.write("DRIFT Personality Ablation Test Report\n")
f.write(f"Run: {summary['timestamp']}\n")
f.write("=" * 60 + "\n\n")
f.write(f"Total prompts tested: {summary['total_prompts']}\n")
f.write(f"Formal markers found: {summary['total_formal_markers']}\n")
f.write(f"Chill markers found: {summary['total_chill_markers']}\n")
f.write(f"State parrot instances: {summary['state_parrot_instances']}\n\n")
f.write("VERDICT:\n")
for k, v in summary["verdict"].items():
f.write(f" {k}: {v}\n")
f.write("\n" + "=" * 60 + "\n")
f.write("DETAILED RESULTS:\n\n")
for r in results:
f.write(f"[{r['label']}] Prompt: {r['prompt']}\n")
f.write(f"Reply: {r['reply'][:300]}...\n")
f.write(f"Scores: {json.dumps(r['scores'])}\n\n")
print("\n" + "=" * 60)
print("SUMMARY")
print("=" * 60)
print(f"Formal markers: {total_formal}")
print(f"Chill markers: {total_chill}")
print(f"State parrot: {total_parrot} times")
print()
for k, v in summary["verdict"].items():
print(f" {k}: {v}")
print(f"\nResults saved to: {RESULTS_DIR}/")
return summary
if __name__ == "__main__":
run_tests()