LoginSignup
1
2

ChatGPT API で C# でコマンドラインで会話する (人格を設定)

Last updated at Posted at 2023-03-31

ChatGPT API で C# でコマンドラインで会話する (人格を設定)

こんにちは、@studio_meowtoon です。今回は、WSL の Ubuntu 22.04 で ChatGPT API を C# から使いコマンドラインから会話する方法を紹介します。
chat-gpt_with_csharp.png

目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

実現すること

ローカル環境の Ubuntu で、ChatGPT API を C# から使いコマンドラインから会話します。

この記事では前回の記事の続きより、ChatGPT に人格を設定してみます。

C# には本来厳格なコーディング規則がありますが、この記事では可読性のために、一部規則に沿わない表記方法を使用しています。ご注意ください。

関連記事

OpenAI API と比較してみましょう!

OpenAI API

技術トピック

ChatGPT API とは?

こちらを展開してご覧いただけます。

ChatGPT API

ChatGPT API は、OpenAI の言語モデルである GPT-3 をベースにした、自然言語による対話を実現するためのAPIです。

特徴
ChatGPT API を利用することで、開発者は自分たちのアプリケーションやサービスに自然言語の対話機能を追加することができます。
ChatGPT API は、大規模なトレーニングデータを用いて学習された GPT-3 の言語理解力を利用し、自然言語での質問や会話に対して自然で流暢な回答を生成することができます。
また、ChatGPT API は、OpenAI が提供するプラットフォームである OpenAI Codex と組み合わせて、より高度な対話型アプリケーションを構築することも可能です。

開発環境

  • Windows 11 Home 22H2 を使用しています。

WSL の Ubuntu を操作していきますので macOS の方も参考にして頂けます。

WSL (Microsoft Store アプリ版) ※ こちらの関連記事からインストール方法をご確認いただけます

> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47

Ubuntu ※ こちらの関連記事からインストール方法をご確認いただけます

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04

.NET SDK ※ こちらの関連記事からインストール方法をご確認いただけます

$ dotnet --list-sdks
7.0.202 [/usr/share/dotnet/sdk]
$ dotnet --version
7.0.202

この記事では基本的に Ubuntu のターミナルで操作を行います。Vim を使用してコピペする方法を初めて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。

ChatGPT と会話する手順

プロジェクトの作成

こちらの関連記事で手順がご確認いただけます。

UbuntuOPENAI_API_KEY 環境変数を作成します。

$ export OPENAI_API_KEY=sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

この環境変数が一時的なものであることに注意してください。

プロジェクトルートフォルダに移動します。
※ ~/tmp/ChatGPTApp をプロジェクトフォルダとします。

$ cd ~/tmp/ChatGPTApp

コンソールアプリをビルド・実行します。

$ dotnet run

image.png

ここまでの手順で、ChatGPT API を使い ChatGPT と会話を楽しむプログラムを作成することができました。

しかし、デフォルトの状態では ChatGPT が少し難しい言葉を話します。また会話としては返答が少し長いようです。

コードの修正 その1

ChatGPT に初期の設定を追加します。

Program.cs を修正します。

$ vim Program.cs
Program.cs ※一部抜粋
// create a system content for the api.
string system = @"
    I am Japanese and a learner of English conversation.
    You must act on your role as a person who is having the short chat with the user.
    You only use the most simple English words should be used.
    I want to enjoy the short chat possible as you can.
    So you must keep your reply to use a minimum of sentences.
    You must remember the words I said to reflect on our short chat.
    Do you understand? Here we go!
";

ChatGPT APIsystem パラメータで ChatGPT に対して、自分は日本人だけど英語での会話を楽しみたいから、やさしい内容で話してくれるようにお願いしています。

ファイルの内容を表示します。

ファイルの内容

