Webアプリ

【C#、Blazor】Webアプリ開発入門編(Ex2)BlazorアプリへChatGPTを組み込む! ~AIチャットの作り方~【ASP.NET Core】

今回はC#BlazorアプリへChatGPTを組み込む方法を解説します。

本記事では、以下について説明します。

  • OpenAI API(Chat Completions API)をC#でどう呼びだすか?
  • Blazorアプリ上でOpenAI APIを使って簡易なAIチャットを作る方法

次のような人に役立つ内容になっています。

  • OpenAIのAPIをC#プログラムで使いたい。
  • AI機能を盛り込んだアプリ開発をしたい。

以下のようなAIチャットができるWebアプリ作成を行います。

ChatGPTはどのようなものか、プログラミングやアプリ開発自体をどのように効率化できるかは以下の記事で紹介しました。

ChatGPTの機能を自分のWebアプリへ組み込むことができれば、アイディア次第で様々なアプリ・機能を実現可能になります。

  • カスタマーサポートチャットボットの構築
  • 対話型ゲームや物語生成システム
  • データ分析や問題解決のための対話インターフェース
プロ太

今回の内容はAIを活用したアプリ作りの最初の一歩です!

演習のコード一式はGitHubにも置いてありますので、参考にしてください。

YouTubeの解説動画もあります。

演習1:コンソールアプリでAIチャットをつくる

OpenAI APIの使い方を学ぶため、最初にC#コンソールアプリでAIチャットを作ってみましょう。

OpenAI APIの呼び出しイメージは以下のようになります。

ここでは、Chat Completions APIを使っています。

Chat Completions APIは、ChatGPTのような対話型AIを自分のアプリやウェブサイトに組み込むために提供されているAPIです。

今回の演習の手順は以下になります。

  • 手順1:OpenAIのアカウントを作成してAPIキーを発行
  • 手順2:C#でChat Completions APIを呼び出してチャットを実装

手順1:OpenAIのアカウントを作成してAPIキーを発行

次のことを行います。

  • アカウントを作成とAPIキーの発行
  • (必要に応じて)クレジットをチャージ

アカウント作成とAPIキーの発行

Chat Completions APIを使うためのAPIキー発行までの手順を簡単に説明します。

まずOpenAIのアカウントを作成します。OpenAIのサイトで作成しましょう。

プロ太

アカウント作成についてはWeb上などで解説記事が多くあるかと思うので、それも参考にしてくださいね。

アカウントを作成した後にOpenAIのページでログインし、APIを選択しましょう。

APIキーを発行します。「API Keys」を選択して「Start verification」をクリックし、自分の電話番号を登録します。

OpenAIから登録した番号へ認証コードが届くのでそれを入力しましょう。

私はもともとOpenAIの別アカウントを持っており、今回記事を書くために電話番号を使いまわして新たにアカウントを作成したため、以下のメッセージがでました。

既に別アカウント持っているんだから、新しく無料APIクレジットはあげないよ」ということですね。

新しくOpenAIアカウントを作成する場合、無料クレジットをもらえる可能性があります。その場合はそのクレジットを使えます(新たにチャージは不要です)。

引き続いて新しいAPIキーを作成する画面がでてきますので、名前を入力してPermissionsはAllとしてキーを作成しましょう。

APIキー(文字列)が表示されるのでコピーして保存しましょう。この画面を一度閉じると再度APIキーをみることはできないため注意してください。

以下のようにキーが表示されています。この画面で新しくキーを追加したり削除したりもできます。

APIキーが流出すると勝手に使われてしまう恐れがあるため、厳重に管理してください。

プロ太

これでOpenAIのAPIが使えるようになりました!

クレジットをチャージ

無料クレジットがもらえない場合やAPIをたくさん使いたいという場合、チャージする必要があります。その手順も説明します。

「Setting>Billing」を選択し「Add payment details」をクリックします。

個人利用の場合はIndivisualを選びましょう。

支払いに使うクレジットカード情報を入力してContinueをクリックし、登録しましょう。

クレジットカード情報を入力すると、「Add to credit balance」という入金用のボタンが出てきますので、これをクリックします。

金額を選んで入金しましょう。最低5$となっています。

これでチャージができました。

手順2:C#でChat Completions APIを呼び出しチャットを実装

Visual Studioで次のようなChat Completions APIの動作を簡単に確認するためのC#コンソールアプリを作成します。

  • コンソールでユーザが質問を入力すると、AIの回答が返ってくる。

Visual Studioを起動して新規プロジェクト作成で「コンソール アプリ」を作成しましょう。途中のオプションはすべてデフォルトのままでよいです。

