Files
TrulyMEM-TrueHumanMEM/graph_memory_tui/services/chat_service.py
JianFeeeee 6689f08456 feat: Add embedded SQLite database and web interface
- Implement EmbeddedGraphDB with full Neo4j compatibility
- Add web interface for browser access
- Fix input box display issue
- Add comprehensive database tests (15/15 passed)
- Simplify startup script (3 steps, no Docker needed)
- Add multi-language support
- Add .gitignore for clean repository
- Update documentation

All tests passed. Ready for production.
2026-04-10 15:43:22 +08:00

105 lines
3.1 KiB
Python

"""聊天服务"""
import asyncio
from datetime import datetime
from typing import AsyncIterator, TYPE_CHECKING
from ..core.imports import GraphMemoryClient
from ..models.message import ToolCall, ToolResult
from .tool_service import ToolService
if TYPE_CHECKING:
from ..core.imports import Neo4jGraph
class ChatService:
"""聊天业务服务"""
def __init__(
self,
graph: "Neo4jGraph",
client: GraphMemoryClient,
tool_service: ToolService
):
self._graph = graph
self._client = client
self._tool_service = tool_service
self._messages: list[dict] = []
async def send_message(self, user_input: str) -> AsyncIterator[dict]:
"""发送消息并流式返回事件"""
# 1. 发送用户消息事件
yield {
"type": "user_message",
"content": user_input
}
try:
# 2. 异步调用 API
response = await self._call_api_async(user_input)
# 3. 处理工具调用
tool_calls = None
tool_results = None
if response.tool_calls:
tool_calls = []
tool_results = []
for tool_call_data in response.tool_calls:
# 创建工具调用对象
tool_call = ToolCall(
id=tool_call_data.id,
name=tool_call_data.function.name,
arguments=tool_call_data.function.arguments
)
tool_calls.append(tool_call)
# 发送工具调用事件
yield {
"type": "tool_call",
"tool_call": tool_call
}
# 执行工具
result = await self._tool_service.execute(tool_call)
tool_results.append(result)
# 发送工具结果事件
log_entry = ToolService._create_log_entry(tool_call, result)
yield {
"type": "tool_result",
"tool_result": result,
"log_entry": log_entry
}
# 4. 返回最终回复
yield {
"type": "assistant_message",
"content": response.content,
"tool_calls": tool_calls,
"tool_results": tool_results
}
except Exception as e:
# 错误处理
yield {
"type": "error",
"error": str(e)
}
async def _call_api_async(self, message: str):
"""异步调用 API"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
None,
lambda: self._client.send_message(message)
)
def clear_history(self) -> None:
"""清空消息历史"""
self._messages.clear()
def get_history(self) -> list[dict]:
"""获取消息历史"""
return self._messages.copy()