Spaces:
Runtime error
Runtime error
File size: 7,086 Bytes
6efc50c 272b97f 6efc50c 0efc7f3 6efc50c |
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 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
import os
import torch
import gradio as gr
from transformers import AutoTokenizer, AutoModelForCausalLM
# ========= 基本設定 =========
# 你的模型 repo id(目前是 private 也沒關係)
MODEL_ID = "aciang/mistral7b-tk-sft-20251019-merged"
# 若模型是 private,建議在 Space 的「Settings → Repository secrets」加上 HF_TOKEN
HF_TOKEN = os.getenv("HF_TOKEN", None)
# 建議預設的「傳統知識」系統提示,可以在介面中修改
DEFAULT_SYSTEM_PROMPT = """你是一位熟悉台灣與國際原住民族傳統知識的學者,
擅長用淺顯但尊重文化脈絡的繁體中文說明各族的夢境、儀式、宇宙觀、傳統醫療與環境知識。
回答原則:
1. 先簡短摘要重點(3–5 點條列)。
2. 儘量說明「族名、場域、情境」與「知識來源背景」,避免抽象空話。
3. 若是推論或類比,要清楚標註「推測」而不是說成唯一正解。
4. 若資料不足或超出目前教材範圍,請誠實說明,並給出安全的延伸建議。
5. 全程使用繁體中文。"""
# ========= 載入模型 =========
print(f"載入模型:{MODEL_ID} ...")
tokenizer = AutoTokenizer.from_pretrained(
MODEL_ID,
use_auth_token=HF_TOKEN,
)
# 保險起見,若沒有 pad_token 就沿用 eos_token
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype=torch.float16,
device_map="auto", # 自動分配到 GPU
use_auth_token=HF_TOKEN,
)
model.eval()
print("模型載入完成。")
# ========= 建立提示詞 =========
def build_prompt(system_prompt: str, history: list[tuple[str, str]], user_message: str) -> str:
"""
將 system_prompt + 歷史對話 + 新問題 組成一段文字 prompt。
這裡用簡單的「使用者 / 助手」格式,對傳統知識生成已經很足夠。
"""
system_prompt = system_prompt.strip()
prompt = f"[系統提示]\n{system_prompt}\n\n"
# 過去對話(若有)
if history:
prompt += "[對話紀錄]\n"
for i, (user, bot) in enumerate(history, start=1):
prompt += f"輪次 {i}:\n使用者:{user}\n助手:{bot}\n\n"
# 最新一輪問題
prompt += "[目前問題]\n"
prompt += f"使用者:{user_message}\n助手:"
return prompt
# ========= 生成函式 =========
def generate_reply(
user_message: str,
chat_history: list[tuple[str, str]],
system_prompt: str,
temperature: float,
max_new_tokens: int,
):
if not user_message.strip():
return chat_history, gr.update(value="")
# 組合成一個大 prompt
prompt_text = build_prompt(system_prompt, chat_history, user_message)
inputs = tokenizer(
prompt_text,
return_tensors="pt",
add_special_tokens=True,
).to(model.device)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=int(max_new_tokens),
do_sample=True,
temperature=float(temperature),
top_p=0.9,
pad_token_id=tokenizer.eos_token_id,
)
# 只取新生成的部分
input_len = inputs["input_ids"].shape[-1]
generated_tokens = outputs[0, input_len:]
answer = tokenizer.decode(generated_tokens, skip_special_tokens=True).strip()
chat_history = chat_history + [(user_message, answer)]
return chat_history, "" # 清空輸入框
def clear_history():
return [], ""
# ========= Gradio 介面 =========
with gr.Blocks(title="語言橋傳統知識聊天機器人 — Mistral7B TK", theme=gr.themes.Soft()) as demo:
gr.Markdown(
"""
# 語言橋傳統知識聊天機器人 — Mistral7B TK
使用你自訓練的 **mistral7b-tk-sft-20251019-merged** 模型,離線在 Hugging Face Space 上回答與傳統知識相關的問題。
建議題材舉例:
- 不同族群對「夢境」的五種層次與詮釋差異
- 布農族狩獵儀式與祖靈信仰
- 排灣族階級制度與紋面、圖騰的意義
- 阿美族年齡階層制與植物分類知識
- 海外原住民(如 Inuit)對身體、疾病與療癒的理解
"""
)
with gr.Row():
# 左側:設定區
with gr.Column(scale=1):
system_prompt_box = gr.Textbox(
label="系統提示(模型角色與回答風格)",
value=DEFAULT_SYSTEM_PROMPT,
lines=16,
)
temperature_slider = gr.Slider(
label="溫度(創造性)",
minimum=0.1,
maximum=1.5,
value=0.7,
step=0.05,
)
max_tokens_slider = gr.Slider(
label="最大回覆長度(token 數,大約字數的 1.5–2 倍)",
minimum=64,
maximum=1024,
value=512,
step=16,
)
gr.Markdown(
"""
**小提醒:**
- 回答太發散 → 降低溫度(0.4–0.7)。
- 回答太短 → 拉高「最大回覆長度」。
- Space 若常 timeout,可以稍微降低最大回覆長度。
"""
)
# 右側:聊天區
with gr.Column(scale=2):
chatbot = gr.Chatbot(
label="傳統知識 Chatbot",
height=480,
show_copy_button=True,
)
user_input = gr.Textbox(
label="輸入你的問題(可多輪對話)",
placeholder="例如:請比較布農族、排灣族和阿美族對治療疾病與夢境預兆的不同理解方式。",
lines=4,
)
with gr.Row():
send_btn = gr.Button("送出問題", variant="primary")
clear_btn = gr.Button("清除對話")
# 狀態:對話歷史
state = gr.State([]) # list[tuple[user, bot]]
# 綁定互動
send_btn.click(
fn=generate_reply,
inputs=[
user_input,
state,
system_prompt_box,
temperature_slider,
max_tokens_slider,
],
outputs=[chatbot, user_input],
).then(
fn=lambda h: h,
inputs=[chatbot],
outputs=[state],
)
user_input.submit(
fn=generate_reply,
inputs=[
user_input,
state,
system_prompt_box,
temperature_slider,
max_tokens_slider,
],
outputs=[chatbot, user_input],
).then(
fn=lambda h: h,
inputs=[chatbot],
outputs=[state],
)
clear_btn.click(
fn=clear_history,
inputs=[],
outputs=[chatbot, user_input],
).then(
fn=lambda: [],
inputs=[],
outputs=[state],
)
# 在 HF Space 中不需要 demo.launch(),平台會自動呼叫 demo
|