File size: 8,036 Bytes
3e3a497
dbf2148
 
 
 
 
 
 
a42e45a
dbf2148
 
 
 
1baee4c
 
a42e45a
dbf2148
a42e45a
dbf2148
 
1baee4c
a42e45a
1baee4c
 
 
 
 
 
dbf2148
1baee4c
 
 
dbf2148
1baee4c
 
 
 
 
 
 
 
 
 
dbf2148
1baee4c
 
 
 
dbf2148
3e3a497
1baee4c
3e3a497
 
 
1baee4c
3e3a497
1baee4c
3e3a497
1baee4c
 
3e3a497
 
 
 
 
 
 
 
 
 
1baee4c
 
3e3a497
1baee4c
dbf2148
1baee4c
 
 
 
3e3a497
 
1baee4c
 
 
 
 
 
 
 
3e3a497
1baee4c
 
 
 
3e3a497
1baee4c
 
 
 
 
 
 
 
3e3a497
1baee4c
a42e45a
dbf2148
 
1baee4c
 
 
dbf2148
1baee4c
dbf2148
 
1baee4c
dbf2148
 
1baee4c
a42e45a
1baee4c
dbf2148
a42e45a
1baee4c
dbf2148
1baee4c
 
 
 
 
 
dbf2148
1baee4c
 
 
 
 
 
a42e45a
 
1baee4c
 
 
 
 
 
 
 
dbf2148
a42e45a
3e3a497
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a42e45a
dbf2148
1baee4c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

import numpy as np
import soundfile as sf
import io
from groq import Groq
from config.settings import settings
from core.rag_system import EnhancedRAGSystem
from core.tts_service import EnhancedTTSService
from core.multilingual_manager import MultilingualManager

