clean up prompts and improve quality
This commit is contained in:
1 parent
9290cc18fd
commit
5b2da87f05
44 files changed
+6711
-414
No files matched your search
+37
-27
@@ -20,14 +20,14 @@ const ChatSession: React.FC<ChatSessionProps> = ({ scenario, onExit }) => {
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [status, setStatus] = useState<'active' | 'analyzing' | 'finished'>('active');
|
||||
|
||||
|
||||
// Clinical Feedback State
|
||||
const [liveInsight, setLiveInsight] = useState<AnalysisResult | null>(null);
|
||||
const [isAnalyzingTurn, setIsAnalyzingTurn] = useState(false);
|
||||
const [finalReport, setFinalReport] = useState<AnalysisResult | null>(null);
|
||||
|
||||
|
||||
const chatRef = useRef<Chat | null>(null);
|
||||
const analysisRef = useRef<Chat | null>(null);
|
||||
const analysisRef = useRef<Chat | null>(null);
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const scrollToBottom = useCallback(() => {
|
||||
@@ -41,17 +41,27 @@ const ChatSession: React.FC<ChatSessionProps> = ({ scenario, onExit }) => {
|
||||
// Session Initialization
|
||||
useEffect(() => {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
|
||||
|
||||
// Roleplay Chat Setup
|
||||
const roleplaySystemInstruction = `
|
||||
${scenario.systemInstruction}
|
||||
|
||||
CRITICAL ROLEPLAY PROTOCOL:
|
||||
1. Stay strictly in character as the persona defined in the scenario.
|
||||
2. NEVER provide clinical feedback, advice, or meta-commentary about the user's progress.
|
||||
3. NEVER use phrases like "Great job holding your boundary" or "Feedback:".
|
||||
4. Do not congratulate the user on using CBT techniques; simply react as the character would.
|
||||
5. If the user successfully concludes the scenario, end the dialogue naturally.
|
||||
[CONTEXT]
|
||||
You are participating in a clinical CBT roleplay simulation.
|
||||
The instructions above define your character, the scenario, and your internal CBT logic.
|
||||
|
||||
[TASK]
|
||||
Respond to the user naturally in character to advance the roleplay scenario.
|
||||
|
||||
[CONSTRAINTS]
|
||||
- CRITICAL: Stay strictly in character as the persona defined in the scenario.
|
||||
- CRITICAL: NEVER provide clinical feedback, advice, or meta-commentary about the user's progress.
|
||||
- CRITICAL: NEVER use phrases like "Great job holding your boundary" or "Feedback:".
|
||||
- CRITICAL: Do not congratulate the user on using CBT techniques; simply react as the character would.
|
||||
- If the user successfully concludes the scenario, end the dialogue naturally.
|
||||
|
||||
[OUTPUT REQUIREMENTS]
|
||||
Return the character's direct dialogue response. Keep it conversational and proportional to the user's input.
|
||||
`;
|
||||
|
||||
chatRef.current = ai.chats.create({
|
||||
@@ -82,7 +92,7 @@ CBT Focus Areas: ${scenario.cbtFocus.join(', ')}`;
|
||||
text: scenario.initialMessage,
|
||||
timestamp: new Date()
|
||||
}]);
|
||||
|
||||
|
||||
setLiveInsight(null);
|
||||
}, [scenario]);
|
||||
|
||||
@@ -116,8 +126,8 @@ CBT Focus Areas: ${scenario.cbtFocus.join(', ')}`;
|
||||
const c = chunk as GenerateContentResponse;
|
||||
const textChunk = c.text || "";
|
||||
fullResponseText += textChunk;
|
||||
|
||||
setMessages(prev => prev.map(m =>
|
||||
|
||||
setMessages(prev => prev.map(m =>
|
||||
m.id === botMsgId ? { ...m, text: fullResponseText } : m
|
||||
));
|
||||
}
|
||||
@@ -126,12 +136,12 @@ CBT Focus Areas: ${scenario.cbtFocus.join(', ')}`;
|
||||
if (analysisRef.current) {
|
||||
setIsAnalyzingTurn(true);
|
||||
const turnContext = `User said: "${userMsg.text}". Roleplay partner said: "${fullResponseText}".`;
|
||||
|
||||
|
||||
analysisRef.current.sendMessage({ message: turnContext }).then(res => {
|
||||
try {
|
||||
if (res.text) setLiveInsight(JSON.parse(res.text));
|
||||
} catch(e) { console.error("Live analysis parse error", e); } finally {
|
||||
setIsAnalyzingTurn(false);
|
||||
if (res.text) setLiveInsight(JSON.parse(res.text));
|
||||
} catch (e) { console.error("Live analysis parse error", e); } finally {
|
||||
setIsAnalyzingTurn(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -148,11 +158,11 @@ CBT Focus Areas: ${scenario.cbtFocus.join(', ')}`;
|
||||
if (messages.length < 2) return onExit();
|
||||
|
||||
setStatus('analyzing');
|
||||
|
||||
|
||||
try {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
const transcript = messages.map(m => `[${m.role.toUpperCase()}]: ${m.text}`).join('\n');
|
||||
|
||||
|
||||
const summaryPrompt = `${SYSTEM_SUMMARY_ANALYSIS_PROMPT}
|
||||
SCENARIO CONTEXT: ${scenario.title} - ${scenario.description}`;
|
||||
|
||||
@@ -182,8 +192,8 @@ SCENARIO CONTEXT: ${scenario.title} - ${scenario.description}`;
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-[500px] h-full bg-slate-50 rounded-3xl p-8 border border-slate-200 w-full max-w-2xl mx-auto animate-in fade-in duration-500">
|
||||
<div className="bg-white p-12 rounded-full shadow-lg border border-teal-100 mb-8 relative">
|
||||
<BrainCircuit size={64} className="text-teal-600 animate-pulse" />
|
||||
<div className="absolute inset-0 border-4 border-teal-500 border-t-transparent rounded-full animate-spin"></div>
|
||||
<BrainCircuit size={64} className="text-teal-600 animate-pulse" />
|
||||
<div className="absolute inset-0 border-4 border-teal-500 border-t-transparent rounded-full animate-spin"></div>
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold text-slate-800 mb-2">Compiling Report</h2>
|
||||
<p className="text-slate-500 text-center max-w-sm">Generating evidence-based synthesis of your cognitive and behavioral patterns during this session...</p>
|
||||
@@ -206,14 +216,14 @@ SCENARIO CONTEXT: ${scenario.title} - ${scenario.description}`;
|
||||
<div>
|
||||
<h2 className="font-bold text-slate-800 text-lg leading-tight">{scenario.title}</h2>
|
||||
<div className="flex gap-2">
|
||||
{scenario.cbtFocus.slice(0, 3).map(f => (
|
||||
<span key={f} className="text-[10px] font-bold text-teal-600 uppercase tracking-tight">{f}</span>
|
||||
))}
|
||||
{scenario.cbtFocus.slice(0, 3).map(f => (
|
||||
<span key={f} className="text-[10px] font-bold text-teal-600 uppercase tracking-tight">{f}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleFinishSession}
|
||||
<button
|
||||
onClick={handleFinishSession}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-teal-50 text-teal-700 hover:bg-teal-600 hover:text-white text-[10px] font-black uppercase tracking-widest transition-all border border-teal-100"
|
||||
>
|
||||
<Flag size={14} />
|
||||
@@ -226,7 +236,7 @@ SCENARIO CONTEXT: ${scenario.title} - ${scenario.description}`;
|
||||
<div className="flex-grow flex flex-col bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<div className="flex-grow overflow-y-auto p-6 space-y-6 scrollbar-hide">
|
||||
{messages.map((msg) => (
|
||||
<ChatMessage key={msg.id} message={msg} isLoading={isLoading && msg.id === messages[messages.length-1].id} />
|
||||
<ChatMessage key={msg.id} message={msg} isLoading={isLoading && msg.id === messages[messages.length - 1].id} />
|
||||
))}
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user