C# WinForm - ChatGPT API 다루기, 프로그램 내에서 ChatGPT 사용하기 (Betalgo.OpenAI)

 

Overview

ChatGPT API를 통해 질문과 답변을 하는 기능을 구현해보자.

우선 결론적으로 말하자면 OpenAI의 ChatGPT는 공식적으로 C# 혹은 .NET(닷넷, DotNet) 라이브러리는 없다.

그러기 때문에 사용하기 편한 패키지를 선택해서 사용하면 된다.

이 포스팅에서는 Betalgo.OpenAI 를 통해 ChatGPT와의 API 통신을 한다.

아래는 지속적으로 대화가 가능하도록 애플리케이션의 UI를 구성하여 만든 WinForm 프로그램이다.

좌: ChatGPT / 우 : 사용자


Dotnet용 ChatGPT API 패키지 설치하기

  • (Visual Studio에서) 도구 - NuGet 패키지 관리자 - 솔루션용 NuGet 패키지 관리

 

  • 'openai' 검색 후 'Betalgo.OpenAI' 설치


API 사용을 위한 API 키 설정

// API 설정
OpenAIService openAiService = new OpenAIService(new OpenAiOptions()
{
    ApiKey = // API 키 입력,
    Organization = // Organization Id 입력, 옵션이므로 필수로 넣지 않아도 됨
});

ChatGPT 샘플 구문

아래 구문은 Betalgo.OpenAI 문서에서 제공된 샘플 구문이다.

2023-09-11 기준으로 모델 호출 부분이 변경되었다.

  • 기존 : Models.ChatGpt3_5Turbo
  • 변경 : Models.Gpt_3_5_Turbo
var completionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
    Messages = new List<ChatMessage>
    {
        ChatMessage.FromSystem("You are a helpful assistant."),
        ChatMessage.FromUser("Who won the world series in 2020?"),
        ChatMessage.FromAssistant("The Los Angeles Dodgers won the World Series in 2020."),
        ChatMessage.FromUser("Where was it played?")
    },
    Model = Models.Gpt_3_5_Turbo
    MaxTokens = 50//optional
});
if (completionResult.Successful)
{
   Console.WriteLine(completionResult.Choices.First().Message.Content);
}

구현

샘플코드 구현

직접 구현해보자.

간단한 문제를 ChatGPT에게 내보고 질문을 받아보자.

ChatCompletionCreateResponse completionResult = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
{
    Messages = new List<ChatMessage>
    {
    ChatMessage.FromUser("물음표 안에 알맞은 수를 써넣으세요.\\n\\frac{?}{9}=1\\n\\frac{?}{7}=2\\n\\frac{8}{2}=?"),
    },
    Model = Models.Gpt_3_5_Turbo
    MaxTokens = 100//optional
});
if (completionResult.Successful)
{
    string test = completionResult.Choices.First().Message.Content;
    MessageBox.Show(test);
}


대화 유지하기 기능 구현

위의 샘플 코드는 일회성 대화만 가능하도록 되어 있다.

때문에 이어서 대화를 하면 ChatGPT가 알아듣지를 못한다.

아래는 대화형으로 애플리케이션의 UI를 디자인한 상태로 진행하였다.

  • 기존 샘플 코드의 문제점 : 일회성 대화만 가능하다.

좌: ChatGPT / 우 : 사용자

 

  • 아래와 같이 대화가 유지되게 하려면?

좌: ChatGPT / 우 : 사용자

가이드 문서에는 대화 유지에 대한 언급이 없다.

아니 있는데 내가 못찾은 것일지도 모르겠다.

초보인 나에게는 대화 유지 기능을 구현하는 데에 꽤나 삽질하는 시간이 많았다.

분명 다른 사람들도 나와 같은 문제로 삽질하는 시간이 발생할 것이라고 생각이 들었고,

그런 무의미한 시간이 줄어들길 바래서 이 포스팅을 작성하게 되었다. 

 

방법은 생각외로 너무나도 간단하다.

일회성 대화는 API 통신 시, 매번 새로운 인스턴스를 생성하기 때문에 대화가 유지되지 않는 것이다.

API 호출 시마다 인스턴스를 생성하지 않게 하면 된다.

 

아래 소스 코드를 예로 들자면,

미리 인스턴스를 생성하여 'AskQuestion'이라는 함수에서 메시지를 추가하여 대화를 유지하도록 구현하였다.

