npc0 commited on
Commit
b8becf7
·
verified ·
1 Parent(s): 1a77671

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +204 -39
app.py CHANGED
@@ -1,58 +1,223 @@
1
  import os
2
- import subprocess
3
  import gradio as gr
4
  from epub2txt import epub2txt
5
- from websocket import create_connection
6
-
7
- if not os.path.exists(os.getenv("checkpoint_path")):
8
- os.system("git clone --recurse-submodules https://github.com/ztxz16/fastllm.git")
9
- os.system("cd fastllm; mkdir build; cd build; cmake ..; make -j; cd tools; python setup.py install --user --prefix=")
10
- os.system("wget https://huggingface.co/huangyuyang/chatglm2-6b-int4.flm/resolve/main/chatglm2-6b-int4.flm")
11
- subprocess.Popen(["uvicorn", "api:app"])
12
 
13
  class GUI:
14
  def __init__(self, *args, **kwargs):
15
- with gr.Blocks() as demo:
 
 
 
 
 
 
16
  with gr.Row():
17
  gr.Markdown(scale=2).attach_load_event(self.hello, None)
18
  gr.LoginButton()
19
  gr.LogoutButton()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  out = gr.Markdown()
21
- inp = gr.File(file_types=['.epub'])
 
 
 
 
 
 
 
 
 
 
 
22
  inp.change(self.process, inp, out)
23
- self.ws = None
24
- self.out = []
25
  demo.queue(concurrency_count=2).launch()
26
 
