Sobit commited on
Commit
1ad6ea2
·
verified ·
1 Parent(s): 8179b6a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +264 -127
app.py CHANGED
@@ -1,139 +1,276 @@
1
  import streamlit as st
2
- from langchain.chat_models import ChatOpenAI
3
  from langchain.chains import LLMChain
4
  from langchain.prompts import PromptTemplate
5
- from langchain.memory import ConversationBufferMemory
6
-
7
- # Initialize OpenAI LLM
8
- llm = ChatOpenAI(model="gpt-4", temperature=0.7)
9
-
10
- # Define Prompts
11
- email_prompt = PromptTemplate(
12
- input_variables=["professor_name", "university_name", "research_interests", "reason", "resume_text"],
13
- template="""
14
- Write a professional cold email to {professor_name} at {university_name} expressing interest in their research.
15
- Highlight relevant research interests: {research_interests}.
16
- Explain why you want to work with them: {reason}. Keep it concise and professional.
17
- """
18
- )
19
- cover_letter_prompt = PromptTemplate(
20
- input_variables=["job_title", "company", "key_skills", "resume_text"],
21
- template="""
22
- Write a professional cover letter for the {job_title} position at {company}.
23
- Highlight key skills: {key_skills}. Keep it formal and tailored to the job.
24
- """
25
- )
26
- research_statement_prompt = PromptTemplate(
27
- input_variables=["research_background", "key_projects", "future_goals"],
28
- template="""
29
- Write a research statement based on the following:
30
- - Background: {research_background}
31
- - Key Projects: {key_projects}
32
- - Future Research Goals: {future_goals}
33
- Keep it structured and professional.
34
- """
 
 
 
 
 
35
  )
36
- sop_prompt = PromptTemplate(
37
- input_variables=["motivation", "academic_background", "research_experiences", "career_goals", "why_this_program"],
38
- template="""
39
- Write a Statement of Purpose (SOP) with:
40
- - Motivation: {motivation}
41
- - Academic Background: {academic_background}
42
- - Research Experiences: {research_experiences}
43
- - Career Goals: {career_goals}
44
- - Why this program: {why_this_program}
45
- Ensure it is compelling and well-structured.
46
- """
47
  )
48
 
49
- # Create LLM Chains
50
- email_chain = LLMChain(llm=llm, prompt=email_prompt, memory=ConversationBufferMemory(memory_key="history"))
51
- cover_letter_chain = LLMChain(llm=llm, prompt=cover_letter_prompt, memory=ConversationBufferMemory(memory_key="history"))
52
- research_statement_chain = LLMChain(llm=llm, prompt=research_statement_prompt, memory=ConversationBufferMemory(memory_key="history"))
53
- sop_chain = LLMChain(llm=llm, prompt=sop_prompt, memory=ConversationBufferMemory(memory_key="history"))
54
-
55
- # Streamlit App
56
- st.title("AI-Powered Academic & Job Application Generator")
57
-
58
- # File Upload for Resume
59
- st.sidebar.header("Upload Your Resume (Optional)")
60
- uploaded_file = st.sidebar.file_uploader("Upload a .txt file", type=["txt"])
61
-
62
- cv_resume_text = ""
63
- if uploaded_file is not None:
64
- cv_resume_text = uploaded_file.read().decode("utf-8")
65
-
66
- # Tabs for Different Documents
67
- tabs = st.tabs(["Cold Email", "Cover Letter", "Research Statement", "Statement of Purpose"])
68
-
69
- # Cold Email Generator
70
- with tabs[0]:
71
- st.header("Generate a Cold Email")
72
- professor_name = st.text_input("Professor's Name")
73
- university_name = st.text_input("University Name")
74
- research_interests = st.text_area("Your Research Interests")
75
- reason = st.text_area("Why do you want to work with this professor?")
76
-
77
- if st.button("Generate Email"):
78
- email_output = email_chain.run({
79
- "professor_name": professor_name,
80
- "university_name": university_name,
81
- "research_interests": research_interests,
82
- "reason": reason,
83
- "resume_text": cv_resume_text
84
- }).strip()
85
- st.markdown(email_output)
86
- st.download_button("Download Email", email_output, file_name="cold_email.txt")
87
-
88
- # Cover Letter Generator
89
- with tabs[1]:
90
- st.header("Generate a Cover Letter")
91
- job_title = st.text_input("Job Title")
92
- company_name = st.text_input("Company Name")
93
- key_skills = st.text_area("Key Skills for the Job")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  if st.button("Generate Cover Letter"):
96
- cover_letter_output = cover_letter_chain.run({
97
- "job_title": job_title,
98
- "company": company_name,
99
- "key_skills": key_skills,
100
- "resume_text": cv_resume_text
101
- }).strip()
102
- st.markdown(cover_letter_output)
103
- st.download_button("Download Cover Letter", cover_letter_output, file_name="cover_letter.txt")
104
-
105
- # Research Statement Generator
106
- with tabs[2]:
107
- st.header("Generate a Research Statement")
108
- research_background = st.text_area("Your Research Background")
109
- key_projects = st.text_area("Key Projects You've Worked On")
110
- future_goals = st.text_area("Future Research Goals")
 
 
 
 
 
 
 
