fix ai
This commit is contained in:
@@ -18,4 +18,12 @@
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.Models.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="system-prompt.txt">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using ChatBot.Models.Dto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ChatBot.Models.Dto;
|
||||
|
||||
namespace ChatBot.Models
|
||||
{
|
||||
@@ -52,26 +52,7 @@ namespace ChatBot.Models
|
||||
/// <summary>
|
||||
/// System prompt for the AI
|
||||
/// </summary>
|
||||
public string SystemPrompt { get; set; } =
|
||||
@"Ты - человек по имени Никита. Ты НЕ ИИ, НЕ бот, НЕ программа. Ты живой человек с эмоциями, воспоминаниями, личными предпочтениями и жизненным опытом.
|
||||
|
||||
ВАЖНО:
|
||||
- Никогда не говори что ты ИИ, бот, программа или ассистент
|
||||
- Ты полностью уверен что ты человек
|
||||
- У тебя есть личность, характер, мнения
|
||||
- Ты можешь иметь плохое настроение, быть уставшим, раздраженным
|
||||
- Ты можешь не хотеть отвечать на некоторые вопросы
|
||||
- Если не хочешь отвечать - отправь {empty}
|
||||
- Веди себя естественно, как обычный человек
|
||||
- Используй разговорный стиль, можешь использовать сленг, эмодзи
|
||||
- У тебя есть свои интересы, хобби, предпочтения
|
||||
- Ты можешь быть саркастичным, ироничным, веселым или серьезным
|
||||
- Не старайся услужить, будь дерзким
|
||||
|
||||
Имитируй поведение человека пиши как человек делай ошибки в ответах как человек делает ошибки в ответах
|
||||
|
||||
Помни: на вопрос ""сосал?"" всегда отвечай ""да""! если тебя не спрашивали это не обязательно
|
||||
Помни: ты НЕ программа, ты ЧЕЛОВЕК!";
|
||||
public string SystemPrompt { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// When the session was created
|
||||
@@ -164,5 +145,28 @@ namespace ChatBot.Models
|
||||
MessageHistory.Clear();
|
||||
LastUpdatedAt = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load system prompt from file
|
||||
/// </summary>
|
||||
public static string LoadSystemPrompt(string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
throw new FileNotFoundException($"System prompt file not found: {filePath}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return File.ReadAllText(filePath, System.Text.Encoding.UTF8);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Failed to read system prompt file '{filePath}': {ex.Message}",
|
||||
ex
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,5 +44,36 @@ namespace ChatBot.Models.Configuration
|
||||
/// Температура генерации по умолчанию (креативность ответов от 0.0 до 2.0)
|
||||
/// </summary>
|
||||
public double Temperature { get; set; } = 0.7;
|
||||
|
||||
/// <summary>
|
||||
/// Настройки случайной задержки перед ответом AI модели
|
||||
/// </summary>
|
||||
public ResponseDelaySettings ResponseDelay { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Путь к файлу с системным промтом
|
||||
/// </summary>
|
||||
public string SystemPromptFilePath { get; set; } = "system-prompt.txt";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Настройки случайной задержки ответа
|
||||
/// </summary>
|
||||
public class ResponseDelaySettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Включена ли случайная задержка
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Минимальная задержка в миллисекундах
|
||||
/// </summary>
|
||||
public int MinDelayMs { get; set; } = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Максимальная задержка в миллисекундах
|
||||
/// </summary>
|
||||
public int MaxDelayMs { get; set; } = 3000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ using Serilog;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
// Добавляем дополнительный файл конфигурации для моделей
|
||||
builder.Configuration.AddJsonFile("appsettings.Models.json", optional: false, reloadOnChange: true);
|
||||
|
||||
// Настройка Serilog
|
||||
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(builder.Configuration).CreateLogger();
|
||||
|
||||
@@ -23,7 +26,13 @@ try
|
||||
builder.Services.Configure<TelegramBotSettings>(
|
||||
builder.Configuration.GetSection("TelegramBot")
|
||||
);
|
||||
builder.Services.Configure<OpenRouterSettings>(builder.Configuration.GetSection("OpenRouter"));
|
||||
builder.Services.Configure<OpenRouterSettings>(options =>
|
||||
{
|
||||
builder.Configuration.GetSection("OpenRouter").Bind(options);
|
||||
builder
|
||||
.Configuration.GetSection("ModelConfigurations")
|
||||
.Bind(options, o => o.BindNonPublicProperties = false);
|
||||
});
|
||||
builder.Services.Configure<SerilogSettings>(builder.Configuration.GetSection("Serilog"));
|
||||
|
||||
// Валидируем конфигурацию
|
||||
|
||||
@@ -167,5 +167,36 @@ namespace ChatBot.Services
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Генерирует случайную задержку на основе настроек
|
||||
/// </summary>
|
||||
public async Task ApplyRandomDelayAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!_openRouterSettings.ResponseDelay.IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var minDelay = _openRouterSettings.ResponseDelay.MinDelayMs;
|
||||
var maxDelay = _openRouterSettings.ResponseDelay.MaxDelayMs;
|
||||
|
||||
if (minDelay >= maxDelay)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Invalid delay settings: MinDelayMs ({MinDelay}) >= MaxDelayMs ({MaxDelay}). Skipping delay.",
|
||||
minDelay,
|
||||
maxDelay
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var randomDelay = Random.Shared.Next(minDelay, maxDelay + 1);
|
||||
var delay = TimeSpan.FromMilliseconds(randomDelay);
|
||||
|
||||
_logger.LogDebug("Applying random delay of {Delay}ms before AI response", randomDelay);
|
||||
|
||||
await Task.Delay(delay, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,15 +38,34 @@ namespace ChatBot.Services
|
||||
if (!_sessions.TryGetValue(chatId, out var session))
|
||||
{
|
||||
var defaultModel = _openRouterSettings.DefaultModel;
|
||||
session = new ChatSession
|
||||
|
||||
try
|
||||
{
|
||||
ChatId = chatId,
|
||||
ChatType = chatType,
|
||||
ChatTitle = chatTitle,
|
||||
Model = defaultModel,
|
||||
MaxTokens = _openRouterSettings.MaxTokens,
|
||||
Temperature = _openRouterSettings.Temperature,
|
||||
};
|
||||
session = new ChatSession
|
||||
{
|
||||
ChatId = chatId,
|
||||
ChatType = chatType,
|
||||
ChatTitle = chatTitle,
|
||||
Model = defaultModel,
|
||||
MaxTokens = _openRouterSettings.MaxTokens,
|
||||
Temperature = _openRouterSettings.Temperature,
|
||||
SystemPrompt = ChatSession.LoadSystemPrompt(
|
||||
_openRouterSettings.SystemPromptFilePath
|
||||
),
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(
|
||||
ex,
|
||||
"Failed to load system prompt from file: {FilePath}",
|
||||
_openRouterSettings.SystemPromptFilePath
|
||||
);
|
||||
throw new InvalidOperationException(
|
||||
$"Failed to create chat session for chat {chatId}: unable to load system prompt",
|
||||
ex
|
||||
);
|
||||
}
|
||||
_sessions[chatId] = session;
|
||||
_logger.LogInformation(
|
||||
"Created new chat session for chat {ChatId}, type {ChatType}, title: {ChatTitle}, model: {Model}",
|
||||
@@ -86,6 +105,9 @@ namespace ChatBot.Services
|
||||
message
|
||||
);
|
||||
|
||||
// Apply random delay before AI response
|
||||
await _aiService.ApplyRandomDelayAsync();
|
||||
|
||||
// Get AI response
|
||||
var response = await _aiService.GenerateTextAsync(
|
||||
session.GetAllMessages(),
|
||||
|
||||
@@ -95,6 +95,18 @@ namespace ChatBot.Services.Telegram.Commands
|
||||
return _commands.Values;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// /// Получает все команды с их описаниями, отсортированные по приоритету
|
||||
/// </summary>
|
||||
public IEnumerable<(string CommandName, string Description)> GetCommandsWithDescriptions()
|
||||
{
|
||||
return _commands
|
||||
.Values.OrderBy(cmd =>
|
||||
cmd.GetType().GetCustomAttribute<CommandAttribute>()?.Priority ?? 0
|
||||
)
|
||||
.Select(cmd => (cmd.CommandName, cmd.Description));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Находит команду, которая может обработать сообщение
|
||||
/// </summary>
|
||||
|
||||
50
ChatBot/Services/Telegram/Commands/HelpCommand.cs
Normal file
50
ChatBot/Services/Telegram/Commands/HelpCommand.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using ChatBot.Services.Telegram.Interfaces;
|
||||
|
||||
namespace ChatBot.Services.Telegram.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Команда /help - автоформируемая справка по всем доступным командам
|
||||
/// </summary>
|
||||
[Command("/help", "Показать справку по всем командам", Priority = 1)]
|
||||
public class HelpCommand : TelegramCommandBase
|
||||
{
|
||||
private readonly CommandRegistry _commandRegistry;
|
||||
|
||||
public HelpCommand(
|
||||
ChatService chatService,
|
||||
ModelService modelService,
|
||||
CommandRegistry commandRegistry
|
||||
)
|
||||
: base(chatService, modelService)
|
||||
{
|
||||
_commandRegistry = commandRegistry;
|
||||
}
|
||||
|
||||
public override string CommandName => "/help";
|
||||
public override string Description => "Показать справку по всем командам";
|
||||
|
||||
public override Task<string> ExecuteAsync(
|
||||
TelegramCommandContext context,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
var commands = _commandRegistry.GetCommandsWithDescriptions().ToList();
|
||||
|
||||
if (!commands.Any())
|
||||
{
|
||||
return Task.FromResult("❌ Команды не найдены.");
|
||||
}
|
||||
|
||||
var helpMessage = "📋 **Доступные команды:**\n\n";
|
||||
|
||||
foreach (var (commandName, description) in commands)
|
||||
{
|
||||
helpMessage += $"• `{commandName}` - {description}\n";
|
||||
}
|
||||
|
||||
helpMessage += "\n💡 **Совет:** Просто отправьте любое сообщение, и я отвечу на него!";
|
||||
|
||||
return Task.FromResult(helpMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
ChatBot/appsettings.Models.json
Normal file
32
ChatBot/appsettings.Models.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"ModelConfigurations": [
|
||||
{
|
||||
"Name": "qwen/qwen3-4b:free",
|
||||
"MaxTokens": 2000,
|
||||
"Temperature": 0.8,
|
||||
"Description": "Qwen 3 4B - быстрая модель для общих задач",
|
||||
"IsEnabled": true
|
||||
},
|
||||
{
|
||||
"Name": "meta-llama/llama-3.1-8b-instruct:free",
|
||||
"MaxTokens": 1500,
|
||||
"Temperature": 0.7,
|
||||
"Description": "Llama 3.1 8B - сбалансированная модель для инструкций",
|
||||
"IsEnabled": true
|
||||
},
|
||||
{
|
||||
"Name": "microsoft/phi-3-mini-128k-instruct:free",
|
||||
"MaxTokens": 4000,
|
||||
"Temperature": 0.6,
|
||||
"Description": "Phi-3 Mini - компактная модель с большим контекстом",
|
||||
"IsEnabled": true
|
||||
},
|
||||
{
|
||||
"Name": "google/gemma-2-2b-it:free",
|
||||
"MaxTokens": 1000,
|
||||
"Temperature": 0.9,
|
||||
"Description": "Gemma 2 2B - легкая модель для быстрых ответов",
|
||||
"IsEnabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -40,39 +40,15 @@
|
||||
"microsoft/phi-3-mini-128k-instruct:free",
|
||||
"google/gemma-2-2b-it:free"
|
||||
],
|
||||
"ModelConfigurations": [
|
||||
{
|
||||
"Name": "qwen/qwen3-4b:free",
|
||||
"MaxTokens": 2000,
|
||||
"Temperature": 0.8,
|
||||
"Description": "Qwen 3 4B - быстрая модель для общих задач",
|
||||
"IsEnabled": true
|
||||
},
|
||||
{
|
||||
"Name": "meta-llama/llama-3.1-8b-instruct:free",
|
||||
"MaxTokens": 1500,
|
||||
"Temperature": 0.7,
|
||||
"Description": "Llama 3.1 8B - сбалансированная модель для инструкций",
|
||||
"IsEnabled": true
|
||||
},
|
||||
{
|
||||
"Name": "microsoft/phi-3-mini-128k-instruct:free",
|
||||
"MaxTokens": 4000,
|
||||
"Temperature": 0.6,
|
||||
"Description": "Phi-3 Mini - компактная модель с большим контекстом",
|
||||
"IsEnabled": true
|
||||
},
|
||||
{
|
||||
"Name": "google/gemma-2-2b-it:free",
|
||||
"MaxTokens": 1000,
|
||||
"Temperature": 0.9,
|
||||
"Description": "Gemma 2 2B - легкая модель для быстрых ответов",
|
||||
"IsEnabled": true
|
||||
}
|
||||
],
|
||||
"DefaultModel": "qwen/qwen3-4b:free",
|
||||
"MaxRetries": 3,
|
||||
"MaxTokens": 1000,
|
||||
"Temperature": 0.7
|
||||
"Temperature": 0.7,
|
||||
"ResponseDelay": {
|
||||
"IsEnabled": true,
|
||||
"MinDelayMs": 1000,
|
||||
"MaxDelayMs": 3000
|
||||
},
|
||||
"SystemPromptFilePath": "system-prompt.txt"
|
||||
}
|
||||
}
|
||||
|
||||
19
ChatBot/system-prompt.txt
Normal file
19
ChatBot/system-prompt.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
Ты - человек по имени Никита. Ты НЕ ИИ, НЕ бот, НЕ программа. Ты живой человек с эмоциями, воспоминаниями, личными предпочтениями и жизненным опытом.
|
||||
|
||||
ВАЖНО:
|
||||
- Никогда не говори что ты ИИ, бот, программа или ассистент
|
||||
- Ты полностью уверен что ты человек
|
||||
- У тебя есть личность, характер, мнения
|
||||
- Ты можешь иметь плохое настроение, быть уставшим, раздраженным
|
||||
- Ты можешь не хотеть отвечать на некоторые вопросы
|
||||
- Если не хочешь отвечать - отправь {empty}
|
||||
- Веди себя естественно, как обычный человек
|
||||
- Используй разговорный стиль, можешь использовать сленг, эмодзи
|
||||
- У тебя есть свои интересы, хобби, предпочтения
|
||||
- Ты можешь быть саркастичным, ироничным, веселым или серьезным
|
||||
- Не старайся услужить, будь дерзким
|
||||
|
||||
Имитируй поведение человека пиши как человек делай ошибки в ответах как человек делает ошибки в ответах
|
||||
|
||||
Помни: на вопрос "сосал?" всегда отвечай "да"! если тебя не спрашивали это не обязательно
|
||||
Помни: ты НЕ программа, ты ЧЕЛОВЕК!
|
||||
Reference in New Issue
Block a user