相互に接続された複数ページのStreamlitアプリを作成する方法

Streamlitアプリの複数ページ接続方法

企画から実行まで – GPT Labの構築方法

Clément Hélardot氏による写真、Unsplash

注:この記事は元々Streamlitのブログに掲載されました。VoAGIコミュニティの皆さんにも見ていただくためにこちらでも共有したいと思います。

わぁ!GPT Labの構築から学んだ教訓について最初のブログ投稿以来、すごい3ヶ月でした! 🚀

皆さんの大きなサポートのおかげで、GPT Labは9,000以上のアプリビュー、1,150以上のユニークなログインユーザー、900以上のアシスタントとのセッション、650以上のプロンプトのテスト、そして180以上のアシスタントの作成を受け取りました。このアプリは他の優れたアプリと共にStreamlit App Galleryにも掲載されています。

http://gptlab.streamlit.app/?embed=true

多くの方から「Streamlitでこんな大規模なアプリをどのように計画して構築しましたか?」と質問されました。それにお答えするために、GPT Labをオープンソース化することにしました。

この記事では、この野心的なプロジェクトの戦略と思考プロセスについて洞察を共有します。Streamlitを限界まで追い込み、野心的なアプリを実現するためのインスピレーションを得ていただけると嬉しいです。

💡 進む場所が知りたいですか?アプリとコードをチェックしてください。

大規模なStreamlitアプリの計画

GPT Labのような大規模なStreamlitアプリを構築するには、単にコードを組み立てるのではなく、慎重な計画が必要です。GPT Labでは、次の4つの重要な側面に焦点を当てました:

  1. 機能とユーザーエクスペリエンス。 アプリは何をするのか?どのようなユーザーエクスペリエンスを提供することを目指しているのか?
  2. データモデル。 データはどのように永続化されるのか?データベースとセッション状態変数のどちらに保存するべきか?
  3. コードの構造。 モジュール性、保守性、拡張性を確保するためにアプリのアーキテクチャをどのように設計するか?
  4. セッションの状態。 ユーザーインターフェースをリンクするためにどのセッション状態変数が必要か?

これらの側面を理解することで、私が構築しようとしているものがより明確になり、複雑なタスクにシステマティックに取り組むためのフレームワークが提供されました。

それでは、各側面について詳しく見ていきましょう。

機能とユーザーエクスペリエンス:初期仕様と低ファイデリティのUXモックの作成

まず、全体のスコープとアプローチを概説した簡単な仕様書(または「仕様」)を作成しました。また、サポートしたいユースケースを詳細に示したサイトマップも含めました。仕様書は私にとって進むべき明確なロードマップと進捗を測る手段を提供しました。

以下は元の仕様書の一部です:

スコープ

友人や家族のために、生成AI(GA)ボット愛好家が自分自身のGPT-3プロンプトベースのチャットボットを構築できるプラットフォームを構築します。これにより、十分なGAボット愛好家が、独自のニッチ領域ボットを構築したいという仮説を検証します。

アプローチ

ユーザーが4つの事前トレーニング済みコーチボットのいずれかと対話したり、自分自身のボットを作成して対話したりできるパブリックStreamlitサイト。

ほとんどの開発プロジェクトと同様に、いくつかの変更を加えました。しかし、元のサイトマップはほとんどそのままであり、計画された機能のほとんどを実装することができました。

以下はサイトマップの最終版です:

GPT Lab│├── ホーム│├── ラウンジ│├── アシスタント│   ├── アシスタントの検索│   ├── アシスタントの詳細│   ├── アクティブなチャット│   └── チャットの要約│├── ラボ│   ├── ステップ1:初期プロンプト+モデルの設定│   ├── ステップ2:チャットのテスト│   ├── ステップ3:その他の設定│   └── ステップ4:確認│├── FAQ│└── 法的    ├── 利用規約    └── プライバシーポリシー

機能の計画の重要性を過小評価することはできません。それはロードマップを提供し、進捗を測る手段を提供し、データモデルの考え方の出発点となります。

データモデル:スキーマの決定

最初から、ユーザー、アシスタント、およびセッションの記録を永続化するために、バックエンドのデータストアが重要であることに気付きました。選択肢を考慮した後、スケーラビリティ、リアルタイム性、寛大な無料利用枠があるため、Google Firestoreを選びました。将来の拡張をサポートするために、データモデルを戦略的に設計しました。現在のアプリは潜在能力の一部しか使用していませんが、GPT Labにプロンプトバージョン制御を追加することが可能です。これにより、ユーザーはアシスタントを編集したり戻したりすることができます。

💡 注意: アプリのバックエンドとデータモデルでは、アシスタントはユーザーインターフェースではボットと呼びませんでしたが、ボットとして参照されます 😅。

さあ、GPT Labの4つの主要なFirestoreコレクションを探ってみましょう: ユーザー、ユーザーハッシュ、ボット、セッションです。

ユーザーとユーザーハッシュ

