File size: 5,258 Bytes
2249ab6
bbb241c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2249ab6
 
 
 
 
 
 
 
 
 
 
 
bbb241c
2249ab6
 
 
bbb241c
2249ab6
 
bbb241c
2249ab6
 
bbb241c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1e828d1
bbb241c
 
 
 
2249ab6
 
 
 
 
 
bbb241c
 
 
 
 
 
 
 
 
 
 
 
 
2249ab6
bbb241c
2249ab6
bbb241c
 
 
 
 
2249ab6
 
bbb241c
2249ab6
bbb241c
2249ab6
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import gradio as gr
from .case_loader import load_case, run_case

# ์‹œ์—ฐ์šฉ ์ผ€์ด์Šค ์ด๋ฆ„ ํ•˜๋“œ์ฝ”๋”ฉ
CASE_NAMES = [
    "ํ๊ณต์žฅ์—์„œ NPC์™€ ๋Œ€ํ™”ํ•˜๋Š” ์žฅ๋ฉด",
    "๋งˆ์„ ๋Œ€์žฅ์žฅ์ด์™€ ๋ฌด๊ธฐ ์ˆ˜๋ฆฌ์— ๋Œ€ํ•ด ๋Œ€ํ™”ํ•˜๋Š” ์žฅ๋ฉด",
    "์ˆฒ์† ์€๋‘”์ž์™€ ํฌ๊ท€ ์•ฝ์ดˆ์— ๋Œ€ํ•ด ๋Œ€ํ™”ํ•˜๋Š” ์žฅ๋ฉด",
    "ํ•ญ๊ตฌ ๊ด€๋ฆฌ๊ด€๊ณผ ์ถœํ•ญ ํ—ˆ๊ฐ€์— ๋Œ€ํ•ด ๋Œ€ํ™”ํ•˜๋Š” ์žฅ๋ฉด",
    "๋งˆ๋ฒ•์‚ฌ ๊ฒฌ์Šต์ƒ๊ณผ ๊ณ ๋Œ€ ์ฃผ๋ฌธ์„œ์— ๋Œ€ํ•ด ๋Œ€ํ™”ํ•˜๋Š” ์žฅ๋ฉด"
]

def format_case_info(case: dict) -> dict:
    """์ผ€์ด์Šค ์ •๋ณด๋ฅผ ๋ณด๊ธฐ ์ข‹๊ฒŒ ์ •๋ฆฌํ•ด์„œ ๋ฐ˜ํ™˜"""
    inp = case["input"]
    tags = inp.get("tags", {})
    context_lines = [f"{h['role'].upper()}: {h['text']}" for h in inp.get("context", [])]

    return {
        "npc_id": inp.get("npc_id", ""),
        "npc_location": inp.get("npc_location", ""),
        "quest_stage": tags.get("quest_stage", ""),
        "relationship": tags.get("relationship", ""),
        "trust": tags.get("trust", ""),
        "npc_mood": tags.get("npc_mood", ""),
        "player_reputation": tags.get("player_reputation", ""),
        "style": tags.get("style", ""),
        "lore": inp.get("lore", ""),
        "description": inp.get("description", ""),
        "player_state": inp.get("player_state", {}),
        "context": "\n".join(context_lines),
        "player_utterance": inp.get("player_utterance", "")
    }

