This commit is contained in:
369
docs/architecture/data-models.md
Normal file
369
docs/architecture/data-models.md
Normal file
@@ -0,0 +1,369 @@
|
||||
# 📊 Модели данных
|
||||
|
||||
Полное описание всех моделей и сущностей в ChatBot.
|
||||
|
||||
## 🗂️ Типы моделей
|
||||
|
||||
### 1. Domain Models (Доменные модели)
|
||||
- `ChatSession` - Основная модель сессии чата
|
||||
- `ChatMessage` - DTO для сообщений
|
||||
|
||||
### 2. Entity Models (Сущности БД)
|
||||
- `ChatSessionEntity` - Сущность сессии в БД
|
||||
- `ChatMessageEntity` - Сущность сообщения в БД
|
||||
|
||||
### 3. Configuration Models (Конфигурация)
|
||||
- `TelegramBotSettings`
|
||||
- `OllamaSettings`
|
||||
- `AISettings`
|
||||
- `DatabaseSettings`
|
||||
|
||||
## 📦 Domain Models
|
||||
|
||||
### ChatSession
|
||||
|
||||
Основная модель для работы с сессией чата.
|
||||
|
||||
```csharp
|
||||
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; } // Макс история
|
||||
}
|
||||
```
|
||||
|
||||
**Ключевые методы:**
|
||||
|
||||
#### Работа с сообщениями
|
||||
```csharp
|
||||
// Добавить сообщение (базовый)
|
||||
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()
|
||||
```
|
||||
|
||||
#### Управление компрессией
|
||||
```csharp
|
||||
void SetCompressionService(IHistoryCompressionService service)
|
||||
```
|
||||
|
||||
**Thread Safety:**
|
||||
Все операции с `_messageHistory` защищены `lock(_lock)`
|
||||
|
||||
**Управление историей:**
|
||||
- Автоматическое обрезание при превышении `MaxHistoryLength`
|
||||
- Сохранение system prompt при обрезке
|
||||
- Поддержка асинхронной компрессии
|
||||
|
||||
### ChatMessage (DTO)
|
||||
|
||||
```csharp
|
||||
public class ChatMessage
|
||||
{
|
||||
public ChatRole Role { get; set; } // user/assistant/system
|
||||
public string Content { get; set; } // Текст сообщения
|
||||
}
|
||||
```
|
||||
|
||||
**ChatRole enum:**
|
||||
```csharp
|
||||
public enum ChatRole
|
||||
{
|
||||
System, // Системный промпт
|
||||
User, // Сообщение пользователя
|
||||
Assistant // Ответ бота
|
||||
}
|
||||
```
|
||||
|
||||
## 💾 Entity Models
|
||||
|
||||
### ChatSessionEntity
|
||||
|
||||
Сущность для хранения в PostgreSQL.
|
||||
|
||||
```csharp
|
||||
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 index
|
||||
- `ChatId` - Index для быстрого поиска
|
||||
|
||||
**Constraints:**
|
||||
- `SessionId` - Required, MaxLength(50)
|
||||
- `ChatId` - Required
|
||||
- `ChatType` - Required, MaxLength(20)
|
||||
|
||||
**Relationships:**
|
||||
- One-to-Many с `ChatMessageEntity`
|
||||
- Cascade Delete - удаление сессии удаляет сообщения
|
||||
|
||||
### ChatMessageEntity
|
||||
|
||||
```csharp
|
||||
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` - Index
|
||||
- `CreatedAt` - Index для сортировки
|
||||
- `(SessionId, MessageOrder)` - Composite index
|
||||
|
||||
**Constraints:**
|
||||
- `Content` - Required, MaxLength(10000)
|
||||
- `Role` - Required, MaxLength(20)
|
||||
|
||||
## ⚙️ Configuration Models
|
||||
|
||||
### TelegramBotSettings
|
||||
|
||||
```csharp
|
||||
public class TelegramBotSettings
|
||||
{
|
||||
public string BotToken { get; set; } = string.Empty;
|
||||
}
|
||||
```
|
||||
|
||||
**Validator:**
|
||||
```csharp
|
||||
RuleFor(x => x.BotToken)
|
||||
.NotEmpty()
|
||||
.MinimumLength(10);
|
||||
```
|
||||
|
||||
### OllamaSettings
|
||||
|
||||
```csharp
|
||||
public class OllamaSettings
|
||||
{
|
||||
public string Url { get; set; } = string.Empty;
|
||||
public string DefaultModel { get; set; } = string.Empty;
|
||||
}
|
||||
```
|
||||
|
||||
**Validator:**
|
||||
```csharp
|
||||
RuleFor(x => x.Url)
|
||||
.NotEmpty()
|
||||
.Must(BeValidUrl);
|
||||
|
||||
RuleFor(x => x.DefaultModel)
|
||||
.NotEmpty();
|
||||
```
|
||||
|
||||
### AISettings
|
||||
|
||||
```csharp
|
||||
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:**
|
||||
```csharp
|
||||
RuleFor(x => x.Temperature)
|
||||
.GreaterThanOrEqualTo(0.0)
|
||||
.LessThanOrEqualTo(2.0);
|
||||
|
||||
RuleFor(x => x.MaxRetryAttempts)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
.LessThanOrEqualTo(10);
|
||||
```
|
||||
|
||||
### DatabaseSettings
|
||||
|
||||
```csharp
|
||||
public class DatabaseSettings
|
||||
{
|
||||
public string ConnectionString { get; set; } = string.Empty;
|
||||
public bool EnableSensitiveDataLogging { get; set; } = false;
|
||||
public int CommandTimeout { get; set; } = 30;
|
||||
}
|
||||
```
|
||||
|
||||
**Validator:**
|
||||
```csharp
|
||||
RuleFor(x => x.ConnectionString)
|
||||
.NotEmpty();
|
||||
|
||||
RuleFor(x => x.CommandTimeout)
|
||||
.GreaterThanOrEqualTo(5)
|
||||
.LessThanOrEqualTo(300);
|
||||
```
|
||||
|
||||
## 🔄 Маппинг Entity ↔ Model
|
||||
|
||||
### Session Entity → Model
|
||||
|
||||
```csharp
|
||||
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
|
||||
|
||||
```csharp
|
||||
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
|
||||
|
||||
```sql
|
||||
-- Таблица сессий
|
||||
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
|
||||
```
|
||||
|
||||
## 📚 См. также
|
||||
|
||||
- [Архитектура слоев](./layers.md)
|
||||
- [База данных](./database.md)
|
||||
- [Сервисы](../development/services.md)
|
||||
Reference in New Issue
Block a user