File size: 2,725 Bytes
1775907
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
classify_memory_reference.py

Detects whether a user message is explicitly recalling a past conversation.
Only when this fires does the system query db5 (long-term FAISS history).

Returns:
  {
    "recalls_past": bool,
    "time_hint":      str | None,   e.g. "last week", "in March", "a while ago"
    "character_hint": str | None,   e.g. "socrates", "diogenes"
  }

Uses Tier C (nano) — binary classifier, minimal tokens.
"""

import json
import re
from typing import Optional

_SYSTEM_PROMPT = """You are a memory-reference detector for a chat application.

Decide if the user's message explicitly tries to recall a PAST conversation —
phrases like "do you remember", "we talked about", "you told me", "last time",
"a while ago you said", "didn't we discuss", "remember when", etc.

Respond ONLY with a JSON object, no prose:
{
  "recalls_past": true | false,
  "time_hint": "<time expression from the message, or null>",
  "character_hint": "<character name mentioned (socrates/diogenes/nietzsche/camus/schopenhauer), or null>"
}"""


def classify_memory_reference(user_msg: str) -> dict:
    """
    Returns {"recalls_past": bool, "time_hint": str|None, "character_hint": str|None}.
    Fails safe: returns recalls_past=False on any error.
    """
    default = {"recalls_past": False, "time_hint": None, "character_hint": None}
    if not user_msg or not user_msg.strip():
        return default

    # Fast path: skip LLM if no memory-signal words present
    _SIGNALS = (
        "remember", "recall", "we talked", "you told", "you said",
        "last time", "last week", "last month", "a while ago", "before",
        "didn't we", "we discussed", "you mentioned",
    )
    msg_lower = user_msg.lower()
    if not any(s in msg_lower for s in _SIGNALS):
        return default

    try:
        from llm_client import client, get_model
        resp = client.chat.completions.create(
            model=get_model("C"),
            messages=[
                {"role": "system", "content": _SYSTEM_PROMPT},
                {"role": "user",   "content": user_msg},
            ],
            temperature=0.0,
            max_tokens=80,
        )
        raw = resp.choices[0].message.content.strip()
        # strip markdown fences if present
        raw = re.sub(r"^```(?:json)?\s*|\s*```$", "", raw, flags=re.DOTALL).strip()
        result = json.loads(raw)
        return {
            "recalls_past":   bool(result.get("recalls_past", False)),
            "time_hint":      result.get("time_hint") or None,
            "character_hint": (result.get("character_hint") or "").lower() or None,
        }
    except Exception as e:
        print(f"[classify_memory_reference] error: {e}")
        return default