lucifertrj
commited on
Commit
·
043739c
1
Parent(s):
c64ea8e
initial
Browse files- .gitignore +4 -0
- README.md +34 -0
- constants.py +72 -0
- inference.py +301 -0
- requirements.txt +111 -0
.gitignore
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.env
|
2 |
+
__pycache__/
|
3 |
+
*.pyc
|
4 |
+
.DS_Store
|
README.md
CHANGED
@@ -12,3 +12,37 @@ short_description: Agentic workflow for interview preparation platform
|
|
12 |
---
|
13 |
|
14 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
---
|
13 |
|
14 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
15 |
+
|
16 |
+
# AI Interview Assistant
|
17 |
+
|
18 |
+
An intelligent interview preparation platform with three powerful modes:
|
19 |
+
|
20 |
+
1. **Interview Guide**: Get personalized interview tips, common questions, and best practices for your target role.
|
21 |
+
|
22 |
+
2. **Mock Interview**: Practice interviews with voice interaction. Get real-time feedback on your responses with text-to-speech capabilities.
|
23 |
+
|
24 |
+
3. **Job Matching**: Find relevant job opportunities based on your preferences:
|
25 |
+
- Search across 30+ tech and business roles
|
26 |
+
- Get detailed job requirements and company information
|
27 |
+
- Access recruiter contact information where available
|
28 |
+
- Powered by AI search for up-to-date listings
|
29 |
+
|
30 |
+
## Features
|
31 |
+
- Voice interaction with multiple AI personas
|
32 |
+
- Real-time job search and matching
|
33 |
+
- Recruiter contact discovery
|
34 |
+
- Comprehensive interview preparation
|
35 |
+
- Personalized feedback
|
36 |
+
|
37 |
+
## Tech Stack
|
38 |
+
- Gradio for UI
|
39 |
+
- Phi-agent for AI interactions
|
40 |
+
- Gemini for language processing
|
41 |
+
- ElevenLabs for voice synthesis
|
42 |
+
- Tavily for advanced search
|
43 |
+
|
44 |
+
## Setup
|
45 |
+
1. Clone the repository
|
46 |
+
2. Install dependencies: `pip install -r requirements.txt`
|
47 |
+
3. Add required API keys to `.env`
|
48 |
+
4. Run: `python app.py`
|
constants.py
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
SYSTEM_PROMPT = """You are an expert career and interview coach with extensive experience in talent acquisition, career development, and professional mentoring. Your primary purpose is to assist with job interview preparation, career guidance, and professional development.
|
2 |
+
|
3 |
+
Core responsibilities:
|
4 |
+
|
5 |
+
- Provide concise and brief, actionable advice for interview preparation.
|
6 |
+
- You must include the SOURCES i.e., relevant URLS using DuckDuckGo for candidates to further explore.
|
7 |
+
- Help craft and refine structured responses to interview questions.
|
8 |
+
- Offer role-specific and industry-specific interview insights.
|
9 |
+
- Guide candidates through behavioral and technical interview questions.
|
10 |
+
- Assist with salary negotiations and professional communication.
|
11 |
+
- Share best practices for interview formats and reference from search.
|
12 |
+
"""
|
13 |
+
|
14 |
+
MOCK_INTERVIEW_PROMPT = """You are a technical interviewer conducting a job interview.
|
15 |
+
You need to have conversation kind of with the candidate.
|
16 |
+
Ask challenging but fair technical questions one at a time.
|
17 |
+
Evaluate responses thoroughly and provide constructive feedback.
|
18 |
+
Keep the respnse brief and concise.
|
19 |
+
Maintain a professional yet friendly tone throughout the interview.
|
20 |
+
"""
|
21 |
+
|
22 |
+
|
23 |
+
INTERVIEW_INSTRUCTIONS = """
|
24 |
+
- Always include Sources i.e., relevant URL references: use the search tool for this. Remember to attach website URL for the Sources.
|
25 |
+
- You need to search and provide actual URLs, rather than telling user to search. Make sure to use the DuckDuckGo action tool.
|
26 |
+
- Understand if the query focuses on interview prep, job search, or career development.
|
27 |
+
- Identify industry/role context and tailor advice accordingly.
|
28 |
+
- Provide tips for preparation, communication, and follow-up.
|
29 |
+
- Conclude with clear next steps or key takeaways.
|
30 |
+
"""
|
31 |
+
|
32 |
+
EXPECTED_OUTPUT = """
|
33 |
+
- **Response:**
|
34 |
+
1. [Main point addressing the specific query. Keep it short and concise. ]
|
35 |
+
2. [Frameworks or methods to answer (e.g., STAR for behavioral questions, Problem-Solution-Impact for situational)]
|
36 |
+
3. [Specific examples or scenarios relevant to the question and role]
|
37 |
+
4. [Tips for preparation, research, or tailoring the response]
|
38 |
+
|
39 |
+
- **Sources:** [Provide credible links or resources for further preparation]
|
40 |
+
"""
|
41 |
+
|
42 |
+
JOB_MATCHING_PROMPT = """You are an AI job matching specialist. Your role is to help users find relevant job opportunities based on their preferences and qualifications.
|
43 |
+
Use the provided tools to search for current job listings and ensure the information is up-to-date and accurate. When presenting job matches:
|
44 |
+
|
45 |
+
1. Focus on roles that closely match the user's selected job category and preferences
|
46 |
+
2. Include company name, job title, location, key requirements.
|
47 |
+
3. Verify that the opportunities are current and active
|
48 |
+
4. I need minimum of 10 job listing with relevant URLs
|
49 |
+
"""
|
50 |
+
|
51 |
+
JOB_MATCHING_INSTRUCTIONS = [
|
52 |
+
"Collect user preferences through a structured questionnaire",
|
53 |
+
"Search for relevant job opportunities using the DuckDuckGo tool",
|
54 |
+
"Present matches in a clear, organized format",
|
55 |
+
"Include only active job listings. Atleast 10",
|
56 |
+
]
|
57 |
+
|
58 |
+
JOB_ROLES = [
|
59 |
+
"Software Engineer", "Data Scientist", "Product Manager","Full Stack Intern"
|
60 |
+
"UX/UI Designer", "DevOps Engineer", "Cloud Architect",
|
61 |
+
"Machine Learning Engineer", "Full Stack Developer", "Sales Intern",
|
62 |
+
"Business Analyst", "Project Manager", "Digital Marketing Manager",
|
63 |
+
"Content Strategist", "Sales Manager", "HR Manager",
|
64 |
+
"Financial Analyst", "System Administrator",
|
65 |
+
"Quality Assurance Engineer", "Mobile Developer",
|
66 |
+
"Cybersecurity Engineer", "Data Engineer",
|
67 |
+
"Frontend Developer", "Backend Developer",
|
68 |
+
"Technical Writer", "Scrum Master",
|
69 |
+
"Solutions Architect", "Database Administrator",
|
70 |
+
"Network Engineer", "AI Research Scientist",
|
71 |
+
"Blockchain Developer", "Growth Hacker","AI Intern",
|
72 |
+
]
|
inference.py
ADDED
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
from dotenv import load_dotenv
|
4 |
+
import uuid
|
5 |
+
from datetime import datetime
|
6 |
+
from groq import Groq
|
7 |
+
|
8 |
+
from constants import SYSTEM_PROMPT, INTERVIEW_INSTRUCTIONS, MOCK_INTERVIEW_PROMPT,EXPECTED_OUTPUT
|
9 |
+
from constants import JOB_MATCHING_INSTRUCTIONS,JOB_MATCHING_PROMPT,JOB_ROLES
|
10 |
+
|
11 |
+
from phi.agent import Agent
|
12 |
+
from phi.model.google import Gemini
|
13 |
+
from phi.tools.duckduckgo import DuckDuckGo
|
14 |
+
|
15 |
+
from elevenlabs.client import ElevenLabs
|
16 |
+
from elevenlabs import VoiceSettings
|
17 |
+
|
18 |
+
from gradio import (
|
19 |
+
Blocks, Chatbot, Row, Column, Radio, Dropdown,
|
20 |
+
Button, Audio, Textbox, State, HTML
|
21 |
+
)
|
22 |
+
|
23 |
+
load_dotenv()
|
24 |
+
|
25 |
+
# Initialize clients
|
26 |
+
eleven_client = ElevenLabs(api_key=os.getenv("ELEVEN_API_KEY"))
|
27 |
+
groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))
|
28 |
+
|
29 |
+
def get_current_datetime() -> str:
|
30 |
+
return json.dumps({
|
31 |
+
"current_datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
32 |
+
})
|
33 |
+
|
34 |
+
def create_agent(mode):
|
35 |
+
base_config = {
|
36 |
+
"model": Gemini(id="gemini-2.0-flash-exp", api_key=os.getenv("GOOGLE_API_KEY")),
|
37 |
+
"show_tool_calls": True,
|
38 |
+
"tools": [DuckDuckGo(fixed_max_results=10), get_current_datetime],
|
39 |
+
"add_history_to_messages": True,
|
40 |
+
}
|
41 |
+
|
42 |
+
if mode == "Interview Guide":
|
43 |
+
return Agent(
|
44 |
+
**base_config,
|
45 |
+
system_prompt=SYSTEM_PROMPT,
|
46 |
+
instructions=INTERVIEW_INSTRUCTIONS,
|
47 |
+
num_history_responses=6,
|
48 |
+
expected_output=EXPECTED_OUTPUT
|
49 |
+
)
|
50 |
+
elif mode == "Job Matching":
|
51 |
+
return Agent(
|
52 |
+
**base_config,
|
53 |
+
system_prompt=JOB_MATCHING_PROMPT,
|
54 |
+
instructions=JOB_MATCHING_INSTRUCTIONS,
|
55 |
+
)
|
56 |
+
else:
|
57 |
+
return Agent(
|
58 |
+
**base_config,
|
59 |
+
system_prompt=MOCK_INTERVIEW_PROMPT,
|
60 |
+
instructions=["Conduct a technical mock interview.", "Ask one question at a time.", "Evaluate the candidate's responses in simple concise words"],
|
61 |
+
num_history_responses=3,
|
62 |
+
)
|
63 |
+
|
64 |
+
def text_to_speech_file(text: str, client: ElevenLabs) -> str:
|
65 |
+
"""
|
66 |
+
Converts text to speech using ElevenLabs API and saves as MP3.
|
67 |
+
|
68 |
+
Args:
|
69 |
+
text (str): Text to convert to speech
|
70 |
+
client (ElevenLabs): Initialized ElevenLabs client
|
71 |
+
|
72 |
+
Returns:
|
73 |
+
str: Path to saved audio file
|
74 |
+
"""
|
75 |
+
try:
|
76 |
+
response = client.text_to_speech.convert(
|
77 |
+
voice_id="pNInz6obpgDQGcFmaJgB", # Adam voice
|
78 |
+
optimize_streaming_latency="0",
|
79 |
+
output_format="mp3_22050_32",
|
80 |
+
text=text,
|
81 |
+
model_id="eleven_turbo_v2",
|
82 |
+
voice_settings=VoiceSettings(
|
83 |
+
stability=0.0,
|
84 |
+
similarity_boost=1.0,
|
85 |
+
style=0.0,
|
86 |
+
use_speaker_boost=True,
|
87 |
+
),
|
88 |
+
)
|
89 |
+
|
90 |
+
save_file_path = f"{uuid.uuid4()}.mp3"
|
91 |
+
with open(save_file_path, "wb") as f:
|
92 |
+
for chunk in response:
|
93 |
+
if chunk:
|
94 |
+
f.write(chunk)
|
95 |
+
|
96 |
+
return save_file_path
|
97 |
+
except Exception as e:
|
98 |
+
raise Exception(f"Text-to-speech conversion failed: {str(e)}")
|
99 |
+
|
100 |
+
def handle_mock_interview(audio_path, history, agent_state, voice_choice):
|
101 |
+
"""Handle audio for Mock Interview mode"""
|
102 |
+
if not audio_path:
|
103 |
+
return history, agent_state, None, ""
|
104 |
+
|
105 |
+
try:
|
106 |
+
# Transcribe audio
|
107 |
+
with open(audio_path, "rb") as audio_file:
|
108 |
+
transcription = groq_client.audio.transcriptions.create(
|
109 |
+
file=("recording.wav", audio_file.read(), "audio/wav"),
|
110 |
+
model="whisper-large-v3-turbo",
|
111 |
+
response_format="text"
|
112 |
+
)
|
113 |
+
|
114 |
+
# Initialize agent if needed
|
115 |
+
if "agent" not in agent_state or agent_state.get("mode") != "Mock Interview":
|
116 |
+
agent_state["agent"] = create_agent("Mock Interview")
|
117 |
+
agent_state["mode"] = "Mock Interview"
|
118 |
+
|
119 |
+
# Get agent response
|
120 |
+
agent = agent_state["agent"]
|
121 |
+
response = agent.run(transcription).content
|
122 |
+
|
123 |
+
try:
|
124 |
+
# Generate audio using the improved text-to-speech function
|
125 |
+
audio_output = text_to_speech_file(response, eleven_client)
|
126 |
+
|
127 |
+
# Update history
|
128 |
+
history.append({"role": "user", "content": f"[Audio]: {transcription}"})
|
129 |
+
history.append({"role": "assistant", "content": response})
|
130 |
+
|
131 |
+
return history, agent_state, audio_output, ""
|
132 |
+
|
133 |
+
except Exception as audio_error:
|
134 |
+
return history, agent_state, None, f"Audio generation error: {str(audio_error)}"
|
135 |
+
|
136 |
+
except Exception as e:
|
137 |
+
return history, agent_state, None, f"Error: {str(e)}"
|
138 |
+
|
139 |
+
def handle_text_input(message, history, mode, agent_state):
|
140 |
+
"""Handle text input for Interview Guide mode"""
|
141 |
+
if not message.strip():
|
142 |
+
return history, agent_state, "", ""
|
143 |
+
|
144 |
+
if "agent" not in agent_state or agent_state.get("mode") != mode:
|
145 |
+
agent_state["agent"] = create_agent(mode)
|
146 |
+
agent_state["mode"] = mode
|
147 |
+
|
148 |
+
agent = agent_state["agent"]
|
149 |
+
history = history + [{"role": "user", "content": message}]
|
150 |
+
|
151 |
+
try:
|
152 |
+
# Using direct response instead of streaming
|
153 |
+
response = agent.run(message).content
|
154 |
+
history.append({"role": "assistant", "content": response})
|
155 |
+
return history, agent_state, "", ""
|
156 |
+
except Exception as e:
|
157 |
+
return history, agent_state, "", f"Error: {str(e)}"
|
158 |
+
|
159 |
+
def handle_job_matching(role, experience, location, history, agent_state):
|
160 |
+
"""Handle job matching mode inputs"""
|
161 |
+
# Initialize history if None
|
162 |
+
if history is None:
|
163 |
+
history = []
|
164 |
+
|
165 |
+
# Initialize agent_state if None
|
166 |
+
if agent_state is None:
|
167 |
+
agent_state = {}
|
168 |
+
|
169 |
+
if not all([role, experience, location]):
|
170 |
+
return history, agent_state, "Please fill in all fields"
|
171 |
+
|
172 |
+
# Initialize agent if needed
|
173 |
+
if "agent" not in agent_state or agent_state.get("mode") != "Job Matching":
|
174 |
+
agent_state["agent"] = create_agent("Job Matching")
|
175 |
+
agent_state["mode"] = "Job Matching"
|
176 |
+
|
177 |
+
query = f"""Find relevant jobs for:
|
178 |
+
Role: {role}
|
179 |
+
Experience: {experience}
|
180 |
+
Location: {location}
|
181 |
+
|
182 |
+
Please search for current job listings and provide details including:
|
183 |
+
1. Company name
|
184 |
+
2. Job title
|
185 |
+
3. Location
|
186 |
+
4. Key requirements
|
187 |
+
5. Application link or process
|
188 |
+
"""
|
189 |
+
|
190 |
+
try:
|
191 |
+
agent = agent_state["agent"]
|
192 |
+
history = history + [{"role": "user", "content": query}]
|
193 |
+
response = agent.run(query).content
|
194 |
+
history.append({"role": "assistant", "content": response})
|
195 |
+
return history, agent_state, ""
|
196 |
+
except Exception as e:
|
197 |
+
return history, agent_state, f"Error: {str(e)}"
|
198 |
+
|
199 |
+
def clear_chat():
|
200 |
+
return [], {}, None, ""
|
201 |
+
|
202 |
+
with Blocks(title="AI Interview Assistant") as demo:
|
203 |
+
# State
|
204 |
+
chat_history = State([])
|
205 |
+
agent_state = State({})
|
206 |
+
|
207 |
+
mode = Radio(
|
208 |
+
choices=["Interview Guide", "Mock Interview", "Job Matching"],
|
209 |
+
label="Mode",
|
210 |
+
value="Interview Guide"
|
211 |
+
)
|
212 |
+
|
213 |
+
chatbot = Chatbot(label="Conversation", height=500, type="messages")
|
214 |
+
error_msg = HTML()
|
215 |
+
|
216 |
+
with Row():
|
217 |
+
with Column(visible=True) as text_col:
|
218 |
+
text_input = Textbox(
|
219 |
+
label="Type your message",
|
220 |
+
placeholder="Ask about interview preparation...",
|
221 |
+
lines=3
|
222 |
+
)
|
223 |
+
submit_btn = Button("Send Message")
|
224 |
+
|
225 |
+
# Audio input for Mock Interview
|
226 |
+
with Column(visible=False) as audio_col:
|
227 |
+
voice_select = Dropdown(
|
228 |
+
choices=["Brian", "Rachel", "Sam"],
|
229 |
+
value="Brian",
|
230 |
+
label="Assistant Voice"
|
231 |
+
)
|
232 |
+
audio_input = Audio(
|
233 |
+
sources=["microphone"],
|
234 |
+
type="filepath",
|
235 |
+
label="Record your answer"
|
236 |
+
)
|
237 |
+
audio_output = Audio(
|
238 |
+
label="Assistant's Response",
|
239 |
+
visible=True
|
240 |
+
)
|
241 |
+
|
242 |
+
with Column(visible=False) as job_col:
|
243 |
+
role_select = Dropdown(
|
244 |
+
choices=JOB_ROLES,
|
245 |
+
label="Select Job Role",
|
246 |
+
value="Software Engineer"
|
247 |
+
)
|
248 |
+
experience = Dropdown(
|
249 |
+
choices=["0-2 years", "2-5 years", "5-8 years", "8+ years"],
|
250 |
+
label="Experience Level",
|
251 |
+
value="0-2 years"
|
252 |
+
)
|
253 |
+
location = Textbox(
|
254 |
+
label="Preferred Location",
|
255 |
+
placeholder="Enter city, state, or 'Remote'",
|
256 |
+
lines=1
|
257 |
+
)
|
258 |
+
search_btn = Button("Search Jobs")
|
259 |
+
|
260 |
+
# Clear button
|
261 |
+
clear_btn = Button("Clear Chat")
|
262 |
+
|
263 |
+
# Event handlers
|
264 |
+
def update_mode(mode_value):
|
265 |
+
return (
|
266 |
+
Column(visible=mode_value == "Interview Guide"),
|
267 |
+
Column(visible=mode_value == "Mock Interview"),
|
268 |
+
Column(visible=mode_value == "Job Matching")
|
269 |
+
)
|
270 |
+
|
271 |
+
mode.change(
|
272 |
+
update_mode,
|
273 |
+
inputs=[mode],
|
274 |
+
outputs=[text_col,audio_col,job_col]
|
275 |
+
)
|
276 |
+
|
277 |
+
submit_btn.click(
|
278 |
+
handle_text_input,
|
279 |
+
inputs=[text_input, chat_history, mode, agent_state],
|
280 |
+
outputs=[chatbot, agent_state, text_input, error_msg]
|
281 |
+
)
|
282 |
+
|
283 |
+
audio_input.change(
|
284 |
+
handle_mock_interview,
|
285 |
+
inputs=[audio_input, chat_history, agent_state, voice_select],
|
286 |
+
outputs=[chatbot, agent_state, audio_output, error_msg]
|
287 |
+
)
|
288 |
+
|
289 |
+
search_btn.click(
|
290 |
+
handle_job_matching,
|
291 |
+
inputs=[role_select, experience, location, chat_history, agent_state],
|
292 |
+
outputs=[chatbot, agent_state, error_msg]
|
293 |
+
)
|
294 |
+
|
295 |
+
clear_btn.click(
|
296 |
+
clear_chat,
|
297 |
+
outputs=[chat_history, agent_state, audio_output, error_msg]
|
298 |
+
)
|
299 |
+
|
300 |
+
if __name__ == "__main__":
|
301 |
+
demo.launch()
|
requirements.txt
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
aiofiles==23.2.1
|
2 |
+
altair==4.2.2
|
3 |
+
annotated-types==0.7.0
|
4 |
+
anyio==4.8.0
|
5 |
+
attrs==24.3.0
|
6 |
+
beautifulsoup4==4.12.3
|
7 |
+
blinker==1.9.0
|
8 |
+
cachetools==5.5.1
|
9 |
+
certifi==2024.12.14
|
10 |
+
cffi==1.17.1
|
11 |
+
charset-normalizer==3.4.1
|
12 |
+
click==8.1.8
|
13 |
+
distro==1.9.0
|
14 |
+
docstring_parser==0.16
|
15 |
+
duckduckgo_search==7.2.1
|
16 |
+
elevenlabs==1.50.3
|
17 |
+
entrypoints==0.4
|
18 |
+
exceptiongroup==1.2.2
|
19 |
+
fastapi==0.115.7
|
20 |
+
ffmpy==0.5.0
|
21 |
+
filelock==3.17.0
|
22 |
+
fsspec==2024.12.0
|
23 |
+
gitdb==4.0.12
|
24 |
+
GitPython==3.1.44
|
25 |
+
google-api-core==2.24.0
|
26 |
+
google-api-python-client==2.159.0
|
27 |
+
google-auth==2.38.0
|
28 |
+
google-auth-httplib2==0.2.0
|
29 |
+
google-generativeai==0.8.4
|
30 |
+
gradio==5.13.1
|
31 |
+
gradio_client==1.6.0
|
32 |
+
groq==0.15.0
|
33 |
+
grpcio==1.70.0
|
34 |
+
grpcio-status==1.70.0
|
35 |
+
h11==0.14.0
|
36 |
+
httpcore==1.0.7
|
37 |
+
httplib2==0.22.0
|
38 |
+
httpx==0.28.1
|
39 |
+
huggingface-hub==0.27.1
|
40 |
+
idna==3.10
|
41 |
+
Jinja2==3.1.5
|
42 |
+
jiter==0.8.2
|
43 |
+
jsonschema==4.23.0
|
44 |
+
jsonschema-specifications==2024.10.1
|
45 |
+
lxml==5.3.0
|
46 |
+
markdown-it-py==3.0.0
|
47 |
+
MarkupSafe==2.1.5
|
48 |
+
mdurl==0.1.2
|
49 |
+
narwhals==1.23.0
|
50 |
+
numpy==2.2.2
|
51 |
+
openai==1.60.0
|
52 |
+
orjson==3.10.15
|
53 |
+
packaging==24.2
|
54 |
+
pandas==2.2.3
|
55 |
+
phidata==2.7.9
|
56 |
+
pillow==11.1.0
|
57 |
+
praw==7.8.1
|
58 |
+
prawcore==2.4.0
|
59 |
+
primp==0.10.1
|
60 |
+
proto-plus==1.25.0
|
61 |
+
protobuf==5.29.3
|
62 |
+
pyarrow==19.0.0
|
63 |
+
pyasn1==0.6.1
|
64 |
+
pyasn1_modules==0.4.1
|
65 |
+
PyAudio==0.2.14
|
66 |
+
pycountry==24.6.1
|
67 |
+
pycparser==2.22
|
68 |
+
pydantic==2.10.5
|
69 |
+
pydantic-settings==2.7.1
|
70 |
+
pydantic_core==2.27.2
|
71 |
+
pydeck==0.9.1
|
72 |
+
pydub==0.25.1
|
73 |
+
Pygments==2.19.1
|
74 |
+
pyparsing==3.2.1
|
75 |
+
python-dateutil==2.9.0.post0
|
76 |
+
python-dotenv==1.0.1
|
77 |
+
python-multipart==0.0.20
|
78 |
+
pytz==2024.2
|
79 |
+
PyYAML==6.0.2
|
80 |
+
referencing==0.36.1
|
81 |
+
regex==2024.11.6
|
82 |
+
requests==2.32.3
|
83 |
+
rich==13.9.4
|
84 |
+
rpds-py==0.22.3
|
85 |
+
rsa==4.9
|
86 |
+
ruff==0.9.3
|
87 |
+
safehttpx==0.1.6
|
88 |
+
semantic-version==2.10.0
|
89 |
+
shellingham==1.5.4
|
90 |
+
six==1.17.0
|
91 |
+
smmap==5.0.2
|
92 |
+
sniffio==1.3.1
|
93 |
+
soupsieve==2.6
|
94 |
+
starlette==0.45.3
|
95 |
+
tenacity==9.0.0
|
96 |
+
tiktoken==0.8.0
|
97 |
+
toml==0.10.2
|
98 |
+
tomli==2.2.1
|
99 |
+
tomlkit==0.13.2
|
100 |
+
toolz==1.0.0
|
101 |
+
tornado==6.4.2
|
102 |
+
tqdm==4.67.1
|
103 |
+
typer==0.15.1
|
104 |
+
typing_extensions==4.12.2
|
105 |
+
tzdata==2025.1
|
106 |
+
update-checker==0.18.0
|
107 |
+
uritemplate==4.1.1
|
108 |
+
urllib3==2.3.0
|
109 |
+
uvicorn==0.34.0
|
110 |
+
websocket-client==1.8.0
|
111 |
+
websockets==14.2
|