lucifertrj's picture
Rename inference.py to app.py
61b4709 verified
import os
import json
from dotenv import load_dotenv
import uuid
from datetime import datetime
from groq import Groq
from constants import SYSTEM_PROMPT, INTERVIEW_INSTRUCTIONS, MOCK_INTERVIEW_PROMPT,EXPECTED_OUTPUT
from constants import JOB_MATCHING_INSTRUCTIONS,JOB_MATCHING_PROMPT,JOB_ROLES
from phi.agent import Agent
from phi.model.google import Gemini
from phi.tools.duckduckgo import DuckDuckGo
from elevenlabs.client import ElevenLabs
from elevenlabs import VoiceSettings
from gradio import (
Blocks, Chatbot, Row, Column, Radio, Dropdown,
Button, Audio, Textbox, State, HTML
)
load_dotenv()
# Initialize clients
eleven_client = ElevenLabs(api_key=os.getenv("ELEVEN_API_KEY"))
groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))
def get_current_datetime() -> str:
return json.dumps({
"current_datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
})
def create_agent(mode):
base_config = {
"model": Gemini(id="gemini-2.0-flash-exp", api_key=os.getenv("GOOGLE_API_KEY")),
"show_tool_calls": True,
"tools": [DuckDuckGo(fixed_max_results=10), get_current_datetime],
"add_history_to_messages": True,
}
if mode == "Interview Guide":
return Agent(
**base_config,
system_prompt=SYSTEM_PROMPT,
instructions=INTERVIEW_INSTRUCTIONS,
num_history_responses=6,
expected_output=EXPECTED_OUTPUT
)
elif mode == "Job Matching":
return Agent(
**base_config,
system_prompt=JOB_MATCHING_PROMPT,
instructions=JOB_MATCHING_INSTRUCTIONS,
)
else:
return Agent(
**base_config,
system_prompt=MOCK_INTERVIEW_PROMPT,
instructions=["Conduct a technical mock interview.", "Ask one question at a time.", "Evaluate the candidate's responses in simple concise words"],
num_history_responses=3,
)
def text_to_speech_file(text: str, client: ElevenLabs) -> str:
"""
Converts text to speech using ElevenLabs API and saves as MP3.
Args:
text (str): Text to convert to speech
client (ElevenLabs): Initialized ElevenLabs client
Returns:
str: Path to saved audio file
"""
try:
response = client.text_to_speech.convert(
voice_id="pNInz6obpgDQGcFmaJgB", # Adam voice
optimize_streaming_latency="0",
output_format="mp3_22050_32",
text=text,
model_id="eleven_turbo_v2",
voice_settings=VoiceSettings(
stability=0.0,
similarity_boost=1.0,
style=0.0,
use_speaker_boost=True,
),
)
save_file_path = f"{uuid.uuid4()}.mp3"
with open(save_file_path, "wb") as f:
for chunk in response:
if chunk:
f.write(chunk)
return save_file_path
except Exception as e:
raise Exception(f"Text-to-speech conversion failed: {str(e)}")
def handle_mock_interview(audio_path, history, agent_state, voice_choice):
"""Handle audio for Mock Interview mode"""
if not audio_path:
return history, agent_state, None, ""
try:
# Transcribe audio
with open(audio_path, "rb") as audio_file:
transcription = groq_client.audio.transcriptions.create(
file=("recording.wav", audio_file.read(), "audio/wav"),
model="whisper-large-v3-turbo",
response_format="text"
)
# Initialize agent if needed
if "agent" not in agent_state or agent_state.get("mode") != "Mock Interview":
agent_state["agent"] = create_agent("Mock Interview")
agent_state["mode"] = "Mock Interview"
# Get agent response
agent = agent_state["agent"]
response = agent.run(transcription).content
try:
# Generate audio using the improved text-to-speech function
audio_output = text_to_speech_file(response, eleven_client)
# Update history
history.append({"role": "user", "content": f"[Audio]: {transcription}"})
history.append({"role": "assistant", "content": response})
return history, agent_state, audio_output, ""
except Exception as audio_error:
return history, agent_state, None, f"Audio generation error: {str(audio_error)}"
except Exception as e:
return history, agent_state, None, f"Error: {str(e)}"
def handle_text_input(message, history, mode, agent_state):
"""Handle text input for Interview Guide mode"""
if not message.strip():
return history, agent_state, "", ""
if "agent" not in agent_state or agent_state.get("mode") != mode:
agent_state["agent"] = create_agent(mode)
agent_state["mode"] = mode
agent = agent_state["agent"]
history = history + [{"role": "user", "content": message}]
try:
# Using direct response instead of streaming
response = agent.run(message).content
history.append({"role": "assistant", "content": response})
return history, agent_state, "", ""
except Exception as e:
return history, agent_state, "", f"Error: {str(e)}"
def handle_job_matching(role, experience, location, history, agent_state):
"""Handle job matching mode inputs"""
# Initialize history if None
if history is None:
history = []
# Initialize agent_state if None
if agent_state is None:
agent_state = {}
if not all([role, experience, location]):
return history, agent_state, "Please fill in all fields"
# Initialize agent if needed
if "agent" not in agent_state or agent_state.get("mode") != "Job Matching":
agent_state["agent"] = create_agent("Job Matching")
agent_state["mode"] = "Job Matching"
query = f"""Find relevant jobs for:
Role: {role}
Experience: {experience}
Location: {location}
Please search for current job listings and provide details including:
1. Company name
2. Job title
3. Location
4. Key requirements
5. Application link or process
"""
try:
agent = agent_state["agent"]
history = history + [{"role": "user", "content": query}]
response = agent.run(query).content
history.append({"role": "assistant", "content": response})
return history, agent_state, ""
except Exception as e:
return history, agent_state, f"Error: {str(e)}"
def clear_chat():
return [], {}, None, ""
with Blocks(title="AI Interview Assistant") as demo:
# State
chat_history = State([])
agent_state = State({})
mode = Radio(
choices=["Interview Guide", "Mock Interview", "Job Matching"],
label="Mode",
value="Interview Guide"
)
chatbot = Chatbot(label="Conversation", height=500, type="messages")
error_msg = HTML()
with Row():
with Column(visible=True) as text_col:
text_input = Textbox(
label="Type your message",
placeholder="Ask about interview preparation...",
lines=3
)
submit_btn = Button("Send Message")
# Audio input for Mock Interview
with Column(visible=False) as audio_col:
voice_select = Dropdown(
choices=["Brian", "Rachel", "Sam"],
value="Brian",
label="Assistant Voice"
)
audio_input = Audio(
sources=["microphone"],
type="filepath",
label="Record your answer"
)
audio_output = Audio(
label="Assistant's Response",
visible=True
)
with Column(visible=False) as job_col:
role_select = Dropdown(
choices=JOB_ROLES,
label="Select Job Role",
value="Software Engineer"
)
experience = Dropdown(
choices=["0-2 years", "2-5 years", "5-8 years", "8+ years"],
label="Experience Level",
value="0-2 years"
)
location = Textbox(
label="Preferred Location",
placeholder="Enter city, state, or 'Remote'",
lines=1
)
search_btn = Button("Search Jobs")
# Clear button
clear_btn = Button("Clear Chat")
# Event handlers
def update_mode(mode_value):
return (
Column(visible=mode_value == "Interview Guide"),
Column(visible=mode_value == "Mock Interview"),
Column(visible=mode_value == "Job Matching")
)
mode.change(
update_mode,
inputs=[mode],
outputs=[text_col,audio_col,job_col]
)
submit_btn.click(
handle_text_input,
inputs=[text_input, chat_history, mode, agent_state],
outputs=[chatbot, agent_state, text_input, error_msg]
)
audio_input.change(
handle_mock_interview,
inputs=[audio_input, chat_history, agent_state, voice_select],
outputs=[chatbot, agent_state, audio_output, error_msg]
)
search_btn.click(
handle_job_matching,
inputs=[role_select, experience, location, chat_history, agent_state],
outputs=[chatbot, agent_state, error_msg]
)
clear_btn.click(
clear_chat,
outputs=[chat_history, agent_state, audio_output, error_msg]
)
if __name__ == "__main__":
demo.launch()