Add podcast research metadata mapping and summary sections
This commit is contained in:
@@ -218,6 +218,9 @@ Listener CTA: {request.analysis.get('listener_cta', 'N/A')}
|
||||
|
||||
summary = ""
|
||||
key_insights = []
|
||||
expert_quotes = []
|
||||
listener_cta_suggestions = []
|
||||
mapped_angles = []
|
||||
|
||||
if raw_content and sources:
|
||||
logger.warning(f"[Podcast Research] Extracting insights from {len(sources)} sources for user {user_id}")
|
||||
@@ -337,13 +340,22 @@ QUALITY STANDARDS:
|
||||
try:
|
||||
summary = data.get("summary", "")
|
||||
key_insights = [PodcastResearchInsight(**insight) for insight in data.get("key_insights", [])]
|
||||
expert_quotes = data.get("expert_quotes", [])
|
||||
listener_cta_suggestions = data.get("listener_cta_suggestions", [])
|
||||
mapped_angles = data.get("mapped_angles", [])
|
||||
except Exception as insight_err:
|
||||
logger.warning(f"[Podcast Research] Failed to parse insights: {insight_err}. Data keys: {list(data.keys()) if isinstance(data, dict) else 'not a dict'}")
|
||||
summary = data.get("summary", "") if isinstance(data, dict) else ""
|
||||
key_insights = []
|
||||
expert_quotes = data.get("expert_quotes", []) if isinstance(data, dict) else []
|
||||
listener_cta_suggestions = data.get("listener_cta_suggestions", []) if isinstance(data, dict) else []
|
||||
mapped_angles = data.get("mapped_angles", []) if isinstance(data, dict) else []
|
||||
else:
|
||||
summary = ""
|
||||
key_insights = []
|
||||
expert_quotes = []
|
||||
listener_cta_suggestions = []
|
||||
mapped_angles = []
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as exc:
|
||||
@@ -423,5 +435,8 @@ QUALITY STANDARDS:
|
||||
search_type=result.get("search_type") if isinstance(result, dict) else None,
|
||||
provider=result.get("provider", "exa") if isinstance(result, dict) else "exa",
|
||||
content=raw_content,
|
||||
mapped_angles=mapped_angles,
|
||||
expert_quotes=expert_quotes,
|
||||
listener_cta_suggestions=listener_cta_suggestions,
|
||||
estimate=estimate,
|
||||
)
|
||||
|
||||
@@ -285,6 +285,78 @@ export const ResearchSummary: React.FC<ResearchSummaryProps> = ({
|
||||
)
|
||||
)}
|
||||
|
||||
{/* Expert Quotes */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="h6" sx={{ mb: 1.5, color: "#0f172a", fontWeight: 700 }}>
|
||||
Expert Quotes
|
||||
</Typography>
|
||||
{research.expertQuotes && research.expertQuotes.length > 0 ? (
|
||||
<Stack spacing={1}>
|
||||
{research.expertQuotes.slice(0, 4).map((quote, idx) => (
|
||||
<Paper key={`${quote.source_index}-${idx}`} elevation={0} sx={{ p: 1.5, border: "1px solid rgba(0,0,0,0.06)", borderRadius: 2 }}>
|
||||
<Typography variant="body2" sx={{ color: "#334155", lineHeight: 1.55 }}>
|
||||
“{quote.quote}”
|
||||
</Typography>
|
||||
<Typography variant="caption" sx={{ color: "#64748b", display: "block", mt: 0.5 }}>
|
||||
Source S{quote.source_index}
|
||||
</Typography>
|
||||
</Paper>
|
||||
))}
|
||||
</Stack>
|
||||
) : (
|
||||
<Typography variant="body2" sx={{ color: "#64748b" }}>
|
||||
No expert quotes extracted yet.
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Listener CTAs */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="h6" sx={{ mb: 1.5, color: "#0f172a", fontWeight: 700 }}>
|
||||
Listener CTAs
|
||||
</Typography>
|
||||
{research.listenerCta && research.listenerCta.length > 0 ? (
|
||||
<Stack spacing={1}>
|
||||
{research.listenerCta.slice(0, 4).map((cta, idx) => (
|
||||
<Paper key={`cta-${idx}`} elevation={0} sx={{ p: 1.5, border: "1px solid rgba(0,0,0,0.06)", borderRadius: 2 }}>
|
||||
<Typography variant="body2" sx={{ color: "#334155", lineHeight: 1.55 }}>
|
||||
{cta}
|
||||
</Typography>
|
||||
</Paper>
|
||||
))}
|
||||
</Stack>
|
||||
) : (
|
||||
<Typography variant="body2" sx={{ color: "#64748b" }}>
|
||||
No listener CTAs suggested yet.
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Mapped Angles */}
|
||||
<Box sx={{ mb: 3 }}>
|
||||
<Typography variant="h6" sx={{ mb: 1.5, color: "#0f172a", fontWeight: 700 }}>
|
||||
Mapped Angles
|
||||
</Typography>
|
||||
{research.mappedAngles && research.mappedAngles.length > 0 ? (
|
||||
<Stack spacing={1}>
|
||||
{research.mappedAngles.slice(0, 4).map((angle, idx) => (
|
||||
<Paper key={`angle-${idx}`} elevation={0} sx={{ p: 1.5, border: "1px solid rgba(0,0,0,0.06)", borderRadius: 2 }}>
|
||||
<Typography variant="subtitle2" sx={{ color: "#0f172a", fontWeight: 700, mb: 0.5 }}>
|
||||
{angle.title || `Angle ${idx + 1}`}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ color: "#334155", lineHeight: 1.55 }}>
|
||||
{angle.why || "No rationale provided."}
|
||||
</Typography>
|
||||
</Paper>
|
||||
))}
|
||||
</Stack>
|
||||
) : (
|
||||
<Typography variant="body2" sx={{ color: "#64748b" }}>
|
||||
No mapped angles available yet.
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Search Queries Used */}
|
||||
{research.searchQueries && research.searchQueries.length > 0 && (
|
||||
<Box sx={{ mt: 4, pt: 3, borderTop: "1px solid rgba(0,0,0,0.04)" }}>
|
||||
|
||||
@@ -198,6 +198,8 @@ const mapExaResearchResponse = (response: any): Research => {
|
||||
source_indices: insight.source_indices || []
|
||||
}));
|
||||
|
||||
// Backend keys must match PodcastExaResearchResponse exactly:
|
||||
// expert_quotes, listener_cta_suggestions, mapped_angles
|
||||
const expertQuotes = (response.expert_quotes || []).map((eq: any) => ({
|
||||
quote: eq.quote || eq.text || "",
|
||||
source_index: eq.source_index ?? 0
|
||||
|
||||
Reference in New Issue
Block a user