🪅

【C#×AI】第1回 - OpenAI APIで始める対話型アプリケーション開発

2024/12/15に公開

この記事について

本記事は「C#×AI」シリーズの第1回目です。C#からOpenAI APIを利用して対話型アプリケーションを開発する方法を解説します。

想定する読者

  • C#の基本的な文法を理解している方
  • APIの基本的な概念を理解している方
  • AIを使ったアプリケーション開発に興味がある方

環境情報

  • .NET 8.0
  • Visual Studio 2022
  • OpenAI.NET SDK (NuGet)
  • OpenAI API Key

はじめに

AIの発展により、開発者がアプリケーションにAI機能を組み込むことが身近になってきました。特にOpenAI APIを使うことで、高度な自然言語処理機能を簡単に実装できます。

この記事では、C#からOpenAI APIを利用して、シンプルな対話型アプリケーションを作成する方法を説明します。

開発環境のセットアップ

1. プロジェクトの作成

まずはコンソールアプリケーションを作成します。

dotnet new console -n ChatGPTApp
cd ChatGPTApp

2. 必要なパッケージのインストール

OpenAI APIを利用するために必要なパッケージをインストールします。

dotnet add package OpenAI_API

3. APIキーの準備

OpenAIのウェブサイトから取得したAPIキーを安全に管理するために、appsettings.jsonを作成します。

{
  "OpenAI": {
    "ApiKey": "your-api-key-here"
  }
}

基本的な実装

ChatServiceの作成

まずは、OpenAI APIとの通信を担当するサービスクラスを作成します。

using OpenAI_API;
using OpenAI_API.Chat;

public class ChatService
{
    private readonly OpenAIAPI _api;
    private readonly List<ChatMessage> _messages;

    public ChatService(string apiKey)
    {
        _api = new OpenAIAPI(apiKey);
        _messages = new List<ChatMessage>();
    }

    public async Task<string> GetResponseAsync(string userInput)
    {
        try
        {
            var chat = _api.Chat.CreateConversation();
            
            // システムプロンプトの設定
            chat.AppendSystemMessage("あなたは親切なアシスタントです。簡潔に応答してください。");
            
            // これまでの会話履歴を追加
            foreach (var message in _messages)
            {
                chat.Messages.Add(message);
            }
            
            // ユーザーの入力を追加
            chat.AppendUserInput(userInput);
            
            // 応答を取得
            string response = await chat.GetResponseFromChatbotAsync();
            
            // 会話履歴を更新
            _messages.Add(new ChatMessage(ChatMessageRole.User, userInput));
            _messages.Add(new ChatMessage(ChatMessageRole.Assistant, response));
            
            return response;
        }
        catch (Exception ex)
        {
            return $"エラーが発生しました: {ex.Message}";
        }
    }
}

Program.csの実装

次に、メインのプログラムを実装します。

using Microsoft.Extensions.Configuration;

class Program
{
    static async Task Main(string[] args)
    {
        // 設定ファイルの読み込み
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();

        var apiKey = configuration["OpenAI:ApiKey"];
        var chatService = new ChatService(apiKey);

        Console.WriteLine("チャットボットを開始します(終了するには 'exit' と入力)");

        while (true)
        {
            Console.Write("\nあなた > ");
            var input = Console.ReadLine();

            if (string.IsNullOrEmpty(input) || input.ToLower() == "exit")
                break;

            Console.Write("AI > ");
            var response = await chatService.GetResponseAsync(input);
            Console.WriteLine(response);
        }
    }
}

エラーハンドリング

実際のアプリケーションでは、以下のようなエラーハンドリングが必要です。

public class OpenAIException : Exception
{
    public int? StatusCode { get; }
    
    public OpenAIException(string message, int? statusCode = null) 
        : base(message)
    {
        StatusCode = statusCode;
    }
}

// ChatServiceに追加するエラーハンドリングメソッド
private async Task<string> SafeApiCallAsync(Func<Task<string>> apiCall)
{
    try
    {
        return await apiCall();
    }
    catch (HttpRequestException ex)
    {
        throw new OpenAIException("API接続エラー", 
            ex.StatusCode?.GetHashCode());
    }
    catch (Exception ex)
    {
        throw new OpenAIException(
            "予期せぬエラーが発生しました", null);
    }
}

プロンプトエンジニアリング

より良い応答を得るためのプロンプト例

public class ChatPrompts
{
    public static string DefaultSystem => @"
あなたは以下の特徴を持つアシスタントです:
- 簡潔で分かりやすい応答を心がける
- 技術的な質問には具体例を交えて説明する
- コードを提示する場合は、必ずコメントを付ける
- 不確かな情報は提供しない
";
}

パフォーマンス最適化

トークン数を管理して、APIコストを最適化する例

public class TokenManager
{
    private const int MaxTokens = 4000;
    private int _currentTokens = 0;

    public void AddMessage(string message)
    {
        // 簡易的なトークン数の見積もり
        int estimatedTokens = message.Length / 4;
        _currentTokens += estimatedTokens;

        // トークン数が上限に近づいたら古いメッセージを削除
        if (_currentTokens > MaxTokens)
        {
            // 実装省略
        }
    }
}

まとめ

本記事では、C#からOpenAI APIを利用して対話型アプリケーションを開発する方法を解説しました。

実装のポイント:

  • APIキーの安全な管理
  • 会話の文脈管理
  • 適切なエラーハンドリング
  • プロンプトエンジニアリング
  • パフォーマンス最適化

参考リンク

Discussion