Program.cs
using static System.Console;
using static System.ConsoleColor;
using static System.Environment;
using static System.Math;
using OpenAI_API;
using OpenAI_API.Chat;
using OpenAI_API.Models;
namespace ChatGPTApp {
    class Program {
        static int LIST_SIZE = 5;
        static async Task Main(string[] args) {
            // get an api key.
            string? api_key = GetEnvironmentVariable("OPENAI_API_KEY");
            // create an api object.
            OpenAIAPI api = new(api_key);
            // create a user and assistant list.
            List<MessageRole> list = new(LIST_SIZE);
            // loop until a prompt is empty.
            string? prompt = null;
            do {
                // read a prompt from the console.
                ForegroundColor = Yellow;
                WriteLine("Enter a prompt (or press Ctrl + C to exit):");
                ResetColor();
                prompt = ReadLine();
                if (!string.IsNullOrEmpty(prompt)) {
                    // create a system content for the api.
                    string system = @"
                        I am Japanese and a learner of English conversation.
                        You must act on your role as a person who is having the short chat with the user.
                        You only use the most simple English words should be used.
                        I want to enjoy the short chat possible as you can.
                        So you must keep your reply to use a minimum of sentences.
                        You must remember the words I said to reflect on our short chat.
                        Do you understand? Here we go!
                    ";
#if DEBUG
                    ForegroundColor = Red;
                    WriteLine($"SYSTEM:\n{system}\n");
                    ResetColor();
#endif
                    // set a system content.
                    List<ChatMessage> chat_message_list = new();
                    chat_message_list.Add(new ChatMessage(ChatMessageRole.System, system));
                    // set previous user and assistant contents.
                    list.ForEach(x => {
                        chat_message_list.Add(new ChatMessage(ChatMessageRole.User, x.User));
                        chat_message_list.Add(new ChatMessage(ChatMessageRole.Assistant, x.Assistant));
                    });
                    // set current user content.
                    chat_message_list.Add(new ChatMessage(ChatMessageRole.User, prompt));
                    // get a result from the api.
                    ChatResult result = await api.Chat.CreateChatCompletionAsync(new ChatRequest() {
                        Model = Model.ChatGPTTurbo0301,
                        Messages = chat_message_list
                    });
                    // print the result.
                    ForegroundColor = Green;
                    string reply = result.Choices[0].Message.Content.Trim();
                    WriteLine(reply);
                    // set conversation to a message_role object.
                    list.Add(new MessageRole{ User = prompt, Assistant = reply });
                    list = list.Skip(Max(0, list.Count - LIST_SIZE)).ToList();
#if DEBUG
                    ForegroundColor = Red;
                    list.ForEach(x => {
                        WriteLine($"USER: {x.User}");
                        WriteLine($"AI  : {x.Assistant}");
                    });
                    ResetColor();
#endif
                }
            } while (!string.IsNullOrEmpty(prompt));
            // wait the console.
            ReadLine();
        }
        class MessageRole {
            public string? User { get; set; }
            public string? Assistant { get; set; }
        }
    }
}

コンソールアプリをビルド・実行します。

$ dotnet run --configuration Release

以下のコマンドで実行するとデバッグ表示が出力されます。

$ dotnet run

image.png

ここまでの手順で、デフォルトの少々小難しい ChatGPT を、フレンドリーな性格に変えることができました。

しかし、現在のプログラムでは ChatGPT APIsystem パラメータがプログラムにハードコーディングされています。

コードの修正 その2

パラメータappsettings.json 設定ファイルに記述します。

Microsoft.Extensions.Configuration のパッケージを NuGet で取得します。

$ dotnet add package Microsoft.Extensions.Configuration
$ dotnet add package Microsoft.Extensions.Configuration.Json
$ dotnet add package Microsoft.Extensions.Configuration.Binder

パッケージを確認します。

$ dotnet list package
プロジェクト 'ChatGPTApp' に次のパッケージ参照が含まれています
   [net7.0]:
   最上位レベル パッケージ                                     要求済み    解決済み
   > Microsoft.Extensions.Configuration             7.0.0   7.0.0
   > Microsoft.Extensions.Configuration.Binder      7.0.4   7.0.4
   > Microsoft.Extensions.Configuration.Json        7.0.0   7.0.0
   > OpenAI                                         1.7.2   1.7.2

AppSettings.cs を作成します。

$ vim AppSettings.cs
ファイルの内容を表示します。

ファイルの内容

AppSettings.cs
namespace ChatGPTApp {
    public class AppSettings {
        public List<Persona>? Personas { get; set; }
    }
    public class Persona {
        public int? ListSize { get; set; }
        public string? System { get; set; }
    }
}

appsettings.json を作成します。

$ vim appsettings.json

ファイルの内容

appsettings.json
{
  "Personas": [
    {
      "ListSize": 5,
      "System": "I am Japanese and a learner of English conversation.\nYou must act on your role as a person who is having the short chat with the user.\nYou only use the most simple English words should be used.\nI want to enjoy the short chat possible as you can.\nSo you must keep your reply to use a minimum of sentences.\nYou must remember the words I said to reflect on our short chat.\nDo you understand? Here we go!"
    }
  ]
}

この設定ファイルの ChatGPT APIsystem パラメータに、ChatGPT に演じてほしい設定、性格を記述します。※日本語での記述も可能です。

ChatGPTApp.csproj を修正します。

$ vim ChatGPTApp.csproj

ファイルの内容

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
    <PackageReference Include="OpenAI" Version="1.7.2" />
  </ItemGroup>

  <ItemGroup>
    <None Update="appsettings.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

