Repository navigation
Expand file tree
/
Copy pathscore.py
More file actions
98 lines (81 loc) · 3.07 KB
/
Copy pathscore.py
File metadata and controls
98 lines (81 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""AI scoring of pickup lines via Claude.
Composite = 0.20 * creativity + 0.30 * response_quality + 0.50 * hookup_probability
"""
from __future__ import annotations
import json
import logging
import re
import time
from typing import Optional
import anthropic
from store import Store
log = logging.getLogger(__name__)
SCORE_MODEL = "claude-haiku-4-5-20251001"
SCORE_PROMPT = """\
Score this pickup line/opener on three dimensions. Return JSON only.
Pickup line: "{line_text}"
Other person's response: {response}
Outcome hint: {outcome_hint}
Context / platform: {context}
Score each dimension 0.0–10.0:
creativity:
How original, witty, or contextually clever is the line?
0-3 = Generic/overused ("Are you tired? You've been running through my mind")
4-6 = Decent, moderately creative
7-10 = Highly original, personalized, genuinely clever
response_quality:
How positively did the other person respond?
0 = No reply / blocked / negative
1-3 = Cold, one-word, disinterested
4-6 = Neutral engagement
7-9 = Enthusiastic, laughing, asking questions back
10 = Exceptional (immediate date suggestion, very enthusiastic)
If response is unknown → 5.0
hookup_probability:
Estimated 0-10 probability this interaction leads to a date or hookup.
Base on response_quality + outcome_hint + overall vibe.
0 = Definitely not (blocked/negative)
5 = Unknown/neutral
10 = Confirmed hookup/date or very high probability
Return ONLY valid JSON — no markdown, no explanation:
{{"creativity": X.X, "response_quality": X.X, "hookup_probability": X.X}}
"""
def score_line(client: anthropic.Anthropic, line: dict) -> Optional[dict]:
prompt = SCORE_PROMPT.format(
line_text=line.get("line_text", ""),
response=repr(line.get("response")) if line.get("response") else "unknown",
outcome_hint=repr(line.get("outcome_hint")) if line.get("outcome_hint") else "unknown",
context=line.get("context") or "dating app",
)
try:
msg = client.messages.create(
model=SCORE_MODEL,
max_tokens=128,
messages=[{"role": "user", "content": prompt}],
)
raw = msg.content[0].text.strip()
raw = re.sub(r"^```(?:json)?\s*|\s*```$", "", raw, flags=re.MULTILINE).strip()
scores = json.loads(raw)
for k in ("creativity", "response_quality", "hookup_probability"):
scores[k] = max(0.0, min(10.0, float(scores.get(k, 5.0))))
return scores
except Exception as e:
log.warning("Scoring failed for line %s: %s", line.get("id"), e)
return None
def score_all(
store: Store,
client: anthropic.Anthropic,
limit: int = 200,
delay: float = 0.3,
) -> int:
"""Score all unscored lines. Returns count scored."""
unscored = store.unscored_lines(limit=limit)
log.info("Scoring %d unscored lines with %s", len(unscored), SCORE_MODEL)
count = 0
for line in unscored:
scores = score_line(client, line)
if scores:
store.upsert_score(line["id"], scores, SCORE_MODEL)
count += 1
time.sleep(delay)
return count