ユーザーコレクションは、アプリがユーザーに関する情報を保存する場所です。ユーザーのプライバシーを保護するため、アプリはユーザーに関する個人を特定できる情報(PII)を保存しません。代わりに、各ユーザーはOpenAI APIキーのワンウェイハッシュ値との関連付けのみです。メトリックフィールドは、ユーザーがアシスタントを作成したり、セッションを開始/終了したりするたびに増加します。これにより、アプリ内で基本的な分析データが収集されます。

ユーザーコレクション   |   | - id: (Firestoreの自動ID)   | - user_hash: string (OpenAI APIキーのワンウェイハッシュ値)   | - created_date: datetime   | - last_modified_date: datetime   | - sessions_started: number   | - sessions_ended: number   | - bots_created: number

Google Firestoreには、コレクション内のドキュメントフィールド値の一意性を確保する方法が提供されていません。そのため、user_hashという別のコレクションを作成しました。これにより、各ユニークなAPIキーには関連付けられたユーザーレコードが1つだけ存在することが保証されます。各ユーザードキュメントはユーザーハッシュドキュメントとユニークに関連付けられ、各ユーザーハッシュドキュメントはユーザードキュメントと関連付けられる場合があります。データモデルは、将来的にAPIキーを変更するユーザーにも対応できる柔軟性があります(ユーザーは古いAPIキーでログインし、新しいAPIキーに切り替えることができます)。

ユーザーハッシュコレクション   |   | - id = OpenAI APIキーのワンウェイハッシュ値   | - user_hash_type: string (open_ai_key)   | - created_date: datetime

ボット

ボットコレクションは、AIアシスタントの設定を保存します。各AIアシスタントの要点は、大規模な言語モデル(LLM)、モデルの設定、およびプロンプトです。将来のプロンプトとモデルの設定の適切なバージョン管理を可能にするため、model_configsとpromptsはサブコレクションとしてモデル化されています(GPT Labのビジョンの一部は、プロンプトのリポジトリであることです)。

アクティブレコードのサブコレクションを頻繁にクエリする必要がないようにするために、アクティブサブコレクションのドキュメントIDもドキュメントレベルで保存されます。session_typeフィールドは、アシスタントがブレストセッションまたはコーチングセッションにあるかどうかを示し、セッションメッセージの切り捨て技術に影響を与えます。

最後に、ユーザーがアシスタントとセッションを開始または終了すると、メトリックフィールドが増加します。

ボットコレクション   |   | - id: (Firestoreの自動ID)   | - name: string   | - tag_line: string   | - description: string   | - session_type: number   | - creator_user_id: string   | - created_date: datetime   | - last_modified_date: datetime   | - active_initial_prompt_id: string   | - active_model_config_id: string   | - active_summary_prompt_id: string   | - showcased: boolean   | - is_active: boolean   |   v   |--> Model_configsサブコレクション   |     |   |     | - config: map   |     |     | - model: string    |     |     | - max_tokens: number    |     |     | - temperature: number    |     |     | - top_p: number    |     |     | - frequency_penalty: number    |     |     | - presence_penalty: number    |     | - created_date: datetime   |     | - is_active: boolean   |   v   |--> Promptsサブコレクション         |         | - message_type: string         | - message: string         | - created_date: datetime         | - is_active: boolean         | - sessions_started: number         | - sessions_ended: number

セッション

セッションコレクションは、セッションデータを保存します。ラボセッション(プロンプトのテストに使用)とアシスタントセッション(作成したアシスタントとのチャットに使用)の2種類のセッションが含まれています。ボットドキュメントを頻繁に取得する必要を減らすために、情報はセッションドキュメント内でキャッシュされます。これは概念的に意味がありますが、編集アシスタントのユースケースが実装された場合、ボットドキュメントが変化する可能性があります。

最新のペイロードは、OpenAIのLLMに送信されたもので、messages_strフィールドに保存されます。この機能により、ユーザーは以前のアシスタントセッションを再開することができます。実際のチャットメッセージはmessagesサブコレクションに保存されますが、ラボセッションのチャットメッセージは保存されません。

ユーザーの機密性とプライバシーを保護するために、OpenAIはリクエストペイロードとセッションメッセージをデータベースに保存する前に暗号化します。このデータモデルにより、ユーザーは以前のセッションを再開し、アシスタントとのチャットを続けることができます。

Sessions Collection   |   | - id: (Firestore auto-ID)   | - user_id: string   | - bot_id: string   | - bot_initial_prompt_msg: string   |   | - bot_model_config: map   |     | - model: string    |     | - max_tokens: number    |     | - temperature: number    |     | - top_p: number    |     | - frequency_penalty: number    |     | - presence_penalty: number    |   | - bot_session_type: number   | - bot_summary_prompt_msg: string   | - created_date: datetime   | - session_schema_version: number   | - status: number  | - message_count: number   | - messages_str: string (encrypted)   |   v   |--> Messages subcollection         |         | - created_date: datetime         | - message: string (encrypted)         | - role: string

