ginipick commited on
Commit
3f1f718
ยท
verified ยท
1 Parent(s): a14e8f5

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +618 -0
app.py ADDED
@@ -0,0 +1,618 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import json
4
+ from datetime import datetime, timedelta
5
+ import base64
6
+ import pandas as pd
7
+ import pydeck as pdk
8
+ import requests
9
+ from paper import (
10
+ literature_research_task, outline_task, draft_writing_task,
11
+ citation_task, editing_task, chatbot_task,
12
+ run_task
13
+ )
14
+
15
+ # Add web search functionality
16
+ def brave_search(query, count=10):
17
+ """
18
+ Perform a web search using Brave Search API
19
+ """
20
+ api_key = os.getenv("SEARCH_API")
21
+ if not api_key:
22
+ return "Error: Brave Search API key not found. Please set the SEARCH_API environment variable."
23
+
24
+ url = "https://api.search.brave.com/res/v1/web/search"
25
+ headers = {
26
+ "Accept": "application/json",
27
+ "Accept-Encoding": "gzip",
28
+ "X-Subscription-Token": api_key
29
+ }
30
+ params = {
31
+ "q": query,
32
+ "count": count
33
+ }
34
+
35
+ try:
36
+ response = requests.get(url, headers=headers, params=params)
37
+ response.raise_for_status()
38
+
39
+ results = response.json()
40
+ formatted_results = []
41
+
42
+ for result in results.get("web", {}).get("results", []):
43
+ formatted_results.append({
44
+ "title": result.get("title", ""),
45
+ "url": result.get("url", ""),
46
+ "description": result.get("description", "")
47
+ })
48
+
49
+ return formatted_results
50
+ except Exception as e:
51
+ return f"Search error: {str(e)}"
52
+
53
+ # st.set_page_config()๋Š” ๋‹ค๋ฅธ Streamlit ํ•จ์ˆ˜๋ณด๋‹ค ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
54
+ st.set_page_config(
55
+ page_title="Your AI Agent for Academic Research",
56
+ page_icon="๐Ÿ“š",
57
+ layout="wide",
58
+ initial_sidebar_state="expanded"
59
+ )
60
+
61
+ # ------------------------------------------
62
+ # ๋‹ค๊ตญ์–ด ์ง€์› (์˜์–ด/ํ•œ๊ตญ์–ด ์˜ˆ์‹œ)
63
+ # ------------------------------------------
64
+ translations = {
65
+ "en": {
66
+ "page_title": "Your AI Agent for Academic Research",
67
+ "header": "Your AI Agent for Academic Research",
68
+ "create_itinerary": "Generate Your Research Paper",
69
+ "trip_details": "Research Details",
70
+ "origin": "Research Topic",
71
+ "destination": "Paper Title",
72
+ "travel_dates": "Due Date",
73
+ "duration": "Paper Length (pages)",
74
+ "preferences": "Keywords/Focus",
75
+ "special_requirements": "Additional Instructions",
76
+ "submit": "๐Ÿš€ Generate My Research Paper",
77
+ "request_details": "Your Research Request",
78
+ "from": "Topic",
79
+ "when": "Due Date",
80
+ "budget": "Paper Type",
81
+ "travel_style": "Writing Style",
82
+ "live_agent_outputs": "Live Agent Outputs",
83
+ "full_itinerary": "Full Paper",
84
+ "details": "Details",
85
+ "download_share": "Download & Share",
86
+ "save_itinerary": "Save Your Paper",
87
+ "plan_another_trip": "๐Ÿ”„ Generate Another Paper",
88
+ "about": "About",
89
+ "how_it_works": "How it works",
90
+ "travel_agents": "Research Agents",
91
+ "share_itinerary": "Share Your Paper",
92
+ "save_for_mobile": "Save for Mobile",
93
+ "built_with": "Built with โค๏ธ for you",
94
+ "itinerary_ready": "Your Research Paper is Ready! ๐ŸŽ‰",
95
+ "personalized_experience": "We've created a personalized academic paper based on your inputs. Explore your paper below.",
96
+ "agent_activity": "Agent Activity",
97
+ "error_origin_destination": "Please enter both the research topic and paper title.",
98
+ "your_itinerary_file": "Your Paper File",
99
+ "text_format": "Text format - Can be opened in any text editor",
100
+ "web_search": "Web Search",
101
+ "search_placeholder": "Search for academic papers, journals, or information...",
102
+ "search_button": "Search",
103
+ "search_results": "Search Results"
104
+ },
105
+ "ko": {
106
+ "page_title": "๋‹น์‹ ์˜ ํ•™์ˆ  ์—ฐ๊ตฌ AI ์—์ด์ „ํŠธ",
107
+ "header": "๋‹น์‹ ์˜ ํ•™์ˆ  ์—ฐ๊ตฌ AI ์—์ด์ „ํŠธ",
108
+ "create_itinerary": "๋…ผ๋ฌธ ์ƒ์„ฑ",
109
+ "trip_details": "์—ฐ๊ตฌ ์„ธ๋ถ€์‚ฌํ•ญ",
110
+ "origin": "์—ฐ๊ตฌ ์ฃผ์ œ",
111
+ "destination": "๋…ผ๋ฌธ ์ œ๋ชฉ",
112
+ "travel_dates": "์ œ์ถœ ๊ธฐํ•œ",
113
+ "duration": "๋…ผ๋ฌธ ๋ถ„๋Ÿ‰ (ํŽ˜์ด์ง€)",
114
+ "preferences": "ํ‚ค์›Œ๋“œ/์ฃผ์š” ์ดˆ์ ",
115
+ "special_requirements": "์ถ”๊ฐ€ ์ง€์‹œ์‚ฌํ•ญ",
116
+ "submit": "๐Ÿš€ ๋‚˜์˜ ๋…ผ๋ฌธ ์ƒ์„ฑ",
117
+ "request_details": "์—ฐ๊ตฌ ์š”์ฒญ ์ •๋ณด",
118
+ "from": "์ฃผ์ œ",
119
+ "when": "์ œ์ถœ ๊ธฐํ•œ",
120
+ "budget": "๋…ผ๋ฌธ ์ข…๋ฅ˜",
121
+ "travel_style": "์ž‘์„ฑ ์Šคํƒ€์ผ",
122
+ "live_agent_outputs": "์‹ค์‹œ๊ฐ„ ์—์ด์ „ํŠธ ๊ฒฐ๊ณผ",
123
+ "full_itinerary": "์ „์ฒด ๋…ผ๋ฌธ",
124
+ "details": "์„ธ๋ถ€์‚ฌํ•ญ",
125
+ "download_share": "๋‹ค์šด๋กœ๋“œ ๋ฐ ๊ณต์œ ",
126
+ "save_itinerary": "๋…ผ๋ฌธ ์ €์žฅ",
127
+ "plan_another_trip": "๐Ÿ”„ ๋‹ค๋ฅธ ๋…ผ๋ฌธ ์ƒ์„ฑ",
128
+ "about": "์†Œ๊ฐœ",
129
+ "how_it_works": "์ž‘๋™ ๋ฐฉ์‹",
130
+ "travel_agents": "์—ฐ๊ตฌ ์—์ด์ „ํŠธ",
131
+ "share_itinerary": "๋…ผ๋ฌธ ๊ณต์œ ",
132
+ "save_for_mobile": "๋ชจ๋ฐ”์ผ ์ €์žฅ",
133
+ "built_with": "๋‹น์‹ ์„ ์œ„ํ•ด โค๏ธ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค",
134
+ "itinerary_ready": "๋…ผ๋ฌธ์ด ์ค€๋น„๋˜์—ˆ์Šต๋‹ˆ๋‹ค! ๐ŸŽ‰",
135
+ "personalized_experience": "์ž…๋ ฅํ•˜์‹  ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋งž์ถคํ˜• ๋…ผ๋ฌธ์ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ ๋…ผ๋ฌธ์„ ํ™•์ธํ•˜์„ธ์š”.",
136
+ "agent_activity": "์—์ด์ „ํŠธ ํ™œ๋™",
137
+ "error_origin_destination": "์—ฐ๊ตฌ ์ฃผ์ œ์™€ ๋…ผ๋ฌธ ์ œ๋ชฉ์„ ๋ชจ๋‘ ์ž…๋ ฅํ•˜์„ธ์š”.",
138
+ "your_itinerary_file": "๋…ผ๋ฌธ ํŒŒ์ผ",
139
+ "text_format": "ํ…์ŠคํŠธ ํ˜•์‹ - ๋ชจ๋“  ํ…์ŠคํŠธ ํŽธ์ง‘๊ธฐ์—์„œ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.",
140
+ "web_search": "์›น ๊ฒ€์ƒ‰",
141
+ "search_placeholder": "ํ•™์ˆ  ๋…ผ๋ฌธ, ์ €๋„ ๋˜๋Š” ์ •๋ณด ๊ฒ€์ƒ‰...",
142
+ "search_button": "๊ฒ€์ƒ‰",
143
+ "search_results": "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ"
144
+ }
145
+ }
146
+
147
+ def t(key):
148
+ lang = st.session_state.get("selected_language", "en")
149
+ return translations[lang].get(key, key)
150
+
151
+ # ---------------------------
152
+ # ์„ธ์…˜ ์ดˆ๊ธฐํ™”
153
+ # ---------------------------
154
+ if 'selected_language' not in st.session_state:
155
+ st.session_state.selected_language = "en"
156
+
157
+ # ------------------------------------------
158
+ # ์‚ฌ์ด๋“œ๋ฐ”์— ์–ธ์–ด ์„ ํƒ ์œ„์ ฏ ์ถ”๊ฐ€
159
+ # ------------------------------------------
160
+ with st.sidebar:
161
+ language = st.selectbox(
162
+ "Language / ์–ธ์–ด",
163
+ ["English", "ํ•œ๊ตญ์–ด"]
164
+ )
165
+ lang_map = {
166
+ "English": "en",
167
+ "ํ•œ๊ตญ์–ด": "ko"
168
+ }
169
+ st.session_state.selected_language = lang_map.get(language, "en")
170
+
171
+ # Add web search component to sidebar
172
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
173
+ st.markdown("### " + t("web_search"))
174
+ search_query = st.text_input(t("search_placeholder"), key="search_query")
175
+ search_button = st.button(t("search_button"))
176
+
177
+ if search_button and search_query:
178
+ with st.spinner("Searching..."):
179
+ search_results = brave_search(search_query)
180
+ if isinstance(search_results, str) and "error" in search_results.lower():
181
+ st.error(search_results)
182
+ else:
183
+ st.success(f"Found {len(search_results)} results")
184
+ st.session_state.search_results = search_results
185
+
186
+ if 'search_results' in st.session_state and st.session_state.search_results:
187
+ st.markdown(f"### {t('search_results')}")
188
+ for i, result in enumerate(st.session_state.search_results[:5]):
189
+ st.markdown(f"**{i+1}. [{result['title']}]({result['url']})**")
190
+ st.markdown(f"{result['description']}")
191
+ st.markdown("---")
192
+ st.markdown('</div>', unsafe_allow_html=True)
193
+
194
+ # ------------------------------------------
195
+ # UI ์‹œ์ž‘
196
+ # ------------------------------------------
197
+ st.markdown("""
198
+ <style>
199
+ :root {
200
+ --primary: #3a86ff;
201
+ --primary-light: #4895ef;
202
+ --primary-dark: #2667ff;
203
+ --background: #f8f9fa;
204
+ --card-bg: #ffffff;
205
+ --text: #212529;
206
+ --border: #e9ecef;
207
+ }
208
+ .main-header {
209
+ font-size: 2.5rem;
210
+ color: var(--primary-dark);
211
+ text-align: center;
212
+ margin-bottom: 0.8rem;
213
+ font-weight: 700;
214
+ }
215
+ .modern-card {
216
+ background-color: var(--card-bg);
217
+ border-radius: 10px;
218
+ padding: 1.2rem;
219
+ margin-bottom: 1.2rem;
220
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
221
+ border: 1px solid var(--border);
222
+ }
223
+ </style>
224
+ """, unsafe_allow_html=True)
225
+
226
+ def get_download_link(text_content, filename):
227
+ b64 = base64.b64encode(text_content.encode()).decode()
228
+ href = f'<a class="download-link" href="data:text/plain;base64,{b64}" download="{filename}"><i>๐Ÿ“ฅ</i> {t("save_itinerary")}</a>'
229
+ return href
230
+
231
+ def display_modern_progress(current_step, total_steps=5):
232
+ if 'progress_steps' not in st.session_state:
233
+ st.session_state.progress_steps = {
234
+ 0: {'status': 'pending', 'name': t("trip_details")},
235
+ 1: {'status': 'pending', 'name': t("about")},
236
+ 2: {'status': 'pending', 'name': t("live_agent_outputs")},
237
+ 3: {'status': 'pending', 'name': t("download_share")},
238
+ 4: {'status': 'pending', 'name': t("full_itinerary")}
239
+ }
240
+ for i in range(total_steps):
241
+ if i < current_step:
242
+ st.session_state.progress_steps[i]['status'] = 'complete'
243
+ elif i == current_step:
244
+ st.session_state.progress_steps[i]['status'] = 'active'
245
+ else:
246
+ st.session_state.progress_steps[i]['status'] = 'pending'
247
+ progress_percentage = (current_step / total_steps) * 100
248
+ st.progress(progress_percentage / 100)
249
+ st.markdown("<div>Progress: " + str(progress_percentage) + "% completed.</div>")
250
+ return progress_percentage
251
+
252
+ def update_step_status(step_index, status):
253
+ if 'progress_steps' in st.session_state and step_index in st.session_state.progress_steps:
254
+ st.session_state.progress_steps[step_index]['status'] = status
255
+
256
+ def run_task_with_logs(task, input_text, log_container, output_container, results_key=None):
257
+ log_message = f"๐Ÿค– Starting {task.agent.role}..."
258
+ st.session_state.log_messages.append(log_message)
259
+ with log_container:
260
+ st.markdown("### " + t("agent_activity"))
261
+ for msg in st.session_state.log_messages:
262
+ st.markdown(msg)
263
+
264
+ # Enhance with web search if needed
265
+ if "include_search" in input_text.lower():
266
+ search_query = task.agent.role + " about " + st.session_state.research_topic
267
+ search_results = brave_search(search_query, count=5)
268
+
269
+ if not isinstance(search_results, str): # If not error message
270
+ search_info = "\n\nWeb Search Results for reference:\n"
271
+ for i, result in enumerate(search_results):
272
+ search_info += f"{i+1}. {result['title']} - {result['url']}\n"
273
+ search_info += f" {result['description']}\n\n"
274
+
275
+ input_text += search_info
276
+ log_message = f"๐Ÿ” Added web search results for {search_query}"
277
+ st.session_state.log_messages.append(log_message)
278
+
279
+ result = run_task(task, input_text)
280
+ if results_key:
281
+ st.session_state.results[results_key] = result
282
+ log_message = f"โœ… {task.agent.role} completed!"
283
+ st.session_state.log_messages.append(log_message)
284
+ with log_container:
285
+ st.markdown("### " + t("agent_activity"))
286
+ for msg in st.session_state.log_messages:
287
+ st.markdown(msg)
288
+ with output_container:
289
+ st.markdown(f"### {task.agent.role} Output")
290
+ st.markdown("<div class='agent-output'>" + result + "</div>", unsafe_allow_html=True)
291
+ return result
292
+
293
+ if 'generated_itinerary' not in st.session_state:
294
+ st.session_state.generated_itinerary = None
295
+ if 'generation_complete' not in st.session_state:
296
+ st.session_state.generation_complete = False
297
+ if 'current_step' not in st.session_state:
298
+ st.session_state.current_step = 0
299
+ if 'results' not in st.session_state:
300
+ st.session_state.results = {
301
+ "literature_review": "",
302
+ "outline": "",
303
+ "draft": "",
304
+ "citations": "",
305
+ "edited": ""
306
+ }
307
+ if 'log_messages' not in st.session_state:
308
+ st.session_state.log_messages = []
309
+ if 'form_submitted' not in st.session_state:
310
+ st.session_state.form_submitted = False
311
+
312
+ st.markdown(f"""
313
+ <div style="text-align: center;">
314
+ <img src="https://img.icons8.com/fluency/96/book.png" width="90">
315
+ <h1 class="main-header">{t("header")}</h1>
316
+ <p>Generate your personalized research paper with AI-powered academic agents.</p>
317
+ </div>
318
+ """, unsafe_allow_html=True)
319
+ st.markdown('<hr>', unsafe_allow_html=True)
320
+
321
+ with st.sidebar:
322
+ st.markdown("""
323
+ <div style="text-align: center;">
324
+ <img src="https://img.icons8.com/fluency/96/book.png" width="80">
325
+ <h3>Your AI Academic Research Assistant</h3>
326
+ <p>AI-Powered Paper Generation</p>
327
+ </div>
328
+ """, unsafe_allow_html=True)
329
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
330
+ st.markdown("### " + t("about"))
331
+ st.info("This tool generates a personalized academic research paper based on your inputs. Fill in the form and let our specialized agents craft your paper!")
332
+ st.markdown('</div>', unsafe_allow_html=True)
333
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
334
+ st.markdown("### " + t("how_it_works"))
335
+ st.markdown("""
336
+ <ol>
337
+ <li>Enter your research details</li>
338
+ <li>AI conducts literature research</li>
339
+ <li>Generate a paper outline</li>
340
+ <li>Draft and edit your paper</li>
341
+ <li>Download your final paper</li>
342
+ </ol>
343
+ """, unsafe_allow_html=True)
344
+ st.markdown('</div>', unsafe_allow_html=True)
345
+
346
+ if not st.session_state.generation_complete:
347
+ st.markdown('<div class="modern-card">', unsafe_allow_html=True)
348
+ st.markdown("<h3>" + t("create_itinerary") + "</h3>", unsafe_allow_html=True)
349
+ st.markdown("<p>Fill in the details below to generate your research paper.</p>", unsafe_allow_html=True)
350
+
351
+ with st.form("research_form"):
352
+ col1, col2 = st.columns(2)
353
+ with col1:
354
+ research_topic = st.text_input(t("origin"), placeholder="e.g., Deep Learning in Healthcare")
355
+ paper_title = st.text_input(t("destination"), placeholder="e.g., Advances in Deep Learning for Medical Diagnosis")
356
+ due_date = st.date_input(t("travel_dates"), min_value=datetime.now())
357
+ with col2:
358
+ paper_length = st.slider(t("duration"), min_value=5, max_value=50, value=10)
359
+ paper_type_options = ["Journal", "Conference", "Thesis", "Review"]
360
+ paper_type = st.selectbox(t("budget"), paper_type_options, help="Select the type of paper")
361
+ writing_style = st.multiselect(t("travel_style"), options=["Formal", "Technical", "Creative"], default=["Formal"])
362
+ additional_instructions = st.text_area(t("special_requirements"), placeholder="Any additional instructions or requirements...")
363
+ keywords = st.text_area(t("preferences"), placeholder="Enter keywords or focus areas, separated by commas")
364
+
365
+ # Add option to include web search
366
+ include_search = st.checkbox("Include web search for latest references", value=True)
367
+
368
+ submit_button = st.form_submit_button(t("submit"))
369
+ st.markdown('</div>', unsafe_allow_html=True)
370
+
371
+ if submit_button:
372
+ if not research_topic or not paper_title:
373
+ st.error(t("error_origin_destination"))
374
+ else:
375
+ st.session_state.form_submitted = True
376
+ st.session_state.research_topic = research_topic
377
+ user_input = {
378
+ "research_topic": research_topic,
379
+ "paper_title": paper_title,
380
+ "due_date": due_date.strftime("%Y-%m-%d"),
381
+ "paper_length": str(paper_length),
382
+ "paper_type": paper_type,
383
+ "writing_style": ", ".join(writing_style),
384
+ "keywords": keywords,
385
+ "additional_instructions": additional_instructions,
386
+ "include_search": "include_search" if include_search else ""
387
+ }
388
+ st.session_state.user_input = user_input
389
+ input_context = f"""Research Request Details:
390
+ Research Topic: {user_input['research_topic']}
391
+ Paper Title: {user_input['paper_title']}
392
+ Due Date: {user_input['due_date']}
393
+ Paper Length: {user_input['paper_length']} pages
394
+ Paper Type: {user_input['paper_type']}
395
+ Writing Style: {user_input['writing_style']}
396
+ Keywords/Focus: {user_input['keywords']}
397
+ Additional Instructions: {user_input['additional_instructions']}
398
+ {user_input['include_search']}
399
+ """
400
+ llm_language_instructions = {
401
+ "en": "Please output the response in English.",
402
+ "ko": "ํ•œ๊ตญ์–ด๋กœ ์ถœ๋ ฅํ•ด ์ฃผ์„ธ์š”."
403
+ }
404
+ selected_lang = st.session_state.get("selected_language", "en")
405
+ language_instruction = llm_language_instructions.get(selected_lang, "Please output the response in English.")
406
+ modified_input_context = language_instruction + "\n" + input_context
407
+
408
+ st.markdown("<div>Processing your request...</div>", unsafe_allow_html=True)
409
+ st.session_state.current_step = 0
410
+ update_step_status(0, 'active')
411
+ progress_placeholder = st.empty()
412
+ with progress_placeholder.container():
413
+ display_modern_progress(st.session_state.current_step)
414
+ log_container = st.container()
415
+ st.session_state.log_messages = []
416
+ output_container = st.container()
417
+ st.session_state.results = {}
418
+
419
+ # Step 1: Literature Research
420
+ literature_review = run_task_with_logs(
421
+ literature_research_task,
422
+ modified_input_context.format(topic=user_input['research_topic'], keywords=user_input['keywords']),
423
+ log_container,
424
+ output_container,
425
+ "literature_review"
426
+ )
427
+ update_step_status(0, 'complete')
428
+ st.session_state.current_step = 1
429
+ update_step_status(1, 'active')
430
+ with progress_placeholder.container():
431
+ display_modern_progress(st.session_state.current_step)
432
+
433
+ # Step 2: Generate Outline
434
+ outline = run_task_with_logs(
435
+ outline_task,
436
+ modified_input_context.format(topic=user_input['research_topic']),
437
+ log_container,
438
+ output_container,
439
+ "outline"
440
+ )
441
+ update_step_status(1, 'complete')
442
+ st.session_state.current_step = 2
443
+ update_step_status(2, 'active')
444
+ with progress_placeholder.container():
445
+ display_modern_progress(st.session_state.current_step)
446
+
447
+ # Step 3: Draft Writing
448
+ draft = run_task_with_logs(
449
+ draft_writing_task,
450
+ modified_input_context.format(topic=user_input['research_topic']),
451
+ log_container,
452
+ output_container,
453
+ "draft"
454
+ )
455
+ update_step_status(2, 'complete')
456
+ st.session_state.current_step = 3
457
+ update_step_status(3, 'active')
458
+ with progress_placeholder.container():
459
+ display_modern_progress(st.session_state.current_step)
460
+
461
+ # Step 4: Citation Generation
462
+ citations = run_task_with_logs(
463
+ citation_task,
464
+ modified_input_context.format(topic=user_input['research_topic']),
465
+ log_container,
466
+ output_container,
467
+ "citations"
468
+ )
469
+ update_step_status(3, 'complete')
470
+ st.session_state.current_step = 4
471
+ update_step_status(4, 'active')
472
+ with progress_placeholder.container():
473
+ display_modern_progress(st.session_state.current_step)
474
+
475
+ # Step 5: Editing and Polishing
476
+ edited = run_task_with_logs(
477
+ editing_task,
478
+ modified_input_context.format(topic=user_input['research_topic']),
479
+ log_container,
480
+ output_container,
481
+ "edited"
482
+ )
483
+ update_step_status(4, 'complete')
484
+ st.session_state.current_step = 5
485
+ with progress_placeholder.container():
486
+ display_modern_progress(st.session_state.current_step)
487
+
488
+ full_paper = f"""Research Paper:
489
+ {input_context}
490
+
491
+ Literature Review:
492
+ {literature_review}
493
+
494
+ Outline:
495
+ {outline}
496
+
497
+ Draft:
498
+ {draft}
499
+
500
+ Citations:
501
+ {citations}
502
+
503
+ Edited Version:
504
+ {edited}
505
+ """
506
+ st.session_state.generated_itinerary = full_paper
507
+ st.session_state.generation_complete = True
508
+ date_str = datetime.now().strftime("%Y-%m-%d")
509
+ st.session_state.filename = f"{user_input['paper_title'].replace(' ', '_')}_{date_str}_paper.txt"
510
+
511
+ if st.session_state.generation_complete:
512
+ st.markdown(f"""
513
+ <div class="modern-card">
514
+ <div style="text-align: center;">
515
+ <h2>{t("itinerary_ready")}</h2>
516
+ <p>{t("personalized_experience")}</p>
517
+ </div>
518
+ </div>
519
+ """, unsafe_allow_html=True)
520
+
521
+ # ํƒญ ์ƒ์„ฑ (์ „์ฒด ๋…ผ๋ฌธ, ์„ธ๋ถ€ ์ •๋ณด, ๋‹ค์šด๋กœ๋“œ/๊ณต์œ , ์‹œ๊ฐํ™”, ์ฑ—๋ด‡)
522
+ full_paper_tab, details_tab, download_tab, visualization_tab, chatbot_tab = st.tabs([
523
+ "๐Ÿ—’๏ธ " + t("full_itinerary"),
524
+ "๐Ÿ’ผ " + t("details"),
525
+ "๐Ÿ’พ " + t("download_share"),
526
+ "๐Ÿ“Š Visualization",
527
+ "๐Ÿค– ์ฑ—๋ด‡ ์ธํ„ฐํŽ˜์ด์Šค"
528
+ ])
529
+
530
+ with full_paper_tab:
531
+ st.text_area("Your Research Paper", st.session_state.generated_itinerary, height=600)
532
+
533
+ with details_tab:
534
+ agent_tabs = st.tabs(["๐Ÿ“š Literature Review", "๐Ÿ“ Outline", "โœ๏ธ Draft", "๐Ÿ”— Citations", "๐Ÿ–‹๏ธ Edited Version"])
535
+ with agent_tabs[0]:
536
+ st.markdown("### Literature Review")
537
+ st.markdown(st.session_state.results.get("literature_review", ""))
538
+ with agent_tabs[1]:
539
+ st.markdown("### Outline")
540
+ st.markdown(st.session_state.results.get("outline", ""))
541
+ with agent_tabs[2]:
542
+ st.markdown("### Draft")
543
+ st.markdown(st.session_state.results.get("draft", ""))
544
+ with agent_tabs[3]:
545
+ st.markdown("### Citations")
546
+ st.markdown(st.session_state.results.get("citations", ""))
547
+ with agent_tabs[4]:
548
+ st.markdown("### Edited Version")
549
+ st.markdown(st.session_state.results.get("edited", ""))
550
+
551
+ with download_tab:
552
+ col1, col2 = st.columns([2, 1])
553
+ with col1:
554
+ st.markdown("### " + t("save_itinerary"))
555
+ st.markdown("Download your research paper to access it offline or share with your colleagues.")
556
+ st.markdown(f"""
557
+ <div style="background-color: #f8f9fa; padding: 15px; border-radius: 10px; margin-top: 20px;">
558
+ <h4>{t("your_itinerary_file")}</h4>
559
+ <p style="font-size: 0.9rem; color: #6c757d;">{t("text_format")}</p>
560
+ </div>
561
+ """, unsafe_allow_html=True)
562
+ st.markdown("<div>" + get_download_link(st.session_state.generated_itinerary, st.session_state.filename) + "</div>", unsafe_allow_html=True)
563
+ st.markdown("### " + t("share_itinerary"))
564
+ st.markdown("*Coming soon: Email your paper or share via social media.*")
565
+ with col2:
566
+ st.markdown("### " + t("save_for_mobile"))
567
+ st.markdown("*Coming soon: QR code for easy access on your phone*")
568
+
569
+ with visualization_tab:
570
+ st.markdown("### Visualization")
571
+ st.markdown("A conceptual diagram or visualization related to your research paper can be displayed here. (Feature under development)")
572
+
573
+ with chatbot_tab:
574
+ st.markdown("### AI ์ฑ—๋ด‡ ์ธํ„ฐํŽ˜์ด์Šค")
575
+ if "chat_history" not in st.session_state:
576
+ st.session_state.chat_history = []
577
+
578
+ user_message = st.text_input("๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”:", key="chat_input")
579
+ if st.button("์ „์†ก", key="send_button"):
580
+ if user_message:
581
+ # Add option to search when chatting
582
+ if "search" in user_message.lower() or "find" in user_message.lower() or "look up" in user_message.lower():
583
+ search_results = brave_search(user_message, count=3)
584
+ if not isinstance(search_results, str):
585
+ search_context = f"I found some information that might help:\n\n"
586
+ for i, result in enumerate(search_results):
587
+ search_context += f"{i+1}. {result['title']} - {result['url']}\n"
588
+ search_context += f" {result['description']}\n\n"
589
+
590
+ enhanced_prompt = f"{user_message}\n\nSearch context: {search_context}"
591
+ response = run_task(chatbot_task, enhanced_prompt)
592
+ else:
593
+ response = run_task(chatbot_task, user_message)
594
+ else:
595
+ response = run_task(chatbot_task, user_message)
596
+
597
+ st.session_state.chat_history.append({
598
+ "speaker": "์‚ฌ์šฉ์ž",
599
+ "message": user_message,
600
+ "time": datetime.now()
601
+ })
602
+ st.session_state.chat_history.append({
603
+ "speaker": "AI",
604
+ "message": response,
605
+ "time": datetime.now()
606
+ })
607
+
608
+ st.markdown("<div style='max-height:400px; overflow-y:auto; padding:10px; border:1px solid #eaeaea; border-radius:6px;'>", unsafe_allow_html=True)
609
+ for chat in st.session_state.chat_history:
610
+ time_str = chat["time"].strftime("%H:%M:%S")
611
+ st.markdown(f"**{chat['speaker']}** ({time_str}): {chat['message']}")
612
+ st.markdown("</div>", unsafe_allow_html=True)
613
+
614
+ st.markdown("""
615
+ <div style="text-align: center; padding: 20px; color: #6c757d; font-size: 0.8rem;">
616
+ <p>""" + t("built_with") + """</p>
617
+ </div>
618
+ """, unsafe_allow_html=True)