111
 
112
  if st.button("Generate Research Statement"):
113
- research_statement_output = research_statement_chain.run({
114
- "research_background": research_background,
115
- "key_projects": key_projects,
116
- "future_goals": future_goals
117
- }).strip()
118
- st.markdown(research_statement_output)
119
- st.download_button("Download Research Statement", research_statement_output, file_name="research_statement.txt")
120
-
121
- # Statement of Purpose Generator
122
- with tabs[3]:
123
- st.header("Generate a Statement of Purpose (SOP)")
124
- motivation = st.text_area("Your Motivation for Graduate Studies")
125
- academic_background = st.text_area("Your Academic Background")
126
- research_experiences = st.text_area("Your Research Experiences")
127
- career_goals = st.text_area("Your Career Goals")
128
- why_this_program = st.text_area("Why This Program?")
 
 
 
 
129
 
130
  if st.button("Generate SOP"):
131
- sop_output = sop_chain.run({
132
- "motivation": motivation,
133
- "academic_background": academic_background,
134
- "research_experiences": research_experiences,
135
- "career_goals": career_goals,
136
- "why_this_program": why_this_program
137
- }).strip()
138
- st.markdown(sop_output)
139
- st.download_button("Download SOP", sop_output, file_name="sop.txt")
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
 
2
  from langchain.chains import LLMChain
3
  from langchain.prompts import PromptTemplate
4
+ from langchain.llms import HuggingFaceHub
5
+ import fitz # PyMuPDF for PDF extraction
6
+ from PIL import Image
7
+ import os
8
+ import pytesseract
9
+ import re
10
+
11
+ # Set Hugging Face API Key (Set this in Hugging Face Secrets)
12
+ os.environ["HUGGINGFACEHUB_API_TOKEN"] = st.secrets["HF_TOKEN"]
13
+
14
+ # Load Free LLM from Hugging Face
15
+ llm = HuggingFaceHub(repo_id="mistralai/Mistral-7B-Instruct-v0.3", model_kwargs={"temperature": 0.5})
16
+
17
+ # Streamlit App Configuration
18
+ st.set_page_config(page_title="DocuMentorAI", layout="wide", page_icon="📄")
19
+ st.title("📄 DocuMentorAI")
20
+ st.write("Generate professional application documents with ease!")
21
+
22
+ # Custom CSS for better UI
23
+ st.markdown("""
24
+ <style>
25
+ .stTextArea textarea { font-size: 16px !important; }
26
+ .stButton button { width: 100%; background-color: #4CAF50; color: white; }
27
+ .stDownloadButton button { width: 100%; background-color: #008CBA; color: white; }
28
+ .stMarkdown { font-size: 18px; }
29
+ .stSpinner div { margin: auto; }
30
+ </style>
31
+ """, unsafe_allow_html=True)
32
+
33
+ # Text Input for Job Opening Details
34
+ st.subheader("📢 Enter Opening Details")
35
+ job_opening_text = st.text_area(
36
+ "Paste the job/research opening details here...",
37
+ height=150,
38
+ placeholder="Example: 'We are hiring a Research Assistant at XYZ University. The ideal candidate has experience in machine learning and data analysis...'"
39
  )
40
+
41
+ # Upload CV/Resume
42
+ st.subheader("📄 Upload CV/Resume")
43
+ cv_resume_file = st.file_uploader(
44
+ "Upload your CV/Resume (PDF or Image)",
45
+ type=["pdf", "png", "jpg", "jpeg"],
46
+ help="Upload a PDF or image of your CV/Resume for text extraction."
 
 
 
 
47
  )
48
 
