sunbal7 commited on
Commit
fbec6c3
Β·
verified Β·
1 Parent(s): be92f78

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +268 -0
app.py ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+
3
+ import os
4
+ import streamlit as st
5
+ import arxiv
6
+ import networkx as nx
7
+ import matplotlib.pyplot as plt
8
+ import datetime
9
+
10
+ # -------------------------------
11
+ # Groq API Client
12
+ # -------------------------------
13
+ from groq import Groq
14
+
15
+ client = Groq(
16
+ api_key=os.environ.get("GROQ_API_KEY"),
17
+ )
18
+
19
+ # -------------------------------
20
+ # Helper Functions (Groq-based)
21
+ # -------------------------------
22
+ def groq_summarize(text: str) -> str:
23
+ """
24
+ Summarize the given text using Groq's chat completion API.
25
+ Adjust the prompt or model as needed.
26
+ """
27
+ response = client.chat.completions.create(
28
+ messages=[
29
+ {
30
+ "role": "user",
31
+ "content": f"Summarize the following text in detail:\n\n{text}"
32
+ }
33
+ ],
34
+ model="llama-3.3-70b-versatile",
35
+ )
36
+ return response.choices[0].message.content.strip()
37
+
38
+ def groq_generate(text: str) -> str:
39
+ """
40
+ Generate text (e.g., research proposals) using Groq's chat completion API.
41
+ Adjust the prompt or model as needed.
42
+ """
43
+ response = client.chat.completions.create(
44
+ messages=[
45
+ {
46
+ "role": "user",
47
+ "content": text
48
+ }
49
+ ],
50
+ model="llama-3.3-70b-versatile",
51
+ )
52
+ return response.choices[0].message.content.strip()
53
+
54
+ # -------------------------------
55
+ # Existing Helper Functions
56
+ # -------------------------------
57
+ def retrieve_papers(query, max_results=5):
58
+ """Retrieve academic papers from arXiv."""
59
+ search = arxiv.Search(query=query, max_results=max_results)
60
+ papers = []
61
+ for result in search.results():
62
+ paper = {
63
+ "title": result.title,
64
+ "summary": result.summary,
65
+ "url": result.pdf_url,
66
+ "authors": [author.name for author in result.authors],
67
+ "published": result.published
68
+ }
69
+ papers.append(paper)
70
+ return papers
71
+
72
+ def summarize_text(text):
73
+ """
74
+ Wrap the groq_summarize function so it's easy to switch
75
+ implementations if needed.
76
+ """
77
+ return groq_summarize(text)
78
+
79
+ def generate_concept_map(papers):
80
+ """Create a concept map (graph) based on author connections."""
81
+ G = nx.Graph()
82
+ for paper in papers:
83
+ G.add_node(paper['title'])
84
+ for i in range(len(papers)):
85
+ for j in range(i + 1, len(papers)):
86
+ if set(papers[i]['authors']) & set(papers[j]['authors']):
87
+ G.add_edge(papers[i]['title'], papers[j]['title'])
88
+ return G
89
+
90
+ def generate_citation(paper):
91
+ """Generate APA-style citation for a paper."""
92
+ authors = ", ".join(paper['authors'])
93
+ if isinstance(paper['published'], datetime.datetime):
94
+ year = paper['published'].year
95
+ else:
96
+ year = "n.d."
97
+ return f"{authors} ({year}). {paper['title']}. Retrieved from {paper['url']}"
98
+
99
+ def generate_proposal_suggestions(text):
100
+ """
101
+ Generate novel research proposal suggestions based on text,
102
+ wrapping the groq_generate function.
103
+ """
104
+ prompt = (
105
+ f"Based on this research summary:\n\n{text}\n\n"
106
+ "Propose novel research directions:"
107
+ )
108
+ return groq_generate(prompt)
109
+
110
+ def get_cached_summary(paper_id, text):
111
+ """
112
+ Retrieve or create a cached summary for a given paper.
113
+ This ensures each paper's summary is generated only once.
114
+ """
115
+ if 'summaries' not in st.session_state:
116
+ st.session_state.summaries = {}
117
+ if paper_id not in st.session_state.summaries:
118
+ st.session_state.summaries[paper_id] = summarize_text(text)
119
+ return st.session_state.summaries[paper_id]
120
+
121
+ # -------------------------------
122
+ # Streamlit Interface
123
+ # -------------------------------
124
+ st.title("πŸ“š PaperPilot – Intelligent Academic Navigator")
125
+
126
+ # Add the Overview subheading
127
+ st.write("""
128
+ PaperPilot is an intelligent academic navigator designed to simplify your research workflow.
129
+ With a single query, it fetches relevant academic papers and provides you with a
130
+ comprehensive toolkit to explore them in depth. You can read a quick summary of each article,
131
+ view a visual concept map to see how different papers are interlinked, generate properly
132
+ formatted citations, and even receive suggestions for novel research proposals. By integrating
133
+ state-of-the-art AI models, PaperPilot streamlines the entire literature review processβ€”making
134
+ it easier to stay organized, discover new insights, and advance your academic endeavors.
135
+ """)
136
+
137
+ # ---------------------------------
138
+ # Sidebar: Search & Navigation
139
+ # ---------------------------------
140
+ with st.sidebar:
141
+ st.header("πŸ” Search Parameters")
142
+ query = st.text_input("Research topic or question:")
143
+
144
+ if st.button("πŸš€ Find Articles"):
145
+ if query.strip():
146
+ with st.spinner("Searching arXiv..."):
147
+ papers = retrieve_papers(query)
148
+ if papers:
149
+ st.session_state.papers = papers
150
+ st.success(f"Found {len(papers)} papers!")
151
+ # Default to showing articles after retrieval
152
+ st.session_state.active_section = "articles"
153
+ else:
154
+ st.error("No papers found. Try different keywords.")
155
+ else:
156
+ st.warning("Please enter a search query")
157
+
158
+ # Navigation buttons (only relevant if we have papers in session)
159
+ if 'papers' in st.session_state and st.session_state.papers:
160
+ st.header("πŸ”€ Navigation")
161
+ if st.button("Show Articles"):
162
+ st.session_state.active_section = "articles"
163
+ if st.button("Literature Review & Summary"):
164
+ st.session_state.active_section = "review"
165
+ if st.button("Concept & Visual Graph"):
166
+ st.session_state.active_section = "graph"
167
+ if st.button("Formatted Citations"):
168
+ st.session_state.active_section = "citations"
169
+ if st.button("Research Proposal"):
170
+ st.session_state.active_section = "proposal"
171
+
172
+ # ---------------------------------
173
+ # Main Content Area
174
+ # ---------------------------------
175
+ if 'active_section' not in st.session_state:
176
+ st.session_state.active_section = "none"
177
+
178
+ if 'papers' in st.session_state and st.session_state.papers:
179
+ papers = st.session_state.papers
180
+
181
+ # ---------------------------------
182
+ # 1) Show Articles
183
+ # ---------------------------------
184
+ if st.session_state.active_section == "articles":
185
+ st.header("πŸ“‘ Retrieved Papers")
186
+ for idx, paper in enumerate(papers, 1):
187
+ with st.expander(f"{idx}. {paper['title']}"):
188
+ st.markdown(f"**Authors:** {', '.join(paper['authors'])}")
189
+ if isinstance(paper['published'], datetime.datetime):
190
+ pub_date = paper['published'].strftime('%Y-%m-%d')
191
+ else:
192
+ pub_date = "n.d."
193
+ st.markdown(f"**Published:** {pub_date}")
194
+ st.markdown(f"**Link:** [PDF Link]({paper['url']})")
195
+ st.markdown("**Abstract:**")
196
+ st.write(paper['summary'])
197
+
198
+ # ---------------------------------
199
+ # 2) Literature Review & Summary
200
+ # ---------------------------------
201
+ elif st.session_state.active_section == "review":
202
+ st.header("πŸ“š Literature Review & Summary")
203
+ combined_summary = ""
204
+
205
+ for idx, paper in enumerate(papers, 1):
206
+ with st.expander(f"Summary: {paper['title']}", expanded=False):
207
+ with st.spinner(f"Analyzing {paper['title']}..."):
208
+ paper_id = f"paper_{idx}"
209
+ summary = get_cached_summary(paper_id, paper['summary'])
210
+ st.write(summary)
211
+ combined_summary += summary + "\n\n"
212
+
213
+ st.session_state.combined_summary = combined_summary
214
+
215
+ # ---------------------------------
216
+ # 3) Concept & Visual Graph
217
+ # ---------------------------------
218
+ elif st.session_state.active_section == "graph":
219
+ st.header("πŸ” Concept & Visual Graph")
220
+ st.write(
221
+ "Below is a concept map that visualizes how the authors are "
222
+ "connected across the retrieved articles. Each node represents a paper, "
223
+ "and edges indicate shared authors."
224
+ )
225
+
226
+ with st.spinner("Generating concept map..."):
227
+ G = generate_concept_map(papers)
228
+ if G.nodes():
229
+ fig, ax = plt.subplots(figsize=(10, 8))
230
+ pos = nx.spring_layout(G, k=0.5, seed=42)
231
+ nx.draw_networkx_nodes(G, pos, node_color='skyblue', node_size=2000, ax=ax)
232
+ nx.draw_networkx_edges(G, pos, edge_color='#666666', ax=ax)
233
+ nx.draw_networkx_labels(G, pos, font_size=10, ax=ax)
234
+ ax.axis('off')
235
+ st.pyplot(fig)
236
+ else:
237
+ st.info("No significant connections found between papers.")
238
+
239
+ # ---------------------------------
240
+ # 4) Formatted Citations
241
+ # ---------------------------------
242
+ elif st.session_state.active_section == "citations":
243
+ st.header("πŸ“ Formatted Citations (APA Style)")
244
+ for paper in papers:
245
+ st.markdown(f"- {generate_citation(paper)}")
246
+
247
+ # ---------------------------------
248
+ # 5) Research Proposal
249
+ # ---------------------------------
250
+ elif st.session_state.active_section == "proposal":
251
+ st.header("πŸ’‘ Research Proposal Suggestions")
252
+
253
+ # Make sure we have a combined summary for the proposals
254
+ if 'combined_summary' not in st.session_state:
255
+ with st.spinner("Synthesizing research overview..."):
256
+ full_text = "\n".join([p['summary'] for p in papers])
257
+ st.session_state.combined_summary = summarize_text(full_text)
258
+
259
+ with st.spinner("Generating innovative ideas..."):
260
+ proposal = generate_proposal_suggestions(st.session_state.combined_summary[:2000])
261
+ st.write(proposal)
262
+
263
+ else:
264
+ st.info("Please select an option from the sidebar to begin.")
265
+ else:
266
+ st.info("Enter a query in the sidebar and click 'Find Articles' to get started.")
267
+
268
+ st.caption("Built with ❀️ using AI")