Streamlit v1.54.0 ウィジェット状態管理の革新と、より洗練されたUI構築への道

Streamlit
この記事は約37分で読めます。

こんにちは、JS2IIUです。

PythonのWebフレームワークとして不動の地位を築いたStreamlitが、2025年に入りさらなる進化を遂げました。2026年2月5日にリリースされたバージョン1.54.0は、前バージョンの1.53.0からのマイナーアップデートという位置づけながら、開発者が長年頭を悩ませてきた「ウィジェットの状態管理」に根本的な解決策を提示し、UIの柔軟性を大幅に向上させる重要なアップデートとなっています。

本記事では、プログラミングとAIを専門とする視点から、v1.54.0で導入された新機能と変更点、そしてそれらが実務の開発にどのようなインパクトを与えるのかを、詳細なサンプルコードと共に解説します。今回もよろしくお願いします。

1. ウィジェット・アイデンティティの変革:keyによる状態維持の安定化

v1.54.0における最大かつ最も画期的な変更は、ウィジェットの同一性(Identity)を判断する基準の刷新です。

従来の課題

これまでのStreamlitでは、ウィジェットを再実行間で「同じもの」と認識させるために、ラベルやオプション、範囲設定などのパラメータが一致している必要がありました。例えば、ユーザーの操作に応じて「ラジオボタンの選択肢(options)」を動的に書き換えると、Streamlitはそれを「新しいウィジェット」と見なし、それまでユーザーが選択していた状態をリセットしてしまうことがありました。

v1.54.0の解決策

新バージョンでは、key パラメータが指定されている場合、ウィジェットの同一性は「キー」のみに基づいて判断されるようになりました。これにより、ラベルの内容やドロップダウンのリストがプログラムによって動的に変更されたとしても、キーが同じであればユーザーの選択状態が可能な限り維持されます。

これは、動的なフォーム作成や、AIの応答に基づいてUIを変化させるアプリケーションにおいて、劇的なユーザー体験の向上をもたらします。

Python
import streamlit as st

st.set_page_config(layout="wide")

st.title("ウィジェット identity 変更デモ (v1.54.0)")

st.markdown("""
## key あり/なしでの label 変更時の挙動の違い

チェックボックスをON/OFFして、label を変更してください。
""")

# label を動的に変更するためのトグル
use_japanese = st.checkbox("日本語ラベルを使用", value=True)

# label を切り替え
if use_japanese:
    label_text = "好きな果物を選んでください"
else:
    label_text = "Select your favorite fruit"

# 同じ options を使用
options = ["りんご", "バナナ", "オレンジ"]

# 2カラムレイアウトで横並び比較
col1, col2 = st.columns(2)

with col1:
    st.subheader("1️⃣ key あり")
    st.caption("✅ label が変わっても選択が保持される(v1.54.0以降)")

    selected_with_key = st.radio(
        label_text,
        options=options,
        key="fruit_with_key"
    )
    st.success(f"選択中: {selected_with_key}")

with col2:
    st.subheader("2️⃣ key なし")
    st.caption("❌ label が変わると選択がリセットされる(従来通り)")

    selected_without_key = st.radio(
        label_text,
        options=options,
    )
    st.success(f"選択中: {selected_without_key}")

st.markdown("---")

st.info("""
**操作手順:**
1. 両方のラジオボタンで「バナナ」(2番目)を選択
2. 「日本語ラベルを使用」チェックボックスをON/OFF
3. 左(key あり)は「バナナ」を保持、右(key なし)は「りんご」にリセットされる
""")

この変更により、開発者は st.session_state を駆使して無理やり状態を復元するような複雑なロジックから解放されます。

2. ブランディングの強化:st.logoの機能拡張

アプリケーションの第一印象を左右するロゴ表示機能 st.logo が大幅に強化されました。これまでは画像ファイルのパス指定が主でしたが、v1.54.0からはより柔軟な指定が可能になっています。

Material Icons と 絵文字のサポート

