File size: 5,336 Bytes
3b9b6a5
d4b8475
 
 
 
3b9b6a5
557b7cf
3b9b6a5
 
 
 
 
d4b8475
3b9b6a5
d4b8475
 
 
 
 
 
3b9b6a5
d4b8475
 
 
 
 
3b9b6a5
d4b8475
 
 
 
3b9b6a5
d4b8475
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3b9b6a5
d4b8475
 
 
 
 
 
 
 
 
 
10493d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d4b8475
 
 
 
10493d1
 
 
 
 
 
d4b8475
 
 
 
 
 
 
10493d1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d4b8475
 
 
 
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
import streamlit as st
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
import PyPDF2
from dotenv import load_dotenv
import os

# Load environment variables from .env
load_dotenv()

# Job API keys and endpoints
access_token = os.getenv("API_KEY")

# Streamlit App Title
st.title("Job Description and CV-Based Email Generator")
st.write("""
This app uses Hugging Face's Gemma model to generate a professional email based on a pre-parsed CV and a job description.
Upload your CV once in the sidebar, and the system will reuse the parsed details for generating emails.
""")

# Sidebar for Settings and CV Upload
st.sidebar.title("Settings and CV Upload")

# File Upload for CV in Sidebar
uploaded_file = st.sidebar.file_uploader("Upload your CV (PDF format):", type=["pdf"])

if "parsed_cv" not in st.session_state:
    st.session_state.parsed_cv = None

if uploaded_file is not None:
    try:
        # Extract text from PDF
        pdf_reader = PyPDF2.PdfReader(uploaded_file)
        cv_text = "".join([page.extract_text() for page in pdf_reader.pages])
        st.sidebar.success("CV uploaded and text extracted successfully!")

        # Parse CV details and save to session state
        def parse_cv(cv_text):
            # Basic parsing logic (can be extended for specific details)
            return f"""
            Name: [Extracted Name]
            Contact Information: [Extracted Contact Info]
            Skills: [Extracted Skills]
            Experience: [Extracted Experience]
            Education: [Extracted Education]
            Summary: {cv_text[:500]}...  # Truncated summary of the CV
            """

        st.session_state.parsed_cv = parse_cv(cv_text)
        st.sidebar.success("CV parsed successfully!")
    except Exception as e:
        st.sidebar.error(f"Failed to extract text from CV: {e}")

if st.session_state.parsed_cv:
    st.sidebar.write("### Parsed CV Details:")
    st.sidebar.text(st.session_state.parsed_cv)

# Ensure Access Token is Provided
if access_token:
    @st.cache_resource
    def initialize_pipeline(access_token):
        try:
            tokenizer = AutoTokenizer.from_pretrained("google/gemma-2b-it", token=access_token)
            model = AutoModelForCausalLM.from_pretrained(
                "google/gemma-2b-it",
                token=access_token,
                device_map="auto"  # Better device handling
            )
            return pipeline(
                "text-generation",
                model=model,
                tokenizer=tokenizer,
                max_new_tokens=512,
                temperature=0.7,  # Add temperature for better generation
                do_sample=True,   # Enable sampling
                top_p=0.95        # Add top_p for better text quality
            )
        except Exception as e:
            st.error(f"Failed to initialize the model: {str(e)}")
            return None

    text_gen_pipeline = initialize_pipeline(access_token)

    @st.cache_resource
    def initialize_memory():
        return ConversationBufferMemory(
            input_key="input",
            output_key="output",
            return_messages=True
        )

    # Input job description
    job_description = st.text_area("Enter the job description:", "")

    # Display generated email
    if st.button("Generate Email"):
        if st.session_state.parsed_cv and job_description.strip():
            try:
                memory = initialize_memory()
                
                # Improved prompt template
                prompt = f"""Task: Write a professional job application email.

CV Summary:
{st.session_state.parsed_cv}

Job Description:
{job_description}

Instructions: Write a concise and professional email expressing interest in the position. 
Highlight relevant experience and skills from the CV that match the job requirements.
Keep the tone professional and enthusiastic.

Email:
"""
                
                # Generate email using the pipeline
                if text_gen_pipeline:
                    response = text_gen_pipeline(
                        prompt,
                        clean_up_tokenization_spaces=True,
                        return_full_text=False
                    )[0]['generated_text']

                    # Store in memory
                    memory.save_context(
                        {"input": f"Job Description: {job_description}"},
                        {"output": response}
                    )

                    # Display response
                    st.subheader("Generated Email:")
                    st.write(response)

                    # Display conversation history
                    st.subheader("Previous Generations:")
                    for entry in memory.load_memory_variables({})['history']:
                        st.write(entry)
                else:
                    st.error("Text generation pipeline not properly initialized.")
            except Exception as e:
                st.error(f"Error generating email: {str(e)}")
        else:
            st.warning("Please upload your CV in the sidebar and enter a job description.")
else:
    st.warning("Please enter your Hugging Face access token in the sidebar to use the app.")