hsuwill000 commited on
Commit
df53ff4
·
verified ·
1 Parent(s): defa84e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -39
app.py CHANGED
@@ -1,12 +1,47 @@
1
  # app.py
2
 
3
  import os
 
 
4
  import gradio as gr
5
  from typing import List, Dict
6
  from huggingface_hub import hf_hub_download
7
- from llama_cpp import Llama
8
 
9
- # --- 1. 模型設定與下載 ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  # 您指定的模型資訊
12
  MODEL_NAME = "Qwen3-0.6B-Q8_0.gguf"
@@ -16,39 +51,36 @@ MODEL_REPO = "Qwen/Qwen3-0.6B-GGUF"
16
  DEFAULT_SYSTEM_MESSAGE = "You are a friendly and helpful assistant. Please answer the user's questions concisely and accurately."
17
 
18
  # 步驟 1: 下載 GGUF 模型
19
- # 模型會被下載到 ~/.cache/huggingface/hub/ 或指定的快取目錄
20
  try:
21
  print(f"嘗試從 {MODEL_REPO} 下載 {MODEL_NAME}...")
22
  model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_NAME)
23
  print(f"模型下載完成,路徑: {model_path}")
24
  except Exception as e:
25
- print(f"**錯誤**:無法下載模型。請檢查網路連線或模型名稱/權限。錯誤訊息: {e}")
26
- # 在 Gradio Space 中,如果模型無法下載,應用程式會無法啟動。
27
- # 這裡可以選擇性地退出或使用本地路徑作為備用(如果存在)。
28
- exit(1)
29
 
30
 
31
- # --- 2. Llama.cpp 初始化 ---
32
 
33
  # 步驟 2: 初始化 Llama.cpp 實例
34
- # n_gpu_layers=0 表示不使用 GPU (CPU 推論),如果環境支援 CUDA/cuBLAS,可以設定為 >0
35
  try:
36
  print("正在初始化 Llama.cpp 實例...")
37
  llm = Llama(
38
  model_path=model_path,
39
  n_ctx=4096, # 上下文長度
40
  n_batch=512, # 批次大小
41
- n_threads=os.cpu_count() // 2 or 1, # 使用一半的 CPU 核心
 
42
  n_gpu_layers=0, # CPU 推論
43
  verbose=False # 關閉內部日誌輸出
44
  )
45
  print("Llama.cpp 模型加載成功。")
46
  except Exception as e:
47
  print(f"**錯誤**:Llama.cpp 實例初始化失敗。錯誤訊息: {e}")
48
- exit(1)
49
 
50
 
51
- # --- 3. 推論核心函式 ---
52
 
