main: 增强工具功能与消息处理
- 添加 `FileReadTool`,支持文件内容读取与安全验证 - 引入 `hasToolMessages` 逻辑,优化工具历史上下文处理 - 修改工具选项逻辑,支持禁用工具时的动态调整 - 增加消息序列化逻辑,优化 Redis 序列管理与数据同步 - 扩展测试覆盖,验证序列化与工具调用场景 - 增强 Docker Compose 脚本,支持应用重置与日志清理 - 调整工具调用超时设置,提升运行时用户体验
This commit is contained in:
@@ -16,6 +16,9 @@ use Illuminate\Support\Str;
|
||||
|
||||
class ChatService
|
||||
{
|
||||
public function __construct(private readonly MessageSequence $messageSequence)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个新聊天会话。
|
||||
@@ -88,41 +91,55 @@ class ChatService
|
||||
}
|
||||
}
|
||||
|
||||
$newSeq = $session->last_seq + 1;
|
||||
$attempts = 0;
|
||||
while (true) {
|
||||
$attempts++;
|
||||
$newSeq = $this->messageSequence->nextForSession($session);
|
||||
|
||||
$message = new Message([
|
||||
'message_id' => (string) Str::uuid(),
|
||||
'session_id' => $session->session_id,
|
||||
'role' => $dto['role'],
|
||||
'type' => $dto['type'],
|
||||
'content' => $dto['content'] ?? null,
|
||||
'payload' => $dto['payload'] ?? null,
|
||||
'reply_to' => $dto['reply_to'] ?? null,
|
||||
'dedupe_key' => $dedupeKey,
|
||||
'seq' => $newSeq,
|
||||
'created_at' => now(),
|
||||
]);
|
||||
$message = new Message([
|
||||
'message_id' => (string) Str::uuid(),
|
||||
'session_id' => $session->session_id,
|
||||
'role' => $dto['role'],
|
||||
'type' => $dto['type'],
|
||||
'content' => $dto['content'] ?? null,
|
||||
'payload' => $dto['payload'] ?? null,
|
||||
'reply_to' => $dto['reply_to'] ?? null,
|
||||
'dedupe_key' => $dedupeKey,
|
||||
'seq' => $newSeq,
|
||||
'created_at' => now(),
|
||||
]);
|
||||
|
||||
try {
|
||||
if ($save) {
|
||||
$message->save();
|
||||
}
|
||||
$isNew = true;
|
||||
} catch (QueryException $e) {
|
||||
if ($this->isUniqueConstraint($e) && $dedupeKey) {
|
||||
$existing = Message::query()
|
||||
->where('session_id', $session->session_id)
|
||||
->where('dedupe_key', $dedupeKey)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
$messageRef = $existing;
|
||||
$wasDeduped = true;
|
||||
return;
|
||||
try {
|
||||
if ($save) {
|
||||
$message->save();
|
||||
}
|
||||
}
|
||||
$isNew = true;
|
||||
break;
|
||||
} catch (QueryException $e) {
|
||||
if ($this->isUniqueConstraint($e) && $dedupeKey) {
|
||||
$existing = Message::query()
|
||||
->where('session_id', $session->session_id)
|
||||
->where('dedupe_key', $dedupeKey)
|
||||
->first();
|
||||
|
||||
throw $e;
|
||||
if ($existing) {
|
||||
$messageRef = $existing;
|
||||
$wasDeduped = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isUniqueConstraint($e) && $this->isSeqUniqueConstraint($e) && $attempts < 3) {
|
||||
$maxPersistedSeq = (int) (Message::query()
|
||||
->where('session_id', $session->session_id)
|
||||
->max('seq') ?? 0);
|
||||
|
||||
$this->messageSequence->syncToAtLeast($session->session_id, max($session->last_seq, $maxPersistedSeq));
|
||||
continue;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$session->update([
|
||||
@@ -327,4 +344,11 @@ class ChatService
|
||||
|
||||
return $sqlState === '23505';
|
||||
}
|
||||
|
||||
private function isSeqUniqueConstraint(QueryException $e): bool
|
||||
{
|
||||
$details = $e->errorInfo[2] ?? $e->getMessage();
|
||||
|
||||
return is_string($details) && str_contains($details, 'messages_session_id_seq_unique');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user