File size: 5,272 Bytes
cb245e5
226a535
cb245e5
 
226a535
cb245e5
 
 
 
 
 
 
 
 
 
 
 
 
 
226a535
cb245e5
 
 
 
 
 
 
 
 
226a535
cb245e5
 
 
 
 
 
 
 
 
 
 
 
 
226a535
cb245e5
 
ad0c832
 
 
 
cb245e5
 
ad0c832
 
 
cb245e5
226a535
cb245e5
 
 
 
 
 
 
 
 
 
 
 
226a535
cb245e5
 
 
 
 
 
 
 
 
 
226a535
cb245e5
 
 
 
 
226a535
cb245e5
 
 
 
 
 
 
226a535
cb245e5
 
 
 
 
 
226a535
cb245e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226a535
cb245e5
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
119
120
121
122
123
124
125
126
127
128
129
# ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
import gradio as gr
import google.generativeai as genai
import os

# --- UI ๋ฐ ์ฑ—๋ด‡ ์„ค๋ช… ---
# Gradio Blocks๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ข€ ๋” ์œ ์—ฐํ•œ UI๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
with gr.Blocks(theme=gr.themes.Default(primary_hue="blue")) as demo:
    gr.Markdown(
        """
        # โ™Š๏ธ Gemini API ์ฑ—๋ด‡ (Secrets ์‚ฌ์šฉ)
        Google Gemini API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฑ—๋ด‡์ž…๋‹ˆ๋‹ค. 
        Hugging Face Spaces์˜ 'Settings' ํƒญ์— ์žˆ๋Š” 'Repository secrets'์— `GEMINI_API_KEY`๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
        [API ํ‚ค ๋ฐœ๊ธ‰๋ฐ›๊ธฐ](https://aistudio.google.com/app/apikey)
        """
    )
    
    # Gradio ์ฑ—๋ด‡ UI ์ปดํฌ๋„ŒํŠธ
    chatbot = gr.Chatbot(label="Gemini ์ฑ—๋ด‡", height=600)

    with gr.Row():
        # ์‚ฌ์šฉ์ž ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ๋ž€
        msg = gr.Textbox(
            label="๋ฉ”์‹œ์ง€ ์ž…๋ ฅ",
            placeholder="๋ฌด์—‡์ด๋“  ๋ฌผ์–ด๋ณด์„ธ์š”...",
            scale=7,
        )
        # ์ „์†ก ๋ฒ„ํŠผ
        submit_button = gr.Button("์ „์†ก", variant="primary", scale=1)

    with gr.Accordion("๊ณ ๊ธ‰ ์„ค์ •", open=False):
        # LLM์˜ ์—ญํ• ์„ ์ •์˜ํ•˜๋Š” ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€
        system_message = gr.Textbox(
            value="You are a helpful and friendly chatbot.", label="์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€"
        )
        # ๋ชจ๋ธ์˜ ์ฐฝ์˜์„ฑ์„ ์กฐ์ ˆํ•˜๋Š” ์Šฌ๋ผ์ด๋”
        temperature = gr.Slider(
            minimum=0.0, maximum=1.0, value=0.7, step=0.1, label="Temperature"
        )
        # ์ƒ์„ฑํ•  ์ตœ๋Œ€ ํ† ํฐ ์ˆ˜๋ฅผ ์กฐ์ ˆํ•˜๋Š” ์Šฌ๋ผ์ด๋”
        max_tokens = gr.Slider(
            minimum=1, maximum=4096, value=1024, step=1, label="Max new tokens"
        )

    # --- Gemini API ํ˜ธ์ถœ ํ•จ์ˆ˜ ---
    def respond(message, chat_history, system_prompt, temp, max_output_tokens):
        # ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ API ํ‚ค๋ฅผ ์ง์ ‘ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
        # ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ฑ ์‹œ์ž‘ ์‹œ์ ์— ํ‚ค๋ฅผ ๋ชป ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
        GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")

        # ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ ๊ฐ€์ ธ์˜จ API ํ‚ค๊ฐ€ ์—†์œผ๋ฉด ์•ˆ๋‚ด ๋ฉ”์‹œ์ง€๋ฅผ ๋„์›๋‹ˆ๋‹ค.
        if not GEMINI_API_KEY:
            # UI์— ์ง์ ‘ ๊ฒฝ๊ณ ๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด gr.Warning์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ,
            # ์—ฌ๊ธฐ์„œ๋Š” ์ฑ„ํŒ… ์‘๋‹ต์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
            yield "โš ๏ธ **์˜ค๋ฅ˜**: `GEMINI_API_KEY`๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.\n\nHugging Face Spaces์˜ **Settings > Repository secrets**์— API ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋Š”์ง€ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
            return

        try:
            # API ํ‚ค๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
            genai.configure(api_key=GEMINI_API_KEY)
        except Exception as e:
            yield f"API ํ‚ค ์„ค์ •์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}"
            return
        
        # ์‚ฌ์šฉํ•  ๋ชจ๋ธ๊ณผ ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
        model = genai.GenerativeModel(
            model_name='gemini-2.0-flash', # ์ตœ์‹  Flash ๋ชจ๋ธ ์‚ฌ์šฉ
            system_instruction=system_prompt
        )

        # Gradio์˜ ๋Œ€ํ™” ๊ธฐ๋ก์„ Gemini API๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
        gemini_history = []
        for user_msg, model_msg in chat_history:
            if user_msg:
                gemini_history.append({"role": "user", "parts": [user_msg]})
            if model_msg:
                gemini_history.append({"role": "model", "parts": [model_msg]})
            
        # ์ด์ „ ๋Œ€ํ™” ๊ธฐ๋ก์„ ๋ฐ”ํƒ•์œผ๋กœ ์ฑ„ํŒ… ์„ธ์…˜์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
        chat = model.start_chat(history=gemini_history)

        # ๋ชจ๋ธ ์ƒ์„ฑ ๊ด€๋ จ ์„ค์ •์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
        generation_config = genai.types.GenerationConfig(
            temperature=temp,
            max_output_tokens=int(max_output_tokens),
        )

        try:
            # ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
            response = chat.send_message(
                message, 
                stream=True, 
                generation_config=generation_config
            )

            # ์ŠคํŠธ๋ฆฌ๋ฐ ์‘๋‹ต์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ UI์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
            full_response = ""
            for chunk in response:
                if hasattr(chunk, 'text'):
                    full_response += chunk.text
                    yield full_response

        except Exception as e:
            # API ํ˜ธ์ถœ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด UI์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
            yield f"์‘๋‹ต ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}"

    # --- Gradio ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ---
    def on_submit(message, chat_history, system_prompt, temp, max_output_tokens):
        chat_history.append((message, None))
        bot_response_stream = respond(message, chat_history, system_prompt, temp, max_output_tokens)
        
        for partial_response in bot_response_stream:
            chat_history[-1] = (message, partial_response)
            yield "", chat_history
    
    msg.submit(
        on_submit, 
        [msg, chatbot, system_message, temperature, max_tokens], 
        [msg, chatbot]
    )
    submit_button.click(
        on_submit, 
        [msg, chatbot, system_message, temperature, max_tokens], 
        [msg, chatbot]
    )

if __name__ == "__main__":
    demo.launch(debug=True)