Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 28d0fbc5ce | |||
| a07de626ad | |||
| f3636dddd6 | |||
| 66fa5db3d7 |
BIN
ai_chat.db
BIN
ai_chat.db
Binary file not shown.
58
main.py
58
main.py
@@ -457,6 +457,64 @@ async def handle_matrix_message(action: str, conversation_id: str = None, user_m
|
|||||||
db.close()
|
db.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if action == "generate_ai_response":
|
||||||
|
# 生成AI回复并同步
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
conv_service = ConversationService(db)
|
||||||
|
conversation = conv_service.get_conversation(conversation_id)
|
||||||
|
|
||||||
|
if conversation:
|
||||||
|
# 发送"正在输入"状态
|
||||||
|
try:
|
||||||
|
await matrix_bot.client.room_typing(room_id, typing_state=True)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 获取会话历史
|
||||||
|
history = conv_service.get_conversation_history(conversation_id, limit=20)
|
||||||
|
|
||||||
|
# 调用AI
|
||||||
|
ai_response = await ai_service.chat(history)
|
||||||
|
|
||||||
|
# 保存AI回复
|
||||||
|
assistant_msg = conv_service.add_message(
|
||||||
|
conversation_id=conversation.id,
|
||||||
|
role='assistant',
|
||||||
|
content=ai_response,
|
||||||
|
source='matrix'
|
||||||
|
)
|
||||||
|
|
||||||
|
# 发送到Matrix
|
||||||
|
await matrix_bot.send_message(room_id, ai_response)
|
||||||
|
|
||||||
|
# 关闭"正在输入"状态
|
||||||
|
try:
|
||||||
|
await matrix_bot.client.room_typing(room_id, typing_state=False)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 同步到网页端WebSocket
|
||||||
|
await manager.send_to_user(MAIN_USER_ID, {
|
||||||
|
"type": "assistant_message",
|
||||||
|
"conversation_id": conversation_id,
|
||||||
|
"message": {
|
||||||
|
"id": assistant_msg.id,
|
||||||
|
"role": "assistant",
|
||||||
|
"content": ai_response,
|
||||||
|
"source": "matrix",
|
||||||
|
"created_at": assistant_msg.created_at.isoformat()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.info(f"Matrix AI回复已发送: {ai_response[:50]}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"生成AI回复失败: {e}")
|
||||||
|
await matrix_bot.send_message(room_id, f"处理消息时出错: {str(e)}")
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
return
|
||||||
|
|
||||||
if action == "chat":
|
if action == "chat":
|
||||||
db = SessionLocal()
|
db = SessionLocal()
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
@tester:matrix.tphai.com AJFVRTHLJY matrix-ed25519 4mRjLhM8xbwjkwQP2T/iB3UZJoaADgP6cCVUiB8AtSk
|
||||||
|
@tester:matrix.tphai.com BDTRXIGPBE matrix-ed25519 gjQNtLEpIEYCjmzUx5ma91G498n4UADh84KUmiReJUM
|
||||||
|
@tester:matrix.tphai.com GALBNVJOSG matrix-ed25519 /a7qD2Od76/+Xrr/naDqWEQJZ982X9XdYkCBbRmKxBU
|
||||||
|
@tester:matrix.tphai.com GVSFGGYNJL matrix-ed25519 8qV2own4G3m2nki+izFDBOrAxtbGl8RoneM3qUPkThU
|
||||||
|
@tester:matrix.tphai.com IMEQIQPXTR matrix-ed25519 6Yd4lmhP6jdkkNvh1rIw6TRK331ZUyiAt5G5hPeYqSE
|
||||||
|
@tester:matrix.tphai.com MIPPYHRVAS matrix-ed25519 s8Ol56sxLCjCOi0Gkv/Kj7LqVMp/8ZmuAJ6QA1rUi7o
|
||||||
|
@tester:matrix.tphai.com UKJGJYQQLT matrix-ed25519 opC9rhsz1nzrvQqNWMKTF5FxWIGuHTDfixx+q/Y8ea0
|
||||||
|
@tester:matrix.tphai.com UPMZGRLESG matrix-ed25519 86c6XPCIYHgesq83C2k5xhXNa0EYMnqTq4jFrTwJX8I
|
||||||
|
@huangzhuang_bro:matrix.tphai.com BQHGFLQEPR matrix-ed25519 IrEHmvqotfHKLyx1JRJp4RthUVyBT8qQX72qBifRRyQ
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
@tester:matrix.tphai.com AJFVRTHLJY matrix-ed25519 4mRjLhM8xbwjkwQP2T/iB3UZJoaADgP6cCVUiB8AtSk
|
||||||
|
@tester:matrix.tphai.com GVSFGGYNJL matrix-ed25519 8qV2own4G3m2nki+izFDBOrAxtbGl8RoneM3qUPkThU
|
||||||
|
@tester:matrix.tphai.com IMEQIQPXTR matrix-ed25519 6Yd4lmhP6jdkkNvh1rIw6TRK331ZUyiAt5G5hPeYqSE
|
||||||
|
@tester:matrix.tphai.com MIPPYHRVAS matrix-ed25519 s8Ol56sxLCjCOi0Gkv/Kj7LqVMp/8ZmuAJ6QA1rUi7o
|
||||||
|
@tester:matrix.tphai.com UKJGJYQQLT matrix-ed25519 opC9rhsz1nzrvQqNWMKTF5FxWIGuHTDfixx+q/Y8ea0
|
||||||
|
@tester:matrix.tphai.com UPMZGRLESG matrix-ed25519 86c6XPCIYHgesq83C2k5xhXNa0EYMnqTq4jFrTwJX8I
|
||||||
|
@huangzhuang_bro:matrix.tphai.com BQHGFLQEPR matrix-ed25519 IrEHmvqotfHKLyx1JRJp4RthUVyBT8qQX72qBifRRyQ
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
@tester:matrix.tphai.com AJFVRTHLJY matrix-ed25519 4mRjLhM8xbwjkwQP2T/iB3UZJoaADgP6cCVUiB8AtSk
|
||||||
|
@tester:matrix.tphai.com BDTRXIGPBE matrix-ed25519 gjQNtLEpIEYCjmzUx5ma91G498n4UADh84KUmiReJUM
|
||||||
|
@tester:matrix.tphai.com GVSFGGYNJL matrix-ed25519 8qV2own4G3m2nki+izFDBOrAxtbGl8RoneM3qUPkThU
|
||||||
|
@tester:matrix.tphai.com IMEQIQPXTR matrix-ed25519 6Yd4lmhP6jdkkNvh1rIw6TRK331ZUyiAt5G5hPeYqSE
|
||||||
|
@tester:matrix.tphai.com MIPPYHRVAS matrix-ed25519 s8Ol56sxLCjCOi0Gkv/Kj7LqVMp/8ZmuAJ6QA1rUi7o
|
||||||
|
@tester:matrix.tphai.com UKJGJYQQLT matrix-ed25519 opC9rhsz1nzrvQqNWMKTF5FxWIGuHTDfixx+q/Y8ea0
|
||||||
|
@tester:matrix.tphai.com UPMZGRLESG matrix-ed25519 86c6XPCIYHgesq83C2k5xhXNa0EYMnqTq4jFrTwJX8I
|
||||||
|
@huangzhuang_bro:matrix.tphai.com BQHGFLQEPR matrix-ed25519 IrEHmvqotfHKLyx1JRJp4RthUVyBT8qQX72qBifRRyQ
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
@huangzhuang_bro:matrix.tphai.com BQHGFLQEPR matrix-ed25519 IrEHmvqotfHKLyx1JRJp4RthUVyBT8qQX72qBifRRyQ
|
||||||
|
@tester:matrix.tphai.com AJFVRTHLJY matrix-ed25519 4mRjLhM8xbwjkwQP2T/iB3UZJoaADgP6cCVUiB8AtSk
|
||||||
|
@tester:matrix.tphai.com GVSFGGYNJL matrix-ed25519 8qV2own4G3m2nki+izFDBOrAxtbGl8RoneM3qUPkThU
|
||||||
|
@tester:matrix.tphai.com IMEQIQPXTR matrix-ed25519 6Yd4lmhP6jdkkNvh1rIw6TRK331ZUyiAt5G5hPeYqSE
|
||||||
|
@tester:matrix.tphai.com MIPPYHRVAS matrix-ed25519 s8Ol56sxLCjCOi0Gkv/Kj7LqVMp/8ZmuAJ6QA1rUi7o
|
||||||
|
@tester:matrix.tphai.com UKJGJYQQLT matrix-ed25519 opC9rhsz1nzrvQqNWMKTF5FxWIGuHTDfixx+q/Y8ea0
|
||||||
Binary file not shown.
@@ -26,6 +26,7 @@ class MatrixBot:
|
|||||||
self.is_running: bool = False
|
self.is_running: bool = False
|
||||||
self.on_message_callback: Optional[Callable] = None
|
self.on_message_callback: Optional[Callable] = None
|
||||||
self.last_room_id: str = ""
|
self.last_room_id: str = ""
|
||||||
|
self.processed_events: set = set() # 已处理的事件ID,防止重复处理
|
||||||
|
|
||||||
async def init_from_config(self):
|
async def init_from_config(self):
|
||||||
"""从数据库配置初始化"""
|
"""从数据库配置初始化"""
|
||||||
@@ -171,6 +172,20 @@ class MatrixBot:
|
|||||||
|
|
||||||
async def _process_message(self, room, sender, message_text, event_id):
|
async def _process_message(self, room, sender, message_text, event_id):
|
||||||
"""处理消息的核心逻辑"""
|
"""处理消息的核心逻辑"""
|
||||||
|
# 检查是否已处理过此事件(防止重复处理)
|
||||||
|
if event_id in self.processed_events:
|
||||||
|
logger.debug(f"忽略已处理的事件: {event_id}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 标记为已处理
|
||||||
|
self.processed_events.add(event_id)
|
||||||
|
logger.info(f"处理消息: event_id={event_id}")
|
||||||
|
|
||||||
|
# 限制集合大小,保留最近的100个
|
||||||
|
if len(self.processed_events) > 100:
|
||||||
|
# 清理旧的一半
|
||||||
|
self.processed_events = set(list(self.processed_events)[-50:])
|
||||||
|
|
||||||
# 忽略自己发送的消息
|
# 忽略自己发送的消息
|
||||||
if sender == self.user_id:
|
if sender == self.user_id:
|
||||||
logger.debug(f"忽略自己发送的消息: {sender}")
|
logger.debug(f"忽略自己发送的消息: {sender}")
|
||||||
@@ -235,45 +250,14 @@ class MatrixBot:
|
|||||||
sender=sender
|
sender=sender
|
||||||
)
|
)
|
||||||
|
|
||||||
# 发送"正在输入"状态
|
# 通知回调处理 AI 回复(不再在这里直接调用 AI)
|
||||||
try:
|
|
||||||
await self.client.room_typing(room.room_id, typing_state=True)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"发送输入状态失败: {e}")
|
|
||||||
|
|
||||||
# 获取AI回复 - 使用字典格式
|
|
||||||
messages = conv_service.get_conversation_history(conversation.conversation_id)
|
|
||||||
ai_response = await ai_service.chat(messages)
|
|
||||||
|
|
||||||
# 保存AI回复
|
|
||||||
conv_service.add_message(
|
|
||||||
conversation_id=conversation.id,
|
|
||||||
role='assistant',
|
|
||||||
content=ai_response,
|
|
||||||
source='matrix'
|
|
||||||
)
|
|
||||||
|
|
||||||
# 发送回复
|
|
||||||
await self.send_message(room.room_id, ai_response)
|
|
||||||
|
|
||||||
# 关闭"正在输入"状态
|
|
||||||
try:
|
|
||||||
await self.client.room_typing(room.room_id, typing_state=False)
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"关闭输入状态失败: {e}")
|
|
||||||
|
|
||||||
# 调用回调(用于网页同步)
|
|
||||||
if self.on_message_callback:
|
if self.on_message_callback:
|
||||||
await self.on_message_callback(
|
await self.on_message_callback(
|
||||||
action="chat",
|
action="generate_ai_response",
|
||||||
conversation_id=conversation.conversation_id,
|
conversation_id=conversation.conversation_id,
|
||||||
user_message=message_text,
|
room_id=room.room_id
|
||||||
room_id=room.room_id,
|
|
||||||
message_id=user_msg.id
|
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.info(f"Matrix回复已发送: {ai_response[:50]}")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"处理Matrix消息失败: {e}")
|
logger.error(f"处理Matrix消息失败: {e}")
|
||||||
import traceback
|
import traceback
|
||||||
|
|||||||
@@ -467,11 +467,10 @@
|
|||||||
messageDiv.className = `message ${role}`;
|
messageDiv.className = `message ${role}`;
|
||||||
|
|
||||||
const avatar = role === 'user' ? '👤' : '🤖';
|
const avatar = role === 'user' ? '👤' : '🤖';
|
||||||
const sourceLabel = source === 'matrix' ? ' [Matrix]' : '';
|
|
||||||
|
|
||||||
messageDiv.innerHTML = `
|
messageDiv.innerHTML = `
|
||||||
<div class="message-avatar">${avatar}</div>
|
<div class="message-avatar">${avatar}</div>
|
||||||
<div class="message-content">${formatContent(content)}${sourceLabel}</div>
|
<div class="message-content">${formatContent(content)}</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
container.appendChild(messageDiv);
|
container.appendChild(messageDiv);
|
||||||
|
|||||||
Reference in New Issue
Block a user