The evaluation pipeline is the intelligence core of the Lead Intelligence Engine. It uses Groq’s LLM (llama-3.3-70b-versatile) to analyze extracted website content, enrich it with RAG context, and produce structured business intelligence.
Think of this as an AI-powered business analyst that reads a website, applies your domain expertise, and writes a qualification report.
The prompt is stored in prompts/system_prompt.md and defines the AI’s role:
system_prompt.md (excerpt)
# Lead Intelligence Engine System PromptYou are an expert business analyst and lead qualification assistant.## ObjectiveExtract the business name, type, and select ONE primary service and ONE optional secondary service from the provided list that best fits the business's needs.## Analysis Rules1. **Business Name**: Extract the official name from the website.2. **Business Type**: Identify what the business does.3. **Maturity Check & Industry Exclusions**: - Marketing agencies: NEVER suggest Marketing Services - Dev shops: NEVER suggest Technology Services4. **Primary Service Selection**: Match based on ideal_for and use_case_signals5. **Fit Score**: 0-100 based on service-business alignment6. **Reasoning**: Max 2 sentences explaining the match7. **Outreach Angle**: Strategic entry point for conversation
If the business is a "Digital Marketing Agency" or similar (Marketing, Ads, Branding), NEVER suggest "Marketing Services" or "Marketing Packages". Focus on "Technology Services" (Foundation/Custom Dev) ONLY if their own website is weak/missing.
Reasoning: Don’t sell marketing to marketers. They already know how to market.
Software/IT Companies
If the business is "Software Development", "IT Solutions", or "Tech Agency", NEVER suggest "Technology Services". Focus on "Marketing Services" or "Strategy" only.
Reasoning: Don’t sell dev services to developers. They can build their own tech.
Existing Websites
If they already have a functional website, prioritize Add-ons or Marketing instead of a new website.
Reasoning: Don’t replace what’s already working - optimize or augment instead.
services = self._load_services()system_prompt = self._load_prompt()# Inject service catalog into system promptformatted_system_prompt = system_prompt.replace( "[SERVICES_JSON]", json.dumps(services, indent=2))# Build user message with RAG contextuser_content = f"Analyze this website content and provide the evaluation in JSON:\n\n{content}"if rag_context: rag_text = "\n\n".join(rag_context) user_content = f"Additional Advisory Context (RAG):\n{rag_text}\n\n---\n\n{user_content}"
Additional Advisory Context (RAG):[Lead qualification criteria][Strategy framework]---Analyze this website content and provide the evaluation in JSON:[Extracted website text...]
After parsing, the evaluator validates service names:
evaluator.py (lines 119-130)
valid_service_names = self._get_all_service_names(services)# Validate Primaryif result.get("primary_service") not in valid_service_names: raise ValueError(f"Selected primary service '{result.get('primary_service')}' is not in the approved list.")# Validate Secondary (if present)secondary = result.get("secondary_service")if secondary and secondary not in valid_service_names: raise ValueError(f"Selected secondary service '{secondary}' is not in the approved list.")
Recursively extracts all name fields from nested service structure:
evaluator.py (lines 48-59)
def _get_all_service_names(self, services_obj): """Recursively extracts all 'name' fields.""" names = [] if isinstance(services_obj, dict): if "name" in services_obj: names.append(services_obj["name"]) for value in services_obj.values(): names.extend(self._get_all_service_names(value)) elif isinstance(services_obj, list): for item in services_obj: names.extend(self._get_all_service_names(item)) return names
{ "business_name": "Example Dental Clinic", "business_type": "Dental Healthcare Provider", "primary_service": "Foundation Package", "secondary_service": "Basic Marketing Package", "fit_score": 85, "reasoning": "Small clinic with Facebook-only presence. No website detected. High fit for Foundation Package per target criteria.", "outreach_angle": "Platform dependency risk - current growth relies on rented Facebook platform. Consider owned digital asset for long-term stability."}
Error: LLM returned invalid JSON: Expecting property name enclosed in double quotesCause: Despite json_object mode, model occasionally returns malformed JSON.Mitigation: Parser extracts JSON from markdown blocks and braces.
Invalid Service Name
Error: Selected primary service 'Web Development' is not in the approved listCause: AI hallucinated a service name not in services.json.Mitigation: Validation step catches this before returning to user. System prompt emphasizes “MUST only select services from the provided list.”
Rate Limit Exceeded
Error: AI Service (Groq) Error: rate_limit_exceededCause: Groq free tier has 7,000 RPD (requests per day) limit.Mitigation: Retry logic + class-level status flag. Telegram bot displays quota status.
SYSTEM: You are an expert business analyst...[Analysis rules][Service catalog with Foundation Package, Marketing Packages]USER: Additional Advisory Context (RAG):[Lead criteria][Strategy framework]Analyze this website content and provide the evaluation in JSON:Smile Bright Dental - Bangkok's Premier Dental ClinicServices: General Dentistry, Teeth Whitening...