3a05chatgpt commited on
Commit
a87aef6
·
verified ·
1 Parent(s): 228df30

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -195
app.py CHANGED
@@ -18,39 +18,25 @@ def set_api_key(user_api_key):
18
  api_key = user_api_key.strip()
19
  if not api_key:
20
  return "❌ API Key 不能為空"
21
-
22
- if not api_key.startswith('sk-'):
23
- return "❌ API Key 格式錯誤,應該以 'sk-' 開頭"
24
-
25
  client = OpenAI(api_key=api_key)
26
-
27
  # 測試 API Key 是否有效
28
- try:
29
- test_response = client.chat.completions.create(
30
- model="gpt-3.5-turbo",
31
- messages=[{"role": "user", "content": "Hello"}],
32
- max_tokens=5
33
- )
34
- return "✅ API Key 已設定並驗證成功!可以開始使用了。"
35
- except Exception as e:
36
- if "incorrect_api_key" in str(e).lower():
37
- return "❌ API Key 無效,請檢查是否正確"
38
- elif "quota" in str(e).lower():
39
- return "⚠️ API Key 有效,但配額不足"
40
- else:
41
- return f"⚠️ API Key 設定成功,但測試時出現問題:{str(e)[:100]}"
42
-
43
  except Exception as e:
44
- return f"❌ 設定失敗:{str(e)}"
45
 
46
  def set_model(model_name):
47
  """設定選擇的模型"""
48
  global selected_model
49
- if model_name:
50
- selected_model = model_name
51
- return f"✅ 模型已更新為:{model_name}"
52
- else:
53
- return "❌ 請選擇一個模型"
54
 
55
  def extract_pdf_text(file_path):
56
  """從 PDF 文件中提取文字"""
@@ -60,8 +46,7 @@ def extract_pdf_text(file_path):
60
  for page_num, page in enumerate(doc):
61
  page_text = page.get_text()
62
  if page_text.strip():
63
- text += f"\n--- 第 {page_num + 1} 頁 ---\n"
64
- text += page_text
65
  doc.close()
66
  return text
67
  except Exception as e:
@@ -70,94 +55,61 @@ def extract_pdf_text(file_path):
70
  def generate_summary(pdf_file):
71
  """從 PDF 內容生成摘要"""
72
  global summary_text, pdf_text
73
-
74
  if not client:
75
  return "❌ 請先設定 OpenAI API Key"
76
-
77
  if not pdf_file:
78
  return "❌ 請先上傳 PDF 文件"
79
-
80
  try:
81
  pdf_text = extract_pdf_text(pdf_file.name)
82
-
83
  if not pdf_text.strip():
84
  return "⚠️ 無法解析 PDF 文字,可能為純圖片 PDF 或空白文件。"
85
-
86
- max_chars = 8000
87
- if len(pdf_text) > max_chars:
88
- pdf_text_truncated = pdf_text[:max_chars] + "\n\n[文本已截斷,僅顯示前 8000 字符]"
89
- else:
90
- pdf_text_truncated = pdf_text
91
-
92
  response = client.chat.completions.create(
93
  model=selected_model,
94
  messages=[
95
- {
96
- "role": "system",
97
- "content": """你是一個專業的文檔摘要助手。請將以下 PDF 內容整理為結構化的摘要:
98
-
99
- 1. 首先提供一個簡短的總體概述
100
- 2. 然後按照重要性列出主要重點(使用項目符號)
101
- 3. 如果有數據或統計信息,請特別標注
102
- 4. 如果有結論或建議,請單獨列出
103
-
104
- 請用繁體中文回答,保持專業且易於理解的語調。"""
105
- },
106
  {"role": "user", "content": pdf_text_truncated}
107
  ],
108
  temperature=0.3
109
  )
110
-
111
  summary_text = response.choices[0].message.content
112
  return summary_text
113
-
114
  except Exception as e:
