Files
ChatBot/docs/architecture/data-models.md
Leonid Pershin e5e69470f8
All checks were successful
SonarQube / Build and analyze (push) Successful in 3m22s
add docs
2025-10-21 05:08:40 +03:00

370 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📊 Модели данных
Полное описание всех моделей и сущностей в 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)