画像ファイルを用意せずとも、st.logo("analytics") のように Google Material Icons の名前を指定したり、st.logo("🚀") のように絵文字を直接指定したりできるようになりました。

リンク設定の柔軟性

st.logolink パラメータを指定することで、ロゴをクリックした際の遷移先を設定できます。また、サイドバーが閉じている時に表示するアイコン(icon_image)の制御もより洗練されました。

Python
import streamlit as st

# st.set_page_config(layout="wide")

st.title("st.logo の Material Icons & 絵文字対応デモ (v1.54.0)")

st.markdown("""
## v1.54.0 の新機能

`st.logo` で **Material Symbols(Material Icons)と絵文字**が直接指定できるようになりました。

### 使用例
""")

# パターン選択
pattern = st.radio(
    "ロゴのパターンを選択してください(サイドバーの左上を確認)",
    [
        "1️⃣ Material Icon のみ",
        "2️⃣ 絵文字のみ",
        "3️⃣ Material Icon + 絵文字(icon_image)",
        "4️⃣ 絵文字 + Material Icon(icon_image)",
    ],
    key="logo_pattern"
)

st.markdown("---")

# パターンに応じて st.logo を設定
if pattern == "1️⃣ Material Icon のみ":
    st.logo(":material/analytics:")

    st.code("""
st.logo(":material/analytics:")
""", language="python")

    st.info("""
    **Material Symbols の指定方法:**
    - 形式: `:material/icon_name:`
    - icon_name は snake_case
    - サイドバー左上に Material Icon が表示されます
    """)

elif pattern == "2️⃣ 絵文字のみ":
    st.logo("🚀")

    st.code("""
st.logo("🚀")
""", language="python")

    st.info("""
    **絵文字の指定方法:**
    - 1文字の絵文字をそのまま文字列として渡す
    - 絵文字ショートコード(:rocket:)は非対応
    """)

elif pattern == "3️⃣ Material Icon + 絵文字(icon_image)":
    st.logo(
        ":material/home:",
        icon_image="🏠"
    )

    st.code("""
st.logo(
    ":material/home:",      # サイドバー展開時
    icon_image="🏠"         # サイドバー折りたたみ時
)
""", language="python")

    st.info("""
    **image と icon_image の使い分け:**
    - `image`: サイドバーが展開されているときに表示
    - `icon_image`: サイドバーが折りたたまれているときに表示

    **確認方法:** サイドバーの左上の「>」をクリックして折りたたんでみてください
    """)

elif pattern == "4️⃣ 絵文字 + Material Icon(icon_image)":
    st.logo(
        "📊",
        icon_image=":material/bar_chart:",
        size="large",
        link="https://streamlit.io"
    )

    st.code("""
st.logo(
    "📊",                              # サイドバー展開時
    icon_image=":material/bar_chart:", # サイドバー折りたたみ時
    size="large",                      # サイズ指定
    link="https://streamlit.io"        # クリック時のリンク
)
""", language="python")

    st.info("""
    **追加パラメータ:**
    - `size`: "small", "medium", "large" を指定可能
    - `link`: ロゴクリック時の遷移先URL

    **確認方法:**
    1. サイドバーの左上の「>」で折りたたんで icon_image を確認
    2. ロゴをクリックすると Streamlit サイトに遷移
    """)

st.markdown("---")

st.subheader("📝 その他の Material Icons 例")

col1, col2, col3 = st.columns(3)

with col1:
    st.code(":material/home:")
    st.markdown("**Home**")

with col2:
    st.code(":material/settings:")
    st.markdown("**Settings**")

with col3:
    st.code(":material/favorite:")
    st.markdown("**Favorite**")

st.markdown("""
### 参考リンク
- [Material Symbols 一覧](https://fonts.google.com/icons)
- [st.logo API リファレンス](https://docs.streamlit.io/develop/api-reference/media/st.logo)
""")

3. データ操作性の向上:st.dataframe の進化

データサイエンスにおいて欠かせない st.dataframe コンポーネントも、ユーザーの利便性を高める修正が行われました。

リスト形式セルのコピーサポート