115
- error_msg = f"❌ 摘要生成失敗: {str(e)}"
116
  print(f"錯誤詳情: {traceback.format_exc()}")
117
- return error_msg
118
 
119
  def ask_question(user_question):
120
  """基於 PDF 內容回答問題"""
121
  if not client:
122
  return "❌ 請先設定 OpenAI API Key"
123
-
124
  if not summary_text and not pdf_text:
125
  return "❌ 請先生成 PDF 摘要"
126
-
127
  if not user_question.strip():
128
  return "❌ 請輸入問題"
129
-
130
  try:
131
  context = f"PDF 摘要:\n{summary_text}\n\n原始內容(部分):\n{pdf_text[:2000]}"
132
-
133
  response = client.chat.completions.create(
134
  model=selected_model,
135
  messages=[
136
- {
137
- "role": "system",
138
- "content": f"""你是一個專業的文檔問答助手。請基於提供的 PDF 內容回答用戶問題。
139
-
140
- 規則:
141
- 1. 只根據提供的文檔內容回答
142
- 2. 如果文檔中沒有相關信息,請明確說明
143
- 3. 引用具體的文檔內容來支持你的回答
144
- 4. 用繁體中文回答
145
- 5. 保持客觀和準確
146
-
147
- 文檔內容:
148
- {context}"""
149
- },
150
  {"role": "user", "content": user_question}
151
  ],
152
  temperature=0.2
153
  )
154
-
155
  return response.choices[0].message.content
156
-
157
  except Exception as e:
158
- error_msg = f"❌ 問答生成失敗: {str(e)}"
159
  print(f"錯誤詳情: {traceback.format_exc()}")
160
- return error_msg
161
 
162
  def clear_all():
163
  """清除所有資料"""
@@ -166,127 +118,35 @@ def clear_all():
166
  pdf_text = ""
167
  return "", "", ""
168
 
169
- # 創建最簡單的 Gradio 介面
170
  with gr.Blocks(title="PDF 摘要助手") as demo:
171
- gr.Markdown("# 📄 PDF 摘要 & 問答助手")
172
-
173
  with gr.Tab("🔧 設定"):
174
- gr.Markdown("## API Key 設定")
175
-
176
- api_key_input = gr.Textbox(
177
- label="輸入 OpenAI API Key",
178
- type="password",
179
- placeholder="請輸入您的 OpenAI API Key (sk-...)"
180
- )
181
-
182
- with gr.Row():
183
- api_key_btn = gr.Button("確認設定 API Key", variant="primary")
184
-
185
- api_key_status = gr.Textbox(
186
- label="API 狀態",
187
- interactive=False,
188
- value="等待設定 API Key..."
189
- )
190
-
191
- gr.Markdown("## 模型選擇")
192
-
193
- model_choice = gr.Radio(
194
- choices=["gpt-4", "gpt-4.1", "gpt-4.5"],
195
- label="選擇 AI 模型",
196
- value="gpt-4"
197
- )
198
-
199
- with gr.Row():
200
- model_btn = gr.Button("確認選擇模型", variant="secondary")
201
-
202
- model_status = gr.Textbox(
203
- label="當前模型",
204
- interactive=False,
205
- value="已選擇:gpt-4"
206
- )
207
-
208
- with gr.Tab("📄 PDF 處理"):
209
- gr.Markdown("## 上傳 PDF 文件")
210
-
211
- pdf_upload = gr.File(
212
- label="選擇 PDF 文件",
213
- file_types=[".pdf"]
214
- )
215
-
216
- with gr.Row():
217
- summary_btn = gr.Button("生成摘要", variant="primary")
218
- clear_btn = gr.Button("清除資料", variant="secondary")
219
-
220
- summary_output = gr.Textbox(
221
- label="PDF 摘要",
222
- lines=15,
223
- placeholder="上傳 PDF 文件並點擊「生成摘要」按鈕"
224
- )
225
-
226
  with gr.Tab("❓ 問答"):