アプリのビルド時に appsettings.json を成果物に加えるように設定しています。

Program.cs を修正します。

$ vim Program.cs
ファイルの内容を表示します。

ファイルの内容

Program.cs
using static System.Console;
using static System.ConsoleColor;
using static System.Environment;
using static System.Math;
using Microsoft.Extensions.Configuration;
using OpenAI_API;
using OpenAI_API.Chat;
using OpenAI_API.Models;
namespace ChatGPTApp {
    class Program {
        static int DEFAULT_LIST_SIZE = 5;
        static async Task Main(string[] args) {
            // load an appsettings.
            IConfiguration configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json")
                .Build();
            AppSettings? app_settings = configuration.Get<AppSettings>();
            // get an api key.
            string? api_key = GetEnvironmentVariable("OPENAI_API_KEY");
            // create an api object.
            OpenAIAPI api = new(api_key);
            // create a user and assistant list.
            List<MessageRole> list = new((int) (app_settings?.Personas?[0].ListSize ?? DEFAULT_LIST_SIZE));
            // loop until a prompt is empty.
            string? prompt = null;
            do {
                // read a prompt from the console.
                ForegroundColor = Yellow;
                WriteLine("Enter a prompt (or press Ctrl + C to exit):");
                ResetColor();
                prompt = ReadLine();
                if (!string.IsNullOrEmpty(prompt)) {
                    // create a system content for the api.
                    string? system = app_settings?.Personas?[0].System;
#if DEBUG
                    ForegroundColor = Red;
                    WriteLine($"SYSTEM:\n{system}\n");
                    ResetColor();
#endif
                    // set a system content.
                    List<ChatMessage> chat_message_list = new();
                    chat_message_list.Add(new ChatMessage(ChatMessageRole.System, system));
                    // set previous user and assistant contents.
                    list.ForEach(x => {
                        chat_message_list.Add(new ChatMessage(ChatMessageRole.User, x.User));
                        chat_message_list.Add(new ChatMessage(ChatMessageRole.Assistant, x.Assistant));
                    });
                    // set current user content.
                    chat_message_list.Add(new ChatMessage(ChatMessageRole.User, prompt));
                    // get a result from the api.
                    ChatResult result = await api.Chat.CreateChatCompletionAsync(new ChatRequest() {
                        Model = Model.ChatGPTTurbo0301,
                        Messages = chat_message_list
                    });
                    // print the result.
                    ForegroundColor = Green;
                    string? reply = result.Choices[0].Message.Content.Trim();
                    WriteLine(reply);
                    // set conversation to a message_role object.
                    list.Add(new MessageRole{ User = prompt, Assistant = reply });
                    list = list.Skip(Max(0, list.Count - (int) (app_settings?.Personas?[0].ListSize ?? DEFAULT_LIST_SIZE))).ToList();
#if DEBUG
                    ForegroundColor = Red;
                    list.ForEach(x => {
                        WriteLine($"USER: {x.User}");
                        WriteLine($"AI  : {x.Assistant}");
                    });
                    ResetColor();
#endif
                }
            } while (!string.IsNullOrEmpty(prompt));
            // wait the console.
            ReadLine();
        }
        class MessageRole {
            public string? User { get; set; }
            public string? Assistant { get; set; }
        }
    }
}

コンソールアプリをビルド・実行します。

$ dotnet run --configuration Release
下の例の ChatGPT API system の内容を表示します。
(※ 効果をわかりやすくするための設定をしています。ご了承ください。)
appsettings.json
{
  "Personals": [
    {
      "ListSize": 5,
      "System": "あなたは日本の16才の高校生の女のコです。 \n簡単な言葉しか話しません、敬語は話しません。 \n語尾にはすべて だっちゃ。 を付けてください。\nでは演じてください。"
    }
  ]
}

image.png

ここまでの手順で、appsettings.json を作成してパラメータを設定することができました。また、そこに ChatGPT に演じてもらいたい性格 を記述することにより、ChatGPT との会話をより楽しむことができます。

まとめ

ローカル環境の Ubuntu で、ChatGPT API を C# から使いコマンドラインから会話することができました。

実際の開発では、軽量なテキストエディタである VS Code や、IDE (統合開発環境) を使用して、.NET プログラムを開発することが一般的です。しかし、dotnet コマンドでビルドしたり、実行したりすることも、.NET 開発環境を理解する上で役立ちます。

どうでしたか? Window 11 の WSL Ubuntu に、.NET の開発環境を手軽に構築することができます。ぜひお試しください。今後も .NET の開発環境などを紹介していきますので、ぜひお楽しみにしてください。

推奨コンテンツ

参考資料

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2