가장 중요한 부분은 ChatCompletionCreateRequest 변수를 미리 선언해서 질문 시에 해당 변수를 가져다가 쓰는 것이고

메시지 부분을 가져다 쓴 변수에 메시지를 추가하는 것이다.

// ChatGPT 설정 변수
ChatCompletionCreateRequest chatRequest;

// ChatGPT 초기 설정
chatRequest = new ChatCompletionCreateRequest
{
    Model = Models.Gpt_3_5_Turbo,
    Temperature = 0.4,
    Messages = new List<ChatMessage> { }
};

// 질문하기
public async Task<string> AskQuestion(string prompt)
{
    // 요청 리퀘스트에 질문 메시지 추가
    ChatMessage chatUserMessage = new ChatMessage("user", prompt);
    chatRequest.Messages.Add(chatUserMessage);

    // 봇 답변 받기
    ChatCompletionCreateResponse chatResult = await openAiService.ChatCompletion.CreateCompletion(chatRequest);

    // 봇 응답이 성공적이면
    if (chatResult.Successful)
    {
        // 봇 답변 내용 저장
        string response = chatResult.Choices.First().Message.Content;

        // 요청 리퀘스트에 답변 메시지 추가, 대화 유지를 위함
        ChatMessage chatBotMessage = new ChatMessage("assistant", response);
        chatRequest.Messages.Add(chatBotMessage);
        return response;
    }
    // 봇 응답이 실패하면
    else
    {
        if (chatResult.Error == null)
        {
            throw new Exception("Unknown Error");
        }
        return $"Error : {chatResult.Error.Code}: {chatResult.Error.Message}";
    }
}

전체 소스 코드

나는 클래스로 정의해서 가져다 쓰고 있다.

클래스 사용 및 메소드 호출 방법은 이 포스팅에서 다루지 않는다.

이해가 어렵다면 아래의 코드를 참고하길 바란다.

using OpenAI;
using OpenAI.Managers;
using OpenAI.ObjectModels;
using OpenAI.ObjectModels.RequestModels;
using OpenAI.ObjectModels.ResponseModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace -
{
    internal class ChatGptApi
    {
        // API 설정
        OpenAIService openAiService = new OpenAIService(new OpenAiOptions()
        {
            ApiKey = Properties.Resources.OpenAiApiKey,
            Organization = Properties.Resources.OrganizationID
        });

        // ChatGPT 설정 변수
        ChatCompletionCreateRequest chatRequest;

        // Temperature 설정
        private static double AiTemperatureValue;

        // 정적 생성자 Temperature 설정 초기화
        static ChatGptApi()
        {
            AiTemperatureValue = 0.4;
        }

        // ChatGPT 대화의 다양성 설정
        public void SetTemperature(double temperature)
        {
            AiTemperatureValue = temperature;
            ChatGptSetting();
        }

        // ChatGPT Temperature 설정값 넘겨주기
        public double GetTemperature()
        {
            return AiTemperatureValue;
        }

        // 새 대화 생성
        public void ChatGptSetting()
        {
            // ChatGPT 초기 설정
            chatRequest = new ChatCompletionCreateRequest
            {
                Model = Models.Gpt_3_5_Turbo,
                Temperature = (float?)AiTemperatureValue,
                Messages = new List<ChatMessage> { }
            };
        }

        // 질문하기
        public async Task<string> AskQuestion(string prompt)
        {
            // 요청 리퀘스트에 질문 메시지 추가
            ChatMessage chatUserMessage = new ChatMessage("user", prompt);
            chatRequest.Messages.Add(chatUserMessage);

            // 봇 답변 받기
            ChatCompletionCreateResponse chatResult = await openAiService.ChatCompletion.CreateCompletion(chatRequest);

            // 봇 응답이 성공적이면
            if (chatResult.Successful)
            {
                // 봇 답변 내용 저장
                string response = chatResult.Choices.First().Message.Content;

                // 요청 리퀘스트에 답변 메시지 추가, 대화 유지를 위함
                ChatMessage chatBotMessage = new ChatMessage("assistant", response);
                chatRequest.Messages.Add(chatBotMessage);
                return response;
            }
            // 봇 응답이 실패하면
            else
            {
                if (chatResult.Error == null)
                {
                    throw new Exception("Unknown Error");
                }
                return $"Error : {chatResult.Error.Code}: {chatResult.Error.Message}";
            }
        }
    }
}

참고