0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【OpenAI API × TypeScript】インタラクティブなチャットボットの開発

Last updated at Posted at 2025-01-31

OpenAI API × TypeScriptでインタラクティブなチャットボットを開発

はじめに

OpenAI APIを活用したインタラクティブなチャットボットアプリケーションを開発したので、ここに記録として残します。

TypeScriptとReactを使用して構築され、マークダウン形式での応答をサポートしています。

デモ画面

チャットインターフェース

チャットボットのメイン画面

シンプルで使いやすいインターフェースを心がけました。マークダウン形式での表示やコードブロックにも対応し、プログラミング関連の会話も快適に行えます。

モデル選択機能

モデル選択画面

用途や予算に応じて最適なモデルを選択できます。
GPT-4やGPT-3.5-turboなど、複数のモデルに対応しています。
また、マウスホバーでモデルの詳細や料金も表示されます。

主な機能

  • OpenAI APIを活用したインテリジェントな応答
  • 複数のGPTモデル対応(gpt-4o, gpt-4o-mini, gpt-3.5-turbo)
  • マークダウン形式でのリッチテキスト表示
  • レスポンシブデザイン(ウィンドウサイズ切り替え対応)
  • リアルタイムのローディング表示
  • 自動スクロールによる快適な会話体験

技術スタック

  • TypeScript
  • React
  • Webpack
  • CSS Modules
  • Axios
  • Marked(マークダウンパーサー)

実装の工夫点

1. 型安全なメッセージ管理

interface Message {
  role: 'user' | 'assistant' | 'system';
  content: string;
  timestamp?: number;
}

interface ChatState {
  messages: Message[];
  isLoading: boolean;
  error: string | null;
}

TypeScriptの型システムを活用して、メッセージの構造を明確に定義しています。
これにより実行時エラーを防ぎ、開発時の補完機能も活用できます。

2. カスタムフックによる状態管理

const useChatState = () => {
  const [state, setState] = useState<ChatState>({
    messages: [],
    isLoading: false,
    error: null
  });

  const addMessage = useCallback((message: Message) => {
    setState(prev => ({
      ...prev,
      messages: [...prev.messages, { ...message, timestamp: Date.now() }]
    }));
  }, []);

  return { state, addMessage };
};

カスタムフックを使用することで、チャットの状態管理ロジックを再利用可能な形で分離しています。

3. エラーハンドリングの実装

const handleSendMessage = async (content: string) => {
  try {
    setIsLoading(true);
    const response = await sendMessage(content);
    addMessage({
      role: 'assistant',
      content: response.choices[0].message.content
    });
  } catch (error) {
    setError(error instanceof Error ? error.message : '不明なエラーが発生しました');
  } finally {
    setIsLoading(false);
  }
};

try-catch-finallyパターンを使用して、API通信の例外処理を適切に行い、ユーザーにフィードバックを提供しています。

4. マークダウンレンダリングの最適化

const MessageContent: React.FC<{ content: string }> = memo(({ content }) => {
  const html = useMemo(() => {
    return marked(content, {
      gfm: true,
      breaks: true,
      sanitize: true
    });
  }, [content]);

  return <div className={styles.message} dangerouslySetInnerHTML={{ __html: html }} />;
});
  • useMemoを使用してマークダウンのパース処理を最適化
  • memoでコンポーネントの不要な再レンダリングを防止
  • XSS対策としてsanitizeオプションを有効化

5. レスポンシブ対応のスタイリング

.chatContainer {
  display: flex;
  flex-direction: column;
  height: 100vh;
  max-width: 800px;
  margin: 0 auto;
  padding: 1rem;
}

@media (max-width: 768px) {
  .chatContainer {
    padding: 0.5rem;
    height: calc(100vh - 60px); /* モバイルブラウザのUIを考慮 */
  }
}

CSSメディアクエリを使用して、デバイスサイズに応じた最適なレイアウトを提供しています。

6. パフォーマンス最適化

