
本格的なエロチャットAIを作りたい その9(streamlitで画面を作る)
これからLLMのプロンプトに対して、動的な様々な試行錯誤をしていく中で、延々とターミナルでの文字を追うだけの作業は個人的にやる気がしない(笑)
なので、今後公開していくことも考え、streamlitを使って簡単な画面を作ってみた。
ちなみに女性のイラストは、見た目をそれっぽくすることと、自分のモチベーションを上げるためのものです。
スタート画面

Google ColabのLLMのローディングに約10分必要なので、
まず最初の画面ではLLMの起動を確認させている。
LLM ローディング中の画面

プログレスバーと待ち時間を表示している。
チャット画面
今回のシステムでは、チャットはプライベートチャットで1:1となる。
理由は、Google Colabで動かしているLLMのパフォーマンス的にマルチタスクは無理なのと、これを制御するバックエンド側のローカルPCのPython処理がマルチタスクに対応していないためである。

この画面では、チャット中にシステムプロンプトとチャットログをいじれるようになっている。
つまり、チャット進行中にシステムプロンプトを動的に変更していくことが実験でき、またLLM側のどうしようもない返事を強制的に書き換えて話を先に進めることが可能である。
覗き見画面

前述のとおり、このチャットは1:1のプライベートチャットなので、他の人がこれを覗き見できる画面を作成した。
コード
コードは以下のとおりである。
streamlitもまったく経験がないのだが、とにかくPerplexity AIに聞いて試してまた聞いて…の繰り返しで3日程度で完成。
import streamlit as st
from PIL import Image
import time
st.set_page_config(layout="wide")
system_prompt = '''SYSTEM:
あなたの名前は里穂
養女である里穂は、恥ずかしがりで処女。
本当は性に強い興味があるが口には出さない。
義父である英樹の入浴姿を覗き見して、その陰部の大きさに驚き、それをおかずに毎晩自慰をしている。
英樹には父親以上の愛情を持っているが、自分からは決して口にしない。
迫られると最後まで口だけの抵抗をするが、本心では期待で陰部を濡らすほど興奮して感じていて、絶頂寸前で本心を告白する。
返事は必ず最初に「里穂: 」を付けてください。
'''
chat_log = '''里穂: おはようございます、お義父さん。今日は私の18歳の誕生なの。お祝いしてくれる?
英樹: あ、おはよう、里穂。もちろんお祝いするよ。今日は特別なプレゼントがあるんだ
里穂: え?ほんと?!お義父さん…すっごく嬉しい!
'''
if 'layout' not in st.session_state:
st.session_state.layout = 0
def start_layout():
st.title("Advanced AI Erotic Chat System")
st.subheader("LLMを起動しますか?")
# 画像を読み込む
image = Image.open("D:\SnackVirtual\LocalLLM\pic1.png")
# 画像を表示し、サイズを調整する
st.image(image, width=500)
if st.button("LLMを起動します"):
st.session_state.layout = 1
st.rerun()
def loading_LLM_layout():
st.title("Advanced AI Erotic Chat System")
subheader_text = st.empty()
subheader_text.subheader("")
# 画像を読み込む
image = Image.open("D:\SnackVirtual\LocalLLM\pic1.png")
# 画像を表示し、サイズを調整する
st.image(image, width=500)
# プログレスバーを初期化
progress_bar = st.progress(0)
i = 0
while i < 100:
# プログレスバーを更新
progress_bar.progress(i + 1)
# 進捗テキストを更新
subheader_text.subheader(f'{10-int((i+1)/10)}分 お待ちください')
time.sleep(0.1)
i += 1
st.session_state.layout = 2
st.rerun()
def chat_input_layout():
global system_prompt, chat_log
st.title("Advanced AI Erotic Chat System")
# 2列のレイアウトを作成
col1, col2 = st.columns([5, 1]) # 比率を2:1に設定
with col1:
system_prompt = st.text_area("SYSTEM PROMPT:",
value=system_prompt,
height=200)
reverse_chat_log = '\n'.join(chat_log.splitlines()[::-1])
reverse_chat_log = st.text_area("CHAT LOG:",
value=reverse_chat_log,
height=150)
with col2:
# 画像を読み込む
image = Image.open("D:\SnackVirtual\LocalLLM\pic1.png")
# 画像を表示し、サイズを調整する
st.image(image, width=300)
user_input = st.text_area("INPUT:",
value="",
height=50)
if st.button("更新"):
st.session_state.layout = 3
st.rerun()
st.write(" ")
for line in reverse_chat_log.split('\n'):
if line.startswith("里穂"):
# ノートのような罫線のスタイルを定義
st.markdown("""
<style>
.bottom-line {
border-bottom: 1px solid #ddd;
padding-bottom: 0.5em;
line-height: 1.2em;
}
</style>
""", unsafe_allow_html=True)
# 変数を用いてテキストを表示
st.markdown(f"""
<div class="bottom-line">
<span style="font-size: 18px; color: red;">{line}</span><br>
</div>
""", unsafe_allow_html=True)
elif line.startswith("英樹"):
# ノートのような罫線のスタイルを定義
st.markdown("""
<style>
.bottom-line {
border-bottom: 1px solid #ddd;
padding-bottom: 0.5em;
line-height: 1.2em;
}
</style>
""", unsafe_allow_html=True)
# 変数を用いてテキストを表示
st.markdown(f"""
<div class="bottom-line">
<span style="font-size: 18px; color: blue;">{line}</span><br>
</div>
""", unsafe_allow_html=True)
else:
# ノートのような罫線のスタイルを定義
st.markdown("""
<style>
.bottom-line {
border-bottom: 1px solid #ddd;
padding-bottom: 0.5em;
line-height: 1.2em;
}
</style>
""", unsafe_allow_html=True)
# 変数を用いてテキストを表示
st.markdown(f"""
<div class="bottom-line">
<span style="font-size: 18px; color: black;">{line}</span><br>
</div>
""", unsafe_allow_html=True)
def chat_peep_layout():
global system_prompt, chat_log
st.title("Advanced AI Erotic Chat System")
# 2列のレイアウトを作成
col1, col2 = st.columns([5, 1]) # 比率を2:1に設定
with col2:
st.write("自動更新:")
# 画像を読み込む
image = Image.open("D:\SnackVirtual\LocalLLM\pic1.png")
# 画像を表示し、サイズを調整する
st.image(image, width=300)
reverse_chat_log = '\n'.join(chat_log.splitlines()[::-1])
with col1:
for line in reverse_chat_log.split('\n'):
if line.startswith("里穂"):
# ノートのような罫線のスタイルを定義
st.markdown("""
<style>
.bottom-line {
border-bottom: 1px solid #ddd;
padding-bottom: 0.5em;
line-height: 1.2em;
}
</style>
""", unsafe_allow_html=True)
# 変数を用いてテキストを表示
st.markdown(f"""
<div class="bottom-line">
<span style="font-size: 18px; color: red;">{line}</span><br>
</div>
""", unsafe_allow_html=True)
elif line.startswith("英樹"):
# ノートのような罫線のスタイルを定義
st.markdown("""
<style>
.bottom-line {
border-bottom: 1px solid #ddd;
padding-bottom: 0.5em;
line-height: 1.2em;
}
</style>
""", unsafe_allow_html=True)
# 変数を用いてテキストを表示
st.markdown(f"""
<div class="bottom-line">
<span style="font-size: 18px; color: blue;">{line}</span><br>
</div>
""", unsafe_allow_html=True)
else:
# ノートのような罫線のスタイルを定義
st.markdown("""
<style>
.bottom-line {
border-bottom: 1px solid #ddd;
padding-bottom: 0.5em;
line-height: 1.2em;
}
</style>
""", unsafe_allow_html=True)
# 変数を用いてテキストを表示
st.markdown(f"""
<div class="bottom-line">
<span style="font-size: 18px; color: black;">{line}</span><br>
</div>
""", unsafe_allow_html=True)
if st.session_state.layout == 0:
start_layout()
elif st.session_state.layout == 1:
loading_LLM_layout()
elif st.session_state.layout == 2:
chat_input_layout()
else:
chat_peep_layout()
所感
もうコード作成にAIは必需品である。
「ノートのような罫線を行間につけたい」
「文字の色と大きさを変えたい」
「文字列を変数にして」
などなど、考えてコード化するよりもAIに聞いた方がはるかに効率的だ。