π¨ Implement core functionality for Job Search MCP Server, including user profile management, job search, cover letter generation, and Q&A response tools. Add configuration and service layers, and establish dependency management with uv. Introduce .gitignore and .python-version files for environment setup.
4fd18a2
"""Q&A tool for drafting responses to interview questions - qa.reply endpoint.""" | |
from typing import Dict, Any, List | |
from ..services import LLMService, ProfileService | |
class QATool: | |
"""Tool for generating responses to interview questions and client inquiries.""" | |
def __init__(self): | |
self.llm_service = LLMService() | |
self.profile_service = ProfileService() | |
def reply(self, user_id: str, question: str, context: str = "") -> Dict[str, Any]: | |
""" | |
Generate a response to an interview question or client inquiry. | |
This is the main qa.reply endpoint that drafts concise answers to | |
client questions like "Why should we hire you?" to speed up | |
Upwork, Fiverr, or LinkedIn chats. | |
Args: | |
user_id: User identifier to access profile for personalization | |
question: The question from potential employer/client to answer | |
context: Additional context about the conversation or role (optional) | |
Returns: | |
Dict with generated response and metadata: | |
{ | |
"success": True, | |
"response": "I bring 5+ years of Python development experience...", | |
"confidence_score": 0.85, # 0.0 to 1.0 confidence in the response | |
"word_count": 78, | |
"estimated_delivery_time": "2-3 days", # For project-based questions | |
"follow_up_suggestions": ["What's the project timeline?", "What's the budget range?"] | |
} | |
""" | |
try: | |
# Get user profile | |
profile = self.profile_service.get_profile(user_id) | |
if not profile: | |
return { | |
"success": False, | |
"message": "User profile not found. Please create a profile first.", | |
} | |
# Validate question | |
if not question or len(question.strip()) < 5: | |
return { | |
"success": False, | |
"message": "Question must be at least 5 characters long", | |
} | |
# Generate response | |
result = self.llm_service.generate_qa_response(profile, question, context) | |
# Add additional features if successful | |
if result.get("success") and result.get("response"): | |
# Add follow-up suggestions | |
result["follow_up_suggestions"] = self._get_follow_up_suggestions( | |
question, context | |
) | |
# Add estimated delivery time for project-related questions | |
if self._is_project_question(question): | |
result["estimated_delivery_time"] = self._estimate_delivery_time( | |
question, profile | |
) | |
# Add question category | |
result["question_category"] = self._categorize_question(question) | |
return result | |
except Exception as e: | |
return {"success": False, "message": f"Error generating response: {str(e)}"} | |
def batch_reply( | |
self, user_id: str, questions: List[Dict[str, str]] | |
) -> Dict[str, Any]: | |
""" | |
Generate responses to multiple questions at once. | |
Args: | |
user_id: User identifier | |
questions: List of question dictionaries with 'question' and optional 'context' | |
Example: [{"question": "Why should we hire you?", "context": "Senior role"}] | |
Returns: | |
Dict with multiple responses | |
""" | |
try: | |
if not questions: | |
return { | |
"success": False, | |
"message": "At least one question is required", | |
} | |
responses = [] | |
errors = [] | |
for i, q_data in enumerate(questions): | |
question = q_data.get("question", "") | |
context = q_data.get("context", "") | |
result = self.reply(user_id, question, context) | |
if result.get("success"): | |
responses.append({"index": i, "question": question, **result}) | |
else: | |
errors.append( | |
{ | |
"index": i, | |
"question": question, | |
"error": result.get("message", "Unknown error"), | |
} | |
) | |
return { | |
"success": True, | |
"responses": responses, | |
"total_processed": len(responses), | |
"errors": errors if errors else None, | |
} | |
except Exception as e: | |
return { | |
"success": False, | |
"message": f"Error processing batch questions: {str(e)}", | |
} | |
def get_common_questions(self, job_type: str = "general") -> Dict[str, Any]: | |
""" | |
Get a list of common interview questions with suggested approaches. | |
Args: | |
job_type: Type of job (e.g., "developer", "designer", "manager", "general") | |
Returns: | |
Dict with common questions and tips | |
""" | |
common_questions = { | |
"general": [ | |
"Tell me about yourself", | |
"Why are you interested in this role?", | |
"What are your greatest strengths?", | |
"What is your biggest weakness?", | |
"Where do you see yourself in 5 years?", | |
"Why should we hire you?", | |
"What motivates you?", | |
"How do you handle stress and pressure?", | |
"What's your ideal work environment?", | |
"Do you have any questions for us?", | |
], | |
"developer": [ | |
"Describe your development process", | |
"How do you stay updated with new technologies?", | |
"Tell me about a challenging bug you fixed", | |
"How do you ensure code quality?", | |
"What's your experience with version control?", | |
"How do you approach debugging?", | |
"What's your preferred development environment?", | |
"How do you handle tight deadlines?", | |
"Tell me about a project you're proud of", | |
"How do you learn new programming languages?", | |
], | |
"freelance": [ | |
"What's your hourly rate?", | |
"How long will this project take?", | |
"Can you show me examples of similar work?", | |
"What's your communication style?", | |
"How do you handle revisions?", | |
"What's included in your price?", | |
"Can you work in our timezone?", | |
"How do you ensure project quality?", | |
"What happens if you miss a deadline?", | |
"Can you sign an NDA?", | |
], | |
} | |
questions = common_questions.get(job_type, common_questions["general"]) | |
return { | |
"success": True, | |
"job_type": job_type, | |
"questions": questions, | |
"tips": self._get_interview_tips(job_type), | |
} | |
def practice_session( | |
self, user_id: str, job_type: str = "general", num_questions: int = 5 | |
) -> Dict[str, Any]: | |
""" | |
Generate a practice interview session with questions and sample answers. | |
Args: | |
user_id: User identifier | |
job_type: Type of job for targeted questions | |
num_questions: Number of questions to include (default: 5) | |
Returns: | |
Dict with practice questions and personalized sample answers | |
""" | |
try: | |
# Get common questions | |
questions_data = self.get_common_questions(job_type) | |
all_questions = questions_data["questions"] | |
# Select subset of questions | |
import random | |
selected_questions = random.sample( | |
all_questions, min(num_questions, len(all_questions)) | |
) | |
# Generate responses for each question | |
practice_qa = [] | |
for question in selected_questions: | |
response_result = self.reply( | |
user_id, question, f"Practice for {job_type} role" | |
) | |
if response_result.get("success"): | |
practice_qa.append( | |
{ | |
"question": question, | |
"sample_answer": response_result["response"], | |
"tips": response_result.get("follow_up_suggestions", []), | |
} | |
) | |
return { | |
"success": True, | |
"job_type": job_type, | |
"practice_questions": practice_qa, | |
"total_questions": len(practice_qa), | |
"general_tips": self._get_interview_tips(job_type), | |
} | |
except Exception as e: | |
return { | |
"success": False, | |
"message": f"Error creating practice session: {str(e)}", | |
} | |
def _get_follow_up_suggestions(self, question: str, context: str) -> List[str]: | |
"""Generate follow-up questions or conversation starters.""" | |
suggestions = [] | |
question_lower = question.lower() | |
if "project" in question_lower or "work" in question_lower: | |
suggestions.extend( | |
[ | |
"What's the expected timeline for this project?", | |
"What's the budget range?", | |
"Who will I be working with?", | |
"What are the main deliverables?", | |
] | |
) | |
if "experience" in question_lower or "skills" in question_lower: | |
suggestions.extend( | |
[ | |
"Would you like to see examples of my work?", | |
"I can provide references from previous clients", | |
"What specific skills are most important for this role?", | |
] | |
) | |
if "rate" in question_lower or "price" in question_lower: | |
suggestions.extend( | |
[ | |
"I'm flexible on pricing for long-term projects", | |
"What's your budget for this project?", | |
"I can provide a detailed project breakdown", | |
] | |
) | |
return suggestions[:3] # Limit to top 3 suggestions | |
def _is_project_question(self, question: str) -> bool: | |
"""Determine if the question is about a specific project.""" | |
project_keywords = [ | |
"project", | |
"timeline", | |
"deadline", | |
"deliver", | |
"complete", | |
"build", | |
"develop", | |
"create", | |
] | |
return any(keyword in question.lower() for keyword in project_keywords) | |
def _estimate_delivery_time(self, question: str, profile) -> str: | |
"""Estimate project delivery time based on question and profile.""" | |
# Simple estimation based on project complexity indicators | |
if any(word in question.lower() for word in ["simple", "basic", "small"]): | |
return "1-2 days" | |
elif any(word in question.lower() for word in ["complex", "large", "advanced"]): | |
return "1-2 weeks" | |
else: | |
return "3-5 days" | |
def _categorize_question(self, question: str) -> str: | |
"""Categorize the type of question.""" | |
question_lower = question.lower() | |
if any( | |
word in question_lower | |
for word in ["experience", "background", "skills", "qualification"] | |
): | |
return "experience" | |
elif any( | |
word in question_lower | |
for word in ["project", "timeline", "deadline", "deliver"] | |
): | |
return "project" | |
elif any( | |
word in question_lower | |
for word in ["rate", "price", "cost", "budget", "payment"] | |
): | |
return "pricing" | |
elif any(word in question_lower for word in ["why", "motivation", "interest"]): | |
return "motivation" | |
else: | |
return "general" | |
def _get_interview_tips(self, job_type: str) -> List[str]: | |
"""Get job-type specific interview tips.""" | |
tips = { | |
"general": [ | |
"Be specific with examples and achievements", | |
"Prepare questions to ask the interviewer", | |
"Research the company beforehand", | |
"Practice your elevator pitch", | |
], | |
"developer": [ | |
"Be ready to discuss your code and technical decisions", | |
"Prepare for coding challenges or technical questions", | |
"Show enthusiasm for learning new technologies", | |
"Discuss your development methodology", | |
], | |
"freelance": [ | |
"Have a portfolio ready to share", | |
"Be clear about your process and timeline", | |
"Discuss communication preferences upfront", | |
"Be professional but personable", | |
], | |
} | |
return tips.get(job_type, tips["general"]) | |