def build_ui():
    with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="purple")) as demo:
        gr.Markdown("""
        # ๐Ÿ‘พ PersonaChatEngine HF-Serve
        **๊ฒŒ์ž„ ๋‚ด NPC ๋ฉ”์ธ ๋ชจ๋ธ ์ถ”๋ก  ์„œ๋ฒ„**  
        Qwen 3B ๊ธฐ๋ฐ˜ LoRA ํŒŒ์ธํŠœ๋‹ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ NPC ๋Œ€์‚ฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
        """)

        with gr.Row():
            gr.Button("๐Ÿ“„ ์ƒ์„ธ ๋ฌธ์„œ ๋ณด๊ธฐ",
                      link="https://huggingface.co/spaces/m97j/PersonaChatEngine_HF-serve/blob/main/README.md")
            gr.Button("๐Ÿ’ป Colab ๋…ธํŠธ๋ถ ์—ด๊ธฐ",
                      link="https://colab.research.google.com/drive/1_-qH8kdoU2Jj58TdaSnswHex-BFefInq?usp=sharing#scrollTo=cFJGv8BJ8oPD")

        gr.Markdown("### ๐ŸŽฏ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ๊ธฐ๋ฐ˜ ๊ฐ„๋‹จ ์‹คํ–‰")
        gr.Markdown("โš ๏ธ ์ถ”๋ก ์—๋Š” ์ˆ˜ ์ดˆ ~ ์ตœ๋Œ€ 1๋ถ„ ์ •๋„ ์†Œ์š”๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ๋งŒ ๊ธฐ๋‹ค๋ ค์ฃผ์„ธ์š”.")

        with gr.Row():
            case_dropdown = gr.Dropdown(choices=CASE_NAMES, label="ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์„ ํƒ", value=CASE_NAMES[0])
            load_btn = gr.Button("์ผ€์ด์Šค ๋ถˆ๋Ÿฌ์˜ค๊ธฐ")

        # ์ผ€์ด์Šค ์ •๋ณด ํ‘œ์‹œ ์˜์—ญ
        with gr.Row():
            with gr.Column():
                npc_id = gr.Textbox(label="NPC ID", interactive=False)
                npc_loc = gr.Textbox(label="NPC Location", interactive=False)
                quest_stage = gr.Textbox(label="Quest Stage", interactive=False)
                relationship = gr.Textbox(label="Relationship", interactive=False)
                trust = gr.Textbox(label="Trust", interactive=False)
                npc_mood = gr.Textbox(label="NPC Mood", interactive=False)
                player_rep = gr.Textbox(label="Player Reputation", interactive=False)
                style = gr.Textbox(label="Style", interactive=False)

            with gr.Column():
                lore = gr.Textbox(label="Lore", lines=3, interactive=False)
                desc = gr.Textbox(label="Description", lines=3, interactive=False)
                player_state = gr.JSON(label="Player State")
                context = gr.Textbox(label="Context", lines=6, interactive=False)

        # Player Utterance๋Š” ๋ณ„๋„ ์ž…๋ ฅ์ฐฝ
        player_input = gr.Textbox(label="Player Utterance", lines=2)

        run_btn = gr.Button("๐Ÿš€ Run Inference", variant="primary")
        npc_resp = gr.Textbox(label="NPC Response")
        deltas = gr.JSON(label="Deltas")
        flags = gr.JSON(label="Flags Probabilities")

        # ์ผ€์ด์Šค ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋™์ž‘
        def on_load_case(name):
            idx = CASE_NAMES.index(name)
            case = load_case(idx)  # TEST_CASES ์ง์ ‘ ์ ‘๊ทผ ๋Œ€์‹  load_case ์‚ฌ์šฉ
            info = format_case_info(case)
            return (
                info["npc_id"], info["npc_location"], info["quest_stage"],
                info["relationship"], info["trust"], info["npc_mood"],
                info["player_reputation"], info["style"], info["lore"],
                info["description"], info["player_state"], info["context"],
                info["player_utterance"]
            )

        load_btn.click(
            fn=on_load_case,
            inputs=[case_dropdown],
            outputs=[
                npc_id, npc_loc, quest_stage, relationship, trust,
                npc_mood, player_rep, style, lore, desc, player_state, context,
                player_input
            ]
        )

        # ์ถ”๋ก  ์‹คํ–‰
        run_btn.click(
            fn=lambda name, utt: run_case(CASE_NAMES.index(name), utt),
            inputs=[case_dropdown, player_input],
            outputs=[npc_resp, deltas, flags]
        )

        gr.Markdown("""
        ---
        โš ๏ธ **์‹ค์ œ ๊ฒŒ์ž„ ํŒŒ์ดํ”„๋ผ์ธ ํ…Œ์ŠคํŠธ**๋Š” [ai-server Swagger](https://huggingface.co/spaces/m97j/PersonaChatEngine_ai_server)์—์„œ ์ง„ํ–‰ํ•˜์„ธ์š”.
        """)

    return demo