added generation prompt tracking and viewing in persona detail view (new tab) for audience brief and research objective
This commit is contained in:
parent
065c368aeb
commit
ece469d15e
10 changed files with 119 additions and 738 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1,2 +1,6 @@
|
|||
venv/
|
||||
*pycache*/
|
||||
dist/
|
||||
|
||||
# Ignore Python cache files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -192,9 +192,23 @@ def complete_and_save_persona():
|
|||
customer_data_session_id = data.get('customer_data_session_id') # Optional parameter
|
||||
llm_model = data.get('llm_model', 'gemini-2.5-pro') # Optional parameter with default
|
||||
|
||||
# Get persona name for logging
|
||||
persona_name = basic_profile.get('name', 'Unknown')
|
||||
|
||||
# Capture generation prompts for storage
|
||||
audience_brief = data.get('audience_brief') # Optional parameter
|
||||
research_objective = data.get('research_objective') # Optional parameter
|
||||
|
||||
# Debug logging for generation prompts
|
||||
if audience_brief or research_objective:
|
||||
print(f"🔍 Backend: Generation prompts received for '{persona_name}':")
|
||||
print(f" - Audience Brief: {'Present' if audience_brief else 'Missing'} ({'~' + str(len(audience_brief)) + ' chars' if audience_brief else 'N/A'})")
|
||||
print(f" - Research Objective: {'Present' if research_objective else 'Missing'} ({'~' + str(len(research_objective)) + ' chars' if research_objective else 'N/A'})")
|
||||
else:
|
||||
print(f"🔍 Backend: No generation prompts received for '{persona_name}'")
|
||||
|
||||
try:
|
||||
# Log the request with model information
|
||||
persona_name = basic_profile.get('name', 'Unknown')
|
||||
print(f"🔄 Backend: Received complete-and-save-persona request for '{persona_name}' with model: {llm_model}")
|
||||
current_app.logger.info(f"Completing persona '{persona_name}' using model: {llm_model}")
|
||||
|
||||
|
|
@ -230,6 +244,14 @@ def complete_and_save_persona():
|
|||
if 'id' in complete_persona_data:
|
||||
del complete_persona_data['id']
|
||||
|
||||
# Add generation prompts to persona data if provided
|
||||
if audience_brief:
|
||||
complete_persona_data['audience_brief'] = audience_brief
|
||||
print(f"📝 Backend: Added audience_brief to persona data (~{len(audience_brief)} chars)")
|
||||
if research_objective:
|
||||
complete_persona_data['research_objective'] = research_objective
|
||||
print(f"📝 Backend: Added research_objective to persona data (~{len(research_objective)} chars)")
|
||||
|
||||
# Save to database
|
||||
persona_id = Persona.create(complete_persona_data, user_id)
|
||||
|
||||
|
|
|
|||
729
dist/assets/index-D1F9eUHr.js
vendored
729
dist/assets/index-D1F9eUHr.js
vendored
File diff suppressed because one or more lines are too long
1
dist/assets/index-QYazl09u.css
vendored
1
dist/assets/index-QYazl09u.css
vendored
File diff suppressed because one or more lines are too long
4
dist/index.html
vendored
4
dist/index.html
vendored
|
|
@ -7,8 +7,8 @@
|
|||
<meta name="description" content="Lovable Generated Project" />
|
||||
<meta name="author" content="Lovable" />
|
||||
<meta property="og:image" content="/og-image.png" />
|
||||
<script type="module" crossorigin src="/semblance/assets/index-D1F9eUHr.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/semblance/assets/index-QYazl09u.css">
|
||||
<script type="module" crossorigin src="/semblance/assets/index-BXPouqjR.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/semblance/assets/index-8o0iGAjY.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
62
src/components/persona/PersonaGenerationPrompts.tsx
Normal file
62
src/components/persona/PersonaGenerationPrompts.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import { FileText, Target } from 'lucide-react';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Persona } from '@/types/persona';
|
||||
|
||||
interface PersonaGenerationPromptsProps {
|
||||
persona: Persona;
|
||||
}
|
||||
|
||||
export function PersonaGenerationPrompts({ persona }: PersonaGenerationPromptsProps) {
|
||||
// Check if generation prompts are available
|
||||
const hasPrompts = persona.audience_brief || persona.research_objective;
|
||||
|
||||
if (!hasPrompts) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<div className="text-center text-slate-500">
|
||||
<FileText className="h-12 w-12 mx-auto mb-4 text-slate-400" />
|
||||
<h3 className="font-sf text-lg font-medium mb-2">Generation prompts not available</h3>
|
||||
<p className="text-sm">Generation prompts are not available for this persona.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{persona.audience_brief && (
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<FileText className="h-5 w-5 text-primary mr-2" />
|
||||
<h3 className="font-sf text-lg font-medium">Audience Brief</h3>
|
||||
</div>
|
||||
|
||||
<div className="bg-slate-50 rounded-lg p-4 max-h-80 overflow-y-auto">
|
||||
<p className="text-sm whitespace-pre-wrap leading-relaxed">
|
||||
{persona.audience_brief}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{persona.research_objective && (
|
||||
<Card>
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center mb-4">
|
||||
<Target className="h-5 w-5 text-emerald-500 mr-2" />
|
||||
<h3 className="font-sf text-lg font-medium">Research Objective</h3>
|
||||
</div>
|
||||
|
||||
<div className="bg-slate-50 rounded-lg p-4 max-h-80 overflow-y-auto">
|
||||
<p className="text-sm whitespace-pre-wrap leading-relaxed">
|
||||
{persona.research_objective}
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import { PersonaSidebar } from './PersonaSidebar';
|
|||
import { PersonaCooperProfile } from './PersonaCooperProfile';
|
||||
import { PersonaPersonality } from './PersonaPersonality';
|
||||
import { PersonaScenarios } from './PersonaScenarios';
|
||||
import { PersonaGenerationPrompts } from './PersonaGenerationPrompts';
|
||||
import { PersonaNotFound } from './PersonaNotFound';
|
||||
import { PersonaProfileSkeleton } from './PersonaProfileSkeleton';
|
||||
import PersonaEditor from './PersonaEditor';
|
||||
|
|
@ -203,7 +204,7 @@ export default function PersonaProfile() {
|
|||
>
|
||||
<ArrowLeft className="h-5 w-5" />
|
||||
</Button>
|
||||
<h1 className="font-sf text-3xl font-bold text-slate-900 mx-auto">Persona Profile</h1>
|
||||
<h1 className="font-sf text-3xl font-bold text-slate-900 ml-16">Persona Profile</h1>
|
||||
<div className="absolute right-0 top-0 flex items-center gap-3">
|
||||
<Button
|
||||
variant="outline"
|
||||
|
|
@ -236,10 +237,11 @@ export default function PersonaProfile() {
|
|||
|
||||
<div className="lg:col-span-2">
|
||||
<Tabs defaultValue="cooper-profile">
|
||||
<TabsList className="grid w-full grid-cols-3">
|
||||
<TabsList className="grid w-full grid-cols-4">
|
||||
<TabsTrigger value="cooper-profile">Cooper Profile</TabsTrigger>
|
||||
<TabsTrigger value="personality">Personality</TabsTrigger>
|
||||
<TabsTrigger value="scenarios">Scenarios</TabsTrigger>
|
||||
<TabsTrigger value="generation-prompts">Generation Prompts</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="cooper-profile" className="mt-6">
|
||||
|
|
@ -253,6 +255,10 @@ export default function PersonaProfile() {
|
|||
<TabsContent value="scenarios" className="mt-6">
|
||||
<PersonaScenarios persona={currentPersona} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="generation-prompts" className="mt-6">
|
||||
<PersonaGenerationPrompts persona={currentPersona} />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -221,10 +221,21 @@ export const aiPersonasApi = {
|
|||
}),
|
||||
|
||||
// Second stage: Complete a single persona and save to database
|
||||
completeAndSavePersona: (basicProfile: any, temperature: number = 0.7) =>
|
||||
completeAndSavePersona: (
|
||||
basicProfile: any,
|
||||
temperature: number = 0.7,
|
||||
audienceBrief?: string,
|
||||
researchObjective?: string,
|
||||
customerDataSessionId?: string,
|
||||
llmModel?: string
|
||||
) =>
|
||||
api.post('/ai-personas/complete-and-save-persona', {
|
||||
basic_profile: basicProfile,
|
||||
temperature
|
||||
temperature,
|
||||
audience_brief: audienceBrief,
|
||||
research_objective: researchObjective,
|
||||
customer_data_session_id: customerDataSessionId,
|
||||
llm_model: llmModel
|
||||
}, {
|
||||
timeout: 600000 // 10 minutes for detailed persona generation and saving
|
||||
}),
|
||||
|
|
@ -276,6 +287,8 @@ export const aiPersonasApi = {
|
|||
api.post('/ai-personas/complete-and-save-persona', {
|
||||
basic_profile: profile,
|
||||
temperature,
|
||||
audience_brief: audienceBrief,
|
||||
research_objective: researchObjective,
|
||||
customer_data_session_id: customerDataSessionId,
|
||||
llm_model: llmModel || 'gemini-2.5-pro'
|
||||
}, {
|
||||
|
|
|
|||
|
|
@ -78,4 +78,8 @@ export interface Persona {
|
|||
folder_ids?: string[]; // Array of folder IDs this persona belongs to
|
||||
folderId?: string; // Legacy: single folder ID (kept for backwards compatibility)
|
||||
folder_id?: string; // Alternative single folder field
|
||||
|
||||
// Generation prompts (for personas created after this feature)
|
||||
audience_brief?: string; // The audience brief used to generate this persona
|
||||
research_objective?: string; // The research objective used to generate this persona
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue