Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -3,127 +3,131 @@ import streamlit as st
|
|
3 |
import arxiv
|
4 |
import random
|
5 |
import datetime
|
6 |
-
import networkx as nx
|
7 |
-
import matplotlib.pyplot as plt
|
8 |
-
from groq import Groq
|
9 |
|
10 |
# -------------------------------
|
11 |
-
#
|
12 |
# -------------------------------
|
|
|
|
|
13 |
client = Groq(
|
14 |
api_key=os.environ.get("GROQ_API_KEY"),
|
15 |
)
|
16 |
|
17 |
# -------------------------------
|
18 |
-
# Helper Functions
|
19 |
# -------------------------------
|
20 |
def groq_summarize(text: str) -> str:
|
21 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
response = client.chat.completions.create(
|
23 |
-
messages=[
|
|
|
|
|
|
|
|
|
|
|
24 |
model="llama-3.3-70b-versatile",
|
25 |
)
|
26 |
return response.choices[0].message.content.strip()
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
papers = []
|
|
|
35 |
for result in search.results():
|
36 |
-
|
37 |
paper = {
|
38 |
"title": result.title,
|
39 |
"summary": result.summary,
|
40 |
"url": result.pdf_url,
|
41 |
"authors": [author.name for author in result.authors],
|
42 |
-
"published": result.published,
|
43 |
-
"
|
44 |
-
"
|
45 |
-
"
|
46 |
-
"
|
47 |
-
"
|
48 |
-
"
|
49 |
-
"scite_ai": f"https://scite.ai/reports/{paper_id}"
|
50 |
}
|
51 |
papers.append(paper)
|
52 |
return papers
|
53 |
|
54 |
-
def calculate_scores(paper):
|
55 |
-
"""Generate Trust & Relevance Scores."""
|
56 |
-
return {
|
57 |
-
"trust_score": round(random.uniform(60, 95), 1),
|
58 |
-
"relevance_score": round(random.uniform(50, 100), 1)
|
59 |
-
}
|
60 |
-
|
61 |
-
def get_cached_summary(paper_id, text):
|
62 |
-
"""Retrieve or create a cached summary for a given paper."""
|
63 |
-
if 'summaries' not in st.session_state:
|
64 |
-
st.session_state.summaries = {}
|
65 |
-
if paper_id not in st.session_state.summaries:
|
66 |
-
full_summary = groq_summarize(text)
|
67 |
-
eli5_summary = groq_summarize(f"Explain the following like I'm 5:\n\n{text}")
|
68 |
-
key_takeaways = groq_summarize(f"Provide key takeaways for:\n\n{text}")
|
69 |
-
st.session_state.summaries[paper_id] = {
|
70 |
-
"full": full_summary,
|
71 |
-
"eli5": eli5_summary,
|
72 |
-
"takeaways": key_takeaways
|
73 |
-
}
|
74 |
-
return st.session_state.summaries[paper_id]
|
75 |
-
|
76 |
# -------------------------------
|
77 |
-
# Streamlit
|
78 |
# -------------------------------
|
79 |
st.title("π PaperPilot β Intelligent Academic Navigator")
|
80 |
|
81 |
with st.sidebar:
|
82 |
st.header("π Search Parameters")
|
83 |
query = st.text_input("Research topic or question:")
|
84 |
-
random_search = st.button("π² Random Papers")
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
st.
|
96 |
-
st.session_state.
|
97 |
-
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
if 'papers' in st.session_state and st.session_state.papers:
|
101 |
-
papers = st.session_state.papers
|
102 |
st.header("π Retrieved Papers")
|
103 |
-
for idx, paper in enumerate(papers, 1):
|
104 |
with st.expander(f"{idx}. {paper['title']}"):
|
105 |
-
scores = calculate_scores(paper)
|
106 |
st.markdown(f"**Authors:** {', '.join(paper['authors'])}")
|
107 |
-
|
108 |
-
st.markdown(f"**
|
109 |
-
st.markdown(f"**DOI:** [Link]({paper['doi']})")
|
110 |
-
st.markdown(f"**Original Paper:** [arXiv]({paper['abs_url']})")
|
111 |
-
st.markdown(f"**Bibliographic Explorer:** [Explore]({paper['bib_explorer']})")
|
112 |
-
st.markdown(f"**Connected Papers:** [View]({paper['connected_papers']})")
|
113 |
-
st.markdown(f"**Litmaps:** [Preview]({paper['litmaps']})")
|
114 |
-
st.markdown(f"**scite.ai:** [Smart Citations]({paper['scite_ai']})")
|
115 |
-
st.markdown(f"**Trust Score:** {scores['trust_score']}% | **Relevance Score:** {scores['relevance_score']}%")
|
116 |
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
|
121 |
-
st.
|
122 |
-
st.
|
123 |
|
124 |
-
st.
|
125 |
-
st.write(summary_data['takeaways'])
|
126 |
else:
|
127 |
-
st.info("Enter a query or click
|
128 |
-
|
129 |
-
st.caption("Built with β€οΈ using AI")
|
|
|
3 |
import arxiv
|
4 |
import random
|
5 |
import datetime
|
|
|
|
|
|
|
6 |
|
7 |
# -------------------------------
|
8 |
+
# Groq API Client
|
9 |
# -------------------------------
|
10 |
+
from groq import Groq
|
11 |
+
|
12 |
client = Groq(
|
13 |
api_key=os.environ.get("GROQ_API_KEY"),
|
14 |
)
|
15 |
|
16 |
# -------------------------------
|
17 |
+
# Helper Functions (Groq-based)
|
18 |
# -------------------------------
|
19 |
def groq_summarize(text: str) -> str:
|
20 |
+
"""
|
21 |
+
Summarize the given text using Groq's chat completion API.
|
22 |
+
"""
|
23 |
+
response = client.chat.completions.create(
|
24 |
+
messages=[
|
25 |
+
{
|
26 |
+
"role": "user",
|
27 |
+
"content": f"Summarize this paper in one sentence and provide 3 key takeaways:\n\n{text}"
|
28 |
+
}
|
29 |
+
],
|
30 |
+
model="llama-3.3-70b-versatile",
|
31 |
+
)
|
32 |
+
return response.choices[0].message.content.strip()
|
33 |
+
|
34 |
+
|
35 |
+
def groq_eli5(text: str) -> str:
|
36 |
+
"""
|
37 |
+
Explain the paper like I'm 5 years old.
|
38 |
+
"""
|
39 |
response = client.chat.completions.create(
|
40 |
+
messages=[
|
41 |
+
{
|
42 |
+
"role": "user",
|
43 |
+
"content": f"Explain this paper as if I were 5 years old in one sentence:\n\n{text}"
|
44 |
+
}
|
45 |
+
],
|
46 |
model="llama-3.3-70b-versatile",
|
47 |
)
|
48 |
return response.choices[0].message.content.strip()
|
49 |
|
50 |
+
|
51 |
+
def calculate_scores(paper):
|
52 |
+
"""
|
53 |
+
Generate trust and relevance scores for a paper.
|
54 |
+
"""
|
55 |
+
trust_score = random.randint(5, 10) # Placeholder, can be improved with citations data
|
56 |
+
relevance_score = random.randint(5, 10) # Placeholder, can use NLP topic matching
|
57 |
+
return trust_score, relevance_score
|
58 |
+
|
59 |
+
|
60 |
+
def retrieve_papers(query=None, max_results=10, random_mode=False):
|
61 |
+
"""
|
62 |
+
Retrieve academic papers from arXiv, either based on search or randomly.
|
63 |
+
"""
|
64 |
+
if random_mode:
|
65 |
+
query = "" # Empty query fetches random results
|
66 |
+
|
67 |
+
search = arxiv.Search(query=query, max_results=max_results)
|
68 |
papers = []
|
69 |
+
|
70 |
for result in search.results():
|
71 |
+
trust_score, relevance_score = calculate_scores(result)
|
72 |
paper = {
|
73 |
"title": result.title,
|
74 |
"summary": result.summary,
|
75 |
"url": result.pdf_url,
|
76 |
"authors": [author.name for author in result.authors],
|
77 |
+
"published": result.published.strftime('%Y-%m-%d') if isinstance(result.published, datetime.datetime) else "n.d.",
|
78 |
+
"doi": f"https://doi.org/10.48550/arXiv.{result.entry_id.split('/')[-1]}",
|
79 |
+
"bib_explorer": f"https://arxiv.org/abs/{result.entry_id.split('/')[-1]}",
|
80 |
+
"litmaps": f"https://app.litmaps.com/preview/{result.entry_id.split('/')[-1]}",
|
81 |
+
"connected_papers": f"https://www.connectedpapers.com/{result.entry_id.split('/')[-1]}",
|
82 |
+
"trust_score": trust_score,
|
83 |
+
"relevance_score": relevance_score
|
|
|
84 |
}
|
85 |
papers.append(paper)
|
86 |
return papers
|
87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
# -------------------------------
|
89 |
+
# Streamlit Interface
|
90 |
# -------------------------------
|
91 |
st.title("π PaperPilot β Intelligent Academic Navigator")
|
92 |
|
93 |
with st.sidebar:
|
94 |
st.header("π Search Parameters")
|
95 |
query = st.text_input("Research topic or question:")
|
|
|
96 |
|
97 |
+
col1, col2 = st.columns([4, 1])
|
98 |
+
with col1:
|
99 |
+
search_button = st.button("π Find Articles")
|
100 |
+
with col2:
|
101 |
+
random_button = st.button("π² Random Papers")
|
102 |
+
|
103 |
+
if search_button:
|
104 |
+
if query.strip():
|
105 |
+
with st.spinner("Searching arXiv..."):
|
106 |
+
st.session_state.papers = retrieve_papers(query=query, max_results=10)
|
107 |
+
st.success(f"Found {len(st.session_state.papers)} papers!")
|
108 |
+
else:
|
109 |
+
st.warning("Please enter a search query")
|
110 |
+
|
111 |
+
if random_button:
|
112 |
+
with st.spinner("Fetching random papers..."):
|
113 |
+
st.session_state.papers = retrieve_papers(max_results=random.randint(5, 15), random_mode=True)
|
114 |
+
st.success(f"Fetched {len(st.session_state.papers)} random papers!")
|
115 |
|
116 |
if 'papers' in st.session_state and st.session_state.papers:
|
|
|
117 |
st.header("π Retrieved Papers")
|
118 |
+
for idx, paper in enumerate(st.session_state.papers, 1):
|
119 |
with st.expander(f"{idx}. {paper['title']}"):
|
|
|
120 |
st.markdown(f"**Authors:** {', '.join(paper['authors'])}")
|
121 |
+
st.markdown(f"**Published:** {paper['published']}")
|
122 |
+
st.markdown(f"**[PDF Link]({paper['url']})** | **[DOI]({paper['doi']})** | **[Bib Explorer]({paper['bib_explorer']})** | **[Litmaps]({paper['litmaps']})** | **[Connected Papers]({paper['connected_papers']})**")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
|
124 |
+
with st.spinner("Generating summaries..."):
|
125 |
+
summary = groq_summarize(paper['summary'])
|
126 |
+
eli5_summary = groq_eli5(paper['summary'])
|
127 |
|
128 |
+
st.markdown(f"**Summary:** {summary}")
|
129 |
+
st.markdown(f"**ELI5:** {eli5_summary}")
|
130 |
|
131 |
+
st.markdown(f"**Trust Score:** {paper['trust_score']} / 10 β | **Relevance Score:** {paper['relevance_score']} / 10 π₯")
|
|
|
132 |
else:
|
133 |
+
st.info("Enter a query or click π² Random Papers to get started.")
|
|
|
|