Spaces:
Running
Running
# 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} | |
""" |