class AudioService:
    def __init__(self, groq_client: Groq, rag_system: EnhancedRAGSystem, tts_service: EnhancedTTSService):
        self.groq_client = groq_client
        self.rag_system = rag_system
        self.tts_service = tts_service
        self.multilingual_manager = MultilingualManager()

    def transcribe_audio(self, audio: tuple) -> tuple:
        """Chuyển đổi giọng nói thành văn bản sử dụng mô hình Whisper."""
        if not audio:
            return "❌ Lỗi: Không có dữ liệu âm thanh", "❌ Vui lòng cung cấp file âm thanh", None, "unknown"
        
        try:
            # Xử lý audio input từ Gradio
            if isinstance(audio, tuple):
                sr, y = audio
            else:
                return "❌ Lỗi: Định dạng âm thanh không hợp lệ", "❌ Định dạng âm thanh không được hỗ trợ", None, "unknown"

            # Kiểm tra và xử lý dữ liệu audio
            if y.size == 0:
                return "❌ Lỗi: Dữ liệu âm thanh trống", "❌ File âm thanh không có dữ liệu", None, "unknown"

            # Chuẩn hóa dữ liệu audio
            if y.ndim > 1:
                y = np.mean(y, axis=1)  # Chuyển đổi sang mono
            y = y.astype(np.float32)
            
            # Normalize âm thanh
            if np.max(np.abs(y)) > 0:
                y /= np.max(np.abs(y))
            else:
                return "❌ Lỗi: Âm thanh quá yếu", "❌ Không thể phát hiện âm thanh", None, "unknown"

            # Tạo buffer với định dạng WAV được hỗ trợ
            buffer = io.BytesIO()
            sf.write(buffer, y, sr, format='WAV', subtype='PCM_16')
            buffer.seek(0)

            # Gọi Groq API với xử lý lỗi tốt hơn
            try:
                print(f"🔄 Đang gửi yêu cầu chuyển đổi giọng nói đến Groq API...")
                
                # SỬA LỖI Ở ĐÂY: Sử dụng đúng parameter names
                transcription = self.groq_client.audio.transcriptions.create(
                    file=("audio.wav", buffer.read(), "audio/wav"),
                    model=settings.WHISPER_MODEL,
                    language="vi",  # Thêm language parameter
                    response_format="text"
                )
                
                # SỬA LỖI Ở ĐÂY: Kiểm tra response structure
                if hasattr(transcription, 'text'):
                    transcription_text = transcription.text
                elif isinstance(transcription, str):
                    transcription_text = transcription
                else:
                    print(f"⚠️ Response structure không mong đợi: {type(transcription)}")
                    transcription_text = str(transcription)
                    
            except Exception as e:
                error_msg = f"❌ Lỗi API chuyển đổi giọng nói: {str(e)}"
                print(f"❌ Chi tiết lỗi: {e}")
                return error_msg, "❌ Không thể chuyển đổi giọng nói thành văn bản", None, "unknown"

            # Kiểm tra transcription có hợp lệ không
            if not transcription_text or len(transcription_text.strip()) == 0:
                return "❌ Không thể nhận dạng giọng nói", "❌ Vui lòng thử lại với âm thanh rõ hơn", None, "unknown"

            print(f"✅ Đã chuyển đổi giọng nói: {transcription_text}")

            # Phát hiện ngôn ngữ và tạo response
            language = self.multilingual_manager.detect_language(transcription_text)
            response = self._generate_response_with_rag(transcription_text, language)

            # Tạo TTS nếu response hợp lệ
            tts_audio = None
            if response and not response.startswith("❌") and not response.startswith("Error"):
                try:
                    print(f"🔊 Đang tạo TTS cho response {len(response)} ký tự...")
                    tts_bytes = self.tts_service.text_to_speech(response, language)
                    if tts_bytes:
                        tts_audio_path = self.tts_service.save_tts_audio(tts_bytes)
                        tts_audio = tts_audio_path
                        print(f"✅ Đã tạo TTS thành công")
                except Exception as e:
                    print(f"⚠️ Lỗi TTS: {e}")
                    # Vẫn trả về text response nếu TTS fail

            return transcription_text, response, tts_audio, language

        except Exception as e:
            error_msg = f"❌ Lỗi hệ thống xử lý âm thanh: {str(e)}"
            print(f"❌ Lỗi tổng hợp: {traceback.format_exc()}")
            return error_msg, "❌ Có lỗi xảy ra trong quá trình xử lý", None, "unknown"

    def _generate_response_with_rag(self, query: str, language: str) -> str:
        """Tạo phản hồi sử dụng hệ thống RAG dựa trên truy vấn và ngôn ngữ."""
        if not query or query.strip() == "" or query.startswith("❌"):
            return "❌ Truy vấn không hợp lệ để tạo phản hồi."
        
        try:
            # Tìm kiếm trong RAG system
            rag_results = self.rag_system.semantic_search(query, top_k=3)
            context_text = ""
            
            if rag_results:
                for result in rag_results:
                    context_text += f"- {result.text}\n"
            
            # Chọn model LLM phù hợp với ngôn ngữ
            llm_model = self.multilingual_manager.get_llm_model(language)
            
            # Tạo system prompt phù hợp với ngôn ngữ
            if language == "vi":
                system_prompt = """Bạn là trợ lý AI thông minh chuyên về tiếng Việt. Hãy trả lời câu hỏi một cách tự nhiên và hữu ích.
                
                Thông tin tham khảo:
                {context}
                
                Nếu có thông tin tham khảo, hãy sử dụng nó. Nếu không, dựa vào kiến thức chung của bạn."""
            else:
                system_prompt = """You are a smart AI assistant. Please answer questions naturally and helpfully.
                
                Reference information:
                {context}
                
                If reference information is available, use it. Otherwise, rely on your general knowledge."""
            
            messages = [
                {
                    "role": "system", 
                    "content": system_prompt.format(context=context_text) if context_text else system_prompt.format(context="Không có thông tin tham khảo cụ thể.")
                },
                {
                    "role": "user", 
                    "content": query
                }
            ]
            
            # Gọi Groq API với xử lý lỗi
            try:
                completion = self.groq_client.chat.completions.create(
                    model=llm_model,
                    messages=messages,
                    max_tokens=512,
                    temperature=0.7,
                )
                
                # SỬA LỖI: Kiểm tra response structure
                if hasattr(completion.choices[0].message, 'content'):
                    return completion.choices[0].message.content.strip()
                else:
                    return "❌ Không thể tạo phản hồi từ AI"
                    
            except Exception as e:
                return f"❌ Lỗi khi gọi Groq API: {str(e)}"
            
        except Exception as e:
            return f"❌ Lỗi tạo phản hồi: {str(e)}"