File size: 6,717 Bytes
e561008
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
889e86b
e561008
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
889e86b
e561008
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
020705e
e561008
 
 
 
 
 
 
 
 
 
 
889e86b
e561008
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
020705e
e561008
 
 
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""
AI Consultation Session Routes
──────────────────────────────────────────────────────────────────────────────
Manages proactive AI Consultation sessions distinct from passive AI Chat.

AI Chat:    passive β€” waits for user questions
Consultation: proactive β€” AI opens with agenda, leads through structured phases
              (Discovery β†’ Analysis β†’ Prescription) and produces a written report

Routes:
  POST /api/consultation/start  β†’ AI reads profile, generates opening message
  POST /api/consultation/report β†’ AI generates structured report from session
"""

import json
from datetime import datetime
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from firebase_admin import firestore
from utils.rate_limiter import with_rate_limit
from utils.groq_client import call_groq_json, HEAVY_MODEL
from utils.pinecone_client import query_book_context

router = APIRouter()


class StartRequest(BaseModel):
    userId:     str
    businessId: str


class ReportRequest(BaseModel):
    userId:     str
    businessId: str
    messages:   list[dict]  # [{"role": "user"|"assistant", "content": "..."}]


def _read_profile(user_id: str, business_id: str) -> dict:
    db  = firestore.client()
    biz = (
        db.collection("user_data").document(user_id)
        .collection("businesses").document(business_id)
    )
    ctx: dict = {}
    for key in ["businessIdentity", "customerProfile", "marketData"]:
        doc = biz.collection("profile_output").document(key).get()
        if doc.exists:
            ctx[key] = doc.to_dict()
    return ctx


@router.post("/start")
def start_consultation(
    body: StartRequest,
    user: dict = Depends(with_rate_limit("generation")),
):
    """
    Reads the entrepreneur's business profile and generates a warm, structured
    opening message with 5 focus areas. The AI has already 'read the brief'
    so the session starts with context rather than from scratch.
    """
    profile = _read_profile(body.userId, body.businessId)
    identity = profile.get("businessIdentity", {})

    biz_name  = identity.get("businessName",    "your business")
    sector    = identity.get("sector",           "")
    value_prop = identity.get("valueProposition", "")
    summary   = identity.get("summary",          "")

    book_ctx = query_book_context(
        "business consultation strategy discovery analysis Nigerian entrepreneur",
        top_k=2,
    )

    system = (
        "You are a senior business consultant at VenThrive, trained in the "
        "Business Footing Framework from 'Built on Rock' by Iyanuoluwa Joseph Akinnusi. "
        "You are warm, direct, and speak in plain everyday English. "
        "You do NOT use business jargon. You speak like a trusted advisor, not a textbook. "
        "Return ONLY valid JSON."
        + (f"\n\n{book_ctx}" if book_ctx else "")
    )

    prompt = f"""
You are starting a consultation session with the founder of "{biz_name}"
({sector}). Their value proposition is: "{value_prop}".
Brief summary: {summary[:300]}

Generate a warm, professional opening message that:
1. Greets them by referencing their specific business (not generic)
2. Mentions you've reviewed their Business Footing Framework profile
3. Presents exactly 5 focus areas as a numbered list
4. Asks them to pick the one they want to focus on today

The 5 focus areas should be:
1. Strategy & Market Position
2. Customer Acquisition & Retention
3. Financial Planning & Pricing
4. Operations & Standard Processes
5. Investor Readiness & Growth

Return JSON:
{{
  "openingMessage": "<your full opening message here>",
  "focusAreas": ["Strategy & Market Position", "Customer Acquisition & Retention", "Financial Planning & Pricing", "Operations & Standard Processes", "Investor Readiness & Growth"]
}}"""

    try:
        result = call_groq_json(system, prompt, model=HEAVY_MODEL, max_tokens=800, fixture="consultation_start")
        return {
            "openingMessage": result.get("openingMessage", ""),
            "focusAreas":     result.get("focusAreas", []),
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Could not start consultation: {str(e)}")


@router.post("/report")
def generate_report(
    body: ReportRequest,
    user: dict = Depends(with_rate_limit("generation")),
):
    """
    Takes the full session transcript and generates a structured consultation
    report with findings, specific recommendations, and next steps.
    """
    if user.get("uid") != body.userId:
        raise HTTPException(status_code=403, detail="Forbidden.")

    if len(body.messages) < 2:
        raise HTTPException(status_code=400, detail="Session too short to generate a report.")

    transcript = "\n".join([
        f"{'CONSULTANT' if m['role'] == 'assistant' else 'ENTREPRENEUR'}: {m['content']}"
        for m in body.messages
    ])

    book_ctx = query_book_context(
        "consultation findings recommendations action plan Nigerian business",
        top_k=2,
    )

    system = (
        "You are a business consultant writing a formal post-consultation report. "
        "Analyze the conversation and produce a structured, actionable document. "
        "Be specific to what was actually discussed β€” no generic advice. "
        "Write in clear, plain English. "
        "Return ONLY valid JSON."
        + (f"\n\n{book_ctx}" if book_ctx else "")
    )

    prompt = f"""
Consultation transcript:
{transcript[:4000]}

Today's date: {datetime.now().strftime('%B %d, %Y')}

Write a formal consultation report. Return JSON:
{{
  "date": "{datetime.now().strftime('%B %d, %Y')}",
  "sessionSummary": "2-3 sentences summarising what was discussed and the main concern addressed",
  "keyFindings": [
    "Specific finding 1 from the conversation",
    "Specific finding 2",
    "Specific finding 3"
  ],
  "recommendations": [
    {{
      "action": "What to do",
      "rationale": "Why this matters for their specific business",
      "timeline": "When to do it (e.g. This week / Within 30 days)"
    }}
  ],
  "nextSteps": [
    "Concrete action step 1",
    "Concrete action step 2",
    "Concrete action step 3"
  ],
  "closingNote": "A personalised, encouraging closing sentence referencing their business."
}}"""

    try:
        result = call_groq_json(system, prompt, model=HEAVY_MODEL, max_tokens=2000, fixture="consultation_report")
        return {"report": result}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Report generation failed: {str(e)}")