Download analyzer.py from paulhemb/reddit_intelligence_platform: direct link, hf CLI and curl.
- Browser
- Download file 5.15 kB
-
https://huggingface.co/spaces/paulhemb/reddit_intelligence_platform/resolve/main/analyzer.py
- Command line
-
hf download hf://spaces/paulhemb/reddit_intelligence_platform/analyzer.py
-
curl -L -o analyzer.py https://huggingface.co/spaces/paulhemb/reddit_intelligence_platform/resolve/main/analyzer.py
5.15 kB
| import os | |
| import time | |
| import json | |
| import logging | |
| import re | |
| from typing import Dict, Any | |
| from groq import Groq | |
| from reddit_client import RateLimiter | |
| from config import GROQ_API_KEY, GROQ_MODEL, GROQ_RPS | |
| logger = logging.getLogger(__name__) | |
| groq_client = Groq(api_key=GROQ_API_KEY, max_retries=0) | |
| SYSTEM_PROMPT = """You are an expert startup analyst. Analyze the Reddit post below. | |
| Return ONLY valid JSON in this exact schema (no extra text): | |
| { | |
| "burning_pain": "string", | |
| "customer_type": "string", | |
| "problem_severity_score": integer 1-10, | |
| "competitor_weakness": "string", | |
| "revenue_opportunity": "string", | |
| "market_timing_score": integer 1-10, | |
| "startup_idea": "string", | |
| "difficulty_to_build": integer 1-10, | |
| "potential_pricing_model": "string", | |
| "confidence_score": integer 1-100 | |
| } | |
| """ | |
| def estimate_tokens(text: str) -> int: | |
| return len(text) // 4 | |
| def detect_pain_intensity(text: str) -> int: | |
| urgent_words = ["urgent", "critical", "desperate", "wasted", "nothing works", "broken", "frustrated"] | |
| score = 1 | |
| for w in urgent_words: | |
| if w in text.lower(): | |
| score += 2 | |
| return min(score, 10) | |
| def detect_founder_persona(text: str) -> str: | |
| personas = { | |
| "indie_hacker": ["indie", "solo", "bootstrapping", "side project"], | |
| "startup_founder": ["co-founder", "funding", "investor", "pitch", "scale"], | |
| "developer": ["api", "code", "build", "stack", "github"], | |
| "product_manager": ["roadmap", "feature", "user story", "product"], | |
| "enterprise_buyer": ["enterprise", "b2b", "sales cycle", "procurement"] | |
| } | |
| text_lower = text.lower() | |
| for persona, keywords in personas.items(): | |
| if any(k in text_lower for k in keywords): | |
| return persona | |
| return "unknown" | |
| def estimate_build_difficulty(text: str, insight: Dict) -> int: | |
| difficulty = insight.get("difficulty_to_build", 5) | |
| if any(term in text.lower() for term in ["ai", "machine learning", "blockchain", "hardware"]): | |
| difficulty += 2 | |
| if any(term in text.lower() for term in ["api integration", "multi-tenant", "compliance"]): | |
| difficulty += 1 | |
| return min(difficulty, 10) | |
| def detect_investor_signal(text: str) -> bool: | |
| signals = ["funding", "investment", "vc", "venture capital", "angel", "seed round", "series a"] | |
| return any(s in text.lower() for s in signals) | |
| def detect_early_startup(text: str) -> bool: | |
| phrases = ["i'm building", "working on", "mvp launching", "just launched", "startup idea"] | |
| return any(p in text.lower() for p in phrases) | |
| # Global rate limiter for Groq | |
| groq_limiter = RateLimiter(GROQ_RPS) | |
| def call_groq_for_insight(reddit_text: str) -> Dict[str, Any]: | |
| truncated = reddit_text[:2000] | |
| input_tokens = estimate_tokens(SYSTEM_PROMPT) + estimate_tokens(truncated) | |
| output_tokens = 300 | |
| total_tokens = input_tokens + output_tokens | |
| required_delay = total_tokens / 300.0 | |
| now = time.time() | |
| elapsed = now - groq_limiter.last_request | |
| if elapsed < required_delay: | |
| time.sleep(required_delay - elapsed) | |
| groq_limiter.last_request = time.time() | |
| max_retries = 2 | |
| for attempt in range(max_retries+1): | |
| try: | |
| response = groq_client.chat.completions.create( | |
| model=GROQ_MODEL, | |
| messages=[ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": f"Reddit Post:\n{truncated}"} | |
| ], | |
| temperature=0.3, | |
| max_tokens=500, | |
| response_format={"type": "json_object"} | |
| ) | |
| raw = response.choices[0].message.content.strip() | |
| if raw.startswith("```json"): raw = raw[7:] | |
| if raw.endswith("```"): raw = raw[:-3] | |
| insight = json.loads(raw) | |
| # Enhance with extra fields | |
| insight["pain_intensity"] = detect_pain_intensity(truncated) | |
| insight["founder_persona"] = detect_founder_persona(truncated) | |
| insight["build_difficulty_est"] = estimate_build_difficulty(truncated, insight) | |
| insight["investor_signal"] = detect_investor_signal(truncated) | |
| insight["early_startup_signal"] = detect_early_startup(truncated) | |
| return insight | |
| except Exception as e: | |
| logger.error(f"Groq error attempt {attempt+1}: {e}") | |
| if attempt < max_retries: | |
| time.sleep(2 ** attempt) | |
| fallback = { | |
| "burning_pain": "Error", | |
| "customer_type": "Error", | |
| "problem_severity_score": 5, | |
| "competitor_weakness": "Error", | |
| "revenue_opportunity": "Error", | |
| "market_timing_score": 5, | |
| "startup_idea": "Error", | |
| "difficulty_to_build": 5, | |
| "potential_pricing_model": "Error", | |
| "confidence_score": 0, | |
| "pain_intensity": 0, | |
| "founder_persona": "unknown", | |
| "build_difficulty_est": 5, | |
| "investor_signal": False, | |
| "early_startup_signal": False | |
| } | |
| return fallback |