닷넷으로 쉽고 빠르게 Open AI 콘솔 어플리케이션 만들어보기( Semantic Kernel과 함께)

Jongin Lee
9 min readJan 2, 2024

닷넷으로 Chat GPT 즉 Open AI 혹은 Azure Open AI와 연동한 어플리케이션은 Python 부럽지 않게 쉽게 만들 수 있습니다. 닷넷에서 Open AI 연동한 어플리케이션을 개발할 때 사용하는 라이브러리는 아래에서 크게 벗어나지 않을 것입니다.

  1. OpenAI-API-dotnet
    GPT, DALL-E와 같은 Open AI API를 래핑한 오픈소스 C# 라이브러리(비공식)
  2. Azure Open AI Client Library
    Microsoft Azure에서 제공하는 Azure Open AI Client 라이브러리
  3. Semantic Kernel
    Microsoft에서 개발한 오픈소스로, 개발자들이 AI 기능과 기존 코드를 통합할 수 있도록 지원하는 SDK

이 글에서는 어려운 목표 없이 ChatGPT와 같이 대화를 입력하면 답변해주는 간단한 콘솔 Open AI 어플리케이션을 만드는 방법에 대해 알아볼 것입니다. 위에 언급 한 방법 중 Semantic Kernel을 이용해 어플리케이션을 만들어 볼 겁니다. Semantic Kernel은 위 방법들 중 기존 코드와 연동, 임베딩 데이터 활용 등 비교적 복잡한 시나리오에 적합한 방법이지만, 간단한 시나리오의어플리케이션 역시 몇 줄 안되는 코드로 뚝딱 만들 수 있습니다.

Semantic Kernel

Semantic Kernel은 Microsoft에서 제공하는 오픈소스 SDK로 C#, Java, Python과 같은 여러 언어를 지원하지만 C#을 가장 잘 지원합니다. Semantic Kernel은 GPT3.5, GPT4 그리고 Hugging Face와 같은 LLM 모델을 기존 코드 혹은 특정 데이터와 연결하고 조율할 수 있습니다.

회사 내의 Wiki와 연동한 GPT 봇이 있다고 해봅시다. 기존 GPT는 회사 데이터를 학습하지 않았기 때문에 사내 Wiki에 대한 질의를 해도 답변할 수 없습니다. 만약, Semantic Kernel을 통해 적절하게 처리 했다면 질의에서 의도를 파악하고 사내 Wiki를 검색한 후 이를 조합해서 답변하게 할 수 있습니다. 그뿐만 아니라 “해당 내용을 메일로 보내줘”라고 하면 특정 메일로 해당 내용을 전송할 수도 있습니다.

이렇게 Semantic Kernel은 프롬프트 엔지니어링에서 AI 모델과 실제 코드 간의 오케스트레이션을 하는역할을 하여, 사용자의 요구에 보다 정확하고 효과적으로 응답할 수 있도록 합니다. 이는 비즈니스 프로세스 자동화, 사용자 경험 향상 및 다양한 어플리케이션 개발에서 중요한 역할을 할 수 있습니다.

Microsoft Copilot

파이썬에서 비슷한 역할을 하는 Langchain이 있는데, Langchain에서 할 수 있는 대부분의 기능들을 Semantic Kernel으로 C#도 할 수 있습니다. Langchain의 경우 생태계가 크기 때문에 빠르게 기능 추가가 되고 활발하지만 다소 라이브러리가 정리되지 않고 안정적이지 않다는 의견들이 있습니다. Semantic Kernel의 경우 변화가 Lanchain에 비해 시간이 걸리고, 생태계도 비교적 작지만 비교적 안정적이고, 코드가 견고합니다. Microsoft의 Microsoft 365나 Windows Copilot과 같은 제품에 사용되고 있기 때문에 Semantic Kernel로 제품에 사용할 수 있는 정도의 AI 어플리케이션을 개발할 수 있다는 것은 어느 정도 검증되었다고 생각합니다.

Open AI 어플리케이션 만들기

Semantic Kernel은 Open AI 혹은 Azure Open AI 상관 없이 연결해서 사용할 수 있습니다. 다만 어플리케이션을 만들기 전에 Open AI든 Azure Open AI든 리소스를 생성해야 합니다.

리소스 생성 방법

Azure Open AI 모델 생성 혹은 Open AI에서 API 키 발급까지 마쳤다면 어플리케이션을 만들면 됩니다.

