Get Hired Faster: How to use Lyzr-Automata to draft personalised cold emails
Tags: python, chatgpt, machinelearning, ai
Published: 2024-04-05 07:30:32

In today’s competitive job market, getting noticed by recruiters can feel like finding a needle in a haystack. What if there was a way to cut through the noise and land yourself more interviews, faster? In this blog post, we’ll explore how **Lyzr-Automata** can empower job seekers to accelerate their job search and increase interview callbacks.

## Setup
Create a folder, set up a virtual environment and activate it. Create `.env` file with your _OPENAI_API_KEY_. Then install the following libraries to get started.
### Libraries

- `streamlit`: for building the web app interface.
- `lyzr_automata` : for implementing our AI models, and tasks.
- `dotenv`: for loading environment variables (API key).
```
lyzr-automata==0.1.2
streamlit==1.32.2
python-dotenv==1.0.1
```
## Getting Started
We will split the task into 2 files. One for frontend components (main.py) while the other for Lyzr-Automata (lyzr_functions.py)

### main.py
**1.Import Libraries**
```python
import streamlit as st
from pypdf import PdfReader 
import os
from lyzr_functions import send_cold_email
```
**2.Helper Functions**
```python
# Save information on a text file that acts as memory for LLM
def save_to_text_file(text_value, mode):
    data_directory = "data"
    os.makedirs(data_directory, exist_ok=True)

    text_file_path = os.path.join(data_directory, 'instructions.txt')
    with open(text_file_path, mode) as file:
        file.write(text_value)

# Parse Resume
def read_pdf(pdf_file_path):
    reader = PdfReader(pdf_file_path) 
    extracted_text = ''.join(page.extract_text() for page in reader.pages)
    return extracted_text
```
**3. Input Components**
- `st.file_uploader` — Upload Resume
- `st.text_area` — Text area to enter job description
- `st.text_input` — Text field to enter list of emails and contact info
- `st.button` — Button to submit input
```python
# Resume Input
uploaded_file = st.file_uploader("Upload Resume", type='pdf')

# Job description Input
job_description = st.text_area("Enter Job Description")

# List of emails to send Input
email_ids = st.text_input('List of Emails', placeholder='Email1, Email2,...')

# Name and contact to sign the email Input
contact_info = st.text_input('Your contact info (to sign the email)', placeholder='Name, Phone Number')

# Submit button Input
is_send_email = st.button('Send Email!')

# env Variables to send email
user_email_address = st.text_input('Your email address')
app_password = st.text_input('Your email app password')
```
**4. Handle Inputs**
```python
if is_send_email:
    # If fields are empty
    if not email_ids or not job_description or not uploaded_file or not contact_info or not user_email_address or not app_password:
        st.error('Enter all the fields!')
    else:
        os.environ["PASSWORD"] = app_password
        os.environ["EMAIL"] = user_email_address
        email_list = email_ids.split(',')
        email_list = [email.strip() for email in email_list] # make a list of emails
        extracted_pdf_text = read_pdf(uploaded_file) # parse pdf
        save_to_text_file(text_value = extracted_pdf_text, mode = "w") # save pdf in txt file
        save_to_text_file(text_value = "\nJob Description : \n" + job_description, mode = "a") # save job desctiption in txt file
        send_cold_email(email_list, contact_info) # send email using Lyzr Automata
        st.success("Email sent!")
```
### lyzr_functions.py
**1.Import Libraries**
```python
from lyzr_automata.ai_models.openai import OpenAIModel
from lyzr_automata import Agent, Task
from lyzr_automata.tasks.task_literals import InputType, OutputType
from lyzr_automata.memory.open_ai import OpenAIMemory
from lyzr_automata.pipelines.linear_sync_pipeline import LinearSyncPipeline
from lyzr_automata import Logger
from lyzr_automata.tools.prebuilt_tools import send_email_by_smtp_tool
from dotenv import load_dotenv
import os

load_dotenv()

# LOAD OUR API KEY
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
PASSWORD = os.getenv("PASSWORD")
EMAIL = os.getenv("EMAIL")
```
**2. send_cold_email function**
- `OpenAIModel` — Create our models using OpenAI Key and specify the model type and name.
- `OpenAIMemory` — email_writer_memory, Create a vector store memory for the agent.
- `Agent` — email_writer_agent, create a Lyzr Agent for text email creation using the memory.
- `Task` — email_writer_task, create Lyzr Task with instructions on writing the email and the agent.
- `Tool` — email_sender_tool, initialise the pre-built email sender tool
- `Task` — send_email_task, create another Lyzr Task that is going to send our email.
- `LinearSyncPipeline` — Pass the Tasks in order of execution.
```python
def send_cold_email(email_list, contact_info):
    # GPT 4 Text Model
    open_ai_model_text = OpenAIModel(
        api_key= OPENAI_API_KEY,
        parameters={
            "model": "gpt-4-turbo-preview",
            "temperature": 0.3,
            "max_tokens": 1500,
        },
    )

    # Load memory from instructions file
    email_writer_memory = OpenAIMemory(
        file_path='data/instructions.txt'
    )

    # Create Agent with Memory
    email_writer_agent = Agent(
        prompt_persona="You are an intelligent email writer agent and assume the persona of a job seeker reaching out to potential employers or recruiters. The email should be professional, concise, and persuasive, highlighting the candidate's skills, experience, and why they are a good fit for the job description.",
        role="Cold Email writer",
        memory=email_writer_memory
    )

    # Create email writer Task
    email_writer_task = Task(
        name="Cold Email Creator",
        agent=email_writer_agent,
        output_type=OutputType.TEXT,
        input_type=InputType.TEXT,
        model=open_ai_model_text,
        instructions="Use the resume information and job description to write a cold email of 250 words to be sent to the recruiter. [IMPORTANT!] send the response in html use bullets for points and beautify it professionally. Return only the email. Don't leave any field empty. My personal details are : " + contact_info,
        log_output=True,
        enhance_prompt=False,
    )

    # Initialize email sender Tool
    email_sender_tool = send_email_by_smtp_tool(
        username=EMAIL,
        password=PASSWORD,
        host="smtp.gmail.com",
        port=587,
        sender_email=EMAIL
    )

    # Create email sender Task
    send_email_task = Task(
        name = "Send Email Task",
        tool = email_sender_tool,
        instructions="Send Email",
        model=open_ai_model_text,
        input_tasks = [email_writer_task],
        default_input = email_list
    )

    # Run Tasks using a pipeline
    logger = Logger()
    LinearSyncPipeline(
        logger=logger,
        name="Cold Emailer",
        completion_message="Email Sent!",
        tasks=[
            email_writer_task,
            send_email_task
        ],
    ).run()
```
### Run App
`streamlit run main.py`

## Flow Diagram

![Flow Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5dpvekxjcj36qm9bl54u.png)

Want to create more of such amazing AI Workflows? Visit our website at **[GitHub](https://github.com/LyzrCore/lyzr-automata)** to learn more about Lyzr-Automata!

Also checkout Lyzr SDKs at **[GitHub](https://github.com/LyzrCore/lyzr)**

**Lyzr Website**: [Lyzr.ai](https://www.lyzr.ai/)
**Lyzr Community Channel**: [Discord](https://discord.com/invite/nm7zSyEFA2)

**Code**: https://github.com/rasswanth-lyzr/cold-emailer
**Video Walkthrough**: https://www.youtube.com/watch?v=hXLAN0qFP9g