27
- def process(self, file, profile: gr.OAuthProfile | None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  if profile is None:
29
  return gr.update(value='Login to access the tool.')
30
 
31
- h = ''
32
- chapter_titles = epub2txt.content_titles
33
- title = epub2txt.title
34
- if self.ws is None:
35
- self.ws = create_connection(f"ws://localhost:8000/ws")
36
- self.ws.send(file.name)
37
- res = ''
38
- while 'output: ' not in res:
39
- res = self.ws.recv()
40
- if 'chsum: ' in res:
41
- self.out.append(res.replace("chsum: ", ""))
42
- elif 'draft_sum: ' in res:
43
- h = res[11:]
44
- elif 'output: ' in res:
45
- self.ws.close()
46
- self.ws = None
47
- self.out = []
48
- yield gr.update(value=res)
49
- yield gr.update(
50
- value=f"# {title}\n\n" +h+ "\n\n".join(
51
- [f"## {ct}\n\n{c}" for ct, c in zip(chapter_titles, self.out)]))
52
-
53
- def hello(self, profile: gr.OAuthProfile | None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  if profile is None:
55
- return '# ePub summarization tool\n\nLogin to access the tool.'
56
- return f"# ePub summarization tool\n\nWelcome {profile.name}!!"
 
 
 
 
57
 
58
- GUI()
 
 
 
1
  import os
2
+ import openai
3
  import gradio as gr
4
  from epub2txt import epub2txt
 
 
 
 
 
 
 
5
 
6
  class GUI:
7
  def __init__(self, *args, **kwargs):
8
+ # Configuration
9
+ self.model_name = os.getenv("POE_MODEL", "GPT-5-mini")
10
+ self.prompt = os.getenv("prompt", "Summarize the following text:")
11
+ self.client = None
12
+ self.api_key = os.getenv("POE_API_KEY")
13
+
14
+ with gr.Blocks(title="ePub Summarizer") as demo:
15
  with gr.Row():
16
  gr.Markdown(scale=2).attach_load_event(self.hello, None)
17
  gr.LoginButton()
18
  gr.LogoutButton()
19
+
20
+ # API Key input section
21
+ with gr.Row(visible=not self.api_key):
22
+ with gr.Column():
23
+ gr.Markdown("""
24
+ ### Poe API Key Required
25
+
26
+ To use this tool, you need a Poe API key:
27
+
28
+ 1. Visit [https://poe.com/api_key](https://poe.com/api_key)
29
+ 2. If you don't have an account, create one first
30
+ 3. Generate a new API key or copy your existing one
31
+ 4. Paste it in the field below
32
+
33
+ **Note**: Your API key is only stored temporarily during this session for security.
34
+ """)
35
+ api_key_input = gr.Textbox(
36
+ label="Poe API Key",
37
+ placeholder="Enter your Poe API key here...",
38
+ type="password"
39
+ )
40
+ api_key_btn = gr.Button("Set API Key", variant="primary")
41
+
42
  out = gr.Markdown()
43
+ inp = gr.File(file_types=['.epub'], visible=bool(self.api_key))
44
+
45
+ # Set up event handlers
46
+ if not self.api_key:
47
+ api_key_btn.click(
48
+ self.set_api_key,
49
+ inputs=[api_key_input],
50
+ outputs=[out, inp]
51
+ )
52
+ else:
53
+ self._initialize_client()
54
+
55
  inp.change(self.process, inp, out)
56
+
 
57
  demo.queue(concurrency_count=2).launch()
58
 
59
+ def _initialize_client(self):
60
+ """Initialize the Poe API client"""
61
+ try:
62
+ self.client = openai.OpenAI(
63
+ api_key=self.api_key,
64
+ base_url="https://api.poe.com/v1",
65
+ )
66
+ return True
67
+ except Exception as e:
68
+ print(f"Error initializing Poe client: {e}")
69
+ return False
70
+
71
+ def set_api_key(self, api_key):
72
+ """Set and validate the API key"""
73
+ if not api_key or not api_key.strip():
74
+ return gr.update(value="⚠️ Please enter a valid API key."), gr.update(visible=False)
75
+
76
+ self.api_key = api_key.strip()
77
+
78
+ if self._initialize_client():
79
+ # Test the API key with a simple request
80
+ try:
81
+ test_chat = self.client.chat.completions.create(
82
+ model=self.model_name,
83
+ messages=[{"role": "user", "content": "Hello"}],
84
+ max_tokens=10
85
+ )
86
+ return (
87
+ gr.update(value="✅ API key validated successfully! You can now upload an ePub file."),
88
+ gr.update(visible=True)
89
+ )
90
+ except Exception as e:
91
+ error_msg = str(e)
92
+ if "401" in error_msg or "unauthorized" in error_msg.lower():
93
+ return (
94
+ gr.update(value="❌ Invalid API key. Please check your key and try again."),
95
+ gr.update(visible=False)
96
+ )
97
+ elif "quota" in error_msg.lower() or "limit" in error_msg.lower():
98
+ return (
99
+ gr.update(value="⚠️ API key valid but quota exceeded. Please check your Poe account."),
100
+ gr.update(visible=False)
101
+ )
102
+ else:
103
+ return (
104
+ gr.update(value=f"❌ API connection error: {error_msg}"),
105
+ gr.update(visible=False)
106
+ )
107
+ else:
108
+ return (
109
+ gr.update(value="❌ Failed to initialize API client."),
110
+ gr.update(visible=False)
111
+ )
112
+
113
+ def get_model_response(self, text: str) -> str:
114
+ """
115
+ Get response from Poe API for the given text
116
+ """
117
+ if not self.client:
118
+ return "Error: API client not initialized"
119
+
120
+ try:
121
+ chat = self.client.chat.completions.create(
122
+ model=self.model_name,
123
+ messages=[{"role": "user", "content": text}],
124
+ )
125
+ return chat.choices[0].message.content
126
+ except Exception as e:
127
+ print(f"Error calling Poe API: {e}")
128
+ return f"Error processing text: {str(e)}"
129
+
130
+ def process(self, file, profile: gr.OAuthProfile | None = None):
131
  if profile is None:
132
  return gr.update(value='Login to access the tool.')
133
 
134
+ if not self.client:
135
+ return gr.update(value='⚠️ Please set your Poe API key first.')
136
+
137
+ if file is None:
138
+ return gr.update(value='Please upload an ePub file.')
139
+
140
+ try:
141
+ # Extract content from ePub
142
+ ch_list = epub2txt(file.name, outputlist=True)
143
+ chapter_titles = epub2txt.content_titles
144
+ title = epub2txt.title
145
+
146
+ yield gr.update(value=f"# {title}\n\nProcessing ePub file...")
147
+
148
+ sm_list = []
149
+
150
+ # Process each chapter (skip first 2 as they're usually metadata)
151
+ for idx, text in enumerate(ch_list[2:], 1):
152
+ if not text.strip():
153
+ continue
154
+
155
+ yield gr.update(value=f"# {title}\n\nProcessing chapter {idx}...")
156
+
157
+ docs = []
158
+ # Split chapter into chunks for processing
159
+ chunk_size = 2000
160
+ for i in range(0, len(text), chunk_size):
161
+ chunk = text[i:i+2048] # Slight overlap for context
162
+ if len(chunk.strip()) > 0:
163
+ response = self.get_model_response(self.prompt + "\n\n" + chunk)
164
+ docs.append(response)
165
+
166
+ # Update UI with current progress
167
+ current_summaries = "\n\n".join([
168
+ f"## {ct}\n\n{sm}"
169
+ for ct, sm in zip(chapter_titles[2:idx+1], sm_list + [f"Processing chunk {len(docs)}..."])
170
+ ])
171
+ yield gr.update(value=f"# {title}\n\n{current_summaries}")
172
+
173
+ # Combine chunk summaries into chapter summary
174
+ if docs:
175
+ if len(docs) == 1:
176
+ hist = docs[0]
177
+ else:
178
+ hist = docs[0]
179
+ for doc in docs[1:]:
180
+ combined_text = f"{self.prompt}\n\nCombine these summaries:\n\n{hist}\n\n{doc}"
181
+ hist = self.get_model_response(combined_text)
182
+
183
+ # Update UI with draft summary
184
+ current_summaries = "\n\n".join([
185
+ f"## {ct}\n\n{sm}"
186
+ for ct, sm in zip(chapter_titles[2:idx+1], sm_list + [f"Draft: {hist}"])
187
+ ])
188
+ yield gr.update(value=f"# {title}\n\n{current_summaries}")
189
+
190
+ sm_list.append(hist)
191
+
192
+ # Update final output for this chapter
193
+ final_summaries = "\n\n".join([
194
+ f"## {ct}\n\n{sm}"
195
+ for ct, sm in zip(chapter_titles[2:idx+1], sm_list)
196
+ ])
197
+ yield gr.update(value=f"# {title}\n\n{final_summaries}")
198
+
199
+ # Final complete summary
200
+ if sm_list:
201
+ complete_summary = f"# {title}\n\n" + "\n\n".join([
202
+ f"## {ct}\n\n{sm}"
203
+ for ct, sm in zip(chapter_titles[2:len(sm_list)+2], sm_list)
204
+ ])
205
+ yield gr.update(value=complete_summary)
206
+ else:
207
+ yield gr.update(value=f"# {title}\n\nNo content found to summarize.")
208
+
209
+ except Exception as e:
210
+ yield gr.update(value=f"Error processing file: {str(e)}")
211
+
212
+ def hello(self, profile: gr.OAuthProfile | None = None):
213
  if profile is None:
214
+ return '# ePub Summarization Tool\n\nLogin to access the tool.'
215
+
216
+ if not self.api_key:
217
+ return f"# ePub Summarization Tool\n\nWelcome {profile.name}!\n\nPlease set your Poe API key below to get started."
218
+
219
+ return f"# ePub Summarization Tool\n\nWelcome {profile.name}! Ready to summarize ePub files."
220
 
221
+ # Run the application
222
+ if __name__ == "__main__":
223
+ GUI()