プロジェクト名は「ChatGPT_API_Console」とします。

Visual Studioのインストールや使い方については以下の記事も参考にしてください。

C#入門編(1)Visual Studioで開発 ~HTMLでHello World~ このC#入門編では、HTMLファイルの生成を題材として、C#の基本的な機能について学んでいきます。 YouTubeの動画でも解説...

JSONを扱うために、Newtonsoft.Jsonパッケージを追加します。

PowerShell等で「ChatGPT_API_Console.csproj」のあるフォルダへ移動し、以下のコマンドを入力してパッケージをインストールします。

dotnet add package Newtonsoft.Json

Program.cs」を次のように修正しましょう。

namespace ChatGPT_API_Console
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("ChatGPTに話しかけてください(eixtで終了):");
            while (true)
            {
                Console.Write("●あなたの質問:");
                string userInput = Console.ReadLine();
                if (userInput == "exit")
                {
                    break;
                }
                try
                {
                    var chatGPTService = new ChatGPTService();
                    var response = await chatGPTService.AskGPT4(userInput);
                    Console.WriteLine("■ChatGPTの回答:" + response);
                }
                catch (Exception e)
                {
                    Console.WriteLine("エラーが発生しました:" + e.Message);
                }
            }
        }
    }
}

exitが入力されるまで、人の質問&AIからの応答を繰り返し行っています。

ChatGPTServiceのクラス定義(「ChatGPTService.cs」コード)は以下になります。

using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Text;

namespace ChatGPT_API_Console
{
    public class ChatGPTService
    {
        private HttpClient _client = new HttpClient();
        //★(a)APIキーを環境変数で指定 
        static readonly string _apiKey = Environment.GetEnvironmentVariable("GPT_APIKEY");
        static readonly string _apiEndpoint = "https://api.openai.com/v1/chat/completions";

        public async Task<string> AskGPT4(string message)
        {
            //★(b)リクエストを送信
            var requestData = new GPTRequest
            {
                model = "gpt-4-turbo-preview",
                messages = [
                    new Message { role = "user", content = message }
                ]
            };
            var requestContent = JsonConvert.SerializeObject(requestData);
            var content = new StringContent(requestContent, Encoding.UTF8, "application/json");
            _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _apiKey);
            var response = await _client.PostAsync(_apiEndpoint, content);
            
            //★(c)レスポンスを受信
            response.EnsureSuccessStatusCode();
            var responseBody = await response.Content.ReadAsStringAsync();
            var responseObject = JsonConvert.DeserializeObject<GPTResponse>(responseBody);

            return responseObject.choices[0].message.content;
        }

        //★(d)リクエストのデータ定義
        record GPTRequest
        {
            public string model { get; init; }
            public Message[] messages { get; init; }
        }

        record Message
        {
            public string role { get; init; }
            public string content { get; init; }
        }

        //★(e)レスポンスのデータ定義
        record GPTResponse
        {
            public Choice[] choices { get; init; }
        }

        record Choice
        {
            public InnerMessage message { get; init; }
        }

        record InnerMessage
        {
            public string content { get; init; }
        }
    }
}

APIキーを環境変数で指定

(a)ではAPIキーを環境変数で指定しています。

環境変数はVisual Studioの「デバッグ>ChatGPT_API_Console(プロジェクト名)のデバッグプロパティ」を選択して設定しましょう。

あらかじめ作成したAPIキーをここで設定します。

誤ってAPIキーが書かれたコードや設定ファイルをGitHub等で公開してしまわないよう注意しましょう。

リクエスト送信とレスポンス受信

ChatCompletionのAPIドキュメントにおけるリクエストとレスポンスのデータ仕様(JSON形式)を参考に作っています。

リクエスト、レスポンスのデータ構造をあらかじめ定義しておきます。ここでは、record型として定義しました。(コードの(d)、(e)のGPTRequest型やGPTResponse型)

そして、HttpClientクラスを使ってOpenAI APIサーバへリクエスト送信とレスポンスの受信を行います。(コードの(b)、(c)部分)

プログラム実行

プログラムをデバッグ実行すると、ChatGPT(正確にはChatCompetionAPIを使ったチャットボットです)との会話を行えます。

プロ太

これでAIチャットができました!

プロ美

あれ、過去の会話を覚えてないようですね?

プロ太

過去の会話も考慮してほしい場合は、リクエストデータへこれまでの会話履歴を明示的に埋め込んで与える必要があります。

演習2:BlazorアプリでAIチャットをつくる

演習1で基礎はできているので、これを応用してBlazorアプリでAIチャットを作ってみましょう。

