10 KiB
10 KiB
📊 Модели данных
Полное описание всех моделей и сущностей в ChatBot.
🗂️ Типы моделей
1. Domain Models (Доменные модели)
ChatSession- Основная модель сессии чатаChatMessage- DTO для сообщений
2. Entity Models (Сущности БД)
ChatSessionEntity- Сущность сессии в БДChatMessageEntity- Сущность сообщения в БД
3. Configuration Models (Конфигурация)
TelegramBotSettingsOllamaSettingsAISettingsDatabaseSettings
📦 Domain Models
ChatSession
Основная модель для работы с сессией чата.
public class ChatSession
{
public string SessionId { get; set; } // Уникальный ID
public long ChatId { get; set; } // Telegram chat ID
public string ChatType { get; set; } // Тип чата
public string ChatTitle { get; set; } // Название
public string Model { get; set; } // AI модель
public DateTime CreatedAt { get; set; } // Создан
public DateTime LastUpdatedAt { get; set; } // Обновлен
public int MaxHistoryLength { get; set; } // Макс история
}
Ключевые методы:
Работа с сообщениями
// Добавить сообщение (базовый)
void AddMessage(ChatMessage message)
// Добавить с компрессией
Task AddMessageWithCompressionAsync(ChatMessage message, int threshold, int target)
// Добавить user сообщение
void AddUserMessage(string content, string username)
Task AddUserMessageWithCompressionAsync(string content, string username, int threshold, int target)
// Добавить assistant сообщение
void AddAssistantMessage(string content)
Task AddAssistantMessageWithCompressionAsync(string content, int threshold, int target)
// Получить все сообщения
List<ChatMessage> GetAllMessages()
// Количество сообщений
int GetMessageCount()
// Очистить историю
void ClearHistory()
Управление компрессией
void SetCompressionService(IHistoryCompressionService service)
Thread Safety:
Все операции с _messageHistory защищены lock(_lock)
Управление историей:
- Автоматическое обрезание при превышении
MaxHistoryLength - Сохранение system prompt при обрезке
- Поддержка асинхронной компрессии
ChatMessage (DTO)
public class ChatMessage
{
public ChatRole Role { get; set; } // user/assistant/system
public string Content { get; set; } // Текст сообщения
}
ChatRole enum:
public enum ChatRole
{
System, // Системный промпт
User, // Сообщение пользователя
Assistant // Ответ бота
}
💾 Entity Models
ChatSessionEntity
Сущность для хранения в PostgreSQL.
public class ChatSessionEntity
{
public int Id { get; set; } // PK (auto-increment)
public string SessionId { get; set; } // Unique, indexed
public long ChatId { get; set; } // Indexed
public string ChatType { get; set; } // Max 20 chars
public string? ChatTitle { get; set; } // Max 200 chars
public string Model { get; set; } // Max 100 chars
public DateTime CreatedAt { get; set; } // Required
public DateTime LastUpdatedAt { get; set; } // Required
public List<ChatMessageEntity> Messages { get; set; } // Navigation property
}
Индексы:
SessionId- Unique indexChatId- Index для быстрого поиска
Constraints:
SessionId- Required, MaxLength(50)ChatId- RequiredChatType- Required, MaxLength(20)
Relationships:
- One-to-Many с
ChatMessageEntity - Cascade Delete - удаление сессии удаляет сообщения
ChatMessageEntity
public class ChatMessageEntity
{
public int Id { get; set; } // PK
public int SessionId { get; set; } // FK
public string Content { get; set; } // Max 10000 chars
public string Role { get; set; } // Max 20 chars
public int MessageOrder { get; set; } // Порядок в диалоге
public DateTime CreatedAt { get; set; } // Время создания
public ChatSessionEntity Session { get; set; } // Navigation property
}
Индексы:
SessionId- IndexCreatedAt- Index для сортировки(SessionId, MessageOrder)- Composite index
Constraints:
Content- Required, MaxLength(10000)Role- Required, MaxLength(20)
⚙️ Configuration Models
TelegramBotSettings
public class TelegramBotSettings
{
public string BotToken { get; set; } = string.Empty;
}
Validator:
RuleFor(x => x.BotToken)
.NotEmpty()
.MinimumLength(10);
OllamaSettings
public class OllamaSettings
{
public string Url { get; set; } = string.Empty;
public string DefaultModel { get; set; } = string.Empty;
}
Validator:
RuleFor(x => x.Url)
.NotEmpty()
.Must(BeValidUrl);
RuleFor(x => x.DefaultModel)
.NotEmpty();
AISettings
public class AISettings
{
public double Temperature { get; set; } = 0.9;
public string SystemPromptPath { get; set; } = "Prompts/system-prompt.txt";
public int MaxRetryAttempts { get; set; } = 3;
public int RetryDelayMs { get; set; } = 1000;
public int RequestTimeoutSeconds { get; set; } = 180;
// Compression settings
public bool EnableHistoryCompression { get; set; } = true;
public int CompressionThreshold { get; set; } = 20;
public int CompressionTarget { get; set; } = 10;
public int MinMessageLengthForSummarization { get; set; } = 50;
public int MaxSummarizedMessageLength { get; set; } = 200;
// Advanced
public bool EnableExponentialBackoff { get; set; } = true;
public int MaxRetryDelayMs { get; set; } = 30000;
public int CompressionTimeoutSeconds { get; set; } = 30;
public int StatusCheckTimeoutSeconds { get; set; } = 10;
}
Validator:
RuleFor(x => x.Temperature)
.GreaterThanOrEqualTo(0.0)
.LessThanOrEqualTo(2.0);
RuleFor(x => x.MaxRetryAttempts)
.GreaterThanOrEqualTo(1)
.LessThanOrEqualTo(10);
DatabaseSettings
public class DatabaseSettings
{
public string ConnectionString { get; set; } = string.Empty;
public bool EnableSensitiveDataLogging { get; set; } = false;
public int CommandTimeout { get; set; } = 30;
}
Validator:
RuleFor(x => x.ConnectionString)
.NotEmpty();
RuleFor(x => x.CommandTimeout)
.GreaterThanOrEqualTo(5)
.LessThanOrEqualTo(300);
🔄 Маппинг Entity ↔ Model
Session Entity → Model
public ChatSession ToModel()
{
var session = new ChatSession
{
SessionId = this.SessionId,
ChatId = this.ChatId,
ChatType = this.ChatType,
ChatTitle = this.ChatTitle ?? string.Empty,
Model = this.Model,
CreatedAt = this.CreatedAt,
LastUpdatedAt = this.LastUpdatedAt
};
// Восстановить сообщения
foreach (var msg in Messages.OrderBy(m => m.MessageOrder))
{
session.AddMessage(new ChatMessage
{
Role = ParseRole(msg.Role),
Content = msg.Content
});
}
return session;
}
Session Model → Entity
public ChatSessionEntity ToEntity()
{
return new ChatSessionEntity
{
SessionId = this.SessionId,
ChatId = this.ChatId,
ChatType = this.ChatType,
ChatTitle = this.ChatTitle,
Model = this.Model,
CreatedAt = this.CreatedAt,
LastUpdatedAt = this.LastUpdatedAt,
Messages = this.GetAllMessages()
.Select((msg, index) => new ChatMessageEntity
{
Content = msg.Content,
Role = msg.Role.ToString(),
MessageOrder = index,
CreatedAt = DateTime.UtcNow
})
.ToList()
};
}
📐 Database Schema
-- Таблица сессий
CREATE TABLE chat_sessions (
id SERIAL PRIMARY KEY,
session_id VARCHAR(50) UNIQUE NOT NULL,
chat_id BIGINT NOT NULL,
chat_type VARCHAR(20) NOT NULL,
chat_title VARCHAR(200),
model VARCHAR(100),
created_at TIMESTAMP NOT NULL,
last_updated_at TIMESTAMP NOT NULL
);
CREATE INDEX idx_chat_sessions_session_id ON chat_sessions(session_id);
CREATE INDEX idx_chat_sessions_chat_id ON chat_sessions(chat_id);
-- Таблица сообщений
CREATE TABLE chat_messages (
id SERIAL PRIMARY KEY,
session_id INTEGER NOT NULL REFERENCES chat_sessions(id) ON DELETE CASCADE,
content VARCHAR(10000) NOT NULL,
role VARCHAR(20) NOT NULL,
message_order INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL
);
CREATE INDEX idx_chat_messages_session_id ON chat_messages(session_id);
CREATE INDEX idx_chat_messages_created_at ON chat_messages(created_at);
CREATE INDEX idx_chat_messages_session_order ON chat_messages(session_id, message_order);
🎯 Жизненный цикл Session
1. Создание (GetOrCreate)
↓
2. Добавление сообщений (AddMessage)
↓
3. Проверка длины истории
↓
4. Компрессия (если нужно)
↓
5. Сохранение в БД (SaveSessionAsync)
↓
6. Обновление LastUpdatedAt