CoolFace
Apppublic

kussssh/IPO-Analyzer

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
scorecard.py88 linesDownload Raw Back to modules
1"""Module 9 — Final IPO Signal Scorecard"""2from langchain_core.prompts import ChatPromptTemplate3 4from backend.schemas import FinalVerdict5from backend.modules.base import get_llm, SYSTEM_PROMPT, _invoke_with_retry6 7 8def run_final_scorecard(m1, m2, m3, m4, m5, m6, m7, m8) -> FinalVerdict:9    """Synthesize all 8 module outputs into a final IPO scorecard."""10    print("\n▶ Running Final Scorecard...")11 12    def sig_to_symbol(sig: str) -> str:13        sig = (sig or "").upper().strip()14        if "POSITIVE" in sig or sig == "+":15            return "+"16        elif "NEGATIVE" in sig or sig == "-":17            return "-"18        return "0"19 20    signals = {21        "Business Quality":    sig_to_symbol(m1.signal),22        "Financial Strength":  sig_to_symbol(m2.signal),23        "Growth Quality":      sig_to_symbol(m3.signal),24        "Valuation":           sig_to_symbol(m4.signal),25        "Promoter Alignment":  sig_to_symbol(m5.signal),26        "Use of Proceeds":     sig_to_symbol(m6.signal),27        "Risk Profile":        sig_to_symbol(m7.signal),28        "Institutional":       sig_to_symbol(m8.signal),29    }30 31    pos = sum(1 for v in signals.values() if v == "+")32    neg = sum(1 for v in signals.values() if v == "-")33    neu = sum(1 for v in signals.values() if v == "0")34 35    if pos >= 5 and neg <= 1:36        verdict = "Strong"37    elif neg >= 3 or (neg >= 2 and pos <= 2):38        verdict = "Avoid"39    else:40        verdict = "Wait & Watch"41 42    summary_input = f"""43    Company: {m1.company_name}44 45    Module Signals:46    - Business Quality ({signals['Business Quality']}): {m1.signal_reasoning}47    - Financial Strength ({signals['Financial Strength']}): {m2.signal_reasoning}48    - Growth Quality ({signals['Growth Quality']}): {m3.signal_reasoning}49    - Valuation ({signals['Valuation']}): {m4.signal_reasoning}50    - Promoter Alignment ({signals['Promoter Alignment']}): {m5.signal_reasoning}51    - Use of Proceeds ({signals['Use of Proceeds']}): {m6.signal_reasoning}52    - Risk Profile ({signals['Risk Profile']}): {m7.signal_reasoning}53    - Institutional ({signals['Institutional']}): {m8.signal_reasoning}54 55    Score: {pos} Positive, {neu} Neutral, {neg} Negative56    Verdict: {verdict}57 58    Generate:59    1. A 2-3 sentence investment thesis (balanced, analytical, no advice)60    2. Top 3 key positives61    3. Top 3 key concerns62    """63 64    llm = get_llm()65    structured_llm = llm.with_structured_output(FinalVerdict)66 67    prompt = ChatPromptTemplate.from_messages([68        ("system", SYSTEM_PROMPT),69        ("human", "{summary}")70    ])71 72    chain = prompt | structured_llm73    result = _invoke_with_retry(chain, {"summary": summary_input}, "Final Scorecard")74 75    # Override computed fields76    result.business_quality_signal = signals["Business Quality"]77    result.financial_strength_signal = signals["Financial Strength"]78    result.valuation_signal = signals["Valuation"]79    result.promoter_alignment_signal = signals["Promoter Alignment"]80    result.risk_profile_signal = signals["Risk Profile"]81    result.positive_count = pos82    result.neutral_count = neu83    result.negative_count = neg84    result.overall_verdict = verdict85 86    print(f"  ✅ Final Verdict: {verdict}")87    return result88