227
- gr.Markdown("## AI 問答")
228
-
229
- question_input = gr.Textbox(
230
- label="請輸入您的問題",
231
- placeholder="例如:這份文件的主要結論是什麼?",
232
- lines=3
233
- )
234
-
235
- with gr.Row():
236
- question_btn = gr.Button("發送問題", variant="primary")
237
-
238
- answer_output = gr.Textbox(
239
- label="AI 回答",
240
- lines=10,
241
- placeholder="AI 回答將顯示在這裡"
242
- )
243
-
244
- # 事件綁定 - 使用最簡單的方式
245
- api_key_btn.click(
246
- fn=set_api_key,
247
- inputs=api_key_input,
248
- outputs=api_key_status
249
- )
250
-
251
- model_btn.click(
252
- fn=set_model,
253
- inputs=model_choice,
254
- outputs=model_status
255
- )
256
-
257
- summary_btn.click(
258
- fn=generate_summary,
259
- inputs=pdf_upload,
260
- outputs=summary_output
261
- )
262
-
263
- question_btn.click(
264
- fn=ask_question,
265
- inputs=question_input,
266
- outputs=answer_output
267
- )
268
-
269
- clear_btn.click(
270
- fn=clear_all,
271
- outputs=[summary_output, question_input, answer_output]
272
- )
273
-
274
- # 也支援 Enter 鍵
275
- api_key_input.submit(
276
- fn=set_api_key,
277
- inputs=api_key_input,
278
- outputs=api_key_status
279
- )
280
-
281
- question_input.submit(
282
- fn=ask_question,
283
- inputs=question_input,
284
- outputs=answer_output
285
- )
286
 
287
  if __name__ == "__main__":
288
- demo.launch(
289
- share=False,
290
- show_api=False,
291
- show_error=True
292
- )
 
18
  api_key = user_api_key.strip()
19
  if not api_key:
20
  return "❌ API Key 不能為空"
21
+
 
 
 
22
  client = OpenAI(api_key=api_key)
23
+
24
  # 測試 API Key 是否有效
25
+ client.chat.completions.create(
26
+ model="gpt-4",
27
+ messages=[{"role": "user", "content": "你好"}],
28
+ max_tokens=5
29
+ )
30
+
31
+ return "✅ API Key 已設定並驗證成功"
 
 
 
 
 
 
 
 
32
  except Exception as e:
33
+ return f"❌ API Key 設定失敗: {str(e)}"
34
 
35
  def set_model(model_name):
36
  """設定選擇的模型"""
37
  global selected_model
38
+ selected_model = model_name
39
+ return f"✅ 模型已選擇:{model_name}"
 
 
 
40
 
41
  def extract_pdf_text(file_path):
42
  """從 PDF 文件中提取文字"""
 
46
  for page_num, page in enumerate(doc):
47
  page_text = page.get_text()
48
  if page_text.strip():
49
+ text += f"\n--- 第 {page_num + 1} 頁 ---\n{page_text}"
 
50
  doc.close()
51
  return text
52
  except Exception as e:
 
55
  def generate_summary(pdf_file):
56
  """從 PDF 內容生成摘要"""
57
  global summary_text, pdf_text
58
+
59
  if not client:
60
  return "❌ 請先設定 OpenAI API Key"
61
+
62
  if not pdf_file:
63
  return "❌ 請先上傳 PDF 文件"
64
+
65
  try:
66
  pdf_text = extract_pdf_text(pdf_file.name)
 
67
  if not pdf_text.strip():
68
  return "⚠️ 無法解析 PDF 文字,可能為純圖片 PDF 或空白文件。"
69
+
70
+ pdf_text_truncated = pdf_text[:8000] # 簡單限制長度
 
 
 
 
 
