# import re # from deepmultilingualpunctuation import PunctuationModel # class MedicalTextNormalizer: # def __init__(self, use_ai_model=True): # self.use_ai = use_ai_model # if self.use_ai: # print("⏳ Đang tải model AI (chỉ chạy lần đầu)...") # self.punct_model = PunctuationModel(model="oliverguhr/fullstop-punctuation-multilang-large") # # 1. Map số cơ bản # self.digits = { # 'không': 0, 'một': 1, 'hai': 2, 'ba': 3, 'bốn': 4, # 'năm': 5, 'lăm': 5, 'nhăm': 5, 'sáu': 6, 'bảy': 7, 'tám': 8, 'chín': 9, # 'mốt': 1, 'tư': 4, 'linh': 0, 'lẻ': 0, # } # # 2. Map đơn vị (Value) # # Lưu ý: 'mười' (10) nằm ở đây để kích hoạt logic tính toán cộng dồn # self.multipliers = { # 'mười': 10, 'mươi': 10, 'chục': 10, # 'trăm': 100, # 'nghìn': 1000, 'ngàn': 1000, # 'triệu': 1000000, # 'tỷ': 1000000000 # } # # 3. Dấu thập phân # self.decimal_points = {'phẩy', 'chấm', '.', ','} # # Tập hợp tất cả từ khóa cần xử lý # self.number_words = set(self.digits.keys()) | set(self.multipliers.keys()) | self.decimal_points # def _vietnamese_text2num(self, words): # if not words: return "" # # CASE 1: SỐ THẬP PHÂN # sep_index = -1 # for idx, w in enumerate(words): # if w in self.decimal_points: # sep_index = idx # break # if sep_index != -1: # int_part = words[:sep_index] # dec_part = words[sep_index+1:] # int_val = self._vietnamese_text2num(int_part) # dec_val = "".join([str(self.digits[w]) for w in dec_part if w in self.digits]) # return f"{int_val}.{dec_val}" # # CASE 2: DÃY SỐ ID (SĐT, Ngày...) # # Logic: Nếu KHÔNG có đơn vị (trăm/nghìn), HOẶC bắt đầu bằng 0 -> Ghép chuỗi # has_multiplier = any(w in self.multipliers for w in words) # starts_with_zero = (words[0] in ['không', 'linh', 'lẻ']) # if (not has_multiplier) or (starts_with_zero and len(words) > 1 and 'trăm' not in words): # return "".join([str(self.digits.get(w, '')) for w in words if w in self.digits]) # # CASE 3: TÍNH TOÁN SỐ LƯỢNG (Logic Cộng Dồn - FIX BUG 7050) # total = 0 # current = 0 # for w in words: # if w in self.digits: # current += self.digits[w] # elif w in self.multipliers: # val = self.multipliers[w] # # Logic mới: Gặp đơn vị là nhân và cộng luôn vào tổng # # Ví dụ: Bảy (7) -> Trăm (100) -> total += 700, current về 0 # total += (current if current > 0 else 1) * val # current = 0 # total += current # return str(total) # def _basic_clean(self, text): # text = text.lower() # # === FIX LỖI SPO2 === # # Thay thế "spo hai" -> "spo2" trước tiên # text = re.sub(r'\bspo\s*(hai|2)\b', 'spo2', text) # # === FIX LỖI ĐƠN VỊ ĐƯỜNG HUYẾT (NEW) === # # "mi limo", "mi lion", "milimon" -> "mmol" # text = re.sub(r'\bmi\s*li\s*(mo|on|mon)\b', 'mmol', text) # replacements = { # r'\bhai chấm\b': ':', r'\bgạch ngang\b': '-', # r'\btrên\b': '/', r'\bbằng\b': '=', # r'\bphần trăm\b': '%', r'\bđộ c\b': 'độ C', # r'\bmit\b': 'mm', r'\bhủy ngân\b': 'Hg', r'\bthủy ngân\b': 'Hg', # r'\bphẩy\b': '.', r'\bchấm\b': '.' # } # for pattern, char in replacements.items(): # text = re.sub(pattern, char, text) # return text # def _convert_spoken_numbers(self, text): # words = text.split() # n = len(words) # result = [] # i = 0 # while i < n: # word = words[i] # # --- BLACKLIST (Bảo vệ từ khóa không phải số) --- # # 1. Triệu chứng # if word == 'triệu' and i+1 < n and words[i+1] == 'chứng': # result.append(word); i += 1; continue # # 2. Tỷ lệ / Tỷ trọng / Tỷ số # if word == 'tỷ' and i+1 < n and words[i+1] in ['lệ', 'trọng', 'số', 'phú']: # result.append(word); i += 1; continue # # 3. Năm (thời gian) # if word == 'năm' and i > 0 and words[i-1] in ['trên', '/', 'mỗi', 'hàng', 'trong', 'số']: # result.append(word); i += 1; continue # # 4. Tư vấn / Tư tưởng / Riêng tư (NEW - Fix lỗi V6.1) # # Nếu gặp "tư" (4), check từ sau xem có phải "vấn", "cách", "nhân", "tưởng" không # if word == 'tư' and i+1 < n and words[i+1] in ['vấn', 'cách', 'nhân', 'tưởng', 'duy']: # result.append(word); i += 1; continue # # --- KIỂM TRA TỪ SỐ --- # if word not in self.number_words: # result.append(word) # i += 1 # continue # # --- QUÉT CỤM SỐ (CHUNK SCANNING) --- # chunk = [] # j = i # while j < n and words[j] in self.number_words: # chunk.append(words[j]) # j += 1 # # --- XỬ LÝ SỐ 0 vs KHÔNG (Phủ định) --- # if len(chunk) == 1 and chunk[0] == 'không': # is_digit = False # # Check sau: là số hoặc đơn vị đo # if j < n and (words[j].isdigit() or words[j] in ['độ', '%', '/', '.', 'lần', 'mg', 'ml']): # is_digit = True # # Check trước: là số # if result and (result[-1].isdigit() or result[-1] == '/'): # is_digit = True # result.append("0" if is_digit else "không") # i = j # continue # # --- CONVERT --- # num_str = self._vietnamese_text2num(chunk) # result.append(num_str) # i = j # text_out = " ".join(result) # # CLEANUP # # 1. Xóa khoảng trắng quanh dấu chấm: 39 . 5 -> 39.5 # text_out = re.sub(r'\s*(\.|,)\s*', r'\1', text_out) # # 2. Gom nhóm số (nhưng trừ Spo2 ra) # text_out = re.sub(r'(? Triệu > Nghìn > Trăm # # Nếu gặp multiplier lớn hơn (Nghìn), cộng current vào total rồi nhân total # # Cách đơn giản nhất cho tiếng Việt: # # Nhóm theo lớp 3 số (Trăm) xử lý riêng, nhưng code dưới đây xử lý linear: # total += current * val # current = 0 # total += current # return str(total) # def _replace_match(self, match): # """Callback function cho regex sub""" # text = match.group(0) # # Nếu chuỗi chỉ là "tư" hoặc "năm" đứng một mình -> giữ nguyên (tránh lỗi ngữ cảnh) # if text in ['tư', 'năm', 'một'] and len(text.split()) == 1: # return text # return self._text_to_int(text) # def _medical_specific_rules(self, text): # """ # Xử lý các mẫu câu y tế đặc thù trước (Grammar-based) # """ # # 1. Huyết áp: "một trăm hai mươi trên tám mươi" -> "120/80" # # Pattern: (Số) + (trên) + (Số) # def bp_replace(match): # sys = self._text_to_int(match.group(1)) # dia = self._text_to_int(match.group(3)) # return f"{sys}/{dia}" # bp_pattern = fr'({self.num_words}.*?)\s+(trên)\s+({self.num_words}.*?)' # # Chỉ apply nếu sau đó là mmHg hoặc kết thúc câu (để tránh false positive) # text = re.sub(bp_pattern, bp_replace, text) # # 2. Nhiệt độ: "ba mươi bảy độ năm" -> "37.5 độ C" # def temp_replace(match): # int_part = self._text_to_int(match.group(1)) # dec_part = self._text_to_int(match.group(3)) # return f"{int_part}.{dec_part} độ C" # temp_pattern = fr'({self.num_words}.*?)\s+(độ)\s+({self.num_words})' # text = re.sub(temp_pattern, temp_replace, text) # # 3. SPO2: "spo hai", "ét pi o hai" -> "SpO2" # text = re.sub(r'\b(spo|ét pi o)\s*(hai|2)\b', 'SpO2', text, flags=re.IGNORECASE) # return text # def process(self, text): # text = text.lower() # # BƯỚC 1: Xử lý Rules Y tế đặc thù (Context-Dependent) # text = self._medical_specific_rules(text) # # BƯỚC 2: Chuẩn hóa đơn vị đo lường # replacements = { # r'\bhai chấm\b': ':', r'\bphẩy\b': '.', r'\bchấm\b': '.', # r'\bphần trăm\b': '%', r'\bđộ c\b': 'độ C', # r'\bmilimon\b': 'mmol', r'\bmi li mon\b': 'mmol', # r'\bmg trên đề xi lít\b': 'mg/dL' # } # for pat, rep in replacements.items(): # text = re.sub(pat, rep, text) # # BƯỚC 3: Xử lý số đếm thông thường (General Numbers) # # Tìm các chuỗi dài nhất có thể là số # # Logic regex: Tìm chuỗi chứa các từ số, nhưng phải check lookbehind/lookahead # # Tạo pattern bắt cụm từ số # # \b((?:không|một|...|mươi|lăm)(\s+|$)){1,} # num_pattern = fr'\b((?:{self.num_words})(?:\s+(?:{self.num_words}))+)\b' # # Xử lý các cụm từ số dài (từ 2 từ trở lên) trước để tránh bị cắt vụn # text = re.sub(num_pattern, self._replace_match, text) # # Xử lý các số đơn lẻ (cần check context kỹ hơn) # # Chỉ convert số đơn nếu nó đứng trước đơn vị đo (Unit allowlist) # single_digit_pattern = fr'\b({self.num_words})\s+({self.unit_allowlist})\b' # text = re.sub(single_digit_pattern, # lambda m: f"{self.digits.get(m.group(1), m.group(1))} {m.group(2)}", # text) # # BƯỚC 4: Restore Punctuation # if self.use_ai: # text = self.punct_model.restore_punctuation(text) # # BƯỚC 5: Post-processing Clean up # # Gộp số cách nhau bởi dấu chấm: "37 . 5" -> "37.5" # text = re.sub(r'(\d)\s*\.\s*(\d)', r'\1.\2', text) # # SpO2 fix casing # text = text.replace('spo2', 'SpO2') # return text # # --- CHẠY THỬ NGHIỆM --- # if __name__ == "__main__": # stt_input = """ # BỆNH ÁN NHI KHOA TIÊU CHẢY CẤP MỘT HÀNH CHÍNH BỆNH NHÂN BÉ GÁI HAI MƯƠI TƯ TUỔI MƯỜI HAI KI LÔ GAM LÝ DO NHẬP VIỆN TIÊU LỎNG NHIỀU LẦN NÔN HAI BỆNH SỬ BỆNH KHỞI PHÁT MỘT NGÀY NAY TRẺ ĐI NGOÀI PHÂN LỎNG TOÀN NƯỚC KHÔNG CÓ MÁU KHOẢNG MƯỜI LẦN MỘT NGÀY TRẺ NÔN BA ĐẾN BỐN LẦN RA THỨC ĂN QUẤY KHÓC KHÁT NƯỚC ĐÒI UỐNG NƯỚC LIÊN TỤC KHÔNG SỐT KHÔNG CO GIẬT BA TIỀN SỬ BẢN THÂN SINH THƯỜNG PHÁT TRIỂN BÌNH THƯỜNG GIA ĐÌNH ANH TRAI CŨNG ĐANG BỊ TIÊU CHẢY BỐN KHÁM LÂM SÀNG TOÀN THÂN TRẺ TỈNH KÍCH THÍCH VẬT VÃ GIẤU MẤT NƯỚC MẮT TRŨNG UỐNG NƯỚC HÁO HỨC MẤT NƯỚC YÊU CHƯƠNG CÓ MẤT NƯỚC NẾP BÉO RA MẤT NHANH BỤNG MỀM CHƯỚNG HƠI NHẸ HẬU MÔN ĐỎ NHẸ QUANH HẬU MÔN NĂM CẬN LÂM SÀNG CÔNG THỨC MÁU BẠCH CẦU BÌNH THƯỜNG SOI TƯƠI PHÂN KHÔNG TỚI HỒNG CẦU BẠCH CẦU NGHĨ NHIỀU DO VIRUS RÔ TA ĐIỆN GIẢI ĐỒ NÁT CHI KALI TRONG GIỚI HẠN BÌNH THƯỜNG SÁU CHẨN ĐOÁN XÁC ĐỊNH TIÊU CHẢY CẤP DO VIRUS CÓ MẤT NƯỚC PHÁT ĐỒ B ĐIỀU TRỊ MỘT HƯỚNG XỬ TRÍ BÚ NƯỚC ĐIỆN GIẢI ĐƯỜNG UỐNG ƯU TIÊN HOẶC CHUYỂN DỊCH NẾU UỐNG KÉM BỔ SUNG KẼM MEN VI SINH DINH DƯỠNG TIẾP TỤC CHO ĂN KHÔNG KIÊNG KHÊM HAI Y LỆNH THUỐC CỤ THỂ BÙ NƯỚC OREN HAI TRĂM BỐN MƯƠI LĂM GÓI PHA HAI TRĂM MI LI LÍT NHÂN BỐN GÓI PHA ĐÚNG TỶ LỆ CHO UỐNG BẢY MƯƠI LĂM MI LI LÍT TRÊN MỘT KI LÔ GAM TRONG BỐN GIỜ ĐẦU TẠI VIỆN KHOẢNG CHÍN TRĂM MI LI LÍT CỘT SUNG KẼM GINCAP HAI MƯƠI MI LI GAM NHÂN MỘT VIÊN HÒA NƯỚC UỐNG MỘT LẦN TRÊN NGÀY DÙNG ĐỦ MƯỜI BỐN NGÀY MEN VI SINH ENTERO GMINIA ỐNG NĂM MI LI LÍT NHÂN HAI ỐNG UỐNG SÁNG CHIỀU HẠ SỐT NẾU SỐT HAPPO MỘT TRĂM ML KHI SỐT TRÊN BA MƯƠI TÁM PHẨY NĂM ĐỘ # """ # stt_input = """ # BỆNH ÁN THẦN KINH RỐI LOẠN TIỀN ĐÌNH NGOẠI BIÊN HÀNH CHÍNH BỆNH NHÂN NỮ BỐN MƯƠI HAI TUỔI LÝ DO NHẬP VIỆN CHÓNG MẶT QUAY CUỒNG NÔN BỆNH SỬ SÁNG MÙA DẬY KHI BỆNH NHÂN NGỒI DẬY THÌ ĐỘT NGỘT THẤY CHÓNG MẶT DỮ DỘI CẢM GIÁC NHÀ CỬA ĐẢO LỘN QUAY CU XUNG QUANH BỆNH NHÂN PHẢI NẶNG NHẮM MẮT HỄ MẤT MỞ HOẶC DÂY ĐẦU LÀ CHÓNG MẶT TĂNG LÊN VÀ BUỒN NÔN BỆNH NHÂN ĐÔN ĐỐC THÁO BA LỆCH DA DỊCH VÀ THỨC ĂN CŨ KHÔNG ĐAU ĐẦU KHÔNG YẾU TAY CHÂN TAI KHÔNG Ủ TIỀN SỬ VÀ THÂN HUYẾT ÁP THẤP ĐÃ TỪNG BỊ CƠ TƯƠNG TỰ CÁCH ĐÂY MỘT NĂM GIA ĐÌNH BÌNH THƯỜNG KHÁM LÂM SÀNG THẤY TOÀN THÂN TỈNH MỆT MỎI DA XANH TÁI THẦN KINH RUNG GIẬT NHÃN CẦU GANG DƯƠNG TÍNH CHIỀU ĐÁNH NHANH VỀ BÊN TRÁI NGỰA PHÁT RO BỆNH NHÂN NGÃ VỀ BÊN PHẢI KHI NHẮM MẮT NGỰA PHÁT NGÓN TAY CHỈ MŨI CHÍNH XÁC KHÔNG CÓ DẤU HIỆU THẦN KINH KHU TRÚ LIỆT MẶT YẾU CHI ÂM TÍNH CÁC CƠ QUAN KHÁC THẤY TIM PHỔI BÌNH THƯỜNG TẬN LỚP SÀNG CHO THẤY CT SCAN ĐỜ SỌ NÃO KHÔNG HÌNH ẢNH XUẤT HUYẾT HAY NHỒI MÁU NÃO DOP LỚP BẠCH MÁU NÃO LƯU LƯỢNG DÒNG CHẢY HỆ THỐNG NỀN HỆ THỐNG SỐNG ĐỀN GIẢM NHẸ SINH HOẠT MÁU ĐIỆN GIẢI ĐỦ BÌNH THƯỜNG CHẨN ĐOÁN XÁC ĐỊNH LÀ HỘI CHỨNG TIỀN ĐÌNH ĐOẠN BIÊN CẤP TỈNH CƠ CHỐNG BỆNH KỊCH PHÁT LẠNH TÍNH ĐIỀU TRỊ HƯỚNG XỬ TRÍ CẮT CƠN CHỐNG MẶT THUỐC ỨC CHẾ TIỀN ĐÌNH CHỐNG NÔN TĂNG CƯỜNG TUẦN HOÀN NÃO NGHỈ HƠI NƠI YÊN TĨNH CHẢY SÁNG MẠNH Y LỆNH THUỐC CỤ THỂ THUỐC CẮT CƠN CHỐNG MẶT TAKENINE ACITY TIÊU LEXIN NĂM TRĂM MI LI GAM HAI ỐNG TIÊM TĨNH MẠCH CHẬM SÁNG ỐNG CHIỀU MỘT ỐNG THUỐC CHỐNG ĐÔN BRIPRAN MƯỜI MIRAGA MỘT ỐNG TIÊM BẮP TẬT HOÀN NÃO PIRA XÌ TAM TÁM TRĂM MI LI GAM HAI VIÊN UỐNG SÁNH CHIỀU MỔ THẦN KINH DÙNG BAGH B SÁU HAI VIÊN UỐNG TRƯA TỐI # """ # print("\n--- ĐẦU VÀO ---") # print(stt_input) # print("\n--- ĐANG XỬ LÝ... ---") # normalizer = MedicalTextNormalizerV2(use_ai_model=True) # result = normalizer.process(stt_input) # print("\n--- KẾT QUẢ FINAL (V4) ---") # print(result) import re from deepmultilingualpunctuation import PunctuationModel from nemo_text_processing.inverse_text_normalization.inverse_normalize import InverseNormalizer # --- SINGLETON CHO MODELS --- class AIModelRegistry: _punctuation_model = None _nemo_itn = None @classmethod def get_punctuation_model(cls): if cls._punctuation_model is None: print("⏳ Đang nạp Punctuation Model...") cls._punctuation_model = PunctuationModel(model="oliverguhr/fullstop-punctuation-multilang-large") return cls._punctuation_model @classmethod def get_nemo_itn(cls): if cls._nemo_itn is None: print("⏳ Đang nạp NVIDIA NeMo ITN (Vietnamese)...") # lang='vi' đã được NeMo hỗ trợ chính thức cho ITN cls._nemo_itn = InverseNormalizer(lang='vi', cache_dir="./nemo_cache") return cls._nemo_itn class MedicalTextNormalizerNeMo: def __init__(self, use_ai=True): self.use_ai = use_ai self.itn = AIModelRegistry.get_nemo_itn() if self.use_ai: self.punct_model = AIModelRegistry.get_punctuation_model() def _pre_process_medical(self, text): """ Xử lý các từ chuyên ngành mà NeMo ITN chung có thể chưa cover hết trước khi đưa vào bộ quy tắc ngữ pháp. """ text = text.lower() # Fix lỗi phát âm STT cho đơn vị y tế replacements = { r'\bspo\s*(hai|2)\b': 'spo2', r'\bmi\s*li\s*(mo|on|mon)\b': 'mmol', r'\bét pi o\b': 'spo', r'\bmi li gam\b': 'mg', r'\bmi li lít\b': 'ml' } for pat, rep in replacements.items(): text = re.sub(pat, rep, text) return text def process(self, text): # Bước 1: Dọn dẹp sơ bộ text = self._pre_process_medical(text) # Bước 2: Dùng NeMo ITN thay thế toàn bộ logic Regex số # NeMo sẽ tự hiểu "ba mươi bảy độ năm" -> "37.5 độ" dựa trên WFST text = self.itn.inverse_normalize(text, verbose=False) # Bước 3: Khôi phục dấu câu bằng AI if self.use_ai: text = self.punct_model.restore_punctuation(text) # Bước 4: Clean up cuối cùng (Post-processing) # Sửa casing cho các thuật ngữ y tế quan trọng text = text.replace('spo2', 'SpO2').replace('Mm Hg', 'mmHg') return text # --- TEST --- if __name__ == "__main__": # raw_stt = """ # BỆNH ÁN NHI KHOA TIÊU CHẢY CẤP MỘT HÀNH CHÍNH BỆNH NHÂN BÉ GÁI HAI MƯƠI TƯ TUỔI MƯỜI HAI KI LÔ GAM LÝ DO NHẬP VIỆN TIÊU LỎNG NHIỀU LẦN NÔN HAI BỆNH SỬ BỆNH KHỞI PHÁT MỘT NGÀY NAY TRẺ ĐI NGOÀI PHÂN LỎNG TOÀN NƯỚC KHÔNG CÓ MÁU KHOẢNG MƯỜI LẦN MỘT NGÀY TRẺ NÔN BA ĐẾN BỐN LẦN RA THỨC ĂN QUẤY KHÓC KHÁT NƯỚC ĐÒI UỐNG NƯỚC LIÊN TỤC KHÔNG SỐT KHÔNG CO GIẬT BA TIỀN SỬ BẢN THÂN SINH THƯỜNG PHÁT TRIỂN BÌNH THƯỜNG GIA ĐÌNH ANH TRAI CŨNG ĐANG BỊ TIÊU CHẢY BỐN KHÁM LÂM SÀNG TOÀN THÂN TRẺ TỈNH KÍCH THÍCH VẬT VÃ GIẤU MẤT NƯỚC MẮT TRŨNG UỐNG NƯỚC HÁO HỨC MẤT NƯỚC YÊU CHƯƠNG CÓ MẤT NƯỚC NẾP BÉO RA MẤT NHANH BỤNG MỀM CHƯỚNG HƠI NHẸ HẬU MÔN ĐỎ NHẸ QUANH HẬU MÔN NĂM CẬN LÂM SÀNG CÔNG THỨC MÁU BẠCH CẦU BÌNH THƯỜNG SOI TƯƠI PHÂN KHÔNG TỚI HỒNG CẦU BẠCH CẦU NGHĨ NHIỀU DO VIRUS RÔ TA ĐIỆN GIẢI ĐỒ NÁT CHI KALI TRONG GIỚI HẠN BÌNH THƯỜNG SÁU CHẨN ĐOÁN XÁC ĐỊNH TIÊU CHẢY CẤP DO VIRUS CÓ MẤT NƯỚC PHÁT ĐỒ B ĐIỀU TRỊ MỘT HƯỚNG XỬ TRÍ BÚ NƯỚC ĐIỆN GIẢI ĐƯỜNG UỐNG ƯU TIÊN HOẶC CHUYỂN DỊCH NẾU UỐNG KÉM BỔ SUNG KẼM MEN VI SINH DINH DƯỠNG TIẾP TỤC CHO ĂN KHÔNG KIÊNG KHÊM HAI Y LỆNH THUỐC CỤ THỂ BÙ NƯỚC OREN HAI TRĂM BỐN MƯƠI LĂM GÓI PHA HAI TRĂM MI LI LÍT NHÂN BỐN GÓI PHA ĐÚNG TỶ LỆ CHO UỐNG BẢY MƯƠI LĂM MI LI LÍT TRÊN MỘT KI LÔ GAM TRONG BỐN GIỜ ĐẦU TẠI VIỆN KHOẢNG CHÍN TRĂM MI LI LÍT CỘT SUNG KẼM GINCAP HAI MƯƠI MI LI GAM NHÂN MỘT VIÊN HÒA NƯỚC UỐNG MỘT LẦN TRÊN NGÀY DÙNG ĐỦ MƯỜI BỐN NGÀY MEN VI SINH ENTERO GMINIA ỐNG NĂM MI LI LÍT NHÂN HAI ỐNG UỐNG SÁNG CHIỀU HẠ SỐT NẾU SỐT HAPPO MỘT TRĂM ML KHI SỐT TRÊN BA MƯƠI TÁM PHẨY NĂM ĐỘ # """ raw_stt = """ BỆNH ÁN THẦN KINH RỐI LOẠN TIỀN ĐÌNH NGOẠI BIÊN HÀNH CHÍNH BỆNH NHÂN NỮ BỐN MƯƠI HAI TUỔI LÝ DO NHẬP VIỆN CHÓNG MẶT QUAY CUỒNG NÔN BỆNH SỬ SÁNG MÙA DẬY KHI BỆNH NHÂN NGỒI DẬY THÌ ĐỘT NGỘT THẤY CHÓNG MẶT DỮ DỘI CẢM GIÁC NHÀ CỬA ĐẢO LỘN QUAY CU XUNG QUANH BỆNH NHÂN PHẢI NẶNG NHẮM MẮT HỄ MẤT MỞ HOẶC DÂY ĐẦU LÀ CHÓNG MẶT TĂNG LÊN VÀ BUỒN NÔN BỆNH NHÂN ĐÔN ĐỐC THÁO BA LỆCH DA DỊCH VÀ THỨC ĂN CŨ KHÔNG ĐAU ĐẦU KHÔNG YẾU TAY CHÂN TAI KHÔNG Ủ TIỀN SỬ VÀ THÂN HUYẾT ÁP THẤP ĐÃ TỪNG BỊ CƠ TƯƠNG TỰ CÁCH ĐÂY MỘT NĂM GIA ĐÌNH BÌNH THƯỜNG KHÁM LÂM SÀNG THẤY TOÀN THÂN TỈNH MỆT MỎI DA XANH TÁI THẦN KINH RUNG GIẬT NHÃN CẦU GANG DƯƠNG TÍNH CHIỀU ĐÁNH NHANH VỀ BÊN TRÁI NGỰA PHÁT RO BỆNH NHÂN NGÃ VỀ BÊN PHẢI KHI NHẮM MẮT NGỰA PHÁT NGÓN TAY CHỈ MŨI CHÍNH XÁC KHÔNG CÓ DẤU HIỆU THẦN KINH KHU TRÚ LIỆT MẶT YẾU CHI ÂM TÍNH CÁC CƠ QUAN KHÁC THẤY TIM PHỔI BÌNH THƯỜNG TẬN LỚP SÀNG CHO THẤY CT SCAN ĐỜ SỌ NÃO KHÔNG HÌNH ẢNH XUẤT HUYẾT HAY NHỒI MÁU NÃO DOP LỚP BẠCH MÁU NÃO LƯU LƯỢNG DÒNG CHẢY HỆ THỐNG NỀN HỆ THỐNG SỐNG ĐỀN GIẢM NHẸ SINH HOẠT MÁU ĐIỆN GIẢI ĐỦ BÌNH THƯỜNG CHẨN ĐOÁN XÁC ĐỊNH LÀ HỘI CHỨNG TIỀN ĐÌNH ĐOẠN BIÊN CẤP TỈNH CƠ CHỐNG BỆNH KỊCH PHÁT LẠNH TÍNH ĐIỀU TRỊ HƯỚNG XỬ TRÍ CẮT CƠN CHỐNG MẶT THUỐC ỨC CHẾ TIỀN ĐÌNH CHỐNG NÔN TĂNG CƯỜNG TUẦN HOÀN NÃO NGHỈ HƠI NƠI YÊN TĨNH CHẢY SÁNG MẠNH Y LỆNH THUỐC CỤ THỂ THUỐC CẮT CƠN CHỐNG MẶT TAKENINE ACITY TIÊU LEXIN NĂM TRĂM MI LI GAM HAI ỐNG TIÊM TĨNH MẠCH CHẬM SÁNG ỐNG CHIỀU MỘT ỐNG THUỐC CHỐNG ĐÔN BRIPRAN MƯỜI MIRAGA MỘT ỐNG TIÊM BẮP TẬT HOÀN NÃO PIRA XÌ TAM TÁM TRĂM MI LI GAM HAI VIÊN UỐNG SÁNH CHIỀU MỔ THẦN KINH DÙNG BAGH B SÁU HAI VIÊN UỐNG TRƯA TỐI """ print("\n--- ĐẦU VÀO ---") print(raw_stt) normalizer = MedicalTextNormalizerNeMo() result = normalizer.process(raw_stt) print("\n--- KẾT QUẢ VỚI NVIDIA NEMO ---") print(result)