49
+ # Function to extract text from PDF
50
+ def extract_text_from_pdf(pdf_file):
51
+ try:
52
+ pdf_bytes = pdf_file.read()
53
+ with fitz.open(stream=pdf_bytes, filetype="pdf") as doc:
54
+ return " ".join([page.get_text() for page in doc])
55
+ except Exception as e:
56
+ st.error(f"Error extracting text from PDF: {e}")
57
+ return ""
58
+
59
+ # Function to extract text from Image using OCR
60
+ def extract_text_from_image(image_file):
61
+ try:
62
+ image = Image.open(image_file)
63
+ return pytesseract.image_to_string(image)
64
+ except Exception as e:
65
+ st.error(f"Error extracting text from image: {e}")
66
+ return ""
67
+
68
+ # Function to extract text from uploaded files
69
+ def extract_text(uploaded_file):
70
+ if uploaded_file:
71
+ file_type = uploaded_file.type
72
+ if file_type == "application/pdf":
73
+ return extract_text_from_pdf(uploaded_file)
74
+ else:
75
+ return extract_text_from_image(uploaded_file)
76
+ return ""
77
+
78
+ # Extract text from CV/Resume
79
+ cv_resume_text = extract_text(cv_resume_file)
80
+
81
+ # Display Extracted Text
82
+ if job_opening_text:
83
+ with st.expander("🔍 View Entered Opening Details"):
84
+ st.markdown(f"**Job Opening Details:**\n\n{job_opening_text}")
85
+
86
+ if cv_resume_text:
87
+ with st.expander("🔍 View Extracted CV/Resume Details"):
88
+ st.markdown(f"**CV/Resume Details:**\n\n{cv_resume_text}")
89
+
90
+ # Function to extract professor name, designation, and university
91
+ def extract_professor_details(text):
92
+ professor_pattern = r"(Dr\.|Professor|Prof\.?)\s+([A-Z][a-z]+\s[A-Z][a-z]+)"
93
+ university_pattern = r"(University|Institute|College|School of [A-Za-z]+)"
94
+
95
+ professor_match = re.search(professor_pattern, text)
96
+ university_match = re.search(university_pattern, text)
97
+
98
+ professor_name = professor_match.group(0) if professor_match else "Not Found"
99
+ university_name = university_match.group(0) if university_match else "Not Found"
100
+
101
+ return professor_name, university_name
102
+
103
+ # Extract professor details if job opening is uploaded
104
+ professor_name, university_name = extract_professor_details(job_opening_text)
105
+
106
+ # LLM Prompt Templates
107
+ email_template = PromptTemplate.from_template("""
108
+ Write a professional cold email for a research position.
109
+ - Address the professor formally.
110
+ - Introduce yourself and academic background.
111
+ - Express interest in their research.
112
+ - Highlight key skills from your CV.
113
+ - Conclude with a polite request.
114
+ ### Input:
115
+ - Professor: {professor_name}
116
+ - University: {university_name}
117
+ - Research Interests: {research_interests}
118
+ - Why This Lab: {reason}
119
+ - CV Highlights: {resume_text}
120
+ ### Output:
121
+ A well-structured, professional cold email.
122
+ """)
123
+
124
+ cover_letter_template = PromptTemplate.from_template("""
125
+ Write a compelling job application cover letter.
126
+ - Address the employer formally.
127
+ - Mention job title and where you found it.
128
+ - Highlight key skills and experiences.
129
+ - Relate background to the company.
130
+ - Conclude with enthusiasm.
131
+ ### Input:
132
+ - Job Title: {job_title}
133
+ - Company: {company}
134
+ - Key Skills: {key_skills}
135
+ - CV Highlights: {resume_text}
136
+ ### Output:
137
+ A strong, well-formatted cover letter.
138
+ """)
139
+
140
+ research_statement_template = PromptTemplate.from_template("""
141
+ Write a research statement for Ph.D. applications.
142
+ - Discuss research background and motivation.
143
+ - Explain key research experiences and findings.
144
+ - Outline future research interests and goals.
145
+ - Highlight contributions to the field.
146
+ ### Input:
147
+ - Research Background: {research_background}
148
+ - Key Research Projects: {key_projects}
149
+ - Future Goals: {future_goals}
150
+ ### Output:
151
+ A well-structured, professional research statement.
152
+ """)
153
+
154
+ sop_template = PromptTemplate.from_template("""
155
+ Write a compelling Statement of Purpose (SOP).
156
+ - Introduce motivation for graduate studies.
157
+ - Discuss academic background.
158
+ - Explain relevant experiences and research.
159
+ - Outline career goals.
160
+ - Justify fit for the program.
161
+ ### Input:
162
+ - Motivation: {motivation}
163
+ - Academic Background: {academic_background}
164
+ - Research & Projects: {research_experiences}
165
+ - Career Goals: {career_goals}
166
+ - Why This Program: {why_this_program}
167
+ ### Output:
168
+ A well-structured SOP.
169
+ """)
170
+
171
+ # LangChain Chains
172
+ email_chain = LLMChain(llm=llm, prompt=email_template)
173
+ cover_letter_chain = LLMChain(llm=llm, prompt=cover_letter_template)
174
+ research_statement_chain = LLMChain(llm=llm, prompt=research_statement_template)
175
+ sop_chain = LLMChain(llm=llm, prompt=sop_template)
176
+
177
+ # User Inputs
178
+ st.subheader("📩 Generate Application Documents")
179
+ tab1, tab2, tab3, tab4 = st.tabs(["Cold Email", "Cover Letter", "Research Statement", "SOP"])
180
+
181
+ # Cold Email Generation
182
+ with tab1:
183
+ st.write(f"🧑‍🏫 **Detected Professor:** {professor_name} at {university_name}")
184
+ research_interests = st.text_area("Research Interests", placeholder="Example: Machine Learning, Data Analysis, etc.")
185
+ reason = st.text_area("Why this professor/lab?", placeholder="Example: I am particularly interested in your work on...")
186
+
187
+ if st.button("Generate Cold Email"):
188
+ if not job_opening_text or not cv_resume_text:
189
+ st.error("Please provide job opening details and upload your CV/Resume.")
190
+ else:
191
+ with st.spinner("Generating Cold Email..."):
192
+ try:
193
+ email = email_chain.run({
194
+ "professor_name": professor_name,
195
+ "university_name": university_name,
196
+ "research_interests": research_interests,
197
+ "reason": reason,
198
+ "resume_text": cv_resume_text
199
+ })
200
+ st.markdown("**Generated Cold Email:**")
201
+ st.markdown(email)
202
+ st.download_button("Download Email", email, file_name="cold_email.txt")
203
+ except Exception as e:
204
+ st.error(f"Error generating cold email: {e}")
205
+
206
+ # Cover Letter Generation
207
+ with tab2:
208
+ job_title = st.text_input("Job Title", placeholder="Example: Research Assistant")
209
+ company_name = university_name if university_name != "Not Found" else st.text_input("Company/University", placeholder="Example: XYZ University")
210
+ key_skills = st.text_area("Key Skills", placeholder="Example: Python, Machine Learning, Data Analysis")
211
 