53
  def llama_inference(
54
  message: str,
@@ -60,32 +92,25 @@ def llama_inference(
60
  ) -> str:
61
  """
62
  使用 Llama.cpp 實例執行推論並返回回應。
63
-
64
- :param message: 當前的使用者輸入。
65
- :param chat_history: Gradio 傳遞的聊天歷史記錄 (list of [user, bot] pairs)。
66
- :return: LLM 的回應文字。
67
  """
68
 
69
- # 將 Gradio 的聊天歷史轉換為 Llama.cpp/OpenAI 格式的 messages 列表
70
  messages = [{"role": "system", "content": system_message}]
71
 
72
  for human, assistant in chat_history:
73
- # 歷史對話
74
  messages.append({"role": "user", "content": human})
75
  messages.append({"role": "assistant", "content": assistant})
76
 
77
- # 當前訊息
78
  messages.append({"role": "user", "content": message})
79
 
80
 
81
  try:
82
- # 呼叫 Llama.cpp 的 create_chat_completion 介面 (與 OpenAI 格式相容)
83
  response = llm.create_chat_completion(
84
  messages=messages,
85
  max_tokens=max_tokens,
86
  temperature=temperature,
87
  top_p=top_p,
88
- # stream=False 是預設值
89
  )
90
 
91
  # 解析回應
@@ -100,23 +125,16 @@ def llama_inference(
100
  return f"❌ 伺服器錯誤 (Llama.cpp 推論失敗): {e}"
101
 
102
 
103
- # --- 4. Gradio 介面設定 ---
104
 
105
- # 定義 Gradio 聊天函式 (用於更新介面)
106
  def chat_interface(message: str, history: List[List[str]]):
107
  """Gradio 介面調用函式。"""
108
 
109
- # 這裡可以固定或從另一個��入元件獲取參數,為了簡化,使用硬編碼值
110
  response = llama_inference(
111
  message=message,
112
  chat_history=history,
113
- system_message=DEFAULT_SYSTEM_MESSAGE,
114
- max_tokens=4096,
115
- temperature=0.7,
116
- top_p=0.95
117
  )
118
 
119
- # Gradio 聊天介面要求回傳回應文字
120
  return response
121
 
122
 
@@ -129,30 +147,22 @@ with gr.Blocks(title="Qwen3-0.6B-GGUF 聊天機器人") as demo:
129
  """
130
  )
131
 
132
- # 聊天元件
133
  chatbot = gr.Chatbot(
134
  label="聊天記錄",
135
  height=500
136
  )
137
 
138
- # 聊天輸入元件
139
  chat_input = gr.Textbox(
140
  show_label=False,
141
  placeholder="請輸入你的問題...",
142
  container=False
143
  )
144
 
145
- # 綁定聊天邏輯
146
- # submit 觸發事件:
147
- # - fn: 要執行的 Python 函式 (chat_interface)
148
- # - inputs: 函式接收的輸入 ([Textbox 的內容, Chatbot 的歷史])
149
- # - outputs: 函式輸出的結果 (Chatbot 的新歷史)
150
  chat_input.submit(
151
  fn=chat_interface,
152
  inputs=[chat_input, chatbot],
153
  outputs=chatbot
154
  ).then(
155
- # 清空輸入框
156
  fn=lambda: "",
157
  inputs=None,
158
  outputs=chat_input,
@@ -161,6 +171,4 @@ with gr.Blocks(title="Qwen3-0.6B-GGUF 聊天機器人") as demo:
161
 
162
  # 啟動應用程式
163
  if __name__ == "__main__":
164
- # 在 Gradio Space 中,會使用 gunicorn 或類似服務來運行,但如果要在本地測試,可以使用以下命令:
165
- # python app.py
166
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  # app.py
2
 
3
  import os
4
+ import sys
5
+ import subprocess
6
  import gradio as gr
7
  from typing import List, Dict
8
  from huggingface_hub import hf_hub_download
 
9
 
10
+ # --- 0. 內嵌安裝 llama-cpp-python ---
11
+ # 警告:這是一個非標準且可能失敗的解決方案。
12
+ # 建議在 Gradio Space 中使用 requirements.txt 來安裝依賴。
13
+ try:
14
+ print("--- 嘗試動態安裝 llama-cpp-python ---")
15
+ # 執行 pip install 命令
16
+ # 使用 sys.executable 確保使用當前的 Python 解譯器
17
+ subprocess.check_call([
18
+ sys.executable,
19
+ "-m",
20
+ "pip",
21
+ "install",
22
+ "llama-cpp-python",
23
+ "--upgrade" # 確保是最新版本
24
+ ])
25
+ print("llama-cpp-python 安裝/更新成功。")
26
+ except subprocess.CalledProcessError as e:
27
+ print(f"**致命錯誤**:llama-cpp-python 安裝失敗。請檢查環境權限或系統依賴。錯誤訊息: {e}")
28
+ # 由於安裝失敗,我們不能繼續執行
29
+ sys.exit(1)
30
+ except Exception as e:
31
+ print(f"**致命錯誤**:發生未知錯誤。錯誤訊息: {e}")
32
+ sys.exit(1)
33
+
34
+
35
+ # --- 1. 引入 llama_cpp ---
36
+ # 必須在嘗試安裝之後才能引入
37
+ try:
38
+ from llama_cpp import Llama
39
+ except ImportError:
40
+ print("**致命錯誤**:即使嘗試安裝,仍然無法引入 llama_cpp。請檢查 pip 安裝日誌。")
41
+ sys.exit(1)
42
+
43
+
44
+ # --- 2. 模型設定與下載 ---
45
 
46
  # 您指定的模型資訊
47
  MODEL_NAME = "Qwen3-0.6B-Q8_0.gguf"
 
51
  DEFAULT_SYSTEM_MESSAGE = "You are a friendly and helpful assistant. Please answer the user's questions concisely and accurately."
52
 
53
  # 步驟 1: 下載 GGUF 模型
 
54
  try:
55
  print(f"嘗試從 {MODEL_REPO} 下載 {MODEL_NAME}...")
56
  model_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_NAME)
57
  print(f"模型下載完成,路徑: {model_path}")
58
  except Exception as e:
59
+ print(f"**錯誤**:無法下載模型。錯誤訊息: {e}")
60
+ sys.exit(1) # 無法下載模型則退出
 
 
61
 
62
 
63
+ # --- 3. Llama.cpp 初始化 ---
64
 
65
  # 步驟 2: 初始化 Llama.cpp 實例
 
66
  try:
67
  print("正在初始化 Llama.cpp 實例...")
68
  llm = Llama(
69
  model_path=model_path,
70
  n_ctx=4096, # 上下文長度
71
  n_batch=512, # 批次大小
72
+ # 為了 Gradio Space 穩定性,使用少量 CPU 核心
73
+ n_threads=os.cpu_count() // 2 or 1,
74
  n_gpu_layers=0, # CPU 推論
75
  verbose=False # 關閉內部日誌輸出
76
  )
77
  print("Llama.cpp 模型加載成功。")
78
  except Exception as e:
79
  print(f"**錯誤**:Llama.cpp 實例初始化失敗。錯誤訊息: {e}")
80
+ sys.exit(1)
81
 
82
 
83
+ # --- 4. 推論核心函式 ---
84
 
85
  def llama_inference(
86
  message: str,
 
92
  ) -> str:
93
  """
94
  使用 Llama.cpp 實例執行推論並返回回應。
 
 
 
 
95
  """
96
 
97
+ # 格式化訊息列表,包含系統提示和聊天歷史
98
  messages = [{"role": "system", "content": system_message}]
99
 
100
  for human, assistant in chat_history:
 
101
  messages.append({"role": "user", "content": human})
102
  messages.append({"role": "assistant", "content": assistant})
103
 
 
104
  messages.append({"role": "user", "content": message})
105
 
106
 
107
  try:
108
+ # 呼叫 Llama.cpp 的 create_chat_completion 介面
109
  response = llm.create_chat_completion(
110
  messages=messages,
111
  max_tokens=max_tokens,
112
  temperature=temperature,
113
  top_p=top_p,
 
114
  )
115
 
116
  # 解析回應
 
125
  return f"❌ 伺服器錯誤 (Llama.cpp 推論失敗): {e}"
126
 
127
 
128
+ # --- 5. Gradio 介面設定 ---
129
 
 
130
  def chat_interface(message: str, history: List[List[str]]):
131
  """Gradio 介面調用函式。"""
132
 
 
133
  response = llama_inference(
134
  message=message,
135
  chat_history=history,
 
 
 
 
136
  )
137
 
 
138
  return response
139
 
140
 
 
147
  """
148
  )
149
 
 
150
  chatbot = gr.Chatbot(
151
  label="聊天記錄",
152
  height=500
153
  )
154
 
 
155
  chat_input = gr.Textbox(
156
  show_label=False,
157
  placeholder="請輸入你的問題...",
158
  container=False
159
  )
160
 
 
 
 
 
 
161
  chat_input.submit(
162
  fn=chat_interface,
163
  inputs=[chat_input, chatbot],
164
  outputs=chatbot
165
  ).then(
 
166
  fn=lambda: "",
167
  inputs=None,
168
  outputs=chat_input,
 
171
 
172
  # 啟動應用程式
173
  if __name__ == "__main__":
 
 
174
  demo.launch(server_name="0.0.0.0", server_port=7860)