diff --git a/examples/game/app.py b/examples/game/app.py
index a174cafda..d015c2fea 100644
--- a/examples/game/app.py
+++ b/examples/game/app.py
@@ -24,6 +24,36 @@
glb_history_chat = []
MAX_NUM_DISPLAY_MSG = 20
+import base64
+# 图片本地路径转换为 base64 格式
+def covert_image_to_base64(image_path):
+ # 获得文件后缀名
+ ext = image_path.split('.')[-1]
+ if ext not in ['gif', 'jpeg', 'png']:
+ ext = 'jpeg'
+
+ with open(image_path, 'rb') as image_file:
+ # Read the file
+ encoded_string = base64.b64encode(image_file.read())
+
+ # Convert bytes to string
+ base64_data = encoded_string.decode('utf-8')
+
+ # 生成base64编码的地址
+ base64_url = f'data:image/{ext};base64,{base64_data}'
+ return base64_url
+
+def format_cover_html(config: dict, bot_avatar_path='assets/bg.png'):
+ image_src = covert_image_to_base64(bot_avatar_path)
+ return f"""
+
+
+
+
+
{config.get("name", "经营餐厅")}
+
{config.get("description", "快来经营你的餐厅吧")}
+
+"""
def export_chat_history():
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
@@ -74,11 +104,26 @@ def start_game():
except ResetException:
print("重置成功")
- with gr.Blocks() as demo:
+ with gr.Blocks(css='assets/app.css') as demo:
# Users can select the interested exp
+ welcome = {
+ "name": "饮食男女",
+ "description": "这是一款模拟餐馆经营的文字冒险游戏, 快来开始吧😊"
+ }
+
+ user_chat_bot_cover = gr.HTML(format_cover_html(welcome))
+ chatbot = GroupChat(label="Dialog", show_label=False, height=600, visible=False)
+
with gr.Row():
- chatbot = GroupChat(label="Dialog", show_label=False, height=600)
+ with gr.Column():
+ new_button = gr.Button(
+ value="🚀新的探险",
+ )
+ with gr.Column():
+ resume_button = gr.Button(
+ value="🔥续写情缘",
+ )
with gr.Row():
with gr.Column():
@@ -87,13 +132,14 @@ def start_game():
placeholder="想说点什么",
show_label=False,
interactive=True,
+ visible=False,
)
user_chat_bot_suggest = gr.Dataset(
label="选择一个",
components=[user_chat_input],
samples=[],
- visible=True,
+ visible=False,
)
user_chat_bot_suggest.select(
@@ -104,17 +150,21 @@ def start_game():
with gr.Column():
send_button = gr.Button(
- value="发送",
+ value="📣发送",
+ visible=False
)
- with gr.Accordion("导出选项", open=False):
+ export = gr.Accordion("导出选项", open=False, visible=False)
+ with export:
with gr.Column():
export_button = gr.Button("导出完整游戏记录")
export_output = gr.File(label="下载完整游戏记录", visible=False)
- reset_button = gr.Button(
- value="重置",
- )
+ return_welcome_button = gr.Button(
+ value="↩️返回首页",
+ visible=False,
+ )
+
def send_message(msg):
send_player_input(msg)
send_chat_msg(msg, "你")
@@ -143,14 +193,60 @@ def update_suggest():
visible=True,
)
- outputs = [chatbot, user_chat_bot_suggest]
+ def game_ui():
+ visible = True
+ invisible = False
+ return {chatbot:GroupChat(visible=visible),
+ user_chat_input: gr.Text(visible=visible),
+ send_button: gr.Button(visible=visible),
+ new_button: gr.Button(visible=invisible),
+ resume_button: gr.Button(visible=invisible),
+ return_welcome_button: gr.Button(visible=visible),
+ user_chat_bot_suggest: gr.Dataset(
+ components=[user_chat_input],
+ visible=visible,
+ ),
+ export: gr.Accordion(visible=visible),
+ user_chat_bot_cover:gr.HTML(visible=invisible)}
+
+ def welcome_ui():
+ visible = True
+ invisible = False
+ return {chatbot:GroupChat(visible=invisible),
+ user_chat_input: gr.Text(visible=invisible),
+ send_button: gr.Button(visible=invisible),
+ new_button: gr.Button(visible=visible),
+ resume_button: gr.Button(visible=visible),
+ return_welcome_button: gr.Button(visible=invisible),
+ user_chat_bot_suggest: gr.Dataset(
+ components=[user_chat_input],
+ visible=invisible,
+ ),
+ export: gr.Accordion(visible=invisible),
+ user_chat_bot_cover:gr.HTML(visible=visible)}
+
+ outputs = [chatbot, user_chat_input, send_button, new_button, resume_button,return_welcome_button, user_chat_bot_suggest, export, user_chat_bot_cover]
+
+ # submit message
send_button.click(send_message, user_chat_input, user_chat_input)
- reset_button.click(send_reset_message)
- export_button.click(export_chat_history, [], export_output)
user_chat_input.submit(send_message, user_chat_input, user_chat_input)
- demo.load(get_chat, inputs=None, outputs=chatbot, every=0.5)
+
+ # change ui
+ new_button.click(game_ui, outputs=outputs)
+ resume_button.click(game_ui, outputs=outputs)
+ return_welcome_button.click(welcome_ui, outputs=outputs)
+
+ # start game
+ new_button.click(send_reset_message)
+ new_button.click(start_game)
+ resume_button.click(start_game)
+
+ # export
+ export_button.click(export_chat_history, [], export_output)
+
+ # update chat history
+ demo.load(get_chat, outputs=chatbot, every=0.5)
demo.load(update_suggest, outputs=user_chat_bot_suggest, every=0.5)
- demo.load(start_game)
demo.queue()
demo.launch()
diff --git a/examples/game/assets/app.css b/examples/game/assets/app.css
new file mode 100644
index 000000000..93b031c74
--- /dev/null
+++ b/examples/game/assets/app.css
@@ -0,0 +1,147 @@
+/* code highlight: https://python-markdown.github.io/extensions/code_hilite/ */
+.codehilite .hll { background-color: #ffffcc }
+.codehilite { background: #f8f8f8; }
+.codehilite .c { color: #408080; font-style: italic } /* Comment */
+.codehilite .err { border: 1px solid #FF0000 } /* Error */
+.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
+.codehilite .o { color: #666666 } /* Operator */
+.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
+.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
+.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
+.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
+.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
+.codehilite .gd { color: #A00000 } /* Generic.Deleted */
+.codehilite .ge { font-style: italic } /* Generic.Emph */
+.codehilite .gr { color: #FF0000 } /* Generic.Error */
+.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.codehilite .gi { color: #00A000 } /* Generic.Inserted */
+.codehilite .go { color: #888888 } /* Generic.Output */
+.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.codehilite .gs { font-weight: bold } /* Generic.Strong */
+.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.codehilite .gt { color: #0044DD } /* Generic.Traceback */
+.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
+.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.codehilite .kt { color: #B00040 } /* Keyword.Type */
+.codehilite .m { color: #666666 } /* Literal.Number */
+.codehilite .s { color: #BA2121 } /* Literal.String */
+.codehilite .na { color: #7D9029 } /* Name.Attribute */
+.codehilite .nb { color: #008000 } /* Name.Builtin */
+.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.codehilite .no { color: #880000 } /* Name.Constant */
+.codehilite .nd { color: #AA22FF } /* Name.Decorator */
+.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
+.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+.codehilite .nf { color: #0000FF } /* Name.Function */
+.codehilite .nl { color: #A0A000 } /* Name.Label */
+.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
+.codehilite .nv { color: #19177C } /* Name.Variable */
+.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
+.codehilite .mb { color: #666666 } /* Literal.Number.Bin */
+.codehilite .mf { color: #666666 } /* Literal.Number.Float */
+.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
+.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
+.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
+.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
+.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
+.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
+.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
+.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
+.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
+.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+.codehilite .sx { color: #008000 } /* Literal.String.Other */
+.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
+.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
+.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
+.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
+.codehilite .fm { color: #0000FF } /* Name.Function.Magic */
+.codehilite .vc { color: #19177C } /* Name.Variable.Class */
+.codehilite .vg { color: #19177C } /* Name.Variable.Global */
+.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
+.codehilite .vm { color: #19177C } /* Name.Variable.Magic */
+.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
+
+.preview_header {
+ font-size: 18px;
+ font-weight: 500;
+ text-align: center;
+ margin-bottom: -12px;
+}
+
+.bot_cover {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ min-height: 650px;
+ border: 1px solid rgb(229, 231, 235);
+ border-radius: 8px;
+ padding: 20px 40px;
+}
+
+.bot_avatar {
+ width: 100px;
+ height: 100px;
+ border-radius: 50%;
+ overflow: hidden;
+}
+
+.bot_avatar img {
+ width: 150px;
+ height: 150px;
+}
+
+.bot_name {
+ font-size: 36px;
+ margin-top: 10px;
+}
+
+.bot_desc {
+ color: #ddd;
+}
+
+.publish_link_container > a {
+ display: block;
+ border-radius: var(--button-large-radius);
+ padding: var(--button-large-padding);
+ font-weight: var(--button-large-text-weight);
+ font-size: var(--button-large-text-size);
+ border: var(--button-border-width) solid var(--button-secondary-border-color);
+ background: var(--button-secondary-background-fill);
+ color: var(--button-secondary-text-color) !important;
+ cursor: pointer;
+ text-decoration: none !important;
+ text-align: center;
+}
+
+.publish_link_container > .disabled {
+ cursor: not-allowed;
+ opacity: .5;
+ filter: grayscale(30%);
+}
+
+.markdown-body .message {
+ white-space: pre-wrap;
+}
+
+.markdown-body details {
+ white-space: nowrap;
+}
+.markdown-body .bot details:not(:last-child) {
+ margin-bottom: 1px;
+}
+.markdown-body summary {
+ background-color: #4b5563;
+ color: #eee;
+ padding: 0 4px;
+ border-radius: 4px;
+ font-size: 0.9em;
+}
diff --git a/examples/game/assets/bg.png b/examples/game/assets/bg.png
new file mode 100644
index 000000000..ffb0ca21e
Binary files /dev/null and b/examples/game/assets/bg.png differ