File size: 4,906 Bytes
1ad6ea2
642f31f
 
 
 
 
 
1ad6ea2
a35fb23
1ad6ea2
 
a35fb23
642f31f
 
 
 
1ad6ea2
642f31f
 
 
 
 
 
 
 
 
 
1ad6ea2
642f31f
 
 
 
 
1ad6ea2
642f31f
a35fb23
c16bb21
642f31f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34bda2a
642f31f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import os
import streamlit as st
import PyPDF2
from langchain_community.llms import HuggingFaceHub

# Streamlit page configuration
st.set_page_config(page_title="Research Position Application Generator", page_icon="🔬")

# Set Hugging Face API Key
os.environ["HUGGINGFACEHUB_API_TOKEN"] = st.secrets["HF_TOKEN"]

# Initialize LLM
llm = HuggingFaceHub(
    repo_id="mistralai/Mistral-7B-Instruct-v0.3", 
    model_kwargs={"temperature": 0.5}
)

def extract_text_from_pdf(uploaded_file):
    """
    Extract text from an uploaded PDF file.
    
    Args:
        uploaded_file (UploadedFile): PDF file uploaded by the user
    
    Returns:
        str: Extracted text from the PDF
    """
    try:
        pdf_reader = PyPDF2.PdfReader(uploaded_file)
        text = ""
        for page in pdf_reader.pages:
            text += page.extract_text()
        return text
    except Exception as e:
        st.error(f"Error extracting PDF text: {e}")
        return ""

def generate_cold_email(position_details, cv_text):
    """
    Generate a professional cold email using the LLM.
    
    Args:
        position_details (dict): Details about the research position
        cv_text (str): Text extracted from the CV/resume
    
    Returns:
        str: Generated cold email
    """
    prompt = f"""Write a professional and concise cold email to Professor {position_details['professor_name']} 
    at {position_details['university']} about the research position in {position_details['research_focus']}. 
    The email should:
    1. Demonstrate knowledge of the professor's research
    2. Highlight relevant experience from the CV
    3. Express genuine interest in the position
    4. Be no more than 250 words

    CV Details:
    {cv_text}

    Research Position Details:
    Research Focus: {position_details['research_focus']}
    Professor: {position_details['professor_name']}
    University: {position_details['university']}
    """
    
    return llm.invoke(prompt)

def generate_cover_letter(position_details, cv_text):
    """
    Generate a formal cover letter using the LLM.
    
    Args:
        position_details (dict): Details about the research position
        cv_text (str): Text extracted from the CV/resume
    
    Returns:
        str: Generated cover letter
    """
    prompt = f"""Write a professional and formal cover letter for a research position with the following details:
    Research Focus: {position_details['research_focus']}
    University: {position_details['university']}

    The cover letter should:
    1. Follow a standard business letter format
    2. Clearly state the purpose of the letter
    3. Highlight relevant skills and experiences from the CV
    4. Demonstrate alignment with the research position
    5. Be 300-400 words long
    6. Include a strong closing paragraph

    CV Details:
    {cv_text}
    """
    
    return llm.invoke(prompt)

def main():
    """
    Main Streamlit app function
    """
    st.title("🔬 Research Position Application Generator")
    
    # Sidebar for position details
    st.sidebar.header("Research Position Details")
    professor_name = st.sidebar.text_input("Professor's Name")
    university = st.sidebar.text_input("University")
    research_focus = st.sidebar.text_input("Research Focus")
    
    # CV Upload
    st.sidebar.header("Upload CV/Resume")
    uploaded_cv = st.sidebar.file_uploader("Choose a PDF file", type="pdf")
    
    # Generate button
    if st.sidebar.button("Generate Documents"):
        # Validate inputs
        if not (professor_name and university and research_focus and uploaded_cv):
            st.error("Please fill in all details and upload a CV")
            return
        
        # Extract CV text
        cv_text = extract_text_from_pdf(uploaded_cv)
        
        # Prepare position details
        position_details = {
            'professor_name': professor_name,
            'university': university,
            'research_focus': research_focus
        }
        
        # Generate documents
        with st.spinner('Generating documents...'):
            cold_email = generate_cold_email(position_details, cv_text)
            cover_letter = generate_cover_letter(position_details, cv_text)
        
        # Display results
        st.header("Generated Documents")
        
        # Cold Email
        st.subheader("Cold Email")
        st.write(cold_email)
        st.download_button(
            label="Download Cold Email",
            data=cold_email,
            file_name="cold_email.txt",
            mime="text/plain"
        )
        
        # Cover Letter
        st.subheader("Cover Letter")
        st.write(cover_letter)
        st.download_button(
            label="Download Cover Letter",
            data=cover_letter,
            file_name="cover_letter.txt",
            mime="text/plain"
        )

if __name__ == "__main__":
    main()