ListColumnMultiselectColumn を使用してデータフレーム内に「タグ(ピル)」を表示している場合、これまではその内容をマウスで選択してコピーすることが困難でした。v1.54.0からは、これらのセル内のテキストを選択し、クリップボードにコピーできるようになりました。

これにより、分析結果を他のドキュメントやレポートに転記する際のストレスが大幅に軽減されます。

Python
import pandas as pd
import streamlit as st

# リストを含むデータフレーム
df = pd.DataFrame({
    "APIエンドポイント": ["/v1/predict", "/v1/train", "/v1/status"],
    "許可メソッド": [["GET", "POST"], ["POST"], ["GET"]]
})

st.subheader("API管理テーブル")
st.dataframe(
    df,
    column_config={
        "許可メソッド": st.column_config.ListColumn("メソッド")
    },
    hide_index=True
)
st.caption("v1.54.0では、上記の『GET』や『POST』のタグを直接選択してコピーできます。")

4. 視覚効果とチャートの柔軟性

グラフやインジケーターの表示についても、細かいながらも重要な改善が含まれています。

チャートのテーマカラー

st.line_chartst.bar_chart などのネイティブチャートにおいて、プロジェクト全体のテーマ設定(.streamlit/config.toml)で定義したカラーパレットがより正確に反映されるようになりました。特に theme.chartDivergingColors 設定の追加により、データの増減を色で表現する際の一貫性が保たれます。

画像キャプションの挙動修正

GitHubのリリースタグでも言及されている通り、st.image に付与する caption の幅が、画像の表示幅と一致するように調整されました。これにより、大きな画像に対して小さなテキストが端に寄ってしまうような不自然なレイアウトが解消され、図解の美しさが向上します。

st.audio の時間制御

st.audio において start_time パラメータが浮動小数点数(float)をサポートするようになりました。これにより、音声データの「1.5秒目から再生」といった緻密な制御が可能になり、音声解析AIのプロトタイプなどで重宝します。

5. パフォーマンスと内部的な改善

v1.54.0では、フロントエンドのコンポーネント読み込みプロセスが最適化されました。

静的アセットの読み込み高速化

内部的な依存関係の見直しにより、アプリ起動時の静的ファイルの配信スピードが向上しています。特に大規模なアプリや、多くのカスタムコンポーネントを配置している場合に、ユーザーが最初に画面を目にするまでの時間が短縮されます。

エラーリンクの表示制御

設定ファイルで client.showErrorLinks = false を指定することで、開発者向けのエラーメッセージに表示される「Streamlitのドキュメントへのリンク」を非表示にできるようになりました。クローズドな環境や、エンドユーザー向けの完成された製品として提供する場合に、内部的なリンクを隠すことが可能です。

6. 実践:v1.54.0 の新機能をフル活用した「AIモデル管理ダッシュボード」

それでは、ここまで紹介した機能を統合し、v1.54.0の恩恵を最大限に受けるダッシュボードの実装例を見ていきましょう。

Python
import streamlit as st
import pandas as pd
import numpy as np
import time

# 1. ページ構成とロゴ設定(v1.54.0: st.logo で Material アイコン・絵文字が利用可能)
# https://docs.streamlit.io/develop/api-reference/media/st.logo
st.set_page_config(page_title="MLOps Console v1.54", layout="wide")

# サイドバーとヘッダーで異なるロゴを利用(Material icon + 絵文字)
st.logo(
    image=":material/smart_toy:",          # サイドバー用(AI を想起させる Material Symbols)
    icon_image="🤖",                       # サイドバーが閉じたときの小さいロゴ
    link="https://github.com/streamlit/streamlit"
)

st.title("次世代 ML モデル管理コンソール v1.54.0")

