ChatGPT API Отвечает самому себе, и генерирует ответы пока не закончатся токены

Рейтинг: 0Ответов: 1Опубликовано: 27.07.2023

Пишу бота в TG на c# для небольшой компании. Главная проблема в том, что ИИ несет полную чушь из разных слов и символов. Также он не останавливается после генерации первого ответа, и генерирует ответы "Бесконечно"

Пробовал менять токен, писать вопрос на английском.

using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Args;

namespace ReengSupport_bot
{
    class Program
    {
        private static TelegramBotClient bot;
        private static string gptApiKey = ""; // В будущем желательно убрать все токены из исполняемого файла, ибо это дыра в безопасности
        private static string gptEndpoint = "https://api.openai.com/v1/engines/curie/completions"; // Адрес для отправки запросов. Так легче, чем везде его вставлять.

        static void Main(string[] args)
        {
            bot = new TelegramBotClient("");

            bot.OnMessage += Bot_OnMessage;
            bot.StartReceiving();

            Console.WriteLine("Успешный запуск бота...");
            Console.ReadKey();

            bot.StopReceiving();
        }

        private static async void Bot_OnMessage(object sender, MessageEventArgs e)
        {
            var message = e.Message;

            if (message.Type == Telegram.Bot.Types.Enums.MessageType.Text)
            {
                string response = await GenerateResponse(message.Text);

                // Проверка, что ответ не пустой и не null
                if (!string.IsNullOrEmpty(response))
                {
                    // Отправляем ответ пользователю
                    await bot.SendTextMessageAsync(message.Chat.Id, response);
                }
                else
                {
                    // Если ответ пустой или null, отправляем сообщение об ошибке
                    await bot.SendTextMessageAsync(message.Chat.Id, "Извините, не удалось получить ответ на ваш запрос :(");
                }
            }
        }

        private static async Task<string> GenerateResponse(string text)
        {
            using (HttpClient httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {gptApiKey}");  // Авторизируемся

                var request = new  // создаем запрос
                {
                    prompt = text,
                    max_tokens = 2000  // Если поставить слишком большой объем, то он не будет работать
                };

                var jsonContent = Newtonsoft.Json.JsonConvert.SerializeObject(request); 
                var httpContent = new StringContent(jsonContent, Encoding.UTF8, "application/json"); // Создание и перевод в JSON

                var response = await httpClient.PostAsync(gptEndpoint, httpContent); // Отправляем POST запрос

                if (response.IsSuccessStatusCode)
                {
                    var resultJson = await response.Content.ReadAsStringAsync(); // считываем строку
                    dynamic result = Newtonsoft.Json.JsonConvert.DeserializeObject(resultJson); // десериализации JSON-строки
                    string generatedText = result.choices[0].text; // GPT может предоставлять нам на выбор несколько ответов. При choices[0] мы выбираем самый первый варинат,
                                                                   // я не знаю как это работает, надо документацию читать очень плотно
                    return generatedText;
                }
                else
                {
                    return null;
                }
            }
        }
    }
} 

Ответы

▲ 0

OpenAI уже предлагает более упрощенный вариант отправки запросов к их API, через специальную библиотеку для .NET: https://platform.openai.com/docs/libraries/dotnet-library

Вот такой вариант отправки запроса на API Chat GPT.

Обращаю внимание что в данном случае перед использованием кода, необходимо поместить ваш API ключ в переменные окружения

public class ChatGpt
{
    private readonly static HttpClient _client = new();
    private const string ENDPOINT = "https://api.openai.com/v1/chat/completions";
    private readonly string _key;

    public ChatGpt()
    {
        _key = Environment.GetEnvironmentVariable("CHATGPT_API_KEY") ??
            throw new ArgumentNullException(nameof(_key), "Failed to get API key from environment");

        _client.DefaultRequestHeaders.Add("Authorization", $"Bearer {_key}");
    }

    public async Task<ChatResponse> GetResponse(string message)
    {
        var json = JsonSerializer.Serialize(new ChatRequest
        {
            Model = "gpt-4o-mini",
            Messages =
            [
                new() { Role = "system", Content = "You are a helpful assistant." },
                new() { Role = "user", Content = message }
            ],
            MaxTokens = 2000
        });

        var content = new StringContent(json, Encoding.UTF8, "application/json");
        var response = await _client.PostAsync(ENDPOINT, content);

        if (!response.IsSuccessStatusCode)
            throw new InvalidOperationException($"Server responses {response.StatusCode} status code");

        return JsonSerializer.Deserialize<ChatResponse>(await response.Content.ReadAsStringAsync()) ??
            throw new InvalidOperationException(
                $"Server responses success status code {response.StatusCode}, but has invalid json object");
    }
}

В ответе получаем объект который представляет из себя десереализованный JSON из ответа (Согласно документации: https://platform.openai.com/docs/api-reference/chat/create)

Которые вы уже можете разобрать по своему усмотрению


public class ChatRequest
{
    [JsonPropertyName("model")]
    public string Model { get; set; }

    [JsonPropertyName("messages")]
    public List<Message> Messages { get; set; }

    [JsonPropertyName("max_tokens")]
    public int MaxTokens { get; set; }
}

public class ChatResponse
{
    [JsonPropertyName("id")]
    public string Id { get; set; }

    [JsonPropertyName("object")]
    public string Object { get; set; }

    [JsonPropertyName("created")]
    public long Created { get; set; }

    [JsonPropertyName("model")]
    public string Model { get; set; }

    [JsonPropertyName("system_fingerprint")]
    public string SystemFingerprint { get; set; }

    [JsonPropertyName("choices")]
    public List<Choice> Choices { get; set; }

    [JsonPropertyName("usage")]
    public Usage Usage { get; set; }
}

public class Choice
{
    [JsonPropertyName("index")]
    public int Index { get; set; }

    [JsonPropertyName("message")]
    public Message Message { get; set; }

    [JsonPropertyName("logprobs")]
    public object Logprobs { get; set; }

    [JsonPropertyName("finish_reason")]
    public string FinishReason { get; set; }
}

public class Message
{
    [JsonPropertyName("role")]
    public string Role { get; set; }

    [JsonPropertyName("content")]
    public string Content { get; set; }
}

public class Usage
{
    [JsonPropertyName("prompt_tokens")]
    public int PromptTokens { get; set; }

    [JsonPropertyName("completion_tokens")]
    public int CompletionTokens { get; set; }

    [JsonPropertyName("total_tokens")]
    public int TotalTokens { get; set; }
}