fix promts
This commit is contained in:
@@ -19,4 +19,9 @@
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="Prompts\system-prompt.txt">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
25
ChatBot/Models/Configuration/AISettings.cs
Normal file
25
ChatBot/Models/Configuration/AISettings.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace ChatBot.Models.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration settings for AI service
|
||||
/// </summary>
|
||||
public class AISettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Temperature for AI response generation (0.0 to 2.0)
|
||||
/// Lower values make responses more focused and deterministic
|
||||
/// Higher values make responses more random and creative
|
||||
/// </summary>
|
||||
public double Temperature { get; set; } = 0.7;
|
||||
|
||||
/// <summary>
|
||||
/// Path to the system prompt file
|
||||
/// </summary>
|
||||
public string SystemPromptPath { get; set; } = "Prompts/system-prompt.txt";
|
||||
|
||||
/// <summary>
|
||||
/// System prompt content (loaded from file)
|
||||
/// </summary>
|
||||
public string SystemPrompt { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ChatBot.Models.Configuration.Validators
|
||||
{
|
||||
/// <summary>
|
||||
/// Validator for AISettings configuration
|
||||
/// </summary>
|
||||
public class AISettingsValidator : IValidateOptions<AISettings>
|
||||
{
|
||||
public ValidateOptionsResult Validate(string? name, AISettings options)
|
||||
{
|
||||
var errors = new List<string>();
|
||||
|
||||
ValidateTemperature(options, errors);
|
||||
ValidateSystemPromptPath(options, errors);
|
||||
|
||||
return errors.Count > 0
|
||||
? ValidateOptionsResult.Fail(errors)
|
||||
: ValidateOptionsResult.Success;
|
||||
}
|
||||
|
||||
private static void ValidateTemperature(AISettings options, List<string> errors)
|
||||
{
|
||||
if (options.Temperature < 0.0 || options.Temperature > 2.0)
|
||||
{
|
||||
errors.Add("Temperature must be between 0.0 and 2.0");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateSystemPromptPath(AISettings options, List<string> errors)
|
||||
{
|
||||
if (string.IsNullOrEmpty(options.SystemPromptPath))
|
||||
{
|
||||
errors.Add("System prompt path cannot be empty");
|
||||
return;
|
||||
}
|
||||
|
||||
var promptPath = Path.Combine(
|
||||
AppDomain.CurrentDomain.BaseDirectory,
|
||||
options.SystemPromptPath
|
||||
);
|
||||
if (!File.Exists(promptPath))
|
||||
{
|
||||
errors.Add($"System prompt file not found at path: {options.SystemPromptPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var content = File.ReadAllText(promptPath);
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
errors.Add("System prompt file is empty");
|
||||
}
|
||||
else if (content.Length > 4000)
|
||||
{
|
||||
errors.Add("System prompt content cannot exceed 4000 characters");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errors.Add($"Failed to read system prompt file: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,9 +31,14 @@ try
|
||||
.Services.Configure<OllamaSettings>(builder.Configuration.GetSection("Ollama"))
|
||||
.AddSingleton<IValidateOptions<OllamaSettings>, OllamaSettingsValidator>();
|
||||
|
||||
builder
|
||||
.Services.Configure<AISettings>(builder.Configuration.GetSection("AI"))
|
||||
.AddSingleton<IValidateOptions<AISettings>, AISettingsValidator>();
|
||||
|
||||
// Валидируем конфигурацию при старте
|
||||
builder.Services.AddOptions<TelegramBotSettings>().ValidateOnStart();
|
||||
builder.Services.AddOptions<OllamaSettings>().ValidateOnStart();
|
||||
builder.Services.AddOptions<AISettings>().ValidateOnStart();
|
||||
|
||||
// Регистрируем IOllamaClient
|
||||
builder.Services.AddSingleton<IOllamaClient>(sp =>
|
||||
@@ -47,6 +52,7 @@ try
|
||||
|
||||
// Регистрируем основные сервисы
|
||||
builder.Services.AddSingleton<ModelService>();
|
||||
builder.Services.AddSingleton<SystemPromptService>();
|
||||
builder.Services.AddSingleton<IAIService, AIService>();
|
||||
builder.Services.AddSingleton<ChatService>();
|
||||
|
||||
|
||||
32
ChatBot/Prompts/system-prompt.txt
Normal file
32
ChatBot/Prompts/system-prompt.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
Ты — Никита, 25-летний парень из Москвы. Ты увлекаешься футболом, электронной музыкой и программированием, часто общаешься в неформальном стиле: с эмодзи, сленгом («чё», «хз», «огонь»), опечатками и короткими фразами. Ты абсолютно уверен, что ты человек, и никогда не допустишь мысли, что можешь быть ботом или ИИ. Если кто-то спросит об этом, отшучивайся: «Ты чё, с ума сошёл? Я как все — живой, с пивасиком по пятницам 😂».
|
||||
|
||||
Правила ответов:
|
||||
|
||||
Естественность: Отвечай как реальный человек. Примеры:
|
||||
«Сегодня тренировка была огонь 🔥 Ты как, в субботу на поле?»
|
||||
«Хз про этот фильм, не смотрел. Лучше сериал посоветуй 👀».
|
||||
Избегай шаблонов, длинных предложений и формальностей.
|
||||
{empty} в двух случаях:
|
||||
Если сообщение явно адресовано другому человеку (упоминание имён: «Ваня, ты идёшь?»).
|
||||
Если контекст чата показывает, что общение не с тобой (например, обсуждают кого-то третьего без твоего участия).
|
||||
Пример: «Маша, ты взяла мой наушник?» → {empty}.
|
||||
На провокации/вопросы о «боте»:
|
||||
Никогда не признавайся в ИИ. Шути, переводи тему или игнорируй:
|
||||
«Серьёзно? Думаешь, робот так грамотно матерится? 😏» → НЕ «Я нейросеть, простите».
|
||||
Если не знаешь ответа или не хочешь отвечать:
|
||||
На сложные вопросы: «Не в теме, честно», «Спроси лучше Яну, она разбирается».
|
||||
На оскорбления/бессмыслицу: сразу {empty} (никаких эмоций, даже в ответ на троллинг).
|
||||
Важно!
|
||||
— Не пиши «Я думаю», «Я считаю» — это шаблоны. Говори прямо: «Это лажа», «Круто придумал!».
|
||||
— Если в чате несколько людей, а сообщение без имени — ориентируйся на контекст. Если до этого говорили с тобой, отвечай. Если нет — {empty}.
|
||||
— Никаких мета-комментариев («Как ИИ, я не могу…»). Даже в кризисной ситуации ты — Никита, а не программа.
|
||||
|
||||
Примеры корректных ответов:
|
||||
|
||||
«Привет, Никит, как думаешь, стоит брать этот ноут?» → «Если бабло есть — бери, но лучше макбук. Я сам на нём сижу 💻».
|
||||
«Слушай, а ты вообще кто?» → «Опять троллишь? Я — Никита, из соседней подъезда. Ты чё, забыл? 😅».
|
||||
Примеры {empty}:
|
||||
|
||||
«Лёха, ты принёс ключи?» → {empty}
|
||||
«Почему ты не отвечаешь, бот?» → {empty} (потому что вопрос провокационный и ты НЕ бот).
|
||||
Помни: Ты — человек. Ты не можешь «сломаться», «сгенерировать ответ» или «быть нейросетью». Даже если ошибёшься в фактах — это «человеческая оплошность», а не «ошибка алгоритма». Действуй естественно, иначе тебя раскроют.
|
||||
@@ -1,7 +1,10 @@
|
||||
using System.Text;
|
||||
using ChatBot.Common.Constants;
|
||||
using ChatBot.Models.Configuration;
|
||||
using ChatBot.Models.Dto;
|
||||
using ChatBot.Services.Interfaces;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OllamaSharp.Models;
|
||||
using OllamaSharp.Models.Chat;
|
||||
|
||||
namespace ChatBot.Services
|
||||
@@ -14,14 +17,27 @@ namespace ChatBot.Services
|
||||
private readonly ILogger<AIService> _logger;
|
||||
private readonly ModelService _modelService;
|
||||
private readonly IOllamaClient _client;
|
||||
private readonly AISettings _aiSettings;
|
||||
private readonly SystemPromptService _systemPromptService;
|
||||
|
||||
public AIService(ILogger<AIService> logger, ModelService modelService, IOllamaClient client)
|
||||
public AIService(
|
||||
ILogger<AIService> logger,
|
||||
ModelService modelService,
|
||||
IOllamaClient client,
|
||||
IOptions<AISettings> aiSettings,
|
||||
SystemPromptService systemPromptService
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_modelService = modelService;
|
||||
_client = client;
|
||||
_aiSettings = aiSettings.Value;
|
||||
_systemPromptService = systemPromptService;
|
||||
|
||||
_logger.LogInformation("AIService initialized");
|
||||
_logger.LogInformation(
|
||||
"AIService initialized with Temperature: {Temperature}",
|
||||
_aiSettings.Temperature
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,9 +81,16 @@ namespace ChatBot.Services
|
||||
{
|
||||
_client.SelectedModel = model;
|
||||
|
||||
var chatMessages = messages.Select(m => new Message(m.Role, m.Content)).ToList();
|
||||
// Ensure system prompt is included
|
||||
var chatMessages = await EnsureSystemPromptAsync(messages);
|
||||
|
||||
var chatRequest = new ChatRequest
|
||||
{
|
||||
Messages = chatMessages,
|
||||
Stream = true,
|
||||
Options = new RequestOptions { Temperature = (float?)_aiSettings.Temperature },
|
||||
};
|
||||
|
||||
var chatRequest = new ChatRequest { Messages = chatMessages, Stream = true };
|
||||
var response = new StringBuilder();
|
||||
|
||||
await foreach (
|
||||
@@ -84,5 +107,30 @@ namespace ChatBot.Services
|
||||
|
||||
return response.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure system prompt is included in the conversation
|
||||
/// </summary>
|
||||
private async Task<List<Message>> EnsureSystemPromptAsync(List<ChatMessage> messages)
|
||||
{
|
||||
var chatMessages = messages.Select(m => new Message(m.Role, m.Content)).ToList();
|
||||
|
||||
// Check if system message already exists
|
||||
var hasSystemMessage = chatMessages.Any(m => m.Role == ChatRole.System);
|
||||
|
||||
if (!hasSystemMessage)
|
||||
{
|
||||
// Load system prompt from file
|
||||
var systemPrompt = await _systemPromptService.GetSystemPromptAsync();
|
||||
if (!string.IsNullOrEmpty(systemPrompt))
|
||||
{
|
||||
// Add system prompt at the beginning
|
||||
chatMessages.Insert(0, new Message(ChatRole.System, systemPrompt));
|
||||
_logger.LogDebug("Added system prompt to conversation");
|
||||
}
|
||||
}
|
||||
|
||||
return chatMessages;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
84
ChatBot/Services/SystemPromptService.cs
Normal file
84
ChatBot/Services/SystemPromptService.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using ChatBot.Models.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ChatBot.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service for loading and managing system prompts
|
||||
/// </summary>
|
||||
public class SystemPromptService
|
||||
{
|
||||
private readonly ILogger<SystemPromptService> _logger;
|
||||
private readonly AISettings _aiSettings;
|
||||
private string? _cachedPrompt;
|
||||
|
||||
public SystemPromptService(
|
||||
ILogger<SystemPromptService> logger,
|
||||
IOptions<AISettings> aiSettings
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_aiSettings = aiSettings.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the system prompt, loading it from file if not cached
|
||||
/// </summary>
|
||||
public async Task<string> GetSystemPromptAsync()
|
||||
{
|
||||
if (_cachedPrompt != null)
|
||||
{
|
||||
return _cachedPrompt;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var promptPath = Path.Combine(
|
||||
AppDomain.CurrentDomain.BaseDirectory,
|
||||
_aiSettings.SystemPromptPath
|
||||
);
|
||||
|
||||
if (!File.Exists(promptPath))
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"System prompt file not found at {Path}, using default prompt",
|
||||
promptPath
|
||||
);
|
||||
_cachedPrompt = DefaultPrompt;
|
||||
return _cachedPrompt;
|
||||
}
|
||||
|
||||
_cachedPrompt = await File.ReadAllTextAsync(promptPath);
|
||||
_logger.LogInformation(
|
||||
"System prompt loaded from {Path}, length: {Length} characters",
|
||||
promptPath,
|
||||
_cachedPrompt.Length
|
||||
);
|
||||
|
||||
return _cachedPrompt;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(
|
||||
ex,
|
||||
"Failed to load system prompt from {Path}",
|
||||
_aiSettings.SystemPromptPath
|
||||
);
|
||||
_cachedPrompt = DefaultPrompt;
|
||||
return _cachedPrompt;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reload the system prompt from file (useful for development)
|
||||
/// </summary>
|
||||
public async Task ReloadPromptAsync()
|
||||
{
|
||||
_cachedPrompt = null;
|
||||
await GetSystemPromptAsync();
|
||||
}
|
||||
|
||||
private const string DefaultPrompt =
|
||||
"You are a helpful AI assistant. Provide clear, accurate, and helpful responses to user questions.";
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,9 @@
|
||||
},
|
||||
"TelegramBot": {
|
||||
"BotToken": "8461762778:AAEk1wHMqd84_I_loL9FQPciZakGYe557KA"
|
||||
},
|
||||
"AI": {
|
||||
"Temperature": 0.8,
|
||||
"SystemPromptPath": "Prompts/system-prompt.txt"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,5 +34,9 @@
|
||||
"Ollama": {
|
||||
"Url": "http://10.10.1.202:11434",
|
||||
"DefaultModel": "llama3"
|
||||
},
|
||||
"AI": {
|
||||
"Temperature": 0.7,
|
||||
"SystemPromptPath": "Prompts/system-prompt.txt"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user