@@ -12,7 +12,6 @@ import {
1212 PriorityLevel ,
1313 CallMessage ,
1414 CallSummary ,
15- ActionItem
1615} from '../contexts/DemoCallContext' ;
1716import { localLLMService , LocalLLMResponse } from './localLLMService' ;
1817
@@ -224,197 +223,46 @@ class AIService {
224223 category ?: CallCategory ,
225224 priority ?: PriorityLevel
226225 ) : Promise < SummaryResponse > {
227- const kb = this . knowledgeBase ;
228-
229- if ( ! kb ) {
230- return this . mockGenerateSummary ( messages , extractedFields , category , priority ) ;
231- }
226+ // Always use Groq via localLLMService — it manages its own availability.
227+ // No knowledge-base guard, no groqAvailable flag, no mock fallback.
228+ console . log ( '🤖 Calling Groq for summary...' ) ;
229+ const result = await localLLMService . summarizeCall (
230+ messages ,
231+ extractedFields ,
232+ category ,
233+ priority
234+ ) ;
232235
233- // Use Groq API for summary
234- if ( this . config . useGroq && this . groqAvailable ) {
235- try {
236- console . log ( '� Calling Groq for summary...' ) ;
237- const result = await localLLMService . summarizeCall (
238- messages ,
239- extractedFields ,
240- category ,
241- priority
242- ) ;
243-
244- const tags : string [ ] = [ ] ;
245- if ( category ) tags . push ( category . id ) ;
246- if ( result . followUpRequired ) tags . push ( 'follow-up' ) ;
247- // Add tags based on enhanced analysis
248- if ( result . seriousnessLevel ?. priority_level === 'critical' ) tags . push ( 'critical' ) ;
249- if ( result . seriousnessLevel ?. priority_level === 'high' ) tags . push ( 'high-priority' ) ;
250- if ( result . issueTopics ?. issue_category ) tags . push ( result . issueTopics . issue_category ) ;
251-
252- // Include caller name in notes if extracted
253- let notes = result . notes ;
254- if ( result . callerName && ! notes . toLowerCase ( ) . includes ( result . callerName . toLowerCase ( ) ) ) {
255- notes = `Caller: ${ result . callerName } . ${ notes } ` . trim ( ) ;
256- }
257-
258- console . log ( '✅ Enhanced summary with function calling complete' ) ;
259- if ( result . sentimentCards ) {
260- console . log ( ` 📊 Generated ${ result . sentimentCards . length } sentiment cards` ) ;
261- }
262-
263- return {
264- summary : {
265- mainPoints : result . mainPoints ,
266- sentiment : result . sentiment as CallSummary [ 'sentiment' ] ,
267- actionItems : [ ] ,
268- followUpRequired : result . followUpRequired ,
269- notes,
270- // Enhanced fields
271- summaryText : result . summary , // Clean summary text for preview
272- suggestions : result . suggestions ,
273- callerIntent : result . callerIntent ,
274- moodIndicators : result . moodIndicators ,
275- topics : result . topics ,
276- resolution : result . resolution ,
277- riskLevel : result . riskLevel ,
278- estimatedPriority : result . estimatedPriority ,
279- } ,
280- tags,
281- callerName : result . callerName ,
282- // Enhanced function calling results
283- analysis : result . analysis ,
284- sentimentCards : result . sentimentCards ,
285- seriousnessLevel : result . seriousnessLevel ,
286- issueTopics : result . issueTopics ,
287- } ;
288-
289- } catch ( error ) {
290- console . error ( '❌ Local LLM summary error:' , error ) ;
291- }
292- }
293-
294- // Step 3: Fallback to mock
295- return this . mockGenerateSummary ( messages , extractedFields , category , priority ) ;
296- }
297-
298- /**
299- * Smart mock response generator with conversation state tracking
300- */
301- private async smartMockResponse (
302- _userMessage : string ,
303- _conversationHistory : CallMessage [ ] ,
304- _existingFields : ExtractedField [ ]
305- ) : Promise < AIResponse > {
306- // All responses must come from the cloudflare model
307- // This function should never be called - model must be available
308- throw new Error ( 'AI model unavailable - all responses must be generated by the cloudflare model. Ensure your cloudflare tunnel is running.' ) ;
309- }
310-
311- /**
312- * Mock summary generator
313- */
314- private async mockGenerateSummary (
315- messages : CallMessage [ ] ,
316- extractedFields : ExtractedField [ ] ,
317- category ?: CallCategory ,
318- priority ?: PriorityLevel
319- ) : Promise < SummaryResponse > {
320- await this . delay ( 400 ) ;
321-
322- const userMessages = messages . filter ( m => m . speaker === 'user' ) ;
323- const mainPoints : string [ ] = [ ] ;
324236 const tags : string [ ] = [ ] ;
325- const actionItems : ActionItem [ ] = [ ] ;
326-
327- const callerName = extractedFields . find ( f => f . id === 'name' ) ?. value ;
328- const purpose = extractedFields . find ( f => f . id === 'purpose' ) ?. value ;
329-
330- if ( callerName ) {
331- mainPoints . push ( `Caller: ${ callerName } ` ) ;
332- }
333- if ( purpose ) {
334- mainPoints . push ( `Purpose: ${ purpose } ` ) ;
335- }
336-
337- userMessages . slice ( 0 , 3 ) . forEach ( ( msg ) => {
338- if ( msg . text . length > 15 ) {
339- mainPoints . push ( msg . text . substring ( 0 , 80 ) + ( msg . text . length > 80 ? '...' : '' ) ) ;
340- }
341- } ) ;
342-
343- extractedFields . forEach ( field => {
344- if ( field . id !== 'name' && field . id !== 'purpose' && field . value ) {
345- mainPoints . push ( `${ field . label } : ${ field . value } ` ) ;
346- }
347- } ) ;
348-
349237 if ( category ) tags . push ( category . id ) ;
350- if ( priority === 'critical' || priority === 'high' ) {
351- tags . push ( 'priority' ) ;
352- tags . push ( 'follow-up-needed' ) ;
353- }
354-
355- const allText = messages . map ( m => m . text ) . join ( ' ' ) . toLowerCase ( ) ;
356- let sentiment : 'positive' | 'neutral' | 'negative' = 'neutral' ;
357-
358- const positiveWords = [ 'thank' , 'great' , 'awesome' , 'excellent' , 'appreciate' , 'helpful' , 'wonderful' ] ;
359- const negativeWords = [ 'frustrated' , 'angry' , 'terrible' , 'awful' , 'disappointed' , 'upset' , 'worst' ] ;
360-
361- const positiveCount = positiveWords . filter ( w => allText . includes ( w ) ) . length ;
362- const negativeCount = negativeWords . filter ( w => allText . includes ( w ) ) . length ;
363-
364- if ( positiveCount > negativeCount ) sentiment = 'positive' ;
365- else if ( negativeCount > positiveCount ) sentiment = 'negative' ;
366-
367- if ( priority === 'critical' || priority === 'high' ) {
368- actionItems . push ( {
369- id : `action-${ Date . now ( ) } -1` ,
370- text : 'Follow up with caller urgently' ,
371- completed : false ,
372- } ) ;
373- }
374- if ( purpose ?. toLowerCase ( ) . includes ( 'appointment' ) || purpose ?. toLowerCase ( ) . includes ( 'schedule' ) ) {
375- actionItems . push ( {
376- id : `action-${ Date . now ( ) } -2` ,
377- text : 'Schedule appointment as requested' ,
378- completed : false ,
379- } ) ;
380- }
381- if ( category ?. id === 'support' ) {
382- actionItems . push ( {
383- id : `action-${ Date . now ( ) } -3` ,
384- text : 'Create support ticket for issue resolution' ,
385- completed : false ,
386- } ) ;
387- }
388-
389- let notes = '' ;
390- if ( callerName ) {
391- notes += `Call from ${ callerName } . ` ;
392- }
393- if ( purpose ) {
394- notes += `Regarding: ${ purpose } . ` ;
395- }
396- if ( category ) {
397- notes += `Categorized as ${ category . name } . ` ;
398- }
399- if ( priority && priority !== 'medium' ) {
400- notes += `Priority: ${ priority } . ` ;
401- }
402- if ( ! notes ) {
403- notes = 'Call completed successfully.' ;
404- }
238+ if ( result . followUpRequired ) tags . push ( 'follow-up' ) ;
239+ if ( result . seriousnessLevel ?. priority_level === 'critical' ) tags . push ( 'critical' ) ;
240+ if ( result . seriousnessLevel ?. priority_level === 'high' ) tags . push ( 'high-priority' ) ;
241+ if ( result . issueTopics ?. issue_category ) tags . push ( result . issueTopics . issue_category ) ;
405242
243+ console . log ( '✅ Groq summary complete' ) ;
406244 return {
407245 summary : {
408- mainPoints : mainPoints . length > 0 ? mainPoints : [ 'Call completed' ] ,
409- sentiment,
410- actionItems,
411- followUpRequired : priority === 'critical' || priority === 'high' ,
412- notes,
413- summaryText : notes ,
414- topics : tags ,
415- suggestions : actionItems . map ( a => a . text ) ,
246+ mainPoints : result . mainPoints ,
247+ sentiment : result . sentiment as CallSummary [ 'sentiment' ] ,
248+ actionItems : [ ] ,
249+ followUpRequired : result . followUpRequired ,
250+ notes : result . notes ,
251+ summaryText : result . summary ,
252+ suggestions : result . suggestions ,
253+ callerIntent : result . callerIntent ,
254+ moodIndicators : result . moodIndicators ,
255+ topics : result . topics ,
256+ resolution : result . resolution ,
257+ riskLevel : result . riskLevel ,
258+ estimatedPriority : result . estimatedPriority ,
416259 } ,
417260 tags,
261+ callerName : result . callerName ,
262+ analysis : result . analysis ,
263+ sentimentCards : result . sentimentCards ,
264+ seriousnessLevel : result . seriousnessLevel ,
265+ issueTopics : result . issueTopics ,
418266 } ;
419267 }
420268
0 commit comments