1

In the following code, it always works fine the first time. As you can see I'm trying to keep the list of previous questions and answers to keep context with the _items List.

So the second time it fails with error 400 bad request, but to test I tried adding the two commented lines to begin my first question with an input of "How old is he?" so it has context and it also fails with error 400 so it cannot be any of the rest of the code! I cannot figure out why it won't let me add more context when all of the examples I've seen online say you can add multiple messages so as to keep context.

private List<RequestMessage> _items = new();

// Method to send a message to the ChatGPT API and return the response
async public Task<string> SendMessage(string message)
{
    Request request = new Request();

    List<RequestMessage> requestMessages = new();

    requestMessages.Add(
        new RequestMessage()
        {
            Role = "system",
            Content = $"You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.\nKnowledge cutoff: 2021-09-01\nCurrent date: {DateTime.Now.ToString("yyyy-MM-dd")}",
        });
    requestMessages.Add(
        new RequestMessage()
        {
            Role = "user",
            Content = "How are you?",
        });
    requestMessages.Add(
        new RequestMessage()
        {
            Role = "assistant",
            Content = "I am doing well",
        });
    /*
    requestMessages.Add(
        new RequestMessage()
        {
            Role = "user",
            Content = "Who is Brendan Fraser?",
        });
    requestMessages.Add(
        new RequestMessage()
        {
            Role = "assistant",
            Content = "Brendan Fraser is a Canadian American actor",
        });
    */
    
    requestMessages.AddRange(_items);

    requestMessages.Add(
        new RequestMessage()
        {
            Role = "user",
            Content = message,
        });

    request.Messages = requestMessages.ToArray();

    string requestData = JsonSerializer.Serialize(request);
    StringContent content = new StringContent(requestData, Encoding.UTF8, "application/json");

    using (HttpClient httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _apiKey);
        httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
        HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(_apiUrl, content);

        if (httpResponseMessage.IsSuccessStatusCode)
        {
            string responseString = await httpResponseMessage.Content.ReadAsStringAsync();
            Response response = JsonSerializer.Deserialize<Response>(responseString);
            string responseText = response.Choices[0].Message.Content;

            _items.Add(new RequestMessage() { Role = "user", Content = message });
            _items.Add(new RequestMessage() { Role = "assistant", Content = responseText });

            return responseText;
        }
        else
        {
            return $"Error: {httpResponseMessage.StatusCode} - {httpResponseMessage.ReasonPhrase}";
        }
    }

}
Helen
  • 87,344
  • 17
  • 243
  • 314
Jay Croghan
  • 445
  • 3
  • 16
  • The first request is a login where you get a token (cookie) in the response. Afterwards you have to send the cookie with each request. – jdweng Aug 21 '23 at 13:06
  • I said in my question that if I uncomment the two RequestMessages to give context it also fails the first time! – Jay Croghan Aug 21 '23 at 13:27
  • What status codes are you getting? You may be getting exceptions. Try stepping through the code. – jdweng Aug 21 '23 at 13:35
  • I have stepped through it, and you're not listening, it works fine the first time, it gives me 400 the second time OR if I uncomment the second initial question to set up context. StatusCode: 400, ReasonPhrase: 'Bad Request' - it's literally in the title. – Jay Croghan Aug 21 '23 at 13:47

1 Answers1

1

The problem was with all of the fancy Json Objects I was using. I did not bother debugging it properly to see why it was going wrong but I changed from this:

public class Request
{
    [JsonPropertyName("model")]
    public string Model { get; set; } = "gpt-3.5-turbo";
    [JsonPropertyName("max_tokens")]
    public int MaxTokens { get; set; } = 4000;
    [JsonPropertyName("messages")]
    public RequestMessage[] Messages { get; set; }
}

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

public class Response
{
    [JsonPropertyName("id")]
    public string Id { get; set; }
    [JsonPropertyName("created")]
    public int Created { get; set; }
    [JsonPropertyName("model")]
    public string Model { get; set; }
    [JsonPropertyName("usage")]
    public ResponseUsage Usage { get; set; }
    [JsonPropertyName("choices")]
    public ResponseChoice[] Choices { get; set; }
}

public class ResponseUsage
{
    [JsonPropertyName("prompt_tokens")]
    public int PromptTokens { get; set; }
    [JsonPropertyName("completion_tokens")]
    public int CompletionTokens { get; set; }
    [JsonPropertyName("total_tokens")]
    public int TotalTokens { get; set; }
}

public class ResponseChoice
{
    [JsonPropertyName("message")]
    public ResponseMessage Message { get; set; }
    [JsonPropertyName("finish_reason")]
    public string FinishReason { get; set; }
    [JsonPropertyName("index")]
    public int Index { get; set; }
}

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

To using direct json

private List<dynamic> messages = new List<dynamic>
{
    new {role = "system",
        content = "You are ChatGPT, a large language " +
                                    "model trained by OpenAI. " +
                                    "Answer as concisely as possible.  " +
                                    "Make a joke every few lines just to spice things up."},
    new {role = "assistant",
        content = "How can I help you?"}
};
messages.Add(new { role = "user", content = message });
var request = new
{
    messages,
    model = "gpt-3.5-turbo",
    max_tokens = 300,
};

And then a much simpler responseObject

var responseObject = JsonConvert.DeserializeAnonymousType(responseString, new
{
    choices = new[] { new { message = new { role = string.Empty, content = string.Empty } } },
    error = new { message = string.Empty }
});

var messageObject = responseObject?.choices[0].message;
messages.Add(messageObject);
Jay Croghan
  • 445
  • 3
  • 16