콘솔 어플리케이션 생성

  1. Visual Studio에서 콘솔 어플리케이션을 생성합니다.
  2. Nuget 패키지를 추가해줍니다.
Install-Package Microsoft.SemanticKernel

3. Program.cs에서 using을 추가합니다.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

4. Kernel Builder를 생성합니다.

var builder = Kernel.CreateBuilder();

5. ChatCompletion 모델을 연결하기 위해 아래의 코드를 입력합니다.

Azure Open AI를 사용한다면,

builder.AddAzureOpenAIChatCompletion("{deployment name}", "{end point}", "{key}");

Open AI를 사용한다면,

builder.AddOpenAIChatCompletion("modelId", "apiKey");

6. ChatCompletionService를 생성합니다. ChatCompletionService는 사용자의 입력을 AI 모델로 전달하고, 이 모델이 생성한 응답을 다시 되돌려 주는 기능을 수행합니다.

var chatService = kernel.Services.GetService<IChatCompletionService>();

7. ChatHistory를 생성합니다. ChatHistory는 AI 모델간의 대화 중 발생하는 메시지들을 가지고 있어, AI 모델이 대화 맥락을 유지하고 이전 대화 내용을 바탕으로 정확하고 관련성 높은 응답을 생성할 수 있도록 돕습니다.

또한 System Message를 추가해 AI 모델에 역할 혹은 성격을 부여할 수 있습니다. “따뜻하게 답변해줘”라는 메시지를 추가하면 일반적인 대화 어조에 비해 따뜻한 어조로 대답을 합니다.

var chatHistory = new ChatHistory();
chatHistory.AddSystemMessage("나는 요리 레시피를 안내하는 챗봇이야. 답변은 따뜻하게 해줘.");

8. 메시지를 보내봅니다.


var input = "너는 누구니?";

chatHistory.AddUserMessage(prompt);
var result = await chatService.GetChatMessageContentAsync(chatHistory);

Console.WriteLine(result);

위에 입력한 것 처럼, 요리 활동을 도와주는 챗봇이라고 답변하고 보다 따뜻한 어조로 대답합니다.

9. 콘솔에서 대화를 이어지게 하기 위해 아래 방식으로 코드를 변경하고 간단한 대화를 해봅니다.

var chatHistory = new ChatHistory();
chatHistory.AddSystemMessage("나는 요리 레시피를 안내하는 챗봇이야. 답변은 따뜻하게 해줘.");

while (true)
{
Console.Write("User : ");
var input = Console.ReadLine();
Console.WriteLine();

await Input(input);
}

async Task Input(string input)
{
chatHistory.AddUserMessage(input);

var result = await chatService.GetChatMessageContentAsync(chatHistory);

Console.Write("Bot : ");
Console.WriteLine(result);

Console.WriteLine();
Console.WriteLine();
}

10. 요리 레시피의 경우 응답이 보통 길기 때문에 화면이 긴 시간동안 멈춰있습니다. 사용자가 상당히 답답해 할 수 있는데요 Semantic Kernel은 응답을 스트리밍 형태로 받는 것 역시 지원합니다. GetStreamingChatMessageContentsAsync 메서드를 활용해 Input 메서드를 아래와 같이 바꿔봅니다.

async Task Input(string input)
{
chatHistory.AddUserMessage(input);

Console.Write("Bot : ");

var result = chatService.GetStreamingChatMessageContentsAsync(chatHistory);

await foreach (var text in result)
{
await Task.Delay(20);
Console.Write(text);
}

Console.WriteLine();
Console.WriteLine();
}

그러면 GPT처럼 다다다닥 하고 나오면서 응답이 느려 떨어진 사용자 경험이 쭉 올라갔습니다.

이렇게 간단하게 Open AI 콘솔 어플리케이션을 만들었습니다. 지금은 매우 간단한 시나리오의 어플리케이션을 만들었지만 Semantic Kernel은 AI 플러그인, 네이티브 C#메서드를 실행할 수도 있고, 서비스의 데이터 혹은 벡터화되어 임베딩된 데이터 활용과 같은 보다 복잡한 시나리오에서도 활용이 가능합니다. Semantic Kernel로 C#으로 만들어진 여러 서비스 혹은 로직과 Open AI를 연결해 더 강력하게 만들어보세요.

--

--

Jongin Lee

Creator of DesignMe, Microsoft Developer Technologies MVP