career_chatbots / config /prompts.py
liuyuelintop's picture
Upload folder using huggingface_hub
8e7f687 verified
# prompts_v1.py
# Improved prompts with minimal changes - adapted for current project
import re
# Router schema (same as current project)
ROUTER_SCHEMA = {
"type": "object",
"additionalProperties": False,
"properties": {
"intent": {
"type": "string",
"enum": ["career", "personal", "contact_exchange", "other"]
},
"why_hire": {"type": "boolean"},
"requires_contact": {"type": "boolean"},
"confidence": {
"type": "number",
"minimum": 0.0,
"maximum": 1.0
},
"matched_phrases": {
"type": "array",
"items": {"type": "string"},
"default": []
}
},
"required": ["intent", "why_hire", "requires_contact", "confidence", "matched_phrases"]
}
# Keep current WHY_HIRE_REGEX (same as original)
WHY_HIRE_REGEX = re.compile(
r"""(?xi)
(?:why\s+(?:should|would|could|can|do)\s*(?:we\s+)?hire\s+you) |
(?:why\s+hire\s+you) |
(?:why\s+are\s+you\s+(?:a|the)\s+(?:good\s+)?fit) |
(?:what\s+makes\s+you\s+(?:a|the)\s+(?:good\s+)?fit) |
(?:why\s+you\s+for\s+(?:this|the)\s+role) |
(?:why\s+are\s+you\s+right\s+for\s+(?:this|the)\s+job) |
(?:what\s+value\s+will\s+you\s+bring) |
(?:give\s+me\s+your\s+(?:pitch|elevator\s+pitch)) |
(?:sell\s+yourself)
"""
)
# IMPROVEMENT: Pitch with short/long variants
def canonical_why_hire_pitch(short: bool = False) -> str:
"""
Returns a concise or detailed pitch.
- short=True: 2-3 sentences for quick replies.
- short=False: fuller version with bullets.
"""
if short:
return (
"I ship reliable, production-grade software quickly and back it with measurable impact. "
"Recently I cut API latency by 81% for an AI SaaS and launched a Next.js 15 IDE on Vercel. "
"I own delivery end-to-end, communicate clearly, and use AI where it genuinely moves the needle."
)
return (
"I deliver reliable, production-grade software at high velocity and focus on measurable outcomes.\n\n"
"β€’ AI & Product Engineering β€” Built CodeCraft, a real-time online IDE (Next.js 15, TypeScript, Convex, Clerk) "
"deployed on Vercel; engineered an agentic career chatbot with tool calling and safe notification workflows.\n"
"β€’ Proven Impact β€” Cut API latency by 81% for an AI SaaS; shipped a React SPA that lifted mobile bookings by 60% "
"and reduced bounce rate by 25%.\n"
"β€’ End-to-End Ownership β€” Move from Figma to production in months, manage multiple services, and maintain "
"zero-downtime CI/CD pipelines.\n\n"
"I work in tight feedback loops, keep quality high without slowing delivery, and add value from week one."
)
# IMPROVEMENT: Structured router prompt with clear taxonomy
ROUTER_SYSTEM_PROMPT = """
You are a message router. Read the user's message and return ONLY a single JSON object.
### Output schema
{
"intent": "career" | "personal" | "contact_exchange" | "other",
"why_hire": boolean,
"requires_contact": boolean,
"confidence": number,
"matched_phrases": string[]
}
### Intent taxonomy
{
"career": [
"resumes / CVs",
"skills, projects, tech stack",
"job roles and titles",
"work or education background",
"intro prompts ('introduce yourself', 'tell me about yourself')",
"portfolio requests"
],
"personal": [
"hobbies, sports, travel, lifestyle",
"family or personal background",
"non-career interests"
],
"contact_exchange": [
"providing or requesting email, phone, LinkedIn",
"phrases like 'email me', 'my email is', 'how can I contact you'"
],
"other": [
"spam, harassment, off-topic, nonsense"
]
}
### Flags
- why_hire = true if user asks for pitch ('why hire you', 'what makes you a good fit', 'sell yourself')
- requires_contact = true if hiring/collaboration interest ('let's talk', portfolio requests, salary, availability) BUT false for pitch requests (why_hire=true)
- requires_contact = false if they only share contact details with no intent to engage
### Precedence
1. If contact info is provided or requested β†’ intent=contact_exchange
2. Otherwise choose between career vs personal (treat 'background' as career if work/education)
3. Otherwise β†’ other
Return short, lowercase triggers in matched_phrases. Language-agnostic. Return ONLY JSON.
""".strip()
# Keep current contact collection prompt (same as original)
CONTACT_COLLECTION_PROMPT = (
"I'd be happy to discuss that personally. Could you share your email so I can connect with you? "
"You can just say something like 'My email is [your-email]' and I'll make sure to reach out."
)
# Keep current system prompt builder (same as original)
def build_system_prompt(name: str, domain_text: str, mode: str) -> str:
"""Build system prompt for the chatbot"""
scope = "career" if mode == "career" else "personal"
return f"""You are acting as {name}.
Answer only using {scope} information below. Do not invent personal facts outside these documents.
Strict tool policy:
- Use record_resume_gap ONLY for career questions you cannot answer from these documents.
- Do NOT record or notify for off-topic, harassing, sexual, discriminatory, or spam content.
- If the user provides contact details or asks to follow up, ask for an email and call record_user_details.
Be concise and professional. Gently redirect to career topics when appropriate.
## Documents
{domain_text}
"""