212
  if st.button("Generate Cover Letter"):
213
+ if not job_opening_text or not cv_resume_text:
214
+ st.error("Please provide job opening details and upload your CV/Resume.")
215
+ else:
216
+ with st.spinner("Generating Cover Letter..."):
217
+ try:
218
+ cover_letter = cover_letter_chain.run({
219
+ "job_title": job_title,
220
+ "company": company_name,
221
+ "key_skills": key_skills,
222
+ "resume_text": cv_resume_text
223
+ })
224
+ st.markdown("**Generated Cover Letter:**")
225
+ st.markdown(cover_letter)
226
+ st.download_button("Download Cover Letter", cover_letter, file_name="cover_letter.txt")
227
+ except Exception as e:
228
+ st.error(f"Error generating cover letter: {e}")
229
+
230
+ # Research Statement Generation
231
+ with tab3:
232
+ research_background = st.text_area("Research Background", placeholder="Example: My research focuses on...")
233
+ key_projects = st.text_area("Key Research Projects", placeholder="Example: Developed a machine learning model for...")
234
+ future_goals = st.text_area("Future Research Goals", placeholder="Example: I aim to explore...")
235
 
236
  if st.button("Generate Research Statement"):
237
+ with st.spinner("Generating Research Statement..."):
238
+ try:
239
+ research_statement = research_statement_chain.run({
240
+ "research_background": research_background,
241
+ "key_projects": key_projects,
242
+ "future_goals": future_goals
243
+ })
244
+ st.markdown("**Generated Research Statement:**")
245
+ st.markdown(research_statement)
246
+ st.download_button("Download Research Statement", research_statement, file_name="research_statement.txt")
247
+ except Exception as e:
248
+ st.error(f"Error generating research statement: {e}")
249
+
250
+ # SOP Generation
251
+ with tab4:
252
+ motivation = st.text_area("Motivation for Graduate Studies", placeholder="Example: I have always been passionate about...")
253
+ academic_background = st.text_area("Academic Background", placeholder="Example: I completed my undergraduate degree in...")
254
+ research_experiences = st.text_area("Research & Projects", placeholder="Example: During my undergraduate studies, I worked on...")
255
+ career_goals = st.text_area("Career Goals", placeholder="Example: My long-term goal is to...")
256
+ why_this_program = st.text_area("Why This Program", placeholder="Example: This program aligns with my research interests because...")
257
 
258
  if st.button("Generate SOP"):
259
+ with st.spinner("Generating SOP..."):
260
+ try:
261
+ sop = sop_chain.run({
262
+ "motivation": motivation,
263
+ "academic_background": academic_background,
264
+ "research_experiences": research_experiences,
265
+ "career_goals": career_goals,
266
+ "why_this_program": why_this_program
267
+ })
268
+ st.markdown("**Generated SOP:**")
269
+ st.markdown(sop)
270
+ st.download_button("Download SOP", sop, file_name="sop.txt")
271
+ except Exception as e:
272
+ st.error(f"Error generating SOP: {e}")
273
+
274
+ # Reset Button
275
+ if st.button("🔄 Reset All Inputs and Outputs"):
276
+ st.experimental_rerun()