File size: 6,119 Bytes
b834a1c
 
 
 
 
f6fcf86
b834a1c
 
 
 
 
 
 
65d76f2
b834a1c
65d76f2
b834a1c
 
 
65d76f2
b834a1c
 
 
65d76f2
b834a1c
 
65d76f2
b834a1c
 
 
 
 
65d76f2
 
 
b834a1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65d76f2
 
 
 
 
b834a1c
 
65d76f2
 
 
 
 
b834a1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65d76f2
b834a1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65d76f2
b834a1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65d76f2
 
 
b834a1c
65d76f2
 
 
 
 
b834a1c
 
65d76f2
 
b834a1c
65d76f2
 
 
 
 
b834a1c
 
65d76f2
b834a1c
 
65d76f2
b834a1c
65d76f2
b834a1c
 
 
 
65d76f2
b834a1c
 
 
 
 
65d76f2
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
import os
import gradio as gr
from openai import OpenAI

# Lấy API key từ environment variable hoặc sử dụng default
API_KEY = os.getenv("HF_API_KEY")

# Khởi tạo OpenAI client với HuggingFace Router
client = OpenAI(
    base_url="https://router.huggingface.co/v1",
    api_key=API_KEY,
)

def predict(message, history, temperature, max_tokens):
    """
    Hàm xử lý tin nhắn và trả về response từ model

    Args:
        message: Tin nhắn mới từ người dùng
        history: Lịch sử hội thoại (Gradio messages format)
        temperature: Độ sáng tạo của model (0.0 - 1.0)
        max_tokens: Số token tối đa trong response
    """
    # Chuyển đổi history sang format OpenAI
    messages = []

    # Thêm system message để model hiểu vai trò của mình
    messages.append({
        "role": "system",
        "content": "Bạn là một trợ lý y tế AI chuyên nghiệp, được đào tạo để cung cấp thông tin y khoa chính xác và hữu ích. Hãy trả lời bằng tiếng Việt một cách rõ ràng, chi tiết và dễ hiểu."
    })

    # Thêm lịch sử hội thoại (Gradio messages format)
    for msg in history:
        messages.append({"role": msg["role"], "content": msg["content"]})

    # Thêm tin nhắn mới
    messages.append({"role": "user", "content": message})

    # Gọi API với streaming
    try:
        stream = client.chat.completions.create(
            model="m42-health/Llama3-Med42-70B:featherless-ai",
            messages=messages,
            temperature=temperature,
            max_tokens=max_tokens,
            stream=True,
        )

        # Stream response từng phần
        partial_response = ""
        for chunk in stream:
            if chunk.choices[0].delta.content:
                partial_response += chunk.choices[0].delta.content
                # Yield full history với response hiện tại
                yield history + [
                    {"role": "user", "content": message},
                    {"role": "assistant", "content": partial_response}
                ]

    except Exception as e:
        error_msg = f"❌ Lỗi: {str(e)}\n\nVui lòng kiểm tra lại API key hoặc kết nối mạng."
        yield history + [
            {"role": "user", "content": message},
            {"role": "assistant", "content": error_msg}
        ]

# Tạo giao diện Gradio
with gr.Blocks(
    theme=gr.themes.Soft(),
    title="Med42-70B Medical Assistant",
    css="""
        .gradio-container {
            font-family: 'Arial', sans-serif;
        }
        footer {
            visibility: hidden;
        }
    """
) as demo:

    gr.Markdown(
        """
        # 🏥 Med42-70B Medical Assistant

        Trợ lý y tế AI được hỗ trợ bởi **Llama3-Med42-70B** - một mô hình ngôn ngữ lớn chuyên biệt cho lĩnh vực y tế.

        💡 **Lưu ý:** Thông tin được cung cấp chỉ mang tính chất tham khảo. Vui lòng tham khảo ý kiến bác sĩ chuyên khoa để được chẩn đoán và điều trị chính xác.
        """
    )

    with gr.Row():
        with gr.Column(scale=4):
            chatbot = gr.Chatbot(
                height=500,
                show_label=False,
                avatar_images=(None, "🤖"),
                type='messages',
            )

        with gr.Column(scale=1):
            gr.Markdown("### ⚙️ Cài đặt")

            temperature = gr.Slider(
                minimum=0.0,
                maximum=1.0,
                value=0.7,
                step=0.1,
                label="Temperature",
                info="Độ sáng tạo (thấp = chính xác hơn, cao = đa dạng hơn)"
            )

            max_tokens = gr.Slider(
                minimum=128,
                maximum=2048,
                value=1024,
                step=128,
                label="Max Tokens",
                info="Độ dài tối đa của câu trả lời"
            )

            gr.Markdown("---")
            gr.Markdown(
                """
                ### 📝 Gợi ý câu hỏi:
                - Triệu chứng và cách điều trị bệnh tiểu đường
                - Cách phòng ngừa bệnh tim mạch
                - Chế độ ăn uống cho người huyết áp cao
                - Tác dụng phụ của thuốc X
                - Cách chăm sóc vết thương
                """
            )

    with gr.Row():
        msg = gr.Textbox(
            placeholder="Nhập câu hỏi của bạn về y tế...",
            show_label=False,
            scale=4,
            container=False
        )
        submit_btn = gr.Button("Gửi", variant="primary", scale=1)

    with gr.Row():
        clear_btn = gr.Button("🗑️ Xóa lịch sử", variant="secondary")
        retry_btn = gr.Button("🔄 Thử lại", variant="secondary")

    gr.Markdown(
        """
        ---
        <div style="text-align: center; color: #666; font-size: 0.9em;">
            Powered by <strong>Llama3-Med42-70B</strong> via HuggingFace Router |
            Built with ❤️ using <strong>Gradio</strong>
        </div>
        """
    )

    # Xử lý sự kiện
    msg.submit(
        predict,
        inputs=[msg, chatbot, temperature, max_tokens],
        outputs=chatbot
    ).then(
        lambda: gr.update(value=""),
        None,
        [msg]
    )

    submit_btn.click(
        predict,
        inputs=[msg, chatbot, temperature, max_tokens],
        outputs=chatbot
    ).then(
        lambda: gr.update(value=""),
        None,
        [msg]
    )

    clear_btn.click(lambda: None, None, chatbot, queue=False)

    retry_btn.click(
        lambda history: history[:-1] if history else history,
        inputs=[chatbot],
        outputs=[chatbot]
    )

# Khởi chạy ứng dụng
if __name__ == "__main__":
    demo.queue()  # Enable queuing for streaming
    demo.launch(
        share=False,
        server_name="0.0.0.0",  # Cho phép truy cập từ bên ngoài
        server_port=7860,
    )