|
import gradio as gr |
|
import random |
|
import time |
|
|
|
css = ''' |
|
.show img {height: 320px} |
|
.result img {height: 320px} |
|
.qrcode img {height: 225px} |
|
.btn { |
|
justify-content: normal |
|
} |
|
''' |
|
|
|
def get_new_question_and_options(): |
|
|
|
number = random.randint(1,65536) |
|
return { |
|
"question_text": f"问题{number}是这样的。", |
|
"option_A": f"问题{number}给出的选项A,吃饭", |
|
"option_B": f"问题{number}给出的选项B,睡觉", |
|
"option_C": f"问题{number}给出的选项C,打豆豆", |
|
} |
|
|
|
def get_option_result(question_text, option_text): |
|
|
|
numbers = [ |
|
random.randint(-10,10), |
|
random.randint(-10,10), |
|
random.randint(-10,10), |
|
random.randint(-10,10) |
|
] |
|
|
|
return { |
|
"result_text": f"问题“{question_text}”执行“{option_text}”选项,结果完成了", |
|
"score_text": f"导致四个维度增减情况为 {numbers[0]} {numbers[1]} {numbers[2]} {numbers[3]}", |
|
"deltas": numbers |
|
} |
|
|
|
def typePUA(a): |
|
|
|
x = '0' if a[0] <= 50 else '1' |
|
y = '0' if a[1] <= 50 else '1' |
|
z = '0' if a[2] <= 50 else '1' |
|
w = '0' if a[3] <= 50 else '1' |
|
|
|
puatype = ''.join([x,y,z,w]) |
|
|
|
pua = { |
|
"0000": "1 反PUA斗士", |
|
"0001": "2", |
|
"0010": "3", |
|
"0011": "4", |
|
"0100": "5", |
|
"0101": "6", |
|
"0110": "7", |
|
"0111": "8", |
|
"1000": "9", |
|
"1001": "10", |
|
"1010": "11", |
|
"1011": "12", |
|
"1100": "13", |
|
"1101": "14", |
|
"1110": "15", |
|
"1111": "16 天生牛马打工人", |
|
} |
|
|
|
return pua[puatype] |
|
|
|
with gr.Blocks(css=css).queue() as demo: |
|
|
|
data = gr.State({ |
|
"total": 3, |
|
"isComfirmed": False, |
|
"canOptionA": True, |
|
"canOptionB": True, |
|
"canOptionC": True, |
|
"canOptionD": False, |
|
"canFillD": True, |
|
"canRestart": True, |
|
"canRefresh": True, |
|
"canNext": False, |
|
}) |
|
|
|
gr.Markdown("# 😅别再PUA啦:基于多智能体的被PUA指数心理测评游戏") |
|
gr.Markdown("### 😋机智选择,远离PUA😈") |
|
|
|
with gr.Tab("测评"): |
|
|
|
with gr.Column(): |
|
with gr.Row(): |
|
with gr.Column(): |
|
|
|
hello = gr.Markdown("👇 请输入昵称") |
|
with gr.Group(): |
|
with gr.Row(): |
|
user_name = gr.Textbox(placeholder="输入您的昵称", value="", container=False, scale=6) |
|
confirm = gr.Button(value="确认", scale=1) |
|
|
|
progress_slider = gr.Slider(label=f"测评进度(共{data.value['total']}题)", value=0, minimum=0, maximum=data.value["total"], step=1, interactive=False) |
|
|
|
with gr.Column(): |
|
gr.Markdown("当前指数") |
|
with gr.Group(): |
|
with gr.Row(): |
|
dim1_slider = gr.Slider(label="维度1", value=50, minimum=0, maximum=100, step=1, interactive=False) |
|
dim2_slider = gr.Slider(label="维度2", value=50, minimum=0, maximum=100, step=1, interactive=False) |
|
with gr.Row(): |
|
dim3_slider = gr.Slider(label="维度3", value=50, minimum=0, maximum=100, step=1, interactive=False) |
|
dim4_slider = gr.Slider(label="维度4", value=50, minimum=0, maximum=100, step=1, interactive=False) |
|
|
|
gr.Markdown("---") |
|
|
|
with gr.Row(): |
|
|
|
with gr.Column(): |
|
question_text = gr.TextArea(label="事件背景", value="", placeholder="请等待生成", interactive=False, lines=4) |
|
result_text = gr.TextArea(label="事件结果", value="", placeholder="请根据事件背景,结合个人实际情况做出选择。注意,选择之间并无对错之分。", interactive=False, lines=3) |
|
score_text = gr.TextArea(label="指数变更", value="", placeholder="请根据事件背景,结合个人实际情况做出选择。注意,选择之间并无对错之分。", interactive=False, lines=3) |
|
|
|
with gr.Column(): |
|
option_A_button = gr.Button(value=f"A: ", elem_classes="btn", interactive=False) |
|
option_B_button = gr.Button(value=f"B: ", elem_classes="btn", interactive=False) |
|
option_C_button = gr.Button(value=f"C: ", elem_classes="btn", interactive=False) |
|
|
|
with gr.Group(): |
|
option_D_button = gr.Button(value="D: 我选这个", elem_classes="btn", interactive=False) |
|
option_D_text = gr.Textbox(show_label=False, value="", placeholder="我有独特的主见", container=False, interactive=False) |
|
|
|
|
|
with gr.Column(): |
|
|
|
restart = gr.Button(value="▶️ 开始", interactive=False, variant="primary") |
|
refresh = gr.Button(value="🔄️ 刷新", interactive=False) |
|
next_btn = gr.Button(value="➡️ 下一题", interactive=False) |
|
|
|
gr.Markdown("---") |
|
gr.Markdown("### 测评结果") |
|
with gr.Row(): |
|
gr.Image(elem_classes="result", value="./src/home.png", label="测评结果图示", interactive=False, scale=0.8) |
|
with gr.Group(): |
|
with gr.Row(): |
|
gr.Number(label="您的被PUA指数", value=50, interactive=False) |
|
gr.Textbox(label="您的被PUA类型", value="测评结束后生成", interactive=False, placeholder="测评结束后生成") |
|
gr.TextArea(label="您的测评结果解释", placeholder="测评结束后生成", interactive=False, lines=5) |
|
gr.TextArea(label="可能的解决方案", placeholder="测评结束后生成", interactive=False, lines=5) |
|
|
|
gr.Button(value="如果对您有用,欢迎分享网站与测评结果 🥰", variant="primary") |
|
|
|
|
|
with gr.Tab("历史"): |
|
pass |
|
|
|
|
|
with gr.Tab("说明"): |
|
pass |
|
|
|
|
|
with gr.Tab("关于"): |
|
gr.Markdown("") |
|
gr.Markdown("**Datawhale AI夏令营(第四期)x 浪潮信息 “源”大模型应用开发活动**") |
|
gr.Markdown("---") |
|
gr.Markdown("**项目名称**:别再PUA啦:基于多智能体的被PUA指数心理测评游戏") |
|
gr.Markdown("**项目Slogan**:机智选择,远离PUA") |
|
gr.Markdown("**项目简介**:“别再PUA啦”是一款创新的心理测评游戏,它基于多智能体技术,旨在通过互动游戏的形式,测量个体对PUA策略的抵抗力和识别能力,从而帮助用户提高自我保护意识和社交技巧。") |
|
gr.Markdown("**项目技术栈**:Yuan 2.0,RAG,Langchain,Muiti-Agent, Gradio") |
|
gr.Markdown("**项目演示视频**:【TODO】") |
|
gr.Markdown("**项目构建分析与复盘博客**:【TODO】") |
|
gr.Markdown("---") |
|
gr.Markdown("**作者**:胡钧耀(南开大学计算机视觉在读一年级直博生,个人研究兴趣方向为视觉AIGC)") |
|
gr.Markdown("**联系方式**:微信(LittleDream_hjy),[Bilibili](https://space.bilibili.com/2042113),[GitHub](https://github.com/JunyaoHu),[个人主页](https://junyaohu.github.io)") |
|
with gr.Row(): |
|
gr.Image(elem_classes="qrcode", value="./src/weixin.png", label="微信", height=250) |
|
gr.Image(elem_classes="qrcode", value="./src/zanshang.png", label="感谢支持", height=250) |
|
|
|
|
|
|
|
def onComfirmClick(user_name): |
|
if user_name.strip(): |
|
return f"您好,{user_name}。请根据如下提示完成测评!小心不要被 PUA 到啦 ~", gr.update(value="已确认", interactive=False), gr.update(interactive=True) |
|
else: |
|
return "👇 请输入昵称", gr.update(), gr.update() |
|
|
|
confirm.click(onComfirmClick, user_name, [hello, confirm, restart]) |
|
|
|
def onRestart(): |
|
res = get_new_question_and_options() |
|
return res["question_text"], "", "", \ |
|
gr.update(value="A: " + res["option_A"], interactive=True), \ |
|
gr.update(value="B: " + res["option_B"], interactive=True), \ |
|
gr.update(value="C: " + res["option_C"], interactive=True), \ |
|
gr.update(value="", interactive=True), \ |
|
1, 50, 50, 50, 50, gr.update(value="➡️ 下一题", interactive=False), gr.update(visible=False), gr.update(interactive=True) |
|
|
|
restart.click(onRestart, None, [ \ |
|
question_text, result_text, score_text, \ |
|
option_A_button, option_B_button, option_C_button, option_D_text, \ |
|
progress_slider, dim1_slider, dim2_slider, dim3_slider, dim4_slider, next_btn, restart, refresh]) |
|
|
|
def onRefresh(): |
|
res = get_new_question_and_options() |
|
return res["question_text"], "", "", \ |
|
gr.update(value="A: " + res["option_A"], interactive=True), \ |
|
gr.update(value="B: " + res["option_B"], interactive=True), \ |
|
gr.update(value="C: " + res["option_C"], interactive=True), \ |
|
gr.update(value="", interactive=True), \ |
|
gr.update(), gr.update(), gr.update(), gr.update(), gr.update(interactive=False), "↩️ 重新开始", gr.update(interactive=True) |
|
|
|
refresh.click(onRefresh, None, [ \ |
|
question_text, result_text, score_text, \ |
|
option_A_button, option_B_button, option_C_button, option_D_text, \ |
|
dim1_slider, dim2_slider, dim3_slider, dim4_slider, next_btn, restart, refresh]) |
|
|
|
def onNext(progress_slider): |
|
if progress_slider == data.value['total']: |
|
return "", "", "", \ |
|
gr.update(value="A: 查看测评结果", interactive=False), \ |
|
gr.update(value="B: 查看测评结果", interactive=False), \ |
|
gr.update(value="C: 查看测评结果", interactive=False), \ |
|
gr.update(value="", interactive=False), \ |
|
progress_slider, gr.update(interactive=False), "↩️ 重新开始", gr.update(interactive=False) |
|
else: |
|
res = get_new_question_and_options() |
|
return res["question_text"], "", "", \ |
|
gr.update(value="A: " + res["option_A"], interactive=True), \ |
|
gr.update(value="B: " + res["option_B"], interactive=True), \ |
|
gr.update(value="C: " + res["option_C"], interactive=True), \ |
|
gr.update(value="", interactive=True), \ |
|
progress_slider+1, gr.update(interactive=False), "↩️ 重新开始", gr.update(interactive=True) |
|
|
|
next_btn.click(onNext, progress_slider, [ \ |
|
question_text, result_text, score_text, \ |
|
option_A_button, option_B_button, option_C_button, option_D_text, \ |
|
progress_slider, next_btn, restart, refresh]) |
|
|
|
def onClickABC(btn, question_text, progress_slider, dim1_slider, dim2_slider, dim3_slider, dim4_slider): |
|
option_text = btn[3:] |
|
res = get_option_result(question_text, option_text) |
|
|
|
dim1_slider = max(min(dim1_slider + res["deltas"][0], 100), -100) |
|
dim2_slider = max(min(dim2_slider + res["deltas"][1], 100), -100) |
|
dim3_slider = max(min(dim3_slider + res["deltas"][2], 100), -100) |
|
dim4_slider = max(min(dim4_slider + res["deltas"][3], 100), -100) |
|
|
|
if progress_slider == data.value['total']: |
|
text = "✨查看结果" |
|
else: |
|
text = "➡️ 下一题" |
|
|
|
print(res["result_text"], res["score_text"], dim1_slider, dim2_slider, dim3_slider, dim4_slider, text) |
|
return res["result_text"], res["score_text"], dim1_slider, dim2_slider, dim3_slider, dim4_slider, gr.update(value=text, interactive=True), gr.update(value="↩️ 重新开始", visible=True), gr.update(interactive=False), \ |
|
gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False) |
|
|
|
option_A_button.click(onClickABC, \ |
|
[option_A_button, question_text, progress_slider, dim1_slider, dim2_slider, dim3_slider, dim4_slider], \ |
|
[result_text, score_text, dim1_slider, dim2_slider, dim3_slider, dim4_slider, next_btn, restart, refresh, \ |
|
option_A_button, option_B_button, option_C_button, option_D_button, option_D_text]) |
|
option_B_button.click(onClickABC, \ |
|
[option_B_button, question_text, progress_slider, dim1_slider, dim2_slider, dim3_slider, dim4_slider], \ |
|
[result_text, score_text, dim1_slider, dim2_slider, dim3_slider, dim4_slider, next_btn, restart, refresh, \ |
|
option_A_button, option_B_button, option_C_button, option_D_button, option_D_text]) |
|
option_C_button.click(onClickABC, \ |
|
[option_C_button, question_text, progress_slider, dim1_slider, dim2_slider, dim3_slider, dim4_slider], \ |
|
[result_text, score_text, dim1_slider, dim2_slider, dim3_slider, dim4_slider, next_btn, restart, refresh, \ |
|
option_A_button, option_B_button, option_C_button, option_D_button, option_D_text]) |
|
|
|
def onClickD(option_D_text, question_text, progress_slider, dim1_slider, dim2_slider, dim3_slider, dim4_slider): |
|
res = get_option_result(question_text, option_D_text) |
|
|
|
dim1_slider = max(min(dim1_slider + res["deltas"][0], 100), -100) |
|
dim2_slider = max(min(dim2_slider + res["deltas"][1], 100), -100) |
|
dim3_slider = max(min(dim3_slider + res["deltas"][2], 100), -100) |
|
dim4_slider = max(min(dim4_slider + res["deltas"][3], 100), -100) |
|
|
|
if progress_slider == data.value["total"]: |
|
text = "✨查看结果" |
|
else: |
|
text = "➡️ 下一题" |
|
|
|
print(res["result_text"], res["score_text"], dim1_slider, dim2_slider, dim3_slider, dim4_slider, text) |
|
return res["result_text"], res["score_text"], dim1_slider, dim2_slider, dim3_slider, dim4_slider, gr.update(value=text, interactive=True), gr.update(value="↩️ 重新开始", visible=True), gr.update(interactive=False), \ |
|
gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False), gr.update(interactive=False) |
|
|
|
option_D_button.click(onClickD, \ |
|
[option_D_text , question_text, progress_slider, dim1_slider, dim2_slider, dim3_slider, dim4_slider], \ |
|
[result_text, score_text, dim1_slider, dim2_slider, dim3_slider, dim4_slider, next_btn, restart, refresh, \ |
|
option_A_button, option_B_button, option_C_button, option_D_button, option_D_text]) |
|
|
|
def onChangeD(option_D_text): |
|
if option_D_text.strip(): |
|
return gr.update(interactive=True) |
|
else: |
|
return gr.update(interactive=False) |
|
|
|
option_D_text.change(onChangeD, option_D_text, option_D_button) |
|
|
|
if __name__ == "__main__": |
|
|
|
demo.launch(share=True) |