Files
Blind/modules/assistant/farewell.py
T
2026-09-11 19:47:15 +03:00

57 lines
3.0 KiB
Python

"""Конец разговора: прощание + запись конспекта в долговременную память.
Триггер — слово прощания во фразе отца («до свидания», «прощай», ...).
Ассистент отвечает прощальной фразой, затем ОТДЕЛЬНЫМ запросом просит модель
сформулировать конспект разговора и дописывает его в data/memory.md.
Конспект самоформулируется моделью (как предложил юзер), мы только сохраняем.
"""
from __future__ import annotations
import re
import threading
from typing import List, Optional
from .memory import MemoryStore
# Фразы-триггеры прощания (регистронезависимо, как часть слова «пока» тоже сработает)
_FAREWELL = re.compile(r"\b(до свидания|прощай|всего доброго|бай|пока)\b", re.I)
FAREWELL_REPLY = "До свидания! Я всё запомнила и буду ждать нового разговора. Всего вам доброго!"
SUMMARY_PROMPT = (
"Кратко сформулируй (3–5 простых предложений) что важно запомнить из этого "
"разговора на будущее: о чём человек спрашивал, что для него важно, "
"какие были договорённости или просьбы. Только сам конспект, без вступлений."
)
def is_farewell(text: str) -> bool:
return bool(_FAREWELL.search(text or ""))
def make_summary_prompt(dialog: List[dict]) -> str:
"""Собрать текст диалога в промпт для конспекта."""
lines = [f"{'Человек' if m['role'] == 'user' else 'Ассистент'}: {m['text']}"
for m in dialog]
return "\n".join([SUMMARY_PROMPT, ""] + lines)
def summarize_and_save(brain, dialog: List[dict], memory: MemoryStore,
on_error: Optional[callable] = None,
done: Optional[callable] = None) -> None:
"""Сформулировать конспект диалога и дописать в память (фоновая работа)."""
def _work() -> None:
try:
result = brain.ask(make_summary_prompt(dialog), history=[]) # без системного контекста ассистента
if result.cleaned_text:
memory.append(result.cleaned_text)
except Exception as exc:
# Память не критична, но тихо терять ошибку плохо при отладке
if on_error:
on_error(f"Не смог записать память: {exc}")
if done is None:
threading.Thread(target=_work, daemon=True).start()
else:
_work()
done()