Initial commit: Air Agent Framework v2:全双工对话智能体(打断、插话、主动开口)
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
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
|
||||
Reference in New Issue
Block a user