@@ -2704,19 +2704,17 @@ async function pickNextQuestion(state) {
27042704 const pastBotMessages = history . filter ( m => m . sender === 'bot' ) . map ( m => m . message ) ;
27052705 const conversationText = history . map ( m => `${ m . sender } : ${ m . message } ` ) . join ( '\n' ) ;
27062706
2707- // Try LLM dynamic question if enabled and we have enough history
2708- if ( state . answers . length >= 1 ) {
2709- const llmQ = await generateNextQuestionWithLLM ( conversationText , profile , pastBotMessages ) ;
2710- if ( llmQ ) {
2711- console . log ( "LLM Generated Question:" , llmQ ) ;
2712- state . lastQuestionTags = llmQ . intended_tags || [ ] ;
2713- state . lastQuestionText = llmQ . question ;
2714- return {
2715- id : `llm_${ Date . now ( ) } ` ,
2716- text : llmQ . question ,
2717- tags : llmQ . intended_tags || [ ]
2718- } ;
2719- }
2707+ // Attempt LLM dynamic question ALWAYS
2708+ const llmQ = await generateNextQuestionWithLLM ( conversationText , profile , pastBotMessages ) ;
2709+ if ( llmQ ) {
2710+ console . log ( "Autonomous AI Question:" , llmQ ) ;
2711+ state . lastQuestionTags = llmQ . intended_tags || [ ] ;
2712+ state . lastQuestionText = llmQ . question ;
2713+ return {
2714+ id : `ai_${ Date . now ( ) } ` ,
2715+ text : llmQ . question ,
2716+ tags : llmQ . intended_tags || [ ]
2717+ } ;
27202718 }
27212719
27222720 // Fallback to randomized static logic
@@ -2925,23 +2923,26 @@ async function generateNextQuestionWithLLM(conversationText, profile, pastBotMes
29252923
29262924 try {
29272925 const prompt = `
2928- Bạn là một chatbot tư vấn nghề nghiệp thông minh .
2926+ Bạn là một CHUYÊN GIA TƯ VẤN NGHỀ NGHIỆP tâm lý và sâu sắc .
29292927 Hồ sơ người dùng: ${ JSON . stringify ( profile ) }
2930- Lịch sử hội thoại gần đây :
2931- ${ conversationText . slice ( - 2000 ) }
2928+ Lịch sử hội thoại:
2929+ ${ conversationText || "Chưa có (đây là câu hỏi đầu tiên)" }
29322930
2933- Nhiệm vụ: Hãy đặt một câu hỏi tiếp theo để tìm hiểu sâu hơn về sở thích, năng lực hoặc định hướng nghề nghiệp của người dùng.
2934-
2935- YÊU CẦU QUAN TRỌNG:
2936- 1. TUYỆT ĐỐI KHÔNG lặp lại các câu hỏi đã hỏi sau đây: ${ JSON . stringify ( pastBotMessages . slice ( - 10 ) ) }
2937- 2. Câu hỏi phải tự nhiên, dựa trên những gì người dùng vừa trả lời.
2938- 3. Nếu người dùng muốn "hỏi thêm", hãy khai thác một khía cạnh mới hoặc đào sâu vào một ngành mà họ có vẻ quan tâm.
2939- 4. Ngôn ngữ thân thiện, gần gũi (dùng "bạn", "mình").
2931+ NHIỆM VỤ:
2932+ - Hãy dẫn dắt buổi tư vấn một cách tự nhiên.
2933+ - Nếu là câu đầu, hãy bắt đầu bằng một lời chào thân thiện và hỏi về đam mê, ước mơ hoặc một khó khăn họ đang gặp phải khi chọn nghề.
2934+ - Nếu đã trò chuyện, hãy phân tích câu trả lời trước đó để hỏi sâu hơn.
2935+ - Đừng chỉ hỏi về môn học, hãy hỏi về giá trị sống, môi trường làm việc mơ ước (trong nhà/ngoài trời, tự do/ổn định).
2936+
2937+ YÊU CẦU:
2938+ 1. KHÔNG lặp lại các câu hỏi đã hỏi: ${ JSON . stringify ( pastBotMessages . slice ( - 10 ) ) }
2939+ 2. Ngôn ngữ ấm áp, khích lệ (dùng "mình", "bạn").
2940+ 3. Câu hỏi ngắn gọn nhưng gợi mở.
29402941
29412942 TRẢ VỀ DUY NHẤT JSON:
29422943 {
2943- "question": "nội dung câu hỏi mới ",
2944- "intended_tags": ["tag_lien_quan1 ", "tag_lien_quan2 "]
2944+ "question": "nội dung câu hỏi",
2945+ "intended_tags": ["tag1 ", "tag2 "]
29452946 }
29462947 ` ;
29472948
@@ -2960,10 +2961,7 @@ async function generateNextQuestionWithLLM(conversationText, profile, pastBotMes
29602961 const jsonMatch = text . match ( / \{ [ \s \S ] * \} / ) ;
29612962 if ( jsonMatch ) {
29622963 const result = JSON . parse ( jsonMatch [ 0 ] ) ;
2963- // Double check uniqueness locally
2964- if ( pastBotMessages . includes ( result . question ) ) {
2965- return null ; // Force fallback to randomized static
2966- }
2964+ if ( pastBotMessages . includes ( result . question ) ) return null ;
29672965 return result ;
29682966 }
29692967 } catch ( e ) {
@@ -2972,6 +2970,41 @@ async function generateNextQuestionWithLLM(conversationText, profile, pastBotMes
29722970 return null ;
29732971}
29742972
2973+ async function getFinalAIEvaluation ( conversationText , profile , recommendations ) {
2974+ const apiKey = localStorage . getItem ( 'GEMINI_API_KEY' ) || 'AIzaSyBufWY4GjPYSXH9jkOD6pjDcdMAgSgA2gM' ;
2975+ if ( ! apiKey ) return "Cảm ơn bạn đã tham gia tư vấn. Dưới đây là kết quả dựa trên số liệu phân tích." ;
2976+
2977+ try {
2978+ const prompt = `
2979+ Bạn là chuyên gia tư vấn nghề nghiệp. Dựa vào:
2980+ Hồ sơ: ${ JSON . stringify ( profile ) }
2981+ Hội thoại: ${ conversationText }
2982+ Gợi ý của hệ thống: ${ JSON . stringify ( recommendations . slice ( 0 , 3 ) ) }
2983+
2984+ HÃY VIẾT:
2985+ 1. Một đoạn tóm tắt về thế mạnh và định hướng của người dùng qua cuộc trò chuyện.
2986+ 2. Giải thích tại sao 3 nghề nghiệp top đầu lại phù hợp với họ.
2987+ 3. Một lời khuyên thực tế để họ bắt đầu (lộ trình học tập hoặc kỹ năng cần luyện).
2988+
2989+ YÊU CẦU: Ngôn ngữ chuyên nghiệp nhưng truyền cảm hứng. Tối đa 250 từ. Trả về text thuần.
2990+ ` ;
2991+
2992+ const response = await fetch ( `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${ apiKey } ` , {
2993+ method : 'POST' ,
2994+ headers : { 'Content-Type' : 'application/json' } ,
2995+ body : JSON . stringify ( {
2996+ contents : [ { parts : [ { text : prompt } ] } ]
2997+ } )
2998+ } ) ;
2999+
3000+ const data = await response . json ( ) ;
3001+ return data . candidates ?. [ 0 ] ?. content ?. parts ?. [ 0 ] ?. text || "Gợi ý của chúng mình dựa trên các tiêu chí bạn đã chia sẻ." ;
3002+ } catch ( e ) {
3003+ return "Chúng mình đánh giá cao sự chia sẻ của bạn. Hãy xem qua danh sách gợi ý bên dưới nhé." ;
3004+ }
3005+ }
3006+
3007+
29753008export const offlineApi = {
29763009 getMe ( token ) {
29773010 if ( ! token || ! token . startsWith ( 'offline:' ) ) return { success : false } ;
@@ -3071,12 +3104,15 @@ export const offlineApi = {
30713104 const enoughInfo = state . answers . length >= 6 ;
30723105 if ( enoughInfo && ! request_more ) {
30733106 const recs = scoreCareers ( state ) ;
3107+ const conversationText = messages . map ( m => `${ m . sender } : ${ m . message } ` ) . join ( '\n' ) ;
3108+ const aiSummary = await getFinalAIEvaluation ( conversationText , state . userProfile , recs ) ;
3109+
30743110 saveRecommendations ( convId , recs ) ;
30753111 saveState ( convId , state ) ;
30763112 return {
30773113 success : true ,
30783114 data : {
3079- bot_reply : 'Đây là gợi ý nghề nghiệp phù hợp:' ,
3115+ bot_reply : aiSummary ,
30803116 recommendations : recs ,
30813117 next_node : null ,
30823118 completed : true ,
0 commit comments