Skip to content

Commit 0bcab8e

Browse files
committed
feat: Add meeting transcript analysis API endpoint and service powered by Gemini, and ignore venv.
1 parent 4c1181e commit 0bcab8e

File tree

3 files changed

+27
-51
lines changed

3 files changed

+27
-51
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ dist/
6060
.next/
6161
out/
6262

63+
venv
64+
6365
# Docker
6466
*.env.docker
6567

backend/app/api/analyze.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ def analyze_meeting(payload: TranscriptRequest):
1616
return analyze_transcript(payload.transcript)
1717
except ValueError as exc:
1818
raise HTTPException(status_code=400, detail=str(exc))
19-
except Exception:
19+
except Exception as exc:
20+
print("Exception", exc)
2021
raise HTTPException(
2122
status_code=500,
2223
detail="Failed to analyze meeting transcript"

backend/app/services/analyzer.py

Lines changed: 23 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,65 +15,38 @@
1515
def analyze_transcript(transcript: str) -> MeetingAnalysisResponse:
1616
"""
1717
Analyze meeting transcript and return structured summary,
18-
decisions, and action items.
18+
decisions, and action items using Gemini's native structured output.
1919
"""
2020

2121
transcript = clean_text(transcript)
2222

2323
if not is_valid_transcript(transcript):
2424
raise ValueError("Transcript content is too short or invalid")
2525

26-
system_prompt = """
27-
You are an AI assistant that analyzes meeting transcripts.
28-
29-
Your task:
30-
- Produce a concise summary
31-
- Extract key decisions
32-
- Extract action items with owner and priority if mentioned
33-
34-
STRICT RULES:
35-
- Respond ONLY in valid JSON
36-
- Do NOT include explanations
37-
- Do NOT add extra fields
38-
- If information is missing, use null or empty lists
39-
40-
JSON FORMAT:
41-
{
42-
"summary": "string",
43-
"decisions": ["string"],
44-
"action_items": [
45-
{
46-
"task": "string",
47-
"owner": "string | null",
48-
"priority": "High | Medium | Low | null"
49-
}
50-
]
51-
}
52-
"""
26+
system_instruction = (
27+
"You are an expert meeting analyst. Your task is to provide a concise summary, "
28+
"identify key decisions made, and list action items with their respective "
29+
"owners and priority levels."
30+
)
5331

54-
response = client.models.generate_content(
55-
model=settings.GEMINI_MODEL,
56-
contents=[
57-
types.Content(
58-
role="user",
59-
parts=[
60-
types.Part(text=system_prompt),
61-
types.Part(text=f"\nTRANSCRIPT:\n{transcript}")
62-
]
32+
try:
33+
# 3. Generate Content with Native Schema Support
34+
response = client.models.generate_content(
35+
model=settings.GEMINI_MODEL,
36+
contents=f"TRANSCRIPT:\n{transcript}",
37+
config=types.GenerateContentConfig(
38+
system_instruction=system_instruction,
39+
temperature=0.2,
40+
response_mime_type="application/json",
41+
# Passing the Pydantic class directly enables native structured output
42+
response_schema=MeetingAnalysisResponse,
6343
)
64-
],
65-
generation_config=types.GenerationConfig(
66-
temperature=0.2,
67-
response_mime_type="application/json"
6844
)
69-
)
7045

71-
raw_text = response.text.strip()
72-
73-
try:
74-
data: Dict[str, Any] = json.loads(raw_text)
75-
except json.JSONDecodeError as exc:
76-
raise ValueError("Gemini returned invalid JSON") from exc
46+
if response.parsed:
47+
return response.parsed
48+
49+
return MeetingAnalysisResponse.model_validate_json(response.text)
7750

78-
# Validate against Pydantic schema
79-
return MeetingAnalysisResponse(**data)
51+
except Exception as exc:
52+
raise ValueError(f"Gemini analysis failed: {str(exc)}") from exc

0 commit comments

Comments
 (0)