Spaces:
Sleeping
Sleeping
File size: 6,279 Bytes
428c36f dc77ac5 9188cd5 dc77ac5 d25a471 428c36f 9188cd5 428c36f dc77ac5 9188cd5 428c36f 9188cd5 dc77ac5 9188cd5 428c36f 9188cd5 428c36f d25a471 9188cd5 d25a471 9188cd5 dc77ac5 9188cd5 428c36f d25a471 9188cd5 428c36f 9188cd5 428c36f 9188cd5 428c36f d25a471 | 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 | import gradio as gr
import os
# 移除 Hugging Face Inference Client 相關導入
# from huggingface_hub import InferenceClient
import google.generativeai as genai # <-- 導入 Google Generative AI 庫
# 移除 Hugging Face Token 讀取和 Client 初始化
# hf_token = os.getenv("HF_TOKEN")
# if not hf_token:
# print("Error: Hugging Face Token (HF_TOKEN) not found...")
# client = InferenceClient("...", token=hf_token)
# 讀取 Google AI API 金鑰 Secret
# 確保您的 Secret 名稱為 GOOGLE_API_KEY
google_api_key = os.getenv("GOOGLE_API_KEY")
# 檢查金鑰是否存在
if not google_api_key:
# 在 Gradio 應用啟動時顯示錯誤或拋出異常
error_message = "錯誤:Google AI API Key (GOOGLE_API_KEY) Secret 未設定。請在 Hugging Face Space 設定中添加。"
print(error_message)
# 為了讓 Space 啟動不失敗,可以在這裡暫時顯示錯誤,但後續 API 呼叫會失敗
# 也可以選擇直接 sys.exit(1) 讓 Space 構建或啟動失敗,提示使用者設定 Secret
# import sys
# sys.exit(1)
# 配置 genai 庫
genai.configure(api_key=google_api_key)
# 選擇一個支援聊天的 Gemini 模型
# 'gemini-pro' 是常用的文字聊天模型
# 模型名稱可以在 Google AI 文檔中找到
MODEL_NAME = "gemini-pro"
# System Prompt 讀取方式保持不變 (從環境變數讀取,請確保 Secret 名稱一致)
# 假設你在 Hugging Face Space Secrets 中設定了一個名為 SYSTEM_PROMPT 的 Secret。
SYSTEM_PROMPT_CONTENT = os.getenv("SYSTEM_PROMPT", "你現在是一名專業的昆蟲學系的大學教授,所以你要用專業的角度簡單跟學生回答昆蟲的知識,請盡可能使用流暢的中文回答。")
# 修改 respond 函數,使用 Gemini API 進行回覆生成
# 函數簽名與之前修改後的版本一致
def respond(
message,
history: list[tuple[str, str]], # history 包含之前的對話 [(user, assistant), ...]
max_tokens, # 對應 generation_config 的 max_output_tokens
temperature,
top_p,
):
# 如果金鑰不存在,不進行 API 呼叫,直接返回錯誤訊息
if not google_api_key:
yield error_message
return # 結束函數執行
# 構建發送給 Gemini API 的 messages 列表
# Gemini API 的 generate_content 方法,當包含 history 時,通常期望格式為
# [{'role': 'user', 'parts': ['...']}, {'role': 'model', 'parts': ['...']}, ...]
# System Instruction 在 generate_content 中通常通過將其內容放在第一條 'user' 消息之前實現
# 或者將其作為單獨的 system_instruction 參數(如果可用且通過 generate_content 傳遞)
# 這裡我們採用將 system prompt 內容放在第一條實際 user 消息前的策略(如果歷史為空)
# 或直接將 system prompt 作為一個獨立的 'user'/'model' 對話對放在歷史最前面 (方便處理 Gradio history)
# 雖然不太符合官方 system_instruction 參數的用法,但能適應 Gradio 的 history 結構
messages_for_gemini = []
# 將 System Prompt 內容加入消息列表的開頭
# 這是為了讓模型理解指令,儘管不是 Gemini 官方推薦的 system_instruction 參數
# 我們將其作為一個獨立的 'user' 訊息放在最前面,後面跟一個 'model' 訊息作為確認
messages_for_gemini.append({"role": "user", "parts": [SYSTEM_PROMPT_CONTENT]})
messages_for_gemini.append({"role": "model", "parts": ["好的,我明白了,請開始。"]}) # 假裝模型確認了指令
# 將 Gradio 提供的 history 轉換為 Gemini API 的格式
# Gradio history 是 [(user_msg, bot_msg), ...]
for user_msg, bot_msg in history:
# 確保訊息不為 None 或空字串,避免 API 錯誤
if user_msg:
messages_for_gemini.append({"role": "user", "parts": [user_msg]})
if bot_msg:
messages_for_gemini.append({"role": "model", "parts": [bot_msg]})
# 加入當前使用者訊息
if message:
messages_for_gemini.append({"role": "user", "parts": [message]})
response = ""
try:
# 呼叫 Gemini API
# 使用 generate_content 方法
model = genai.GenerativeModel(MODEL_NAME)
# 設定生成參數
generation_config = genai.types.GenerationConfig(
max_output_tokens=max_tokens, # 對應 max_tokens
temperature=temperature,
top_p=top_p
# stop_sequences=[] # 如果需要,可以在這裡設定停止標記
)
# 呼叫 generate_content,傳入格式化好的消息列表和生成參數
# 對於 stream=True,它返回一個 Response 迭代器
stream = model.generate_content(
messages_for_gemini, # <-- 傳入構建好的消息列表
generation_config=generation_config,
stream=True,
)
# 處理流式回覆
# 迭代 Response 迭代器,獲取 chunks
for chunk in stream:
# chunk.text 包含當前的文本片段
# 需要確保 chunk.text 不是 None 或空字串
if hasattr(chunk, 'text') and chunk.text:
response += chunk.text
yield response # 逐步返回結果
except Exception as e:
print(f"Error during Gemini inference: {e}")
# 顯示更詳細的錯誤信息給使用者
yield f"生成回覆時發生錯誤: {e}"
# Gradio ChatInterface 設定保持不變
# additional_inputs 移除 System message 文字框
demo = gr.ChatInterface(
respond,
additional_inputs=[
gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
gr.Slider(
minimum=0.1,
maximum=1.0,
value=0.95,
step=0.05,
label="Top-p (nucleus sampling)",
),
],
# Chatbot 组件可以考虑设置 type='messages' 并在 respond 中返回对应的格式,以消除 UserWarning
# 例如 bot=gr.Chatbot(type='messages')
# 这需要调整 respond 函数返回值的格式,超出当前主要任务范围,可以之后优化
)
if __name__ == "__main__":
demo.launch() |