71
  response = client.chat.completions.create(
72
  model=selected_model,
73
  messages=[
74
+ {"role": "system", "content": "請將以下 PDF 內容整理為條列式摘要,並用繁體中文回答:"},
 
 
 
 
 
 
 
 
 
 
75
  {"role": "user", "content": pdf_text_truncated}
76
  ],
77
  temperature=0.3
78
  )
79
+
80
  summary_text = response.choices[0].message.content
81
  return summary_text
82
+
83
  except Exception as e:
 
84
  print(f"錯誤詳情: {traceback.format_exc()}")
85
+ return f"❌ 摘要生成失敗: {str(e)}"
86
 
87
  def ask_question(user_question):
88
  """基於 PDF 內容回答問題"""
89
  if not client:
90
  return "❌ 請先設定 OpenAI API Key"
91
+
92
  if not summary_text and not pdf_text:
93
  return "❌ 請先生成 PDF 摘要"
94
+
95
  if not user_question.strip():
96
  return "❌ 請輸入問題"
97
+
98
  try:
99
  context = f"PDF 摘要:\n{summary_text}\n\n原始內容(部分):\n{pdf_text[:2000]}"
 
100
  response = client.chat.completions.create(
101
  model=selected_model,
102
  messages=[
103
+ {"role": "system", "content": f"根據以下 PDF 內容回答用戶的問題,請用繁體中文回答並客觀精準:\n{context}"},
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  {"role": "user", "content": user_question}
105
  ],
106
  temperature=0.2
107
  )
 
108
  return response.choices[0].message.content
109
+
110
  except Exception as e:
 
111
  print(f"錯誤詳情: {traceback.format_exc()}")
112
+ return f"❌ 問答生成失敗: {str(e)}"
113
 
114
  def clear_all():
115
  """清除所有資料"""
 
118
  pdf_text = ""
119
  return "", "", ""
120
 
121
+ # Gradio 介面
122
  with gr.Blocks(title="PDF 摘要助手") as demo:
123
+ gr.Markdown("# 📄 PDF 摘要 & 問答助手 (修正版)")
124
+
125
  with gr.Tab("🔧 設定"):
126
+ api_key_input = gr.Textbox(label="🔑 輸入 OpenAI API Key", type="password")
127
+ api_key_status = gr.Textbox(label="狀態", interactive=False, value="等待設定 API Key...")
128
+ api_key_btn = gr.Button("確認設定 API Key")
129
+ api_key_btn.click(set_api_key, inputs=api_key_input, outputs=api_key_status)
130
+
131
+ model_choice = gr.Radio(["gpt-4", "gpt-4.1", "gpt-4.5"], label="選擇 AI 模型", value="gpt-4")
132
+ model_status = gr.Textbox(label="模型狀態", interactive=False, value="✅ 已選擇:gpt-4")
133
+ model_choice.change(set_model, inputs=model_choice, outputs=model_status)
134
+
135
+ with gr.Tab("📄 PDF 摘要"):
136
+ pdf_upload = gr.File(label="選擇 PDF 文件", file_types=[".pdf"])
137
+ summary_btn = gr.Button("生成摘要")
138
+ summary_output = gr.Textbox(label="PDF 摘要", lines=10)
139
+ summary_btn.click(generate_summary, inputs=pdf_upload, outputs=summary_output)
140
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  with gr.Tab("❓ 問答"):
142
+ question_input = gr.Textbox(label="請輸入您的問題", lines=2)
143
+ question_btn = gr.Button("送出問題")
144
+ answer_output = gr.Textbox(label="AI 回答", lines=10)
145
+ question_btn.click(ask_question, inputs=question_input, outputs=answer_output)
146
+ question_input.submit(ask_question, inputs=question_input, outputs=answer_output)
147
+
148
+ clear_btn = gr.Button("🗑️ 清除所有資料")
149
+ clear_btn.click(clear_all, outputs=[summary_output, question_input, answer_output])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  if __name__ == "__main__":
152
+ demo.launch(show_error=True)