次のようなアプリを作ります。

  • Web画面でユーザが質問を入力すると、AIの回答が返ってくる。

次の手順で作成します。

  • 手順1:ひな型作成とパッケージインストール
  • 手順2:チャット機能を実装
  • 手順3:APIキーを環境変数で指定

手順1:ひな型作成とパッケージインストール

まずはプロジェクトを配置するフォルダを作成し、シェル(PowerShell等)でそのフォルダへ移動しましょう。

以下のコマンドでBlazorアプリのひな型プロジェクトを作成します。

dotnet new blazor -n ChatGPT_API_Blazor -o ChatGPT_API_Blazor -f net8.0 --interactivity Auto -au Individual --use-local-db false

次に、「ChatGPT_API_Blazor/ChatGPT_API_Blazor」フォルダ(ChatGPT_API_Blazor.csprojがあるフォルダ)へ移動し、演習1と同様にJSON用パッケージをインストールします。

dotnet add package Newtonsoft.Json

手順2:チャット機能を実装

Visual Studioで以下のように追加・修正します。

①修正:チャット画面へのリンク

NavMenu.razorで「Wether」と「Auth Requred」の間に、チャット画面へのリンク「Chat」を追加します。

         …    
         <NavLink class="nav-link" href="weather">
                 <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
             </NavLink>
         </div>
 
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="chat">
                <span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Chat
            </NavLink>
        </div>

         <div class="nav-item px-3">
             <NavLink class="nav-link" href="auth">
                 <span class="bi bi-lock-nav-menu" aria-hidden="true"></span> Auth Required
         …

②追加:チャット画面

チャット画面用のChat.razorを追加します。

@page "/chat"
@using ChatGPT_API_Blazor.Services
@rendermode InteractiveServer
@inject ChatGPTService chatGPTService;

<h3>ChatGPT Chat</h3>

<div class="chat-input">
    <input @bind="_userInput" class="input-text" placeholder="Type your message here..." />
    <button @onclick="SendQuery" class="send-button">Send</button>
</div>

<div class="chat-messages">
    @if (_messages != null)
    {
        <div>
            @foreach (var message in _messages)
            {
                <div class="message">@message</div>
                <hr>
            }
        </div>
    }
</div>

@code {
    private string _userInput;
    private List<string> _messages = new();

    private async Task SendQuery()
    {
        if (!string.IsNullOrWhiteSpace(_userInput))
        {
            _messages.Add($"You: {_userInput}");
            var response = await chatGPTService.AskGPT4(_userInput);
            _messages.Add($"ChatGPT: {response}");
            _userInput = "";
            StateHasChanged();        }
    }
}

③追加:Chat Comletions APIを使ったロジック

ChatGPTService.csを追加します。内容は演習1と同じです。

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;

namespace ChatGPT_API_Blazor.Services
{
    public class ChatGPTService
    {
       …クラス定義は演習1のChatGPTServiceクラスと同じ…
    }
}

④修正:ChatServiceをDIコンテナへ追加

builder.Build()の前に、ChatServiceをDIコンテナへ登録(AddScoped)するコードを追加します。

…
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
builder.Services.AddScoped<ChatGPTService>();
var app = builder.Build();
…

手順3:APIキーを環境変数で指定

演習1と同様、デバッグ用の環境変数を設定しておきましょう。例えば、デバッグ実行にhttpsを使うならば、httpsの欄で設定します。

プログラム実行

デバッグ実行すると、次のようにチャット画面でAIと会話できます。

プロ美

AIチャット機能を搭載したWebアプリができたよ!

まとめ

OpenAI API(Chat Completions API)をC#でどう呼びだすかについて説明しました。

そして、Blazor上で簡易なAIチャット機能を実現しました。

少しのコードを書くだけで、ChatGPTのような機能が実現できました。

今回の内容をベースとして、アイディア次第で様々なアプリ・機能を実現可能になります。

ぜひ色々試して、AIを使った面白いアプリを考えてみてください。

プロ太

引き続き、Webアプリ開発とBlazorを一緒に学んでいきましょう!

ABOUT ME
プロ太
プログラミングを勉強している人へ情報を発信していきます! ・情報工学分野で博士(工学)の学位取得 ・言語:C# 、Java、C/C++、Python、JavaScript/TypeScript等 ・仕事は主に上流工程(WF開発・Agile開発、OSS開発経験あり) ・趣味で開発:3Dゲーム、Webアプリ、言語処理系等

ご依頼・ご相談について

プログラミング学習のご相談、お仕事のご依頼については、
こちらのお問い合わせページをご確認ください。