const ChatHistory: React.FC<{ messages: Message[] }> = memo(({ messages }) => {
  const bottomRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  return (
    <div className={styles.history}>
      {messages.map((msg, idx) => (
        <MessageBubble key={msg.timestamp ?? idx} message={msg} />
      ))}
      <div ref={bottomRef} />
    </div>
  );
});
  • 仮想スクロールの実装検討(メッセージ数が多い場合)
  • useRefを使用した効率的なDOM操作
  • メッセージの一意性を保証するためのタイムスタンプ活用

7. セキュリティ対策

const API_KEY = process.env.REACT_APP_OPENAI_API_KEY;
if (!API_KEY) {
  throw new Error('OpenAI API key is not configured');
}

const headers = {
  'Content-Type': 'application/json',
  'Authorization': `Bearer ${API_KEY}`,
  'X-Request-ID': crypto.randomUUID()
};
  • 環境変数による機密情報の管理
  • リクエストヘッダーでのセキュリティ強化
  • ユニークなリクエストIDによるトレーサビリティの確保

開発時の課題と解決策

  1. APIレートリミット対策

    • デバウンス処理の実装
    • エラー時の再試行ロジック
    • ユーザーへの適切なフィードバック
  2. レスポンス時間の最適化

    • ストリーミングレスポンスの実装
    • プログレッシブローディングの導入
    • キャッシュ戦略の検討
  3. UX改善

    • タイピングインジケーターの実装
    • エラー状態の視覚的フィードバック
    • ショートカットキーのサポート

開発プロセスでの工夫

開発効率の向上

開発プロセスでは、以下のようなツールや手法を活用して効率化を図りました:

  1. コード品質の維持

    • ESLintとPrettierによる一貫したコードスタイルの維持
    • GitHub Actionsによる自動テストとビルド
    • AIアシスタントを活用したコードレビューと改善提案
  2. ドキュメント管理

    • TypeDocによるAPI文書の自動生成
    • AIツールを活用した文書校正と翻訳支援
    • マークダウンベースの技術文書管理
  3. イテレーティブな開発

    • 小規模な機能から段階的に実装
    • フィードバックループの短縮化
    • AIによるコード提案を参考にした実装の最適化

これらのツールや手法を組み合わせることで、開発効率を向上させながら、コードの品質維持を実現しています。

プロジェクト構造

/
├── dist/ # ビルド出力ディレクトリ
├── docs/ # ドキュメント関連ファイル
│ └── images/ # スクリーンショットなどの画像
├── src/ # ソースコードディレクトリ
│ ├── index.tsx # Reactアプリケーションのエントリーポイント
│ ├── components/ # Reactコンポーネント
│ │ └── Chatbot.tsx # チャットボットメインコンポーネント
│ ├── config/ # 設定ファイル
│ │ └── models.ts # モデル設定
│ └── styles/ # コンポーネント固有のスタイル
│ └── Chatbot.css # チャットボットのスタイル
├── .env.example # 環境変数テンプレート
├── .env # 環境変数(非公開)
├── .gitignore # Git除外設定
├── package.json # プロジェクト設定・依存関係
├── package-lock.json # 依存関係のロックファイル
├── README.md # プロジェクト説明
├── requirements.md # 要件定義
├── tsconfig.json # TypeScript設定
└── webpack.config.js # Webpack設定

セットアップガイド

インストールと起動方法

  1. リポジトリをクローン

    git clone https://github.com/sorein-mio/chatbot.git
    cd chatbot
    
  2. 依存関係のインストール

    npm install
    
  3. 環境変数の設定

    • .env.exampleをコピーして.envを作成
    • OpenAI APIキーを設定
  4. 開発サーバーの起動

    npm start
    

アプリケーションは http://localhost:8080 で起動します。

セキュリティ注意事項

APIキーは.envファイルで管理し、GitHubにはコミットしないでください。本番環境では適切な環境変数管理を行ってください。

今後の展望

  • チャット履歴の永続化
  • プロンプトテンプレート機能
  • ファイル添付機能
  • 最新モデルの対応
  • モデルの単価などの自動更新機能

ライセンスと貢献

このプロジェクトはISCライセンスで公開しています。貢献を歓迎しますので、プルリクエストをお待ちしています。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?