Roberta2024 commited on
Commit
de02f53
·
verified ·
1 Parent(s): 16fae2b

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +258 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,260 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
1
  import streamlit as st
2
+ import PyPDF2
3
+ import pandas as pd
4
+ import os
5
+ import google.generativeai as genai
6
+ import csv
7
+ from datetime import datetime
8
+ import logging
9
+ import sys
10
+ import io
11
+ import tempfile
12
+ import base64
13
+
14
+ # 設定日誌
15
+ logging.basicConfig(
16
+ level=logging.INFO,
17
+ format='%(asctime)s - %(levelname)s - %(message)s',
18
+ handlers=[
19
+ logging.FileHandler("pdf_processing.log"),
20
+ logging.StreamHandler(sys.stdout)
21
+ ]
22
+ )
23
+ logger = logging.getLogger(__name__)
24
+
25
+ # 設定頁面配置
26
+ st.set_page_config(
27
+ page_title="PDF處理與Gemini翻譯工具",
28
+ page_icon="📄",
29
+ layout="wide",
30
+ initial_sidebar_state="expanded"
31
+ )
32
+
33
+ # 應用程式標題和介紹
34
+ st.title("📄 PDF處理與Gemini翻譯工具")
35
+ st.markdown("上傳PDF檔案,選擇要處理的頁面,讓Gemini解釋內容並翻譯成繁體中文。")
36
+
37
+ # 側邊欄 - 設定區域
38
+ with st.sidebar:
39
+ st.header("設定")
40
+
41
+ # API金鑰輸入
42
+ api_key = st.text_input(
43
+ "Gemini API金鑰",
44
+ value="AIzaSyC3fbJVYQbINa8ztuOS5dFE4ud0I9jhy3o", # 預設值,實際使用應從設定檔讀取
45
+ type="password"
46
+ )
47
+
48
+ # 上傳PDF檔案
49
+ uploaded_file = st.file_uploader("上傳PDF檔案", type=["pdf"])
50
+
51
+ # 處理選項區塊
52
+ with st.expander("處理選項", expanded=True):
53
+ # 初始化session_state
54
+ if 'total_pages' not in st.session_state:
55
+ st.session_state.total_pages = 0
56
+ if 'page_content' not in st.session_state:
57
+ st.session_state.page_content = {}
58
+
59
+ # 頁面選擇(只在上傳檔案後顯示)
60
+ if uploaded_file is not None:
61
+ # 讀取PDF並獲取頁數
62
+ try:
63
+ pdf_reader = PyPDF2.PdfReader(uploaded_file)
64
+ st.session_state.total_pages = len(pdf_reader.pages)
65
+
66
+ # 加載PDF內容到session_state(如果尚未加載)
67
+ if len(st.session_state.page_content) == 0:
68
+ with st.spinner("正在加載PDF..."):
69
+ for i in range(st.session_state.total_pages):
70
+ st.session_state.page_content[i+1] = pdf_reader.pages[i].extract_text()
71
+
72
+ # 頁面選擇滑桿
73
+ page_to_process = st.slider(
74
+ "選擇要處理的頁面",
75
+ min_value=1,
76
+ max_value=st.session_state.total_pages,
77
+ value=1
78
+ )
79
+
80
+ st.info(f"PDF共有 {st.session_state.total_pages} 頁")
81
+ except Exception as e:
82
+ st.error(f"無法讀取PDF: {str(e)}")
83
+ else:
84
+ st.info("請先上傳PDF檔案")
85
+ page_to_process = 1
86
+
87
+ # 進階選項
88
+ with st.expander("進階選項"):
89
+ # 給Gemini的指示詞
90
+ instruction = st.text_area(
91
+ "給Gemini的指示詞",
92
+ value="請詳細解釋以下內容的主要要點和重要信息",
93
+ height=100
94
+ )
95
+
96
+ # 輸出檔名
97
+ output_filename = st.text_input(
98
+ "輸出CSV檔名",
99
+ value="gemini_translated_results.csv"
100
+ )
101
+
102
+ # 主要功能函數
103
+ def setup_gemini_api(api_key):
104
+ """設置Gemini API"""
105
+ try:
106
+ os.environ["GOOGLE_API_KEY"] = api_key
107
+ genai.configure(api_key=api_key)
108
+ return genai.GenerativeModel("gemini-1.5-flash")
109
+ except Exception as e:
110
+ logger.error(f"Gemini API設置失敗: {e}")
111
+ st.error(f"API設置失敗: {str(e)}")
112
+ return None
113
+
114
+ def process_with_gemini(model, text, instruction):
115
+ """使用Gemini處理文本"""
116
+ try:
117
+ prompt = f"{instruction}:\n\n{text}"
118
+ response = model.generate_content(prompt)
119
+ return response.text.strip()
120
+ except Exception as e:
121
+ logger.error(f"Gemini處理失敗: {e}")
122
+ return f"處理失敗: {str(e)}"
123
+
124
+ def translate_with_gemini(model, text):
125
+ """使用Gemini將文本翻譯成繁體中文"""
126
+ try:
127
+ prompt = f"""
128
+ 請將以下文本翻譯成繁體中文,保持專業和準確性:
129
+
130
+ {text}
131
+
132
+ 只需要返回翻譯後的文本,不要加入其他解釋或備註。
133
+ """
134
+
135
+ response = model.generate_content(prompt)
136
+ return response.text.strip()
137
+ except Exception as e:
138
+ logger.error(f"Gemini翻譯失敗: {e}")
139
+ return f"翻譯失敗: {str(e)}"
140
+
141
+ def get_csv_download_link(df, filename="data.csv"):
142
+ """生成CSV檔案下載連結"""
143
+ csv = df.to_csv(index=False)
144
+ b64 = base64.b64encode(csv.encode()).decode()
145
+ href = f'<a href="data:file/csv;base64,{b64}" download="{filename}">下載 CSV 檔案</a>'
146
+ return href
147
+
148
+ # 主要內容區域
149
+ if uploaded_file is not None:
150
+ # 顯示頁面內容預覽
151
+ st.header("頁面內容預覽")
152
+
153
+ # 從session_state獲取選定頁面的內容
154
+ if page_to_process in st.session_state.page_content:
155
+ page_text = st.session_state.page_content[page_to_process]
156
+ st.text_area(
157
+ f"第 {page_to_process} 頁內容",
158
+ value=page_text,
159
+ height=150,
160
+ disabled=True
161
+ )
162
+ else:
163
+ st.warning("無法獲取選定頁面的內容")
164
+
165
+ # 處理按鈕
166
+ process_button = st.button("處理並翻譯", type="primary", use_container_width=True)
167
+
168
+ # 當按下處理按鈕
169
+ if process_button:
170
+ if not api_key:
171
+ st.error("請輸入Gemini API金鑰!")
172
+ else:
173
+ # 設置進度顯示
174
+ progress_placeholder = st.empty()
175
+ results_placeholder = st.empty()
176
+
177
+ with st.spinner("正在處理中..."):
178
+ progress_bar = progress_placeholder.progress(0)
179
+
180
+ # 設置API
181
+ model = setup_gemini_api(api_key)
182
+ if model:
183
+ progress_bar.progress(20)
184
+
185
+ # 獲取選定頁面的內容
186
+ page_text = st.session_state.page_content[page_to_process]
187
+
188
+ # 使用Gemini處理
189
+ progress_placeholder.text("正在使用Gemini解釋內容...")
190
+ explanation = process_with_gemini(model, page_text, instruction)
191
+ progress_bar.progress(60)
192
+
193
+ # 翻譯成繁體中文
194
+ progress_placeholder.text("正在翻譯成繁體中文...")
195
+ translation = translate_with_gemini(model, explanation)
196
+ progress_bar.progress(90)
197
+
198
+ # 創建結果DataFrame
199
+ results_data = {
200
+ "時間戳記": [datetime.now().isoformat()],
201
+ "原始內容": [page_text[:5000] + "..." if len(page_text) > 5000 else page_text],
202
+ "Gemini解釋": [explanation],
203
+ "繁體中文翻譯": [translation]
204
+ }
205
+ results_df = pd.DataFrame(results_data)
206
+
207
+ # 保存為CSV(臨時)
208
+ results_df.to_csv(output_filename, index=False, encoding="utf-8-sig")
209
+
210
+ # 完成
211
+ progress_bar.progress(100)
212
+ progress_placeholder.empty()
213
+
214
+ # 顯示結果
215
+ st.success("處理完成!")
216
+
217
+ # 創建選項卡顯示結果
218
+ tab1, tab2, tab3 = st.tabs(["Gemini解釋", "繁體中文翻譯", "CSV資料"])
219
+
220
+ with tab1:
221
+ st.subheader("Gemini解釋結果")
222
+ st.write(explanation)
223
+
224
+ with tab2:
225
+ st.subheader("繁體中文翻譯")
226
+ st.write(translation)
227
+
228
+ with tab3:
229
+ st.subheader("CSV資料預覽")
230
+ st.dataframe(results_df)
231
+ st.markdown(get_csv_download_link(results_df, output_filename), unsafe_allow_html=True)
232
+ st.info(f"CSV檔案已準備好下載。檔名: {output_filename}")
233
+ else:
234
+ # 未上傳檔案時顯示的內容
235
+ st.info("👈 請從側邊欄上傳PDF檔案開始")
236
+
237
+ # 顯示使用說明
238
+ with st.expander("使用說明", expanded=True):
239
+ st.markdown("""
240
+ ### 如何使用這個工具:
241
+
242
+ 1. **上傳PDF檔案** - 從側邊欄選擇並上傳PDF檔案
243
+ 2. **選擇頁面** - 使用滑桿選擇要處理的頁面
244
+ 3. **設定API金鑰** - 輸入您的Gemini API金鑰(預設已填入,可修改)
245
+ 4. **自訂指示詞** - 可選擇修改給Gemini的指示詞
246
+ 5. **處理與翻譯** - 點擊"處理並翻譯"按鈕
247
+ 6. **查看結果** - 在選項卡中查看Gemini的解釋和繁體中文翻譯
248
+ 7. **下載結果** - 下載CSV格式的結果檔案
249
+
250
+ ### 功能特點:
251
+
252
+ - 逐頁預覽PDF內容
253
+ - 使用Gemini AI解釋文本
254
+ - 自動翻譯成繁體中文
255
+ - 結果以CSV格式儲存
256
+ """)
257
 
258
+ # 頁尾
259
+ st.markdown("---")
260
+ st.markdown("📄 PDF處理與Gemini翻譯工具 | 由Streamlit和Google Gemini AI提供技術支持")