Guanyu-Lin commited on
Commit
7d66a52
β€’
1 Parent(s): bada0eb
Files changed (4) hide show
  1. app.py +28 -23
  2. arxiv_agent.py +42 -4
  3. mail_simple.py +172 -0
  4. requirements.txt +1 -0
app.py CHANGED
@@ -22,18 +22,15 @@ def set_profile(name):
22
 
23
 
24
  def edit_profile(profile, author_name):
25
- # names = author_name.split(" ")
26
- # for n in names:
27
- # if len(n) == 0:
28
- # gr.Info("Please input standard name format.")
29
- # return "", False
30
- # elif n[0].islower():
31
- # gr.Info("Please input standard name format.")
32
- # return "", False
33
 
34
  msg = agent.edit_profile(profile, author_name)
35
  gr.Info("Edit profile successfully!")
36
  return profile
 
 
 
 
 
37
 
38
  def confirm_date(date, profile_input):
39
  # Simulate fetching data based on the selected date
@@ -97,7 +94,7 @@ with gr.Blocks(css="""#chat_container {height: 820px; width: 1000px; margin-left
97
 
98
  ✨ **Guidance**:
99
 
100
- Step (1) Enter researcher name and generate research profile in "Set your profile!"πŸ§‘β€πŸ’Ό
101
 
102
  Step (2) Select time range and get relevant topic trend and ideas in "Get research trend and ideas!"πŸ’‘
103
 
@@ -114,33 +111,41 @@ with gr.Blocks(css="""#chat_container {height: 820px; width: 1000px; margin-left
114
  with gr.Accordion("Set your profile!", open=True):
115
  gr.Markdown(
116
  """
117
- You can input your name in standard format to get your profile from arxiv here. Standard examples: Yoshua Bengio. Wrong examples: yoshua bengio, Yoshua bengio, yoshua Bengio.
118
  """
119
  )
120
  with gr.Row():
121
- with gr.Column(scale=2, min_width=300):
122
  name_input = gr.Textbox(label="Input your name:")
123
  set_button = gr.Button("Set Profile")
124
- profile_text = gr.Textbox(label="Generated profile (can be edited):", interactive=True, scale=7, lines=5, max_lines=5)
125
- edit_button = gr.Button("Edit Profile", scale=1)
 
 
126
  set_button.click(set_profile, inputs=name_input, outputs=[profile_text])
127
  edit_button.click(edit_profile, inputs=[profile_text, name_input], outputs=[profile_text])
128
-
129
  with gr.Accordion("Get research trend and ideas!", open=True):
130
  gr.Markdown(
131
  """
132
- We will give you personalized research trend and ideas if you have set your profile. Otherwise, general research trend will be provided.
 
 
133
  """
134
  )
135
  with gr.Column():
136
  with gr.Row():
137
- with gr.Column(scale=2, min_width=300):
138
- # gr.Dropdown(
139
- # ["day", "week", "bird"], label="Select time range", info="Will add more animals later!"
140
- # ),
141
- date_choice = gr.Radio(["day", "week", "all"], label="Select Time Range", value="day")
142
- date_button = gr.Button("Confirm")
143
- papers_text = gr.Textbox(label="Trend Papers", interactive=False, scale=8, lines=5, max_lines=5)
 
 
 
 
144
 
145
  with gr.Row():
146
  topic_text = gr.Textbox(label="Topic Trend", interactive=False, scale=5, lines=12, max_lines=15)
@@ -148,7 +153,7 @@ with gr.Blocks(css="""#chat_container {height: 820px; width: 1000px; margin-left
148
  ideas_text = gr.Textbox(label="Ideas Related to Topic Trend", interactive=False, scale=5, lines=12, max_lines=15)
149
 
150
  date_button.click(confirm_date, inputs=[date_choice, profile_text], outputs=[topic_text, papers_text, ideas_text])
151
-
152
  with gr.Accordion("Chat with Arxiv Copilot!", open=True):
153
  gr.Markdown(
154
  """
 
22
 
23
 
24
  def edit_profile(profile, author_name):
 
 
 
 
 
 
 
 
25
 
26
  msg = agent.edit_profile(profile, author_name)
27
  gr.Info("Edit profile successfully!")
28
  return profile
29
+
30
+ def sign_email(profile, email):
31
+ msg = agent.sign_email(profile, email)
32
+ gr.Info(email + " signs up successfully!")
33
+ # return profile
34
 
35
  def confirm_date(date, profile_input):
36
  # Simulate fetching data based on the selected date
 
94
 
95
  ✨ **Guidance**:
96
 
97
+ Step (1) Enter researcher name and generate research profile in "Set your profile!"; Here you also can sign up with email to get monthly research news πŸ§‘β€πŸ’Ό
98
 
99
  Step (2) Select time range and get relevant topic trend and ideas in "Get research trend and ideas!"πŸ’‘
100
 
 
111
  with gr.Accordion("Set your profile!", open=True):
112
  gr.Markdown(
113
  """
114
+ Input your name: You can input your name in standard format to get your profile from arxiv here. Standard examples: Yoshua Bengio. Wrong examples: yoshua bengio, Yoshua bengio, yoshua Bengio.
115
  """
116
  )
117
  with gr.Row():
118
+ with gr.Column(scale=2, min_width=300, variant = 'compact'):
119
  name_input = gr.Textbox(label="Input your name:")
120
  set_button = gr.Button("Set Profile")
121
+ with gr.Column(scale=8, min_width=300):
122
+ with gr.Row(variant = 'compact'):
123
+ profile_text = gr.Textbox(label="Generated profile (can be edited):", interactive=True, scale=7, lines=5, max_lines=5)
124
+ edit_button = gr.Button("Edit Profile", scale=1)
125
  set_button.click(set_profile, inputs=name_input, outputs=[profile_text])
126
  edit_button.click(edit_profile, inputs=[profile_text, name_input], outputs=[profile_text])
127
+
128
  with gr.Accordion("Get research trend and ideas!", open=True):
129
  gr.Markdown(
130
  """
131
+ (1) Input your email: You can sign up with your email and we will send research trend, ideas, and top papers related to your profile on 1st of every month.
132
+
133
+ (2) Select time range: We will give you personalized research trend and ideas under selected time range if you have set your profile. Otherwise, general research trend will be provided.
134
  """
135
  )
136
  with gr.Column():
137
  with gr.Row():
138
+ with gr.Column(scale=2.1, min_width=300):
139
+ with gr.Column(scale=2.1, min_width=300, variant = 'compact'):
140
+ # gr.Dropdown(
141
+ # ["day", "week", "bird"], label="Select time range", info="Will add more animals later!"
142
+ # ),
143
+ email_input = gr.Textbox(label="Input your email:")
144
+ sign_button = gr.Button("Sign Up")
145
+ with gr.Column(scale=2.1, min_width=300, variant = 'compact'):
146
+ date_choice = gr.Radio(["day", "week", "all"], label="Select time range: ", value="day")
147
+ date_button = gr.Button("Confirm")
148
+ papers_text = gr.Textbox(label="Trend Papers", interactive=False, scale=8, lines=12, max_lines=15)
149
 
150
  with gr.Row():
151
  topic_text = gr.Textbox(label="Topic Trend", interactive=False, scale=5, lines=12, max_lines=15)
 
153
  ideas_text = gr.Textbox(label="Ideas Related to Topic Trend", interactive=False, scale=5, lines=12, max_lines=15)
154
 
155
  date_button.click(confirm_date, inputs=[date_choice, profile_text], outputs=[topic_text, papers_text, ideas_text])
156
+ sign_button.click(sign_email, inputs=[profile_text, email_input])
157
  with gr.Accordion("Chat with Arxiv Copilot!", open=True):
158
  gr.Markdown(
159
  """
arxiv_agent.py CHANGED
@@ -10,11 +10,13 @@ from pathlib import Path
10
  import requests
11
  from datasets import load_dataset_builder
12
  import warnings
 
 
13
  warnings.filterwarnings("ignore")
14
  os.environ['KMP_DUPLICATE_LIB_OK']='True'
15
  from utils import *
16
  import thread6
17
- MAX_DAILY_PAPER = 200
18
  DAY_TIME = 60 * 60 * 24
19
  DAY_TIME_MIN = 60 * 24
20
  DATA_REPO_ID = "cmulgy/ArxivCopilot_data"
@@ -150,6 +152,10 @@ def dailySave(agent_ls):
150
 
151
  with open(agent.profile_path,"w") as f:
152
  json.dump(agent.profile,f)
 
 
 
 
153
  with open(agent.comment_path,"w") as f:
154
  json.dump(agent.comment,f)
155
 
@@ -160,6 +166,8 @@ class ArxivAgent:
160
  self.thought_path = DATASET_DIR / "dataset/thought.json"
161
  self.trend_idea_path = DATASET_DIR / "dataset/trend_idea.json"
162
  self.profile_path = DATASET_DIR / "dataset/profile.json"
 
 
163
  self.comment_path = DATASET_DIR / "dataset/comment.json"
164
 
165
  self.embedding_path = DATASET_DIR / "dataset/paper_embedding.pkl"
@@ -179,7 +187,9 @@ class ArxivAgent:
179
  self.download()
180
  try:
181
  thread6.run_threaded(dailyDownload, [self])
 
182
  thread6.run_threaded(dailySave, [self])
 
183
  except:
184
  print("Error: unable to start thread")
185
 
@@ -188,7 +198,13 @@ class ArxivAgent:
188
  self.profile[author_name]=profile
189
 
190
  return "Successfully edit profile!"
191
-
 
 
 
 
 
 
192
  def get_profile(self, author_name):
193
  if author_name == "": return None
194
 
@@ -213,6 +229,15 @@ class ArxivAgent:
213
  offset_day = today - datetime.timedelta(days=i)
214
  str_day = offset_day.strftime("%m/%d/%Y")
215
 
 
 
 
 
 
 
 
 
 
216
  if str_day in self.paper:
217
  # print(str_day)
218
  paper_by_date[str_day] = self.paper[str_day]
@@ -237,8 +262,7 @@ class ArxivAgent:
237
  idea = self.trend_idea[profile][key_update][method]["idea"]
238
  isQuery = True
239
 
240
- # import pdb
241
- # pdb.set_trace()
242
  if not(isQuery):
243
  trend, paper_link = summarize_research_field(profile, "Machine Learning", dataset,data_chunk_embedding) # trend
244
  reference = papertitleAndLink(paper_link)
@@ -424,6 +448,20 @@ class ArxivAgent:
424
  m = {}
425
  self.profile = m.copy()
426
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
 
428
  filename = self.thought_path
429
  filename_emb = self.thought_embedding_path
 
10
  import requests
11
  from datasets import load_dataset_builder
12
  import warnings
13
+ from mail_simple import *
14
+
15
  warnings.filterwarnings("ignore")
16
  os.environ['KMP_DUPLICATE_LIB_OK']='True'
17
  from utils import *
18
  import thread6
19
+ MAX_DAILY_PAPER = int(os.environ['MAX_DAILY_PAPER'])
20
  DAY_TIME = 60 * 60 * 24
21
  DAY_TIME_MIN = 60 * 24
22
  DATA_REPO_ID = "cmulgy/ArxivCopilot_data"
 
152
 
153
  with open(agent.profile_path,"w") as f:
154
  json.dump(agent.profile,f)
155
+
156
+ with open(agent.email_pool_path,"w") as f:
157
+ json.dump(agent.email_pool,f)
158
+
159
  with open(agent.comment_path,"w") as f:
160
  json.dump(agent.comment,f)
161
 
 
166
  self.thought_path = DATASET_DIR / "dataset/thought.json"
167
  self.trend_idea_path = DATASET_DIR / "dataset/trend_idea.json"
168
  self.profile_path = DATASET_DIR / "dataset/profile.json"
169
+ self.email_pool_path = DATASET_DIR / "dataset/email.json"
170
+
171
  self.comment_path = DATASET_DIR / "dataset/comment.json"
172
 
173
  self.embedding_path = DATASET_DIR / "dataset/paper_embedding.pkl"
 
187
  self.download()
188
  try:
189
  thread6.run_threaded(dailyDownload, [self])
190
+ thread6.run_threaded(monthlyEmail, [self])
191
  thread6.run_threaded(dailySave, [self])
192
+
193
  except:
194
  print("Error: unable to start thread")
195
 
 
198
  self.profile[author_name]=profile
199
 
200
  return "Successfully edit profile!"
201
+
202
+ def sign_email(self, profile, email):
203
+
204
+ self.email_pool[email]=profile
205
+ sign_up_email(email, profile)
206
+ return "Successfully sign up!"
207
+
208
  def get_profile(self, author_name):
209
  if author_name == "": return None
210
 
 
229
  offset_day = today - datetime.timedelta(days=i)
230
  str_day = offset_day.strftime("%m/%d/%Y")
231
 
232
+ if str_day in self.paper:
233
+ # print(str_day)
234
+ paper_by_date[str_day] = self.paper[str_day]
235
+ chunk_embedding_date[str_day] = self.paper_embedding[str_day]
236
+ elif method == "month":
237
+ for i in range(30):
238
+ offset_day = today - datetime.timedelta(days=i)
239
+ str_day = offset_day.strftime("%m/%d/%Y")
240
+
241
  if str_day in self.paper:
242
  # print(str_day)
243
  paper_by_date[str_day] = self.paper[str_day]
 
262
  idea = self.trend_idea[profile][key_update][method]["idea"]
263
  isQuery = True
264
 
265
+
 
266
  if not(isQuery):
267
  trend, paper_link = summarize_research_field(profile, "Machine Learning", dataset,data_chunk_embedding) # trend
268
  reference = papertitleAndLink(paper_link)
 
448
  m = {}
449
  self.profile = m.copy()
450
 
451
+ filename = self.email_pool_path
452
+ # if os.path.exists(filename):
453
+ try:
454
+ hf_hub_download(repo_id=DATA_REPO_ID, filename="dataset/email.json", local_dir = ".", repo_type="dataset")
455
+ with open(filename,"rb") as f:
456
+ content = f.read()
457
+ if not content:
458
+ m = {}
459
+ else:
460
+ m = json.loads(content)
461
+ except:
462
+ with open(filename, mode='w', encoding='utf-8') as ff:
463
+ m = {}
464
+ self.email_pool = m.copy()
465
 
466
  filename = self.thought_path
467
  filename_emb = self.thought_embedding_path
mail_simple.py ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import smtplib
2
+ from email.mime.multipart import MIMEMultipart
3
+ from email.mime.text import MIMEText
4
+ import time
5
+ import schedule
6
+ from functools import partial
7
+ import markdown
8
+ from datetime import date
9
+
10
+ DAY_TIME = 60 * 60 * 24
11
+ import os
12
+ APP_PASSWORD = os.environ['APP_PASSWORD']
13
+ def send_email(sender_email, app_password, recipient_email, subject, body):
14
+ # Create the email message
15
+ msg = MIMEMultipart()
16
+ msg['From'] = sender_email
17
+ msg['Subject'] = subject
18
+ msg['To'] = recipient_email
19
+ msg.attach(MIMEText(body, 'html'))
20
+
21
+ try:
22
+ # Set up the SMTP server
23
+ server = smtplib.SMTP('smtp.gmail.com', 587)
24
+ server.starttls() # Secure the connection
25
+ server.login(sender_email, app_password) # Log in to your Gmail account
26
+
27
+ # Send the email
28
+ # for recipient_email in recipient_emails:
29
+
30
+
31
+ server.sendmail(sender_email, recipient_email, msg.as_string())
32
+
33
+ # print("Email sent successfully!" + recipient_email)
34
+ except Exception as e:
35
+ print(f"Failed to send email: {e}")
36
+ finally:
37
+ server.quit() # Terminate the SMTP session
38
+
39
+ def sign_up_email(email, profile):
40
+ sender_email = "arxivcopilot@gmail.com"
41
+ app_password = "mqxq jzhq tjhz dwda"
42
+ recipient_email = email
43
+ # for recipient_email in email_pool.keys():
44
+ email_input = {}
45
+ email_input['profile'] = profile
46
+ body = \
47
+ ('''
48
+ # Welcome to Arxiv Copilot Monthly Updates!
49
+
50
+ ## Hello,
51
+
52
+ Thank you for signing up for our monthly update service! We are thrilled to have you on board and look forward to providing you with the latest research topics, ideas, and papers tailored to your interests.
53
+
54
+ The updates will be sent on 1st of every month at 20:30 (EDT).
55
+
56
+ ---
57
+
58
+ ### πŸ“ **Your Profile Summary**
59
+
60
+ {profile}
61
+
62
+
63
+ ---
64
+
65
+ ### πŸ”” **What to Expect**
66
+
67
+ - Each month, you will receive an email with:
68
+ - **Trending Research Topics**: Stay updated on what's popular in your field.
69
+ - **Research Ideas**: Get inspired with new ideas tailored to your interests.
70
+ - **Recommended Papers**: Discover papers that match your research focus.
71
+
72
+
73
+ Thank you for choosing Arxiv Copilot. We are excited to support your research journey and keep you informed with the latest developments in your field.
74
+
75
+ Best regards,
76
+ **The Arxiv Copilot Team**
77
+
78
+ ---
79
+
80
+ *If you are unsatisfied with your profile, please edit it at Arxiv Copilot (https://huggingface.co/spaces/ulab-ai/ArxivCopilot) and sign up again!*
81
+ ''').format_map(email_input)
82
+ body = markdown.markdown(body)
83
+ # body = MIMEText(body, "html")
84
+
85
+ subject = "ArxivCopilot Monthly"
86
+ send_email(sender_email, app_password, recipient_email, subject, body)
87
+
88
+
89
+ # Example usage
90
+ def send_to_users(agent):
91
+ if date.today().day != 1:
92
+ return
93
+ sender_email = "arxivcopilot@gmail.com"
94
+ app_password = APP_PASSWORD
95
+ for recipient_email in agent.email_pool.keys():
96
+ profile_input = agent.email_pool[recipient_email]
97
+ topics, papers, ideas = agent.select_date("month", profile_input)
98
+ email_input = {}
99
+ email_input['profile'] = profile_input
100
+ email_input['topics'] = topics[0]
101
+ email_input['ideas'] = ideas[0]
102
+ paper_input = ""
103
+ for paper in papers.split(';\n'):
104
+ paper_input = paper_input + "- " + paper + ";\n"
105
+
106
+ email_input['papers'] = paper_input
107
+ body = \
108
+ ('''
109
+ # Monthly Update from Arxiv Copilot
110
+
111
+ ## Hello,
112
+
113
+ We are excited to share your personalized monthly update from Arxiv Copilot! Here’s what we have for you this month:
114
+
115
+ ---
116
+
117
+ ### πŸ“ **Your Profile Summary**
118
+
119
+ {profile}
120
+
121
+
122
+ ---
123
+
124
+ ### πŸ”₯ **Trending Research Topics**
125
+
126
+ {topics}
127
+
128
+ ---
129
+
130
+ ### πŸ’‘ **Research Ideas for You**
131
+
132
+ {ideas}
133
+
134
+ ---
135
+
136
+ ### πŸ“„ **Recommended Papers**
137
+
138
+ We have curated a list of papers you might find interesting:
139
+
140
+ {papers}
141
+
142
+
143
+
144
+ Thank you for being a part of Arxiv Copilot. We look forward to supporting your research journey.
145
+
146
+ Best regards,
147
+ **The Arxiv Copilot Team**
148
+
149
+ ---
150
+
151
+ *If you are unsatisfied with your profile, please edit it at Arxiv Copilot (https://huggingface.co/spaces/ulab-ai/ArxivCopilot) and sign up again!*
152
+ ''').format_map(email_input)
153
+
154
+ body = markdown.markdown(body)
155
+ subject = "ArxivCopilot Monthly"
156
+ send_email(sender_email, app_password, recipient_email, subject, body)
157
+ print("sent to"+recipient_email)
158
+
159
+
160
+
161
+ def monthlyEmail(agent_ls):
162
+
163
+ agent = agent_ls[0]
164
+ job_with_para = partial(send_to_users, agent)
165
+ # schedule.every().minute.do(job_with_para)
166
+ # schedule.every().month.do(job_with_para).day.at("00:00")
167
+ schedule.every().day.at("20:30", "America/New_York").do(job_with_para)
168
+
169
+ while True:
170
+ schedule.run_pending()
171
+ time.sleep(59)
172
+
requirements.txt CHANGED
@@ -5,3 +5,4 @@ arxiv
5
  requests
6
  openai==0.28
7
  thread6
 
 
5
  requests
6
  openai==0.28
7
  thread6
8
+ schedule