| |
| """ |
| 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 = [ |
| ("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"), |
| ] |
|
|
| |
| 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", |
| ] |
|
|
| |
| 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 |
|
|
| |
| 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, |
| } |
|
|
| |
| full_path = os.path.join(RESULTS_DIR, "full_results.json") |
| with open(full_path, "w") as f: |
| json.dump(summary, f, indent=2) |
|
|
| |
| 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() |
|
|