@@ -61,17 +61,28 @@ Context from user's documents will be provided below.`;
6161 * Chat with documents using RAG
6262 */
6363export async function POST ( request : NextRequest ) {
64+ const startTime = Date . now ( ) ;
65+ console . log ( '[Chat API] Starting request' ) ;
66+
6467 try {
68+ console . log ( '[Chat API] Verifying user...' ) ;
6569 const user = await verifyUser ( request ) ;
6670 if ( ! user ) {
71+ console . log ( '[Chat API] User verification failed' ) ;
6772 return NextResponse . json (
6873 { success : false , error : 'Unauthorized' } ,
6974 { status : 401 }
7075 ) ;
7176 }
77+ console . log ( '[Chat API] User verified:' , user . id , 'Time:' , Date . now ( ) - startTime , 'ms' ) ;
7278
7379 const body = await request . json ( ) ;
74- const { message, documentId, contextSize = 5 } = body ;
80+ const { message, documentId, contextSize = 3 } = body ;
81+ console . log ( '[Chat API] Request body parsed, message length:' , message ?. length ) ;
82+
83+ // Groq free tier limit is ~6000 tokens (~4 chars per token)
84+ // Limit context to ~2000 tokens (8000 chars) leaving room for system prompt + response
85+ const MAX_CONTEXT_CHARS = 8000 ;
7586
7687 if ( ! message || typeof message !== 'string' ) {
7788 return NextResponse . json (
@@ -105,31 +116,50 @@ export async function POST(request: NextRequest) {
105116 . eq ( 'status' , 'ready' ) ;
106117
107118 if ( ! docCount || docCount === 0 ) {
119+ console . log ( '[Chat API] No documents found for user' ) ;
108120 return NextResponse . json ( {
109121 success : true ,
110122 response : "You don't have any processed documents yet. Please upload and process some documents first, then I can answer questions about them." ,
111123 sources : [ ] ,
112124 provider
113125 } ) ;
114126 }
127+ console . log ( '[Chat API] Found' , docCount , 'documents. Time:' , Date . now ( ) - startTime , 'ms' ) ;
115128
116129 // Generate embedding for the query
117- const queryEmbedding = await generateEmbedding ( message ) ;
130+ console . log ( '[Chat API] Generating query embedding...' ) ;
131+ const embeddingStartTime = Date . now ( ) ;
132+ let queryEmbedding : number [ ] ;
133+ try {
134+ queryEmbedding = await generateEmbedding ( message ) ;
135+ console . log ( '[Chat API] Embedding generated in' , Date . now ( ) - embeddingStartTime , 'ms' ) ;
136+ } catch ( embeddingError ) {
137+ console . error ( '[Chat API] Embedding generation failed:' , embeddingError ) ;
138+ return NextResponse . json (
139+ { success : false , error : 'Failed to process query. Please try again.' } ,
140+ { status : 503 }
141+ ) ;
142+ }
118143
119144 // Search for relevant chunks
145+ console . log ( '[Chat API] Searching for relevant chunks...' ) ;
146+ const searchStartTime = Date . now ( ) ;
120147 const { data : searchResults , error : searchError } = await supabase . rpc ( 'match_documents' , {
121148 query_embedding : `[${ queryEmbedding . join ( ',' ) } ]` ,
122149 match_count : contextSize ,
123150 filter_user_id : user . id
124151 } ) ;
125152
153+ console . log ( '[Chat API] Search completed in' , Date . now ( ) - searchStartTime , 'ms' ) ;
154+
126155 if ( searchError ) {
127- console . error ( 'Search error:' , searchError ) ;
156+ console . error ( '[Chat API] Search error:' , searchError ) ;
128157 return NextResponse . json (
129158 { success : false , error : 'Failed to search documents' } ,
130159 { status : 500 }
131160 ) ;
132161 }
162+ console . log ( '[Chat API] Found' , searchResults ?. length || 0 , 'relevant chunks' ) ;
133163
134164 // Filter by documentId if provided
135165 let relevantChunks = searchResults || [ ] ;
@@ -151,12 +181,28 @@ export async function POST(request: NextRequest) {
151181 ( documents || [ ] ) . map ( ( d : { id : string ; name : string } ) => [ d . id , d . name ] )
152182 ) ;
153183
154- // Build context from relevant chunks
155- const contextParts = relevantChunks . map ( ( chunk : {
156- document_id : string ;
157- content : string ;
158- similarity : number ;
159- } , index : number ) => {
184+ // Build context from relevant chunks, respecting token limits
185+ let totalChars = 0 ;
186+ const truncatedChunks : Array < { document_id : string ; content : string ; similarity : number } > = [ ] ;
187+
188+ for ( const chunk of relevantChunks as Array < { document_id : string ; content : string ; similarity : number } > ) {
189+ const chunkLength = chunk . content . length ;
190+ if ( totalChars + chunkLength > MAX_CONTEXT_CHARS ) {
191+ // Truncate this chunk to fit
192+ const remainingSpace = MAX_CONTEXT_CHARS - totalChars ;
193+ if ( remainingSpace > 200 ) {
194+ truncatedChunks . push ( {
195+ ...chunk ,
196+ content : chunk . content . substring ( 0 , remainingSpace ) + '... [truncated]'
197+ } ) ;
198+ }
199+ break ;
200+ }
201+ truncatedChunks . push ( chunk ) ;
202+ totalChars += chunkLength ;
203+ }
204+
205+ const contextParts = truncatedChunks . map ( ( chunk , index : number ) => {
160206 const docName = documentMap . get ( chunk . document_id ) || 'Unknown Document' ;
161207 return `[Source ${ index + 1 } : ${ docName } ]\n${ chunk . content } ` ;
162208 } ) ;
@@ -177,6 +223,8 @@ export async function POST(request: NextRequest) {
177223 } ) ) ;
178224
179225 // Try to generate response using LLM
226+ console . log ( '[Chat API] Calling LLM, provider:' , provider , 'context chars:' , totalChars ) ;
227+ const llmStartTime = Date . now ( ) ;
180228 try {
181229 const llmResponse = await generateLLMResponse (
182230 [
@@ -195,6 +243,9 @@ export async function POST(request: NextRequest) {
195243 }
196244 ) ;
197245
246+ console . log ( '[Chat API] LLM response received in' , Date . now ( ) - llmStartTime , 'ms' ) ;
247+ console . log ( '[Chat API] Total request time:' , Date . now ( ) - startTime , 'ms' ) ;
248+
198249 return NextResponse . json ( {
199250 success : true ,
200251 response : llmResponse . content ,
@@ -204,6 +255,7 @@ export async function POST(request: NextRequest) {
204255 } ) ;
205256
206257 } catch ( llmError ) {
258+ console . error ( '[Chat API] LLM call failed after' , Date . now ( ) - llmStartTime , 'ms' ) ;
207259 // Handle LLM-specific errors with helpful fallbacks
208260 if ( llmError instanceof Error ) {
209261 // For API key errors, return context-only response
@@ -233,7 +285,8 @@ export async function POST(request: NextRequest) {
233285 }
234286
235287 // User-friendly error message
236- console . error ( 'LLM error:' , llmError . message ) ;
288+ console . error ( '[Chat API] LLM error:' , llmError . message ) ;
289+ console . error ( '[Chat API] LLM error stack:' , llmError . stack ) ;
237290 return NextResponse . json (
238291 { success : false , error : 'AI service temporarily unavailable. Please try again in a moment.' } ,
239292 { status : 503 }
@@ -244,7 +297,8 @@ export async function POST(request: NextRequest) {
244297 }
245298
246299 } catch ( error ) {
247- console . error ( 'Chat error:' , error ) ;
300+ console . error ( '[Chat API] Unhandled error:' , error ) ;
301+ console . error ( '[Chat API] Stack:' , error instanceof Error ? error . stack : 'no stack' ) ;
248302
249303 return NextResponse . json (
250304 { success : false , error : 'Internal server error' } ,
0 commit comments