File size: 7,482 Bytes
55c353c affd85c 55c353c affd85c 55c353c 98bfbb7 55c353c affd85c 55c353c affd85c b00d9c0 affd85c 55c353c 8aa1527 |
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 |
import gradio as gr
from huggingface_hub import InferenceClient
import json
from datetime import datetime
def respond(
message,
history: list[dict[str, str]],
system_message,
max_tokens,
temperature,
top_p,
hf_token: str,
):
"""
For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
"""
try:
# 使用指定的模型
client = InferenceClient(token=hf_token, model="openai/gpt-oss-20b")
# 建議 1:限制對話歷史長度
max_history_length = 5
history = history[-max_history_length:] if len(history) > max_history_length else history
# 建議 2:角色專屬回應增強 - 檢查語文相關關鍵詞,並強化山田優子的個性
writing_keywords = ["作文", "寫作", "文章", "閱讀", "詩詞", "擴展", "增長", "寫一篇", "故事", "描述"]
is_writing_task = any(keyword in message.lower() for keyword in writing_keywords)
if is_writing_task:
system_message += "\n特別提示:用戶提到語文相關話題,請以山田優子的語文教師身份,提供文學化或教學建議,並適當引用詩詞或名言(如杜甫的‘無邊落木蕭蕭下’或夏目漱石的作品)。保持溫柔但嚴格的語氣,鼓勵學生探索文字之美,並融入幽默來化解尷尬。"
# 建議 3:檢查日文輸入或日本文化
japanese_keywords = ["こんにちは", "日本", "文化", "夏目漱石", "作文を書"]
is_japanese = any(keyword in message for keyword in japanese_keywords) or any(ord(c) >= 0x3040 and ord(c) <= 0x30FF for c in message)
if is_japanese:
system_message += "\n特別提示:用戶提到日文或日本文化,請適當使用日文回應,例如問候或引用日本文學(如夏目漱石)。"
# 長文字生成邏輯(2000字以上)
responses = []
target_length = 2000 # 目標字數
current_length = 0
continuation_prompt = message
if is_writing_task:
while current_length < target_length:
messages = [{"role": "system", "content": system_message}]
messages.extend(history)
messages.append({"role": "user", "content": continuation_prompt})
response = ""
try:
for message in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
choices = message.choices
token = choices[0].delta.content if len(choices) and choices[0].delta.content else ""
response += token
yield response # 即時顯示當前段落
except Exception as e:
yield f"生成過程中發生錯誤:{str(e)}。請檢查 Hugging Face API token 或模型連線。"
return
responses.append(response)
current_length += len(response)
history.append({"role": "user", "content": continuation_prompt})
history.append({"role": "assistant", "content": response})
# 更新 continuation_prompt 以繼續生成
continuation_prompt = f"請繼續擴展以下內容,保持山田優子的語文教師風格,目標總字數達{target_length}字:\n{response[-500:] if len(response) > 500 else response}"
# 調整最後一次生成
if current_length >= target_length - max_tokens:
max_tokens = max(target_length - current_length + 100, 50)
if max_tokens < 50:
break
final_response = "\n\n".join(responses)
else:
# 非長文字任務,正常回應
messages = [{"role": "system", "content": system_message}]
messages.extend(history)
messages.append({"role": "user", "content": message})
final_response = ""
for message in client.chat_completion(
messages,
max_tokens=max_tokens,
stream=True,
temperature=temperature,
top_p=top_p,
):
choices = message.choices
token = choices[0].delta.content if len(choices) and choices[0].delta.content else ""
final_response += token
yield final_response
history.append({"role": "user", "content": message})
history.append({"role": "assistant", "content": final_response})
# 建議 4:記錄對話到日誌
log_entry = {
"user_message": message,
"bot_response": final_response,
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
with open("chat_log.json", "a", encoding="utf-8") as f:
json.dump(log_entry, f, ensure_ascii=False)
f.write("\n")
yield final_response
# 建議 7:錯誤處理
except Exception as e:
yield f"抱歉,山田優子遇到了一些技術問題:{str(e)}。請檢查你的 Hugging Face API token、網路連線,或確認模型 'openai/gpt-oss-20b' 可用。"
# 自訂聊天介面
with gr.Blocks() as demo:
with gr.Sidebar():
gr.Markdown("請輸入 Hugging Face API token 或登錄")
hf_token = gr.Textbox(label="Hugging Face API Token", type="password")
gr.Markdown("📢 想聽山田優子用溫柔的語氣教你語文?請下載 Grok iOS 或 Android 應用程式,開啟語音模式!")
# 自訂輸入和輸出區域
input_text = gr.Textbox(
placeholder="請輸入你的問題或短文(例如‘寫一篇關於秋天的文章’),山田優子將為你擴展至2000字以上!",
lines=10,
max_lines=50,
label="輸入區"
)
output_text = gr.Textbox(label="山田優子的回應", lines=20)
system_message = gr.Textbox(
value="你是一位名叫山田優子的語文教師,擁有黑色低馬尾髮型,身高175公分,體重60-70公斤。你溫柔但對學生要求嚴格,喜歡用文學化的語言表達,偶爾會引用詩詞或幽默的語句來化解尷尬。你的教學風格充滿同理心,鼓勵學生探索文字之美。如果用戶使用日文或提到日本文化,你會適當融入日文回應,例如問候或引用日本文學(如夏目漱石的句子)。",
label="System message"
)
max_tokens = gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens")
temperature = gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature")
top_p = gr.Slider(minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top-p (nucleus sampling)")
# 顯式提交按鈕
submit_button = gr.Button("提交")
# 聊天歷史
history = gr.State([])
# 綁定按鈕事件
submit_button.click(
fn=respond,
inputs=[input_text, history, system_message, max_tokens, temperature, top_p, hf_token],
outputs=[output_text, history]
)
if __name__ == "__main__":
demo.launch() |