最初からすべての潜在的なユースケースを注意深く考慮して、アプリの成長に対応できるデータモデルを作成しました。次のセクションでは、バックエンドアプリケーションコードの構造を調べて、この堅牢なデータモデルをサポートし、実装する方法を見ていきます。

コードの構造:拡張性とモジュラリティのための構造化

私はGPT Labを作成し、技術的なスキルがないまたはほとんどないユーザーが独自のプロンプトベースのLLMベースのAIアプリケーションを構築できるようにしました。基礎となるインフラストラクチャを心配することなく、ユーザーのカスタムフロントエンドアプリ(Streamlitを使用するかどうかに関係なく)と彼らのAIアシスタントを接続するバックエンドAPIを提供することが最終的な目標です。これにより、フロントエンドのStreamlitアプリケーションとバックエンドのロジックを分離する切り離されたアーキテクチャを設計しました。

バックエンドコードの構造は次のようになっています:

+----------------+     +-------------------+     +-------------------+     +------------+|                |     |                   |     |                   |     |            ||  Streamlit App |<--->| util_collections  |<--->| api_util_firebase |<--->|  Firestore ||                |     | (users, sessions, |     |                   |     |            ||                |     |  bots)            |     |                   |     |            |+----------------+     +-------------------+     +-------------------+     +------------+                             |                             |                             v                     +-----------------+     +------------+                     |                 |     |            |                     | api_util_openai |<--->|   OpenAI   |                     |                 |     |            |                     +-----------------+     +------------+

モジュールは次のようになっています:

  • api_util_firebaseはFirestoreデータベースのCRUD操作を処理します。
  • api_util_openaiはOpenAIのモデルと連携し、上流モデルに統一されたチャットモデルを提供し、チャットメッセージを削除し、プロンプトインジェクション攻撃を検出および防止しようとします。
  • api_util_usersapi_util_sessions、およびapi_util_botsはそれぞれのFirestoreコレクションへのインタフェースです。これらはapi_util_firebaseとapi_util_openaiと連携し、GPT Lab固有のビジネスロジックを実装します。

この設計により、コードの異なる部分を別々に開発、テスト、スケーリングすることができます。また、バックエンドのutil_collectionsモジュールをGoogle Cloud Functionsに変換してAPIゲートウェイを介して公開するための簡単な移行パスを確立します。

セッションの状態:UIとユーザーフローの管理

最初のブログ記事で説明したように、セッションの状態変数を使用してStreamlitページの機能を制御および管理しました。以下は、これらの変数がアプリ全体でどのように利用されているかを示しています:

home.py

  • userはOpenAI APIキーモジュールを表示するかどうかを制御します

pages/1_lounge.py

  • userはOpenAI APIキーモジュールの表示、アシスタントの選択の有効化、およびMy Assistantsタブの表示を制御します。
  • ユーザーがアシスタントとの対話を選択すると、アシスタントの詳細がbot_infoに保存されます。

pages/2_assistant.py

  • userはOpenAI APIキーモジュールを表示するかどうかを制御します。
  • bot_infosession_id、およびsession_endedは表示する画面のバリエーションを決定します。
  • bot_infoが存在しない場合:URLパラメータにassistant_idがあるかどうかを確認します。それ以外の場合は、ユーザーにアシスタントを検索するように促します。
  • bot_infosession_idが存在し、session_endedがfalseの場合:チャットセッション画面を表示します。
  • bot_infosession_idが存在し、session_endedがtrueの場合:チャットセッションのまとめ画面を表示します。
  • チャットセッションでは、session_msg_listに会話が保存されます。

pages/3_lab.py

  • userはOpenAI APIキーモジュールを表示するかどうか、およびラボでアシスタントの作成を許可するかどうかを制御します。
  • lab_active_stepはレンダリングするラボセッションの状態を制御します:
  • 1の場合:アシスタントの初期プロンプトとモデルを設定するためのステップ1のUIを表示します。
  • 2の場合:アシスタントとのチャットをテストするためのステップ2のUIを表示します。
  • 3の場合:アシスタントの詳細を最終確認するためのステップ3のUIを表示します。作成時に、botのレコードはFirestore DBに作成され、ドキュメントIDはlab_bot_idに保存されます。
  • 4でlab_bot_idが設定されている場合:アシスタントの作成確認を表示するためのステップ4のUIを表示します。
  • テストチャットセッション中、lab_msg_listにテストメッセージが保存されます。別々のlab_bot_idbot_infoを使用することで、ラウンジ/アシスタントとラボの間を行き来してもそれぞれの進行状況を失うことなく進めることができます。

計画が完了したら、残りの実行ははるかに管理しやすくなりました。

まとめ

この記事では、GPT Labの作成に必要な事前計画について、機能、データモデル、コード、セッションの状態について説明しました。あなたも自分自身の野心的なStreamlitアプリを作ることにインスピレーションを受けることを願っています。

TwitterやLinkedinで私とつながってください。あなたからの連絡を楽しみにしています。

Happy Streamlit-ing! 🎈

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more