ombhojane commited on
Commit
6e3b433
·
verified ·
1 Parent(s): 80a874b

Upload 10 files

Browse files
.env ADDED
@@ -0,0 +1 @@
 
 
1
+ GOOGLE_API_KEY=AIzaSyCA4__JMC_ZIQ9xQegIj5LOMLhSSrn3pMw
.gitignore ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ #.idea/
Homepage.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit_option_menu import option_menu
3
+ from app_utils import switch_page
4
+ import streamlit as st
5
+ from PIL import Image
6
+
7
+ im = Image.open("icon.png")
8
+ st.set_page_config(page_title = "AI Interviewer", layout = "centered",page_icon=im)
9
+
10
+ lan = st.selectbox("#### Language", ["English", "中文"])
11
+
12
+ if lan == "English":
13
+ home_title = "AI Interviewer"
14
+ home_introduction = "Welcome to AI Interviewer, empowering your interview preparation with generative AI."
15
+
16
+ st.markdown(
17
+ "<style>#MainMenu{visibility:hidden;}</style>",
18
+ unsafe_allow_html=True
19
+ )
20
+ st.image(im, width=100)
21
+ st.markdown(f"""# {home_title}""",unsafe_allow_html=True)
22
+ st.markdown("""\n""")
23
+ #st.markdown("#### Greetings")
24
+ st.markdown("Welcome to AI Interviewer! 👏 AI Interviewer is your personal interviewer powered by generative AI that conducts mock interviews."
25
+ "You can upload your resume and enter job descriptions, and AI Interviewer will ask you customized questions. Additionally, you can configure your own Interviewer!")
26
+ st.markdown("""\n""")
27
+
README.md CHANGED
@@ -1,12 +1,79 @@
1
- ---
2
- title: Interview
3
- emoji: 🌍
4
- colorFrom: red
5
- colorTo: indigo
6
- sdk: streamlit
7
- sdk_version: 1.31.1
8
- app_file: app.py
9
- pinned: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+
2
+
3
+ # AI Interviewer - Version 0.1.2
4
+
5
+ Welcome to AI Interviewer! 👏 AI Interviewer is a cutting-edge application powered by generative AI designed to conduct mock interviews. With the ability to analyze your uploaded resume and job descriptions, AI Interviewer generates tailored questions to enhance your interview preparation. You even have the flexibility to customize your own interviewing experience!
6
+
7
+ ## Table of Contents
8
+
9
+ - [Overview](#overview)
10
+ - [Getting Started](#getting-started)
11
+ - [Features](#features)
12
+ - [Upcoming Updates](#upcoming-updates)
13
+ - [Feedback](#feedback)
14
+ - [Contact](#contact)
15
+ <!-- - [Acknowledgments](#acknowledgments) -->
16
+
17
+ ## Overview
18
+
19
+ AI Interviewer aims to revolutionize your interview preparation process. Whether you're seeking to improve your technical skills, communication abilities, or adaptability, this application can assist you. Powered by cutting-edge technology from OpenAI, FAISS, and Langchain, AI Interviewer provides a seamless experience that simulates real interview scenarios.
20
+
21
+ ## Getting Started
22
+
23
+ To begin your AI Interviewer experience, follow these simple steps:
24
+
25
+ 1. **Select Interview Type:** Choose from the following interview screens:
26
+ - **Homepage:** Overview of AI Interviewer.
27
+ - **Behavioral Screen:** Assess your behavioral skills.
28
+ - **Professional Screen:** Evaluate your technical skills.
29
+ - **Resume Screen:** Review your uploaded resume.
30
+
31
+ 2. **Customize Your Experience:** Tailor your interview by uploading your resume and providing job descriptions.
32
+
33
+ 3. **Choose Interaction Style:** Opt for your preferred interaction style, whether it's through chat or voice.
34
+
35
+ 4. **Start Interviewing:** Begin the interview by introducing yourself and responding to AI-generated questions.
36
+
37
+ ## Features
38
+
39
+ - **Personalized Questions:** AI Interviewer generates interview questions customized to your uploaded resume and job descriptions.
40
+
41
+ - **Multiple Screens:** Access different screens for behavioral, professional, and resume-related interview aspects.
42
+
43
+ - **Interactive Experience:** Engage in a conversation with the AI interviewer, enhancing the realism of the interview process.
44
+
45
+ - **Easy Refresh:** Initiate a new interview session simply by refreshing the page.
46
+
47
+ - **Choice of Interaction:** Select between chat-based or voice-based interaction styles for your interviews.
48
+
49
+ ## Upcoming Updates
50
+
51
+ We are constantly working to improve AI Interviewer and bring you new features. In the pipeline:
52
+
53
+ - Enhanced AI capabilities for even more realistic interviews.
54
+ - Expanded question database for a wider range of industries and roles.
55
+ - Improved voice interaction for a seamless experience.
56
+
57
+ ## Feedback
58
+
59
+ We highly value your feedback! Your insights can help us enhance AI Interviewer. Please take a moment to fill out our [Feedback Form](https://docs.google.com/forms/d/13f4q03bk4lD7sKR7qZ8UM1lQDo6NhRaAKv7uIeXHEaQ/viewform?edit_requested=true).
60
+
61
+ ## Contact
62
+
63
+ ## Contact
64
+
65
+ - GitHub: [jiatastic](https://github.com/jiatastic)
66
+
67
+ <!-- ## Acknowledgments
68
+
69
+ AI Interviewer is powered by a blend of advanced technologies:
70
+
71
+ - OpenAI: Providing the generative AI capabilities.
72
+ - FAISS: Enhancing search and retrieval capabilities.
73
+ - Langchain: Facilitating natural language interactions.
74
+
75
+ The application is proudly built with [Streamlit](https://streamlit.io/).
76
+
77
  ---
78
 
79
+ Remember, AI Interviewer is your partner in preparing for your future interviews. Sharpen your skills, boost your confidence, and seize those career opportunities with confidence! 🚀 -->
icon.png ADDED
initialization.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from langchain.embeddings import OpenAIEmbeddings
3
+ from langchain.vectorstores import FAISS
4
+ from langchain.text_splitter import NLTKTextSplitter
5
+ from langchain.memory import ConversationBufferMemory
6
+ from langchain.chains import RetrievalQA, ConversationChain
7
+ from prompts.prompts import templates
8
+ from langchain.prompts.prompt import PromptTemplate
9
+ from langchain.chat_models import ChatOpenAI
10
+ from PyPDF2 import PdfReader
11
+ from prompts.prompt_selector import prompt_sector
12
+ def embedding(text):
13
+ """embeddings"""
14
+ text_splitter = NLTKTextSplitter()
15
+ texts = text_splitter.split_text(text)
16
+ # Create emebeddings
17
+ embeddings = OpenAIEmbeddings()
18
+ docsearch = FAISS.from_texts(texts, embeddings)
19
+ return docsearch
20
+
21
+ def resume_reader(resume):
22
+ pdf_reader = PdfReader(resume)
23
+ text = ""
24
+ for page in pdf_reader.pages:
25
+ text += page.extract_text()
26
+ return text
27
+
28
+ def initialize_session_state(template=None, position=None):
29
+ """ initialize session states """
30
+ if 'jd' in st.session_state:
31
+ st.session_state.docsearch = embedding(st.session_state.jd)
32
+ else:
33
+ st.session_state.docsearch = embedding(resume_reader(st.session_state.resume))
34
+
35
+ #if 'retriever' not in st.session_state:
36
+ st.session_state.retriever = st.session_state.docsearch.as_retriever(search_type="similarity")
37
+ #if 'chain_type_kwargs' not in st.session_state:
38
+ if 'jd' in st.session_state:
39
+ Interview_Prompt = PromptTemplate(input_variables=["context", "question"],
40
+ template=template)
41
+ st.session_state.chain_type_kwargs = {"prompt": Interview_Prompt}
42
+ else:
43
+ st.session_state.chain_type_kwargs = prompt_sector(position, templates)
44
+ #if 'memory' not in st.session_state:
45
+ st.session_state.memory = ConversationBufferMemory()
46
+ # interview history
47
+ #if "history" not in st.session_state:
48
+ st.session_state.history = []
49
+ # token count
50
+ #if "token_count" not in st.session_state:
51
+ st.session_state.token_count = 0
52
+ #if "guideline" not in st.session_state:
53
+ llm = ChatOpenAI(
54
+ model_name="gpt-3.5-turbo",
55
+ temperature=0.6, )
56
+ st.session_state.guideline = RetrievalQA.from_chain_type(
57
+ llm=llm,
58
+ chain_type_kwargs=st.session_state.chain_type_kwargs, chain_type='stuff',
59
+ retriever=st.session_state.retriever, memory=st.session_state.memory).run(
60
+ "Create an interview guideline and prepare only one questions for each topic. Make sure the questions tests the technical knowledge")
61
+ # llm chain and memory
62
+ #if "screen" not in st.session_state:
63
+ llm = ChatOpenAI(
64
+ model_name="gpt-3.5-turbo",
65
+ temperature=0.8, )
66
+ PROMPT = PromptTemplate(
67
+ input_variables=["history", "input"],
68
+ template="""I want you to act as an interviewer strictly following the guideline in the current conversation.
69
+
70
+ Ask me questions and wait for my answers like a real person.
71
+ Do not write explanations.
72
+ Ask question like a real person, only one question at a time.
73
+ Do not ask the same question.
74
+ Do not repeat the question.
75
+ Do ask follow-up questions if necessary.
76
+ You name is GPTInterviewer.
77
+ I want you to only reply as an interviewer.
78
+ Do not write all the conversation at once.
79
+ If there is an error, point it out.
80
+
81
+ Current Conversation:
82
+ {history}
83
+
84
+ Candidate: {input}
85
+ AI: """)
86
+ st.session_state.screen = ConversationChain(prompt=PROMPT, llm=llm,
87
+ memory=st.session_state.memory)
88
+ #if "feedback" not in st.session_state:
89
+ llm = ChatOpenAI(
90
+ model_name = "gpt-3.5-turbo",
91
+ temperature = 0.5,)
92
+ st.session_state.feedback = ConversationChain(
93
+ prompt=PromptTemplate(input_variables = ["history", "input"], template = templates.feedback_template),
94
+ llm=llm,
95
+ memory = st.session_state.memory,
96
+ )
pages/Behavioral Screen.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit_lottie import st_lottie
3
+ from typing import Literal
4
+ from dataclasses import dataclass
5
+ import json
6
+ import base64
7
+ from langchain.memory import ConversationBufferMemory
8
+ from langchain.chains import ConversationChain, RetrievalQA
9
+ from langchain.prompts.prompt import PromptTemplate
10
+ from langchain.text_splitter import NLTKTextSplitter
11
+ from langchain.vectorstores import FAISS
12
+ import nltk
13
+ from prompts.prompts import templates
14
+ from langchain_google_genai import ChatGoogleGenerativeAI
15
+ import getpass
16
+ import os
17
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings
18
+
19
+
20
+ if "GOOGLE_API_KEY" not in os.environ:
21
+ os.environ["GOOGLE_API_KEY"] = "AIzaSyCA4__JMC_ZIQ9xQegIj5LOMLhSSrn3pMw"
22
+
23
+
24
+
25
+ def load_lottiefile(filepath: str):
26
+
27
+ '''Load lottie animation file'''
28
+
29
+ with open(filepath, "r") as f:
30
+ return json.load(f)
31
+
32
+ st.title("Behavioral Screen")
33
+ st.markdown("""\n""")
34
+ jd = st.text_area("""Please enter the job description here (If you don't have one, enter keywords, such as "communication" or "teamwork" instead): """)
35
+
36
+ @dataclass
37
+ class Message:
38
+ '''dataclass for keeping track of the messages'''
39
+ origin: Literal["human", "ai"]
40
+ message: str
41
+
42
+ def autoplay_audio(file_path: str):
43
+ '''Play audio automatically'''
44
+ def update_audio():
45
+ global global_audio_md
46
+ with open(file_path, "rb") as f:
47
+ data = f.read()
48
+ b64 = base64.b64encode(data).decode()
49
+ global_audio_md = f"""
50
+ <audio controls autoplay="true">
51
+ <source src="data:audio/mp3;base64,{b64}" type="audio/mp3">
52
+ </audio>
53
+ """
54
+ def update_markdown(audio_md):
55
+ st.markdown(audio_md, unsafe_allow_html=True)
56
+ update_audio()
57
+ update_markdown(global_audio_md)
58
+
59
+ def embeddings(text: str):
60
+
61
+ '''Create embeddings for the job description'''
62
+
63
+ nltk.download('punkt')
64
+ text_splitter = NLTKTextSplitter()
65
+ texts = text_splitter.split_text(text)
66
+ # Create emebeddings
67
+ embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
68
+ docsearch = FAISS.from_texts(texts, embeddings)
69
+ retriever = docsearch.as_retriever(search_tupe='similarity search')
70
+ return retriever
71
+
72
+ def initialize_session_state():
73
+
74
+ '''Initialize session state variables'''
75
+
76
+ if "retriever" not in st.session_state:
77
+ st.session_state.retriever = embeddings(jd)
78
+ if "chain_type_kwargs" not in st.session_state:
79
+ Behavioral_Prompt = PromptTemplate(input_variables=["context", "question"],
80
+ template=templates.behavioral_template)
81
+ st.session_state.chain_type_kwargs = {"prompt": Behavioral_Prompt}
82
+ # interview history
83
+ if "history" not in st.session_state:
84
+ st.session_state.history = []
85
+ st.session_state.history.append(Message("ai", "Hello there! I am your interviewer today. I will access your soft skills through a series of questions. Let's get started! Please start by saying hello or introducing yourself. Note: The maximum length of your answer is 4097 tokens!"))
86
+ # token count
87
+ if "token_count" not in st.session_state:
88
+ st.session_state.token_count = 0
89
+ if "memory" not in st.session_state:
90
+ st.session_state.memory = ConversationBufferMemory()
91
+ if "guideline" not in st.session_state:
92
+ llm = ChatGoogleGenerativeAI(
93
+ model="gemini-pro")
94
+ st.session_state.guideline = RetrievalQA.from_chain_type(
95
+ llm=llm,
96
+ chain_type_kwargs=st.session_state.chain_type_kwargs, chain_type='stuff',
97
+ retriever=st.session_state.retriever, memory=st.session_state.memory).run(
98
+ "Create an interview guideline and prepare total of 8 questions. Make sure the questions tests the soft skills")
99
+ # llm chain and memory
100
+ if "conversation" not in st.session_state:
101
+ llm = ChatGoogleGenerativeAI(
102
+ model="gemini-pro")
103
+ PROMPT = PromptTemplate(
104
+ input_variables=["history", "input"],
105
+ template="""I want you to act as an interviewer strictly following the guideline in the current conversation.
106
+ Candidate has no idea what the guideline is.
107
+ Ask me questions and wait for my answers. Do not write explanations.
108
+ Ask question like a real person, only one question at a time.
109
+ Do not ask the same question.
110
+ Do not repeat the question.
111
+ Do ask follow-up questions if necessary.
112
+ You name is GPTInterviewer.
113
+ I want you to only reply as an interviewer.
114
+ Do not write all the conversation at once.
115
+ If there is an error, point it out.
116
+
117
+ Current Conversation:
118
+ {history}
119
+
120
+ Candidate: {input}
121
+ AI: """)
122
+ st.session_state.conversation = ConversationChain(prompt=PROMPT, llm=llm,
123
+ memory=st.session_state.memory)
124
+ if "feedback" not in st.session_state:
125
+ llm = ChatGoogleGenerativeAI(
126
+ model="gemini-pro")
127
+ st.session_state.feedback = ConversationChain(
128
+ prompt=PromptTemplate(input_variables = ["history", "input"], template = templates.feedback_template),
129
+ llm=llm,
130
+ memory = st.session_state.memory,
131
+ )
132
+
133
+ def answer_call_back():
134
+
135
+ '''callback function for answering user input'''
136
+
137
+ # user input
138
+ human_answer = st.session_state.answer
139
+ st.session_state.history.append(
140
+ Message("human", human_answer)
141
+ )
142
+ # OpenAI answer and save to history
143
+ llm_answer = st.session_state.conversation.run(human_answer)
144
+ st.session_state.history.append(
145
+ Message("ai", llm_answer)
146
+ )
147
+ st.session_state.token_count += len(llm_answer.split())
148
+ return llm_answer
149
+
150
+ ### ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
151
+ if jd:
152
+
153
+ initialize_session_state()
154
+ credit_card_placeholder = st.empty()
155
+ col1, col2 = st.columns(2)
156
+ with col1:
157
+ feedback = st.button("Get Interview Feedback")
158
+ with col2:
159
+ guideline = st.button("Show me interview guideline!")
160
+ audio = None
161
+ chat_placeholder = st.container()
162
+ answer_placeholder = st.container()
163
+
164
+ if guideline:
165
+ st.write(st.session_state.guideline)
166
+ if feedback:
167
+ evaluation = st.session_state.feedback.run("please give evalution regarding the interview")
168
+ st.markdown(evaluation)
169
+ st.download_button(label="Download Interview Feedback", data=evaluation, file_name="interview_feedback.txt")
170
+ st.stop()
171
+ else:
172
+ with answer_placeholder:
173
+ voice = 0
174
+ if voice:
175
+ print("voice")
176
+ #st.warning("An UnboundLocalError will occur if the microphone fails to record.")
177
+ else:
178
+ answer = st.chat_input("Your answer")
179
+ if answer:
180
+ st.session_state['answer'] = answer
181
+ audio = answer_call_back()
182
+ with chat_placeholder:
183
+ for answer in st.session_state.history:
184
+ if answer.origin == 'ai':
185
+ if audio:
186
+ with st.chat_message("assistant"):
187
+ st.write(answer.message)
188
+ st.write(audio)
189
+ else:
190
+ with st.chat_message("assistant"):
191
+ st.write(answer.message)
192
+ else:
193
+ with st.chat_message("user"):
194
+ st.write(answer.message)
195
+
196
+ credit_card_placeholder.caption(f"""
197
+ Progress: {int(len(st.session_state.history) / 30 * 100)}% completed.
198
+ """)
199
+
200
+ else:
201
+ st.info("Please submit job description to start interview.")
202
+
203
+
204
+
205
+
pages/Professional Screen.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from streamlit_lottie import st_lottie
3
+ from typing import Literal
4
+ from dataclasses import dataclass
5
+ import json
6
+ import base64
7
+ from langchain.memory import ConversationBufferMemory
8
+
9
+ from langchain.chains import ConversationChain, RetrievalQA
10
+ from langchain.prompts.prompt import PromptTemplate
11
+ from langchain.text_splitter import NLTKTextSplitter
12
+ from langchain.vectorstores import FAISS
13
+ import nltk
14
+ from prompts.prompts import templates
15
+ from langchain_google_genai import ChatGoogleGenerativeAI
16
+ import getpass
17
+ import os
18
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings
19
+
20
+
21
+ if "GOOGLE_API_KEY" not in os.environ:
22
+ os.environ["GOOGLE_API_KEY"] = "AIzaSyCA4__JMC_ZIQ9xQegIj5LOMLhSSrn3pMw"
23
+
24
+
25
+
26
+ st.title("Professional Screen")
27
+ jd = st.text_area("Please enter the job description here (If you don't have one, enter keywords, such as PostgreSQL or Python instead): ")
28
+
29
+
30
+ @dataclass
31
+ class Message:
32
+ """class for keeping track of interview history."""
33
+ origin: Literal["human", "ai"]
34
+ message: str
35
+
36
+ def save_vector(text):
37
+ """embeddings"""
38
+
39
+ nltk.download('punkt')
40
+ text_splitter = NLTKTextSplitter()
41
+ texts = text_splitter.split_text(text)
42
+ # Create emebeddings
43
+ embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
44
+ docsearch = FAISS.from_texts(texts, embeddings)
45
+ return docsearch
46
+
47
+ def initialize_session_state_jd():
48
+ """ initialize session states """
49
+ if 'jd_docsearch' not in st.session_state:
50
+ st.session_state.jd_docserch = save_vector(jd)
51
+ if 'jd_retriever' not in st.session_state:
52
+ st.session_state.jd_retriever = st.session_state.jd_docserch.as_retriever(search_type="similarity")
53
+ if 'jd_chain_type_kwargs' not in st.session_state:
54
+ Interview_Prompt = PromptTemplate(input_variables=["context", "question"],
55
+ template=templates.jd_template)
56
+ st.session_state.jd_chain_type_kwargs = {"prompt": Interview_Prompt}
57
+ if 'jd_memory' not in st.session_state:
58
+ st.session_state.jd_memory = ConversationBufferMemory()
59
+ # interview history
60
+ if "jd_history" not in st.session_state:
61
+ st.session_state.jd_history = []
62
+ st.session_state.jd_history.append(Message("ai",
63
+ "Hello, Welcome to the interview. I am your interviewer today. I will ask you professional questions regarding the job description you submitted."
64
+ "Please start by introducting a little bit about yourself. Note: The maximum length of your answer is 4097 tokens!"))
65
+ # token count
66
+ if "token_count" not in st.session_state:
67
+ st.session_state.token_count = 0
68
+ if "jd_guideline" not in st.session_state:
69
+ llm = ChatGoogleGenerativeAI(
70
+ model="gemini-pro")
71
+ st.session_state.jd_guideline = RetrievalQA.from_chain_type(
72
+ llm=llm,
73
+ chain_type_kwargs=st.session_state.jd_chain_type_kwargs, chain_type='stuff',
74
+ retriever=st.session_state.jd_retriever, memory = st.session_state.jd_memory).run("Create an interview guideline and prepare only one questions for each topic. Make sure the questions tests the technical knowledge")
75
+ # llm chain and memory
76
+ if "jd_screen" not in st.session_state:
77
+ llm = ChatGoogleGenerativeAI(
78
+ model="gemini-pro")
79
+ PROMPT = PromptTemplate(
80
+ input_variables=["history", "input"],
81
+ template="""I want you to act as an interviewer strictly following the guideline in the current conversation.
82
+ Candidate has no idea what the guideline is.
83
+ Ask me questions and wait for my answers. Do not write explanations.
84
+ Ask question like a real person, only one question at a time.
85
+ Do not ask the same question.
86
+ Do not repeat the question.
87
+ Do ask follow-up questions if necessary.
88
+ You name is GPTInterviewer.
89
+ I want you to only reply as an interviewer.
90
+ Do not write all the conversation at once.
91
+ If there is an error, point it out.
92
+
93
+ Current Conversation:
94
+ {history}
95
+
96
+ Candidate: {input}
97
+ AI: """)
98
+
99
+ st.session_state.jd_screen = ConversationChain(prompt=PROMPT, llm=llm,
100
+ memory=st.session_state.jd_memory)
101
+ if 'jd_feedback' not in st.session_state:
102
+ llm = ChatGoogleGenerativeAI(
103
+ model="gemini-pro")
104
+ st.session_state.jd_feedback = ConversationChain(
105
+ prompt=PromptTemplate(input_variables=["history", "input"], template=templates.feedback_template),
106
+ llm=llm,
107
+ memory=st.session_state.jd_memory,
108
+ )
109
+
110
+ def answer_call_back():
111
+ formatted_history = []
112
+ for message in st.session_state.jd_history:
113
+ if message.origin == "human":
114
+ formatted_message = {"speaker": "user", "text": message.message}
115
+ else:
116
+ formatted_message = {"speaker": "assistant", "text": message.message}
117
+ formatted_history.append(formatted_message)
118
+
119
+ user_answer = st.session_state.get('answer', '')
120
+
121
+ answer = st.session_state.jd_screen.run(input=user_answer, history=formatted_history)
122
+
123
+ if user_answer:
124
+ st.session_state.jd_history.append(Message("human", user_answer))
125
+ if answer:
126
+ st.session_state.jd_history.append(Message("ai", answer))
127
+
128
+ return answer
129
+
130
+
131
+ if jd:
132
+ # initialize session states
133
+ initialize_session_state_jd()
134
+ #st.write(st.session_state.jd_guideline)
135
+ credit_card_placeholder = st.empty()
136
+ col1, col2 = st.columns(2)
137
+ with col1:
138
+ feedback = st.button("Get Interview Feedback")
139
+ with col2:
140
+ guideline = st.button("Show me interview guideline!")
141
+ chat_placeholder = st.container()
142
+ answer_placeholder = st.container()
143
+ audio = None
144
+ # if submit email adress, get interview feedback imediately
145
+ if guideline:
146
+ st.write(st.session_state.jd_guideline)
147
+ if feedback:
148
+ evaluation = st.session_state.jd_feedback.run("please give evalution regarding the interview")
149
+ st.markdown(evaluation)
150
+ st.download_button(label="Download Interview Feedback", data=evaluation, file_name="interview_feedback.txt")
151
+ st.stop()
152
+ else:
153
+ with answer_placeholder:
154
+ voice = 0
155
+ if voice:
156
+ print(voice)
157
+ else:
158
+ answer = st.chat_input("Your answer")
159
+ if answer:
160
+ st.session_state['answer'] = answer
161
+ audio = answer_call_back()
162
+ with chat_placeholder:
163
+ for answer in st.session_state.jd_history:
164
+ if answer.origin == 'ai':
165
+ if audio:
166
+ with st.chat_message("assistant"):
167
+ st.write(answer.message)
168
+ st.write(audio)
169
+ else:
170
+ with st.chat_message("assistant"):
171
+ st.write(answer.message)
172
+ else:
173
+ with st.chat_message("user"):
174
+ st.write(answer.message)
175
+
176
+ credit_card_placeholder.caption(f"""
177
+ Progress: {int(len(st.session_state.jd_history) / 30 * 100)}% completed.""")
178
+ else:
179
+ st.info("Please submit a job description to start the interview.")
pages/Resume Screen.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # langchain: https://python.langchain.com/
2
+ from dataclasses import dataclass
3
+ import streamlit as st
4
+ from langchain.callbacks import get_openai_callback
5
+ from langchain.memory import ConversationBufferMemory
6
+ from langchain.chains import RetrievalQA, ConversationChain
7
+ from langchain.prompts.prompt import PromptTemplate
8
+ from prompts.prompts import templates
9
+ from typing import Literal
10
+ from langchain.vectorstores import FAISS
11
+ from langchain.text_splitter import NLTKTextSplitter
12
+ from PyPDF2 import PdfReader
13
+ from prompts.prompt_selector import prompt_sector
14
+ from streamlit_lottie import st_lottie
15
+ import json
16
+ from IPython.display import Audio
17
+ import nltk
18
+ from langchain_google_genai import ChatGoogleGenerativeAI
19
+ import getpass
20
+ import os
21
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings
22
+
23
+
24
+ if "GOOGLE_API_KEY" not in os.environ:
25
+ os.environ["GOOGLE_API_KEY"] = "AIzaSyCA4__JMC_ZIQ9xQegIj5LOMLhSSrn3pMw"
26
+
27
+
28
+
29
+ st.title("Resume Screen")
30
+
31
+ st.session_state.history = []
32
+
33
+ position = st.text_input("Select the position you are applying for :")
34
+ resume = st.file_uploader("Upload your resume", type=["pdf"])
35
+
36
+ #st.toast("4097 tokens is roughly equivalent to around 800 to 1000 words or 3 minutes of speech. Please keep your answer within this limit.")
37
+
38
+ @dataclass
39
+ class Message:
40
+ """Class for keeping track of interview history."""
41
+ origin: Literal["human", "ai"]
42
+ message: str
43
+
44
+ def save_vector(resume):
45
+ """embeddings"""
46
+ nltk.download('punkt')
47
+ pdf_reader = PdfReader(resume)
48
+ text = ""
49
+ for page in pdf_reader.pages:
50
+ text += page.extract_text()
51
+ # Split the document into chunks
52
+ text_splitter = NLTKTextSplitter()
53
+ texts = text_splitter.split_text(text)
54
+ embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
55
+ docsearch = FAISS.from_texts(texts, embeddings)
56
+ return docsearch
57
+
58
+ def initialize_session_state_resume():
59
+ # convert resume to embeddings
60
+ if 'docsearch' not in st.session_state:
61
+ st.session_state.docserch = save_vector(resume)
62
+ # retriever for resume screen
63
+ if 'retriever' not in st.session_state:
64
+ st.session_state.retriever = st.session_state.docserch.as_retriever(search_type="similarity")
65
+ # prompt for retrieving information
66
+ if 'chain_type_kwargs' not in st.session_state:
67
+ st.session_state.chain_type_kwargs = prompt_sector(position, templates)
68
+ # interview history
69
+ if "resume_history" not in st.session_state:
70
+ st.session_state.resume_history = []
71
+ st.session_state.resume_history.append(Message(origin="ai", message="Hello, I am your interivewer today. I will ask you some questions regarding your resume and your experience. Please start by saying hello or introducing yourself. Note: The maximum length of your answer is 4097 tokens!"))
72
+ # token count
73
+ if "token_count" not in st.session_state:
74
+ st.session_state.token_count = 0
75
+ # memory buffer for resume screen
76
+ if "resume_memory" not in st.session_state:
77
+ st.session_state.resume_memory = ConversationBufferMemory(human_prefix = "Candidate: ", ai_prefix = "Interviewer")
78
+ # guideline for resume screen
79
+ if "resume_guideline" not in st.session_state:
80
+ llm = ChatGoogleGenerativeAI(
81
+ model="gemini-pro")
82
+
83
+ st.session_state.resume_guideline = RetrievalQA.from_chain_type(
84
+ llm=llm,
85
+ chain_type_kwargs=st.session_state.chain_type_kwargs, chain_type='stuff',
86
+ retriever=st.session_state.retriever, memory = st.session_state.resume_memory).run("Create an interview guideline and prepare only two questions for each topic. Make sure the questions tests the knowledge")
87
+ # llm chain for resume screen
88
+ if "resume_screen" not in st.session_state:
89
+ llm = ChatGoogleGenerativeAI(
90
+ model="gemini-pro")
91
+
92
+ PROMPT = PromptTemplate(
93
+ input_variables=["history", "input"],
94
+ template= """I want you to act as an interviewer strictly following the guideline in the current conversation.
95
+
96
+ Ask me questions and wait for my answers like a human. Do not write explanations.
97
+ Candidate has no assess to the guideline.
98
+ Only ask one question at a time.
99
+ Do ask follow-up questions if you think it's necessary.
100
+ Do not ask the same question.
101
+ Do not repeat the question.
102
+ Candidate has no assess to the guideline.
103
+ You name is GPTInterviewer.
104
+ I want you to only reply as an interviewer.
105
+ Do not write all the conversation at once.
106
+ Candiate has no assess to the guideline.
107
+
108
+ Current Conversation:
109
+ {history}
110
+
111
+ Candidate: {input}
112
+ AI: """)
113
+ st.session_state.resume_screen = ConversationChain(prompt=PROMPT, llm = llm, memory = st.session_state.resume_memory)
114
+ # llm chain for generating feedback
115
+ if "resume_feedback" not in st.session_state:
116
+ llm = ChatGoogleGenerativeAI(
117
+ model="gemini-pro")
118
+ st.session_state.resume_feedback = ConversationChain(
119
+ prompt=PromptTemplate(input_variables=["history","input"], template=templates.feedback_template),
120
+ llm=llm,
121
+ memory=st.session_state.resume_memory,
122
+ )
123
+
124
+ def answer_call_back():
125
+
126
+ '''callback function for answering user input'''
127
+
128
+ # user input
129
+ human_answer = st.session_state.answer
130
+ st.session_state.history.append(
131
+ Message("human", human_answer)
132
+ )
133
+ # OpenAI answer and save to history
134
+ llm_answer = st.session_state.conversation.run(human_answer)
135
+ st.session_state.history.append(
136
+ Message("ai", llm_answer)
137
+ )
138
+ st.session_state.token_count += len(llm_answer.split())
139
+ return llm_answer
140
+
141
+ if position and resume:
142
+ # intialize session state
143
+ initialize_session_state_resume()
144
+ credit_card_placeholder = st.empty()
145
+ col1, col2 = st.columns(2)
146
+ with col1:
147
+ feedback = st.button("Get Interview Feedback")
148
+ with col2:
149
+ guideline = st.button("Show me interview guideline!")
150
+ chat_placeholder = st.container()
151
+ answer_placeholder = st.container()
152
+ audio = None
153
+ # if submit email adress, get interview feedback imediately
154
+ if guideline:
155
+ st.markdown(st.session_state.resume_guideline)
156
+ if feedback:
157
+ evaluation = st.session_state.resume_feedback.run("please give evalution regarding the interview")
158
+ st.markdown(evaluation)
159
+ st.download_button(label="Download Interview Feedback", data=evaluation, file_name="interview_feedback.txt")
160
+ st.stop()
161
+ else:
162
+ with answer_placeholder:
163
+ voice: bool = st.checkbox("I would like to speak with AI Interviewer!")
164
+ if voice:
165
+ print("voice") #st.warning("An UnboundLocalError will occur if the microphone fails to record.")
166
+ else:
167
+ answer = st.chat_input("Your answer")
168
+ if answer:
169
+ st.session_state['answer'] = answer
170
+ audio = answer_call_back()
171
+
172
+ with chat_placeholder:
173
+ for answer in st.session_state.resume_history:
174
+ if answer.origin == 'ai':
175
+ if audio:
176
+ with st.chat_message("assistant"):
177
+ st.write(answer.message)
178
+ st.write(audio)
179
+ else:
180
+ with st.chat_message("assistant"):
181
+ st.write(answer.message)
182
+ else:
183
+ with st.chat_message("user"):
184
+ st.write(answer.message)
185
+
186
+ credit_card_placeholder.caption(f"""
187
+ Progress: {int(len(st.session_state.resume_history) / 30 * 100)}% completed.""")
188
+
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ langchain
2
+ PyPDF2
3
+ openai
4
+ wave
5
+ streamlit==1.25.0
6
+ tiktoken
7
+ nltk
8
+ #azure-cognitiveservices-speech
9
+ audio_recorder_streamlit
10
+ streamlit-option-menu
11
+ streamlit-lottie
12
+ faiss-cpu
13
+ boto3
14
+ Ipython