debug: add diagnostic logging for label suggestion flow
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 42s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 42s
Log key points in /api/ai/tags and ContextualAutoTagService to trace where label suggestions fail: notebook lookup, AI raw response, JSON parsing, filtered results. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,7 @@ export async function POST(req: NextRequest) {
|
|||||||
// If notebookId is provided, use contextual suggestions (IA2)
|
// If notebookId is provided, use contextual suggestions (IA2)
|
||||||
if (notebookId) {
|
if (notebookId) {
|
||||||
try {
|
try {
|
||||||
|
console.log('[/api/ai/tags] contextual request — notebookId:', notebookId, 'content length:', content.length)
|
||||||
const suggestions = await contextualAutoTagService.suggestLabels(
|
const suggestions = await contextualAutoTagService.suggestLabels(
|
||||||
content,
|
content,
|
||||||
notebookId,
|
notebookId,
|
||||||
@@ -38,6 +39,8 @@ export async function POST(req: NextRequest) {
|
|||||||
language
|
language
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log('[/api/ai/tags] suggestions:', suggestions.length, suggestions.map(s => `${s.label}(${s.confidence})`))
|
||||||
|
|
||||||
const convertedTags = suggestions.map(s => ({
|
const convertedTags = suggestions.map(s => ({
|
||||||
tag: s.label,
|
tag: s.label,
|
||||||
confidence: s.confidence,
|
confidence: s.confidence,
|
||||||
|
|||||||
@@ -50,12 +50,16 @@ export class ContextualAutoTagService {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!notebook) {
|
if (!notebook) {
|
||||||
|
console.log('[ContextualAutoTag] notebook not found for id:', notebookId)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('[ContextualAutoTag] notebook:', notebook.name, 'labels:', notebook.labels.map((l: any) => l.name))
|
||||||
|
|
||||||
// CASE 1: Notebook has existing labels → suggest from them (IA2)
|
// CASE 1: Notebook has existing labels → suggest from them (IA2)
|
||||||
if (notebook.labels.length > 0) {
|
if (notebook.labels.length > 0) {
|
||||||
const existing = await this.suggestFromExistingLabels(noteContent, notebook, language)
|
const existing = await this.suggestFromExistingLabels(noteContent, notebook, language)
|
||||||
|
console.log('[ContextualAutoTag] existing label suggestions:', existing.length)
|
||||||
if (existing.length > 0) return existing
|
if (existing.length > 0) return existing
|
||||||
// Fallback: no existing label matched → suggest new ones too
|
// Fallback: no existing label matched → suggest new ones too
|
||||||
}
|
}
|
||||||
@@ -83,6 +87,7 @@ export class ContextualAutoTagService {
|
|||||||
|
|
||||||
// Use generateText with JSON response
|
// Use generateText with JSON response
|
||||||
const response = await provider.generateText(prompt)
|
const response = await provider.generateText(prompt)
|
||||||
|
console.log('[ContextualAutoTag] AI raw response (existing):', response?.substring(0, 300))
|
||||||
|
|
||||||
// Improved JSON parsing with multiple fallback strategies
|
// Improved JSON parsing with multiple fallback strategies
|
||||||
let parsed: any
|
let parsed: any
|
||||||
@@ -111,7 +116,7 @@ export class ContextualAutoTagService {
|
|||||||
cleanedJson = cleanedJson.replace(/([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1"$2":')
|
cleanedJson = cleanedJson.replace(/([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1"$2":')
|
||||||
parsed = JSON.parse(cleanedJson)
|
parsed = JSON.parse(cleanedJson)
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Could not extract JSON from response')
|
console.error('[ContextualAutoTag] Could not extract JSON from response')
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +129,7 @@ export class ContextualAutoTagService {
|
|||||||
} else if (Array.isArray(parsed)) {
|
} else if (Array.isArray(parsed)) {
|
||||||
suggestionsArray = parsed
|
suggestionsArray = parsed
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Invalid response structure:', parsed)
|
console.error('[ContextualAutoTag] Invalid response structure:', parsed)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,6 +151,7 @@ export class ContextualAutoTagService {
|
|||||||
.sort((a: any, b: any) => b.confidence - a.confidence)
|
.sort((a: any, b: any) => b.confidence - a.confidence)
|
||||||
.slice(0, 5)
|
.slice(0, 5)
|
||||||
|
|
||||||
|
console.log('[ContextualAutoTag] filtered existing suggestions:', suggestions.length, suggestions.map((s: any) => `${s.label}(${s.confidence})`))
|
||||||
return suggestions as LabelSuggestion[]
|
return suggestions as LabelSuggestion[]
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to suggest labels:', error)
|
console.error('Failed to suggest labels:', error)
|
||||||
@@ -170,6 +176,7 @@ export class ContextualAutoTagService {
|
|||||||
|
|
||||||
// Use generateText with JSON response
|
// Use generateText with JSON response
|
||||||
const response = await provider.generateText(prompt)
|
const response = await provider.generateText(prompt)
|
||||||
|
console.log('[ContextualAutoTag] AI raw response (new):', response?.substring(0, 300))
|
||||||
|
|
||||||
// Improved JSON parsing with multiple fallback strategies
|
// Improved JSON parsing with multiple fallback strategies
|
||||||
let parsed: any
|
let parsed: any
|
||||||
@@ -198,7 +205,7 @@ export class ContextualAutoTagService {
|
|||||||
cleanedJson = cleanedJson.replace(/([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1"$2":')
|
cleanedJson = cleanedJson.replace(/([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1"$2":')
|
||||||
parsed = JSON.parse(cleanedJson)
|
parsed = JSON.parse(cleanedJson)
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Could not extract JSON from response')
|
console.error('[ContextualAutoTag] Could not extract JSON from new-labels response')
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,7 +218,7 @@ export class ContextualAutoTagService {
|
|||||||
} else if (Array.isArray(parsed)) {
|
} else if (Array.isArray(parsed)) {
|
||||||
suggestionsArray = parsed
|
suggestionsArray = parsed
|
||||||
} else {
|
} else {
|
||||||
console.error('❌ Invalid response structure:', parsed)
|
console.error('[ContextualAutoTag] Invalid new-labels response structure:', parsed)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,6 +236,7 @@ export class ContextualAutoTagService {
|
|||||||
.sort((a: any, b: any) => b.confidence - a.confidence)
|
.sort((a: any, b: any) => b.confidence - a.confidence)
|
||||||
.slice(0, 5)
|
.slice(0, 5)
|
||||||
|
|
||||||
|
console.log('[ContextualAutoTag] new label suggestions:', suggestions.length, suggestions.map((s: any) => `${s.label}(${s.confidence})`))
|
||||||
return suggestions as LabelSuggestion[]
|
return suggestions as LabelSuggestion[]
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Failed to suggest new labels:', error)
|
console.error('❌ Failed to suggest new labels:', error)
|
||||||
|
|||||||
Reference in New Issue
Block a user