「社内でAIチャットツールを使いたいけど、ChatGPTをそのまま業務に使うのはセキュリティ面が不安」という声をよく聞きます。そんなとき、Antigravity(Gemini API)とStreamlitを組み合わせると、自社のシステムプロンプトを設定したカスタムチャットツールを驚くほど短い時間で作れます。
Streamlitはデータサイエンティストや個人開発者に人気のPythonウェブフレームワークで、フロントエンドの知識がなくてもインタラクティブなUIを構築できます。今回は、会話履歴の保持・ストリーミング表示・システムプロンプトのカスタマイズまでを含む、実用的なチャットツールを一緒に作っていきましょう。
なぜ Streamlit と Antigravity の組み合わせなのか
React や Next.js でチャットUIを作ることもできますが、バックエンドのセットアップやデプロイの手間がかかります。StreamlitならPythonファイル1つで完結するのが大きな利点です。
私がこの組み合わせを選ぶのは、主に次のようなケースです。
- 社内のエンジニアやチームメンバーが使う、プロトタイプ段階のツール
- 特定の業務(コードレビュー支援・ドキュメント要約・Q&A対応)に特化したチャットbot
- まず動作確認して、後でNext.jsなど本番向けに移植する前の検証環境
ポイントは「完璧なUIではなく、まず動くものを早く作る」という目的に向いている点です。Antigravity(Gemini 2.5 Pro)のAPIと組み合わせると、性能面でも十分実用に耐えます。
環境構築
必要なパッケージは3つだけです。
pip install streamlit google-genai python-dotenvAPIキーは環境変数で管理します。プロジェクトのルートに .env ファイルを作成してください。
GEMINI_API_KEY=YOUR_GEMINI_API_KEY
.env をバージョン管理に含めないよう、.gitignore に追加しておくことも忘れずに。
echo ".env" >> .gitignore基本的なチャットUIを作る
まず、最もシンプルな構成でチャットUIを動かしてみましょう。app.py というファイルを作成します。
import streamlit as st
from google import genai
from dotenv import load_dotenv
import os
# 環境変数の読み込み
load_dotenv()
# Antigravity(Gemini)クライアントの初期化
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
# ページ設定
st.set_page_config(page_title="社内AIチャット", page_icon="🤖", layout="wide")
st.title("🤖 社内AIアシスタント")
# 会話履歴をセッションステートで管理
# Streamlit はページが再レンダリングされるたびにスクリプトが再実行される
# st.session_state を使わないとメッセージ履歴が毎回リセットされてしまう
if "messages" not in st.session_state:
st.session_state.messages = []
# 過去メッセージを画面に表示
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# チャット入力
if prompt := st.chat_input("メッセージを入力してください..."):
# ユーザーメッセージを表示・保存
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
# Antigravity にリクエスト(会話履歴を含めて送信)
with st.chat_message("assistant"):
history = [
{"role": m["role"], "parts": [{"text": m["content"]}]}
for m in st.session_state.messages[:-1]
]
response = client.models.generate_content(
model="gemini-2.5-pro",
contents=history + [{"role": "user", "parts": [{"text": prompt}]}],
)
answer = response.text
st.markdown(answer)
# アシスタントの返答を履歴に保存
st.session_state.messages.append({"role": "assistant", "content": answer})これを実行するには次のコマンドを使います。
streamlit run app.pyブラウザが自動的に開き、チャットUIが表示されます。ここまでで、すでに会話が成立する最小構成の完成です。
ストリーミング表示を追加する
上の実装では、Antigravityの返答が完全に生成されてから一括で表示されます。長い返答だと数秒間何も表示されないため、使い心地が悪くなります。ストリーミングを使えば、回答がリアルタイムで流れるように表示されます。
変更点は generate_content を generate_content_stream に切り替えるだけです。
with st.chat_message("assistant"):
answer_placeholder = st.empty() # テキスト更新用プレースホルダー
full_answer = ""
# stream=True でストリーミングを有効化
for chunk in client.models.generate_content_stream(
model="gemini-2.5-pro",
contents=history + [{"role": "user", "parts": [{"text": prompt}]}],
):
if chunk.text:
full_answer += chunk.text
# チャンクが届くたびに表示を更新(末尾のカーソルで生成中を示す)
answer_placeholder.markdown(full_answer + "▌")
# 最終的な回答を確定表示(カーソルを消す)
answer_placeholder.markdown(full_answer)
st.session_state.messages.append({"role": "assistant", "content": full_answer})▌ を末尾に付けることで、生成中であることをカーソルで示せます。細かい工夫ですが、実際に使うと受け取り印象がずいぶん変わります。
システムプロンプトで業務に特化させる
汎用チャットではなく特定の業務に特化させるには、システムプロンプトを設定します。Gemini APIでは system_instruction パラメータとして渡します。
# 業務に合わせてカスタマイズするシステムプロンプト
SYSTEM_PROMPT = """
あなたは〇〇株式会社の社内AIアシスタントです。以下のルールに従って回答してください。
- 回答は必ず日本語で行う
- 社外秘情報や個人情報には言及しない
- 不明な点は「確認が必要です」と伝え、推測で回答しない
- コードの質問には具体的なサンプルを示す
"""
# APIリクエストにシステムプロンプトを追加
response = client.models.generate_content(
model="gemini-2.5-pro",
contents=history + [{"role": "user", "parts": [{"text": prompt}]}],
config=genai.types.GenerateContentConfig(
system_instruction=SYSTEM_PROMPT,
temperature=0.3, # 業務用途は低めに設定してハルシネーションを抑える
max_output_tokens=2048,
),
)temperature を低めに設定(0.1〜0.4)することで、創造的な回答よりも正確な回答を優先させられます。業務用途では特に意識しておきたい設定です。私の経験では、ドキュメント要約やQ&A用途には 0.2 前後が安定しています。
サイドバーでモデルと設定を切り替えられるようにする
Streamlitのサイドバーを使うと、使用するモデルの切り替えや会話履歴のリセットボタンを追加できます。
with st.sidebar:
st.header("設定")
# 使用モデルの選択(Pro は高精度、Flash は高速・低コスト)
model_name = st.selectbox(
"モデル",
["gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.0-flash"],
)
# 温度パラメータのスライダー
temperature = st.slider("Temperature", 0.0, 1.0, 0.3, 0.1)
st.divider()
# 会話リセットボタン
if st.button("🔄 会話をリセット", type="secondary"):
st.session_state.messages = []
st.rerun()gemini-2.5-flash はレスポンスが速く、コストも抑えられるため、業務用の日常的なQ&A対応には十分なケースが多いです。用途に応じて切り替えられるUIにしておくと、チームメンバーから喜ばれます。
Streamlit Community Cloud へのデプロイ
作成したアプリをチームに共有するには、Streamlit Community Cloudが最も手軽です。無料で使えて、GitHubと連携した自動デプロイが設定できます。
デプロイ時はAPIキーを環境変数ではなく .streamlit/secrets.toml で管理します。
# .streamlit/secrets.toml(GitHubにはpushしない)
GEMINI_API_KEY = "YOUR_GEMINI_API_KEY"コード側では、ローカルとデプロイ環境の両方に対応するよう読み込み方を変えます。
# ローカルは .env を、Streamlit Cloud では st.secrets を使う
api_key = st.secrets.get("GEMINI_API_KEY") or os.environ.get("GEMINI_API_KEY")
if not api_key:
st.error("GEMINI_API_KEY が設定されていません")
st.stop() # APIキーがない場合はアプリを停止する
client = genai.Client(api_key=api_key)GitHubにコードをpushしたら、Streamlit Community Cloud(share.streamlit.io)でリポジトリを選択するだけでデプロイが完了します。URLをチームに共有すれば、ブラウザからすぐに使い始められます。
Streamlitによる実装の良いところは、「まず動くものを見せてフィードバックをもらいながら改善できる」点にあると思います。完成度よりもスピードを優先したいフェーズで、この構成は本当に重宝します。
Antigravity Python APIのさらに詳しい使い方は、google-genai SDK 実践クイックスタートやPython SDK 本番運用マスターガイドも参考にしてみてください。
まず今日、pip install streamlit google-genai の1コマンドから始めてみましょう。