# 2. ウィジェット同一性の維持を活用した動的サイドバー
# v1.54.0 では、多くのウィジェットが「key ベースの identity」に移行しており、
# key を固定すればパラメータ変更時のリセットが起きにくくなるとされています。
# https://docs.streamlit.io/develop/quick-reference/release-notes
# https://docs.streamlit.io/develop/concepts/architecture/widget-behavior
with st.sidebar:
    st.header("コントロールパネル")

    # モデル種別の切り替え(radio は v1.54.0 で key ベース identity 対象)
    model_type = st.radio(
        "ターゲットモデル",
        ["LLM", "画像認識"],
        key="model_type_selector",
    )

    # モデルタイプに応じてハイパーパラメータの選択肢を動的に変える
    if model_type == "LLM":
        param_label = "Temperature (生成の多様性)"
        min_v, max_v = 0.0, 2.0
        default_v = 0.7
    else:
        param_label = "Confidence Threshold (確信度閾値)"
        min_v, max_v = 0.0, 1.0
        default_v = 0.7

    # slider も v1.54.0 で key ベース identity 対象に含まれています(release notes で列挙)。
    # ここでは key を固定しつつ min/max を動的に変更。
    param_value = st.slider(
        param_label,
        min_value=min_v,
        max_value=max_v,
        value=default_v,
        key="dynamic_model_param",
    )

    st.caption(f"現在の {param_label}: {param_value:.2f}")

# 3. メインエリア:メトリクスとチャート
# v1.54.0: line_chart / bar_chart / area_chart / scatter_chart の color パラメータが
# テーマの基本カラーパレットに対応。[[2026 release notes](https://docs.streamlit.io/develop/quick-reference/release-notes/2026)]
col1, col2 = st.columns(2, border=True)

with col1:
    st.subheader("モデル KPI")

    st.metric("本番モデル精度", "94.2%", "+1.2%")
    st.metric("平均レイテンシ", "45 ms", "-5 ms")

    # 精度・損失の推移を line_chart で表示(color パラメータを利用)
    history = pd.DataFrame(
        np.random.randn(30, 2).cumsum(axis=0),
        columns=["精度", "損失"],
    )
    st.line_chart(
        history,
        color=["#00b894", "#d63031"],  # テーマに合わせた 2 色(例)
    )

with col2:
    st.subheader("システムログ & オペレーション")

    # v1.54.0: st.spinner(show_time=True) で経過時間を表示
    # https://docs.streamlit.io/develop/api-reference/status/st.spinner
    if st.button("最新ログを同期", key="sync_logs_btn"):
        with st.spinner("ログ同期中...", show_time=True):
            time.sleep(1.8)  # 通信のシミュレーション
        st.success("同期完了")
        st.code(
            "INFO  [model_v4] loaded successfully\n"
            "DEBUG [latency] p95=45ms\n"
            "INFO  [router] traffic shifted to model_v4",
            language="bash",
        )

    # チャートの color パラメータを使ったエラーレート推移
    error_rate = pd.DataFrame(
        {
            "エラー率": np.clip(np.random.rand(30) / 10, 0, 0.15),
        }
    )
    st.area_chart(
        error_rate,
        color="#e17055",
    )

# 4. デプロイ済みエージェント一覧(ListColumn のコピー性向上)
# v1.54.0 では ListColumn / MultiselectColumn の pill テキストがコピーしやすくなったとされています。
# https://docs.streamlit.io/develop/quick-reference/release-notes/2026
st.subheader("デプロイ済みエージェント一覧")

agent_data = pd.DataFrame(
    {
        "エージェントID": ["AG-001", "AG-002", "AG-003"],
        "モデル種別": ["LLM", "画像認識", "LLM"],
        "バージョン": ["v4.1", "v2.3", "v3.0"],
        "割り当て機能": [
            ["自然言語理解", "要約"],
            ["画像分類"],
            ["音声認識", "翻訳"],
        ],
    }
)

st.dataframe(
    agent_data,
    column_config={
        "エージェントID": st.column_config.TextColumn("ID", pinned=True),
        "モデル種別": st.column_config.TextColumn("Type"),
        "バージョン": st.column_config.TextColumn("Version"),
        # ListColumn: pill テキストを選択してコピーしやすい
        "割り当て機能": st.column_config.ListColumn("Capabilities"),
    },
    use_container_width=True,  # v1.52 以降で width="content" もサポートされていますが、ここでは幅いっぱいを使用
)

