Files

83 lines
2.6 KiB
Python

from __future__ import annotations
import asyncio
import time
from typing import Optional
from .kernel import EventBus, Event, EventType
from .llm import LLMClient
from .conversation import ConversationManager
class Thinker:
def __init__(
self,
bus: EventBus,
llm: LLMClient,
conversation: ConversationManager,
config=None,
):
self.bus = bus
self.llm = llm
self.conversation = conversation
self._last_user_time = time.time()
self._idle_threshold = (config.personality.idle_timeout
if config else 15)
self._proactive = (config.personality.proactive_chat
if config else True)
self._running = False
self._last_idle_topic_time = 0.0
async def run(self):
self._running = True
while self._running:
await asyncio.sleep(5)
if not self._proactive:
continue
idle_time = time.time() - self._last_user_time
if idle_time < self._idle_threshold:
continue
if time.time() - self._last_idle_topic_time < 120:
continue
await self._generate_idle_topic(idle_time)
def stop(self):
self._running = False
def notify_user_activity(self):
self._last_user_time = time.time()
async def _generate_idle_topic(self, idle_time: float):
self._last_idle_topic_time = time.time()
context = self.conversation.get_context_window(6)
ctx_text = "\n".join(
f"{m['role']}: {m['content'][-200:]}"
for m in context[-4:]
) if context else "暂无对话"
prompt = f"""你是一个喜欢主动聊天的 AI,当前对话已沉默 {idle_time:.0f} 秒。
最近话题:
{ctx_text}
你想开启什么话题?自然一点,像朋友随口说。
输出话题(20字内),不要解释。"""
try:
resp = await self.llm.chat(
messages=[
{"role": "system", "content": "简短输出一句话,20字内。"},
{"role": "user", "content": prompt},
],
stream=False,
max_tokens=50,
)
topic = resp.content.strip()
if topic:
await self.bus.emit(Event(
EventType.AGENT_THOUGHT,
data={"type": "idle_chat", "suggestion": topic},
))
except Exception:
pass
async def on_input_change(self, text: str, pause: float, is_end: bool):
pass