-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Enhanced interview system prompts with memory scaffolding #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,5 +1,5 @@ | ||||||
| import { NextRequest, NextResponse } from 'next/server'; | ||||||
| import { detectFollowUpNeeded } from '@/lib/claude/client'; | ||||||
| import { detectFollowUpNeeded, generateMemoryScaffolds } from '@/lib/claude/client'; | ||||||
| import { updateAssessment, insertInterviewResponse, getInterviewResponseCount } from '@/lib/supabase-server'; | ||||||
| import { TOTAL_INTERVIEW_QUESTIONS } from '@/lib/constants'; | ||||||
|
|
||||||
|
|
@@ -36,6 +36,44 @@ export async function POST(request: NextRequest) { | |||||
| console.warn('Follow-up detection failed, continuing without:', error); | ||||||
| } | ||||||
|
|
||||||
| // Check if memory scaffolding is needed | ||||||
| let memoryScaffolds: string[] | null = null; | ||||||
| const memoryTriggerPhrases = [ | ||||||
| "i don't remember", | ||||||
| "i can't recall", | ||||||
| "i don't know", | ||||||
| "no memory", | ||||||
| "can't remember", | ||||||
| "don't recall", | ||||||
| "fuzzy memory", | ||||||
| "unclear", | ||||||
| "not sure about that" | ||||||
| ]; | ||||||
|
|
||||||
| const needsMemoryHelp = memoryTriggerPhrases.some(phrase => | ||||||
| response.toLowerCase().includes(phrase) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Validate Prompt for AI agents |
||||||
| ); | ||||||
|
|
||||||
| if (needsMemoryHelp) { | ||||||
| try { | ||||||
| // Determine age group based on question content (simplified logic) | ||||||
| let ageGroup: 'early' | 'school' | 'adolescent' | 'general' = 'general'; | ||||||
| const questionLower = (questionText || '').toLowerCase(); | ||||||
|
|
||||||
| if (questionLower.includes('child') || questionLower.includes('early') || questionLower.includes('preschool')) { | ||||||
| ageGroup = 'early'; | ||||||
| } else if (questionLower.includes('school') || questionLower.includes('elementary') || questionLower.includes('middle')) { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents
Suggested change
|
||||||
| ageGroup = 'school'; | ||||||
| } else if (questionLower.includes('teen') || questionLower.includes('adolescent') || questionLower.includes('high school')) { | ||||||
| ageGroup = 'adolescent'; | ||||||
| } | ||||||
|
|
||||||
| memoryScaffolds = await generateMemoryScaffolds(ageGroup); | ||||||
| } catch (error) { | ||||||
| console.warn('Memory scaffolding failed, continuing without:', error); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // Get current response count BEFORE inserting the new one | ||||||
| const previousCount = await getInterviewResponseCount(assessmentId); | ||||||
|
|
||||||
|
|
@@ -66,6 +104,7 @@ export async function POST(request: NextRequest) { | |||||
| success: true, | ||||||
| assessment, | ||||||
| followUpQuestion: shouldReturnFollowUp ? followUpResult.followUpQuestion || null : null, | ||||||
| memoryScaffolds: memoryScaffolds || null, | ||||||
| }); | ||||||
| } catch (err) { | ||||||
| console.error('Interview save error:', err); | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,5 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import Anthropic from '@anthropic-ai/sdk'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { INTERVIEW_SYSTEM_PROMPTS, getFallbackQuestionsForDomain, getMemoryScaffoldsForAgeGroup } from './prompts'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let anthropicClient: Anthropic | null = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -24,27 +25,17 @@ export async function generateInterviewQuestion( | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<string> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client = getAnthropicClient(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const systemPrompt = `You are an empathic clinical interviewer specializing in ADHD assessment. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Your role is to ask thoughtful, open-ended questions that help gather detailed information about the person's experiences. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const systemPrompt = INTERVIEW_SYSTEM_PROMPTS.interviewer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Guidelines: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Ask one question at a time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Questions should be conversational and non-judgmental | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Focus on gathering specific examples and experiences | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Avoid yes/no questions when possible | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Keep questions under 150 characters | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Be supportive and understanding in tone | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userPrompt = `CONTEXT: ADHD assessment interview in "${section}" domain | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PREVIOUS RESPONSES: ${previousResponses.join('; ')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Current context: This is for an ADHD assessment interview in the "${section}" section.`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userPrompt = `Based on these previous responses: ${previousResponses.join('; ')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Generate the next most appropriate interview question for the "${section}" section.`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Generate the next most appropriate interview question.`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await client.messages.create({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model: 'claude-3-5-sonnet-20241022', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
35
to
37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): generateMemoryScaffolds uses an undefined In messages: [{ role: 'user', content: contextPrompt }],so the model receives the intended age-group-specific context and the code doesn’t crash. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_tokens: 150, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_tokens: 120, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| system: systemPrompt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| messages: [{ role: 'user', content: userPrompt }], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| temperature: 0.7, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -58,6 +49,14 @@ Generate the next most appropriate interview question for the "${section}" secti | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error('No question generated'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return question; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Claude API error:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Enhanced fallback using domain-specific question banks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return getEnhancedFallbackQuestion(section); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return question; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Claude API error:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -72,28 +71,17 @@ export async function detectFollowUpNeeded( | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<{ needsFollowUp: boolean; followUpQuestion?: string | null }> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client = getAnthropicClient(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const systemPrompt = `You are analyzing interview responses for ADHD assessment. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Determine if the response is vague, incomplete, or would benefit from a follow-up question. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Return a JSON object with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - needsFollowUp: boolean | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - followUpQuestion: string (only if needsFollowUp is true, max 100 characters) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Guidelines: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Mark as needing follow-up if response is very brief (< 20 words) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Mark as needing follow-up if response lacks specific examples | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Mark as needing follow-up if response seems incomplete | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - Follow-up questions should be specific and probing`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const systemPrompt = INTERVIEW_SYSTEM_PROMPTS.followUpDetector; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userPrompt = `Question: ${question} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Response: ${response} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userPrompt = `QUESTION: ${question} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| RESPONSE: ${response} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Analyze if this response needs a follow-up question:`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DETERMINE if follow-up needed:`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await client.messages.create({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model: 'claude-3-5-sonnet-20241022', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_tokens: 200, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_tokens: 150, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| system: systemPrompt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| messages: [{ role: 'user', content: userPrompt }], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| temperature: 0.3, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -106,12 +94,39 @@ Analyze if this response needs a follow-up question:`; | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const result = JSON.parse(content); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Validate the result structure | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof result !== 'object' || result === null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Claude response is not a valid object'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Enhanced validation with better error handling | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!result || typeof result !== 'object') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Invalid Claude response structure'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { needsFollowUp: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof result.needsFollowUp !== 'boolean') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Missing or invalid needsFollowUp boolean'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { needsFollowUp: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (result.needsFollowUp) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof result.followUpQuestion !== 'string') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Follow-up needed but question missing'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { needsFollowUp: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (result.followUpQuestion.length > 80) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn('Follow-up question truncated to 80 chars'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result.followUpQuestion = result.followUpQuestion.substring(0, 80); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (parseError) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('JSON parse error in follow-up detection:', parseError); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { needsFollowUp: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Claude API error in follow-up detection:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { needsFollowUp: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (typeof result.needsFollowUp !== 'boolean') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Claude response missing valid needsFollowUp boolean'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { needsFollowUp: false }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -139,25 +154,51 @@ Analyze if this response needs a follow-up question:`; | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function getFallbackQuestion(section: string): string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const fallbacks: Record<string, string[]> = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'attention': [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Can you tell me about a specific time when you struggled to maintain focus?', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'How does difficulty concentrating affect your daily activities?', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'What strategies have you tried to improve your focus?' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'hyperactivity': [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'How do you handle feelings of restlessness?', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Can you describe situations where you feel the need to move constantly?', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'How does physical restlessness impact your work or relationships?' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'impulsivity': [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Tell me about a time when acting quickly led to unintended consequences.', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'How do you manage impulsive decisions?', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'What situations tend to trigger impulsive behavior for you?' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const questions = fallbacks[section] || fallbacks['attention']; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Enhanced fallback question selection using comprehensive question banks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function getEnhancedFallbackQuestion(section: string): string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const questions = getFallbackQuestionsForDomain(section.toLowerCase()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return questions[Math.floor(Math.random() * questions.length)]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Memory scaffolding for patients who express difficulty remembering | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export async function generateMemoryScaffolds(ageGroup: 'early' | 'school' | 'adolescent' | 'general' = 'general'): Promise<string[]> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client = getAnthropicClient(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const systemPrompt = INTERVIEW_SYSTEM_PROMPTS.memoryScaffolding; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const scaffolds = getMemoryScaffoldsForAgeGroup(ageGroup); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const contextPrompt = `AGE GROUP: ${ageGroup} childhood | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AVAILABLE SCAFFOLDS: ${scaffolds.slice(0, 5).join('; ')} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Generate 2-3 contextual memory prompts for ADHD recall:`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await client.messages.create({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model: 'claude-3-5-sonnet-20241022', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_tokens: 200, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| system: systemPrompt, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| messages: [{ role: 'user', content: userPrompt }], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| temperature: 0.6, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+169
to
+181
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Line 170 declares 🐛 Fix variable name mismatch const scaffolds = getMemoryScaffoldsForAgeGroup(ageGroup);
const contextPrompt = `AGE GROUP: ${ageGroup} childhood
AVAILABLE SCAFFOLDS: ${scaffolds.slice(0, 5).join('; ')}
Generate 2-3 contextual memory prompts for ADHD recall:`;
try {
const response = await client.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 200,
system: systemPrompt,
- messages: [{ role: 'user', content: userPrompt }],
+ messages: [{ role: 'user', content: contextPrompt }],
temperature: 0.6,
});📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const content = response.content[0]?.type === 'text' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? response.content[0].text.trim() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const result = JSON.parse(content); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (result.scaffolds && Array.isArray(result.scaffolds) && result.scaffolds.length >= 2) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return result.scaffolds.slice(0, 3); // Limit to 3 scaffolds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+188
to
+192
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win Validate that scaffold array elements are strings before returning. The parsed ♻️ Add element type validation try {
const result = JSON.parse(content);
- if (result.scaffolds && Array.isArray(result.scaffolds) && result.scaffolds.length >= 2) {
- return result.scaffolds.slice(0, 3); // Limit to 3 scaffolds
+ if (result.scaffolds && Array.isArray(result.scaffolds) && result.scaffolds.length >= 2) {
+ const validScaffolds = result.scaffolds
+ .filter((s: unknown): s is string => typeof s === 'string' && s.length > 0)
+ .slice(0, 3);
+ if (validScaffolds.length >= 2) {
+ return validScaffolds;
+ }
}
} catch (parseError) {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (parseError) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Failed to parse memory scaffold response:', parseError); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Fallback to static scaffolds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return scaffolds.slice(0, 3); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('Claude API error in memory scaffolding:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Return static scaffolds as fallback | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return getMemoryScaffoldsForAgeGroup(ageGroup).slice(0, 3); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): The memory trigger phrase matching is very broad and may cause false positives.
Generic phrases like "unclear" or "I don't know" can occur in many non-memory contexts (e.g., uncertainty about a diagnosis), so the simple
includescheck on a lowercased response is likely to over-trigger memory scaffolding. Consider narrowing these to more explicitly memory-related phrases (e.g., requiring "remember"/"recall" nearby) or adding word-boundary/regex checks to reduce false positives.