st.caption("※Capabilities 列のタグは、直接選択してコピーすることが可能です。")

# 5. モデル詳細ビュー(dataframe + column_config の活用)
# https://docs.streamlit.io/develop/api-reference/data/st.dataframe
st.subheader("モデル別メトリクス詳細")

model_metrics = pd.DataFrame(
    {
        "Model": ["model_v4", "model_v3", "model_v2"],
        "Accuracy": np.round(np.random.uniform(0.9, 0.97, 3), 3),
        "Latency(ms)": np.random.randint(30, 80, 3),
        "Traffic(%)": np.round(np.random.uniform(10, 80, 3), 1),
        "History": np.random.randint(0, 1000, size=(3, 30)).tolist(),
    }
)

st.dataframe(
    model_metrics,
    column_config={
        "Model": "モデル名",
        "Accuracy": st.column_config.NumberColumn(
            "精度",
            format="%.3f",
            help="検証データにおける Accuracy",
        ),
        "Latency(ms)": st.column_config.NumberColumn(
            "レイテンシ (ms)",
            format="%d ms",
        ),
        "Traffic(%)": st.column_config.NumberColumn(
            "トラフィック比率",
            format="%.1f %%",
        ),
        # LineChartColumn: 各モデルのトラフィック推移などを簡易表示
        "History": st.column_config.LineChartColumn(
            "リクエスト数 (過去30分)",
            y_min=0,
        ),
    },
    hide_index=True,
)

7. 注意点:非推奨機能の削除(Breaking Changes)

v1.54.0へのアップデートに際して、開発者が最も注意すべき点は、長らく「experimental(実験的)」として提供されていた機能の完全削除です。

削除された主な機能

  • st.experimental_get_query_params および st.experimental_set_query_params:
    これらは完全に削除されました。今後は st.query_params を使用してください。新しいAPIは辞書型のオブジェクトとして振る舞い、st.query_params["user"] = "admin" のように直感的に記述できます。
  • st.experimental_user:
    正式版の st.user へ移行してください。
  • Bokeh チャートのサポート:
    Streamlit内部でのBokehライブラリの直接的な統合が終了しました。Bokehを利用し続けたい場合は、st.components.v1 を使用してHTMLとしてレンダリングするか、AltairやPlotlyといった他の推奨ライブラリへの移行を検討してください。

削除への対応

移行のコストを概算する場合、以下のような単純なモデルで考えることができます。

$$
Cost_{migration} = \sum_{i \in ExpFunctions} (N_{occurrences} \times T_{replace})
$$

ここで \(N_{occurrences}\) は実験的関数の使用箇所数、\(T_{replace}\) は標準APIへの書き換え時間です。st.query_params への移行は非常に単純ですが、Bokehからの移行は可視化ロジックの再構築が必要になるため、余裕を持ったスケジュールが必要です。

まとめ

Streamlit v1.54.0は、ウィジェットの「状態」をより自然に、かつ強力に管理できるようになったことで、開発者がUIの制約を気にせずにロジックに集中できる環境を整えてくれました。

  • Widget Identity: key による安定した状態管理。
  • UI Flexibility: st.logo の Material Icons 対応やチャートのテーマ向上。
  • User Experience: データフレームのコピー機能向上や画像レイアウトの修正。
  • Cleanup: 実験的機能の整理によるライブラリの健全化。

これらのアップデートは、特に複雑なデータの可視化や、ユーザーとの対話を繰り返すAIアプリケーションにおいて、その真価を発揮します。まずは pip install --upgrade streamlit で最新版を手に入れ、自身のプロジェクトの experimental_ 関数を整理するところから始めてみてはいかがでしょうか。

Streamlitの進化は、単なる「簡単にWebアプリが作れるツール」から、「洗練されたフロントエンドを、エンジニアが直感的に構築できるプラットフォーム」へと、確実にシフトしています。

最後まで読んでいただきありがとうございます。

コメント

タイトルとURLをコピーしました