Spaces:
Running
Running
File size: 5,545 Bytes
8e7f687 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
# 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}
""" |