Spaces:
Runtime error
Runtime error
| import os | |
| from pathlib import Path | |
| import json | |
| from docx import Document | |
| from langchain_huggingface import HuggingFaceEmbeddings | |
| from tqdm import tqdm | |
| from langchain_docling import DoclingLoader | |
| from langchain_docling.loader import ExportType | |
| from langchain_text_splitters import RecursiveCharacterTextSplitter | |
| from transformers import AutoTokenizer | |
| class DocumentProcessor: | |
| def __init__(self): | |
| print('Initializing embedding model...') | |
| self.tokenizer = AutoTokenizer.from_pretrained( | |
| "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2") | |
| self.embedding_model = HuggingFaceEmbeddings( | |
| model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2" | |
| ) | |
| # Define text splitter | |
| self.text_splitter = RecursiveCharacterTextSplitter( | |
| chunk_size=10000, # Characters, not tokens | |
| chunk_overlap=3000 | |
| ) | |
| # Define program folder mappings | |
| self.folder_mappings = { | |
| "Chương trình An toàn thông tin": { | |
| "department_brief": "FIT", | |
| "department_name": "Khoa Công nghệ thông tin", | |
| "program_brief": "IS", | |
| "program_name": "Chương trình An toàn thông tin", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân An toàn thông tin/Bachelor of Information Security", | |
| "major_code": "7480202", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình An toàn thông tin/CTĐT ngành An toàn thông tin.docx" | |
| }, | |
| "Chương trình Công nghệ thông tin": { | |
| "department_brief": "FIT", | |
| "department_name": "Khoa Công nghệ thông tin", | |
| "program_brief": "IT", | |
| "program_name": "Chương trình Công nghệ thông tin", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Công nghệ thông tin/Bachelor of Information Technology", | |
| "major_code": "7480201", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Công nghệ thông tin/Công nghệ thông tin_CTĐT_2023.docx" | |
| }, | |
| "Chương trình Khoa học máy tính": { | |
| "department_brief": "FIT", | |
| "department_name": "Khoa Công nghệ thông tin", | |
| "program_brief": "CS", | |
| "program_name": "Chương trình Khoa học máy tính", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Khoa học máy tính/Bachelor of Computer Science", | |
| "major_code": "7480101", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Khoa học máy tính/Khoa học máy tính_CTĐT_2023.docx" | |
| }, | |
| "Chương trình Kỹ thuật phần mềm": { | |
| "department_brief": "FIT", | |
| "department_name": "Khoa Công nghệ thông tin", | |
| "program_brief": "SE", | |
| "program_name": "Chương trình Kỹ thuật phần mềm", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Kỹ thuật phần mềm/Bachelor of Software Engineering", | |
| "major_code": "7480103", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Kỹ thuật phần mềm/CTĐT ngành Kỹ thuật phần mềm.docx" | |
| }, | |
| "Chương trình Định phí bảo hiểm và Quản trị rủi ro": { | |
| "department_brief": "MFE", | |
| "department_name": "Khoa Toán kinh tế", | |
| "program_brief": "Actuary", | |
| "program_name": "Chương trình Định phí bảo hiểm và Quản trị rủi ro", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Định phí bảo hiểm và Quản trị rủi ro/Bachelor of Actuarial Science", | |
| "major_code": "7310108", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Định phí bảo hiểm và Quản trị rủi ro/CTĐT ngành Định phí bảo hiểm và Quản trị rủi ro.docx" | |
| }, | |
| "Chương trình Hệ thống thông tin": { | |
| "department_brief": "MIS", | |
| "department_name": "Khoa Hệ thống thông tin quản lý", | |
| "program_brief": "IS", | |
| "program_name": "Chương trình Hệ thống thông tin", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Hệ thống thông tin/Bachelor of Information Systems", | |
| "major_code": "7480104", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Hệ thống thông tin/CTĐT ngành HTTT.docx" | |
| }, | |
| "Chương trình Hệ thống thông tin quản lý": { | |
| "department_brief": "MIS", | |
| "department_name": "Khoa Hệ thống thông tin quản lý", | |
| "program_brief": "MIS", | |
| "program_name": "Chương trình Hệ thống thông tin quản lý", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Hệ thống thông tin quản lý/Bachelor of Management Information Systems", | |
| "major_code": "7340405", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Hệ thống thông tin quản lý/Hệ thống thông tin quản lý_CTĐT_2023.docx" | |
| }, | |
| "Chương trình Phân tích dữ liệu trong Kinh tế": { | |
| "department_brief": "MFE", | |
| "department_name": "Khoa Toán kinh tế", | |
| "program_brief": "DSEB", | |
| "program_name": "Chương trình Phân tích dữ liệu trong Kinh tế", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Khoa học dữ liệu trong kinh tế và kinh doanh/Bachelor of Data Science in Economics and Business", | |
| "major_code": "7310108", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Phân tích dữ liệu trong Kinh tế/DSEB_khung_chuong_trinh.docx" | |
| }, | |
| "Chương trình Thống kê kinh tế": { | |
| "department_brief": "KTK", | |
| "department_name": "Khoa thống kê", | |
| "program_brief": "ES", | |
| "program_name": "Chương trình Thống kê kinh tế", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Thống kê kinh tế/Bachelor of Economic Statistics", | |
| "major_code": "7310107", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Thống kê kinh tế/Thống kê kinh tế_CTĐT_2023.docx" | |
| }, | |
| "Chương trình Toán kinh tế": { | |
| "department_brief": "MFE", | |
| "department_name": "Khoa Toán kinh tế", | |
| "program_brief": "TOKT", | |
| "program_name": "Chương trình Toán kinh tế", | |
| "degree": "Cử nhân/Bachelor", | |
| "level": "Đại học/Undergraduate", | |
| "major_name": "Cử nhân Toán kinh tế/Bachelor of Mathematical Economics", | |
| "major_code": "7310108", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Toán kinh tế/Toán kinh tế_CTĐT_2023.docx" | |
| }, | |
| "Chương trình Trí tuệ nhân tạo": { | |
| "department_brief": "FDA", | |
| "department_name": "Khoa Khoa học dữ liệu và Trí tuệ nhân tạo", | |
| "program_brief": "TTNT", | |
| "program_name": "Chương trình Trí tuệ nhân tạo", | |
| "degree": "", | |
| "level": "Đại học/Undergraduate", | |
| # "major_name": "Trí tuệ nhân tạo/ of Artificial Intelligence", | |
| "major_name": "", | |
| "major_code": "7480107", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Trí tuệ nhân tạo/22.5.1.CTĐT_ngành TTNT_cử nhân.docx" | |
| }, | |
| "Chương trình Khoa học dữ liệu": { | |
| "department_brief": "FDA", | |
| "department_name": "Khoa Khoa học dữ liệu và Trí tuệ nhân tạo", | |
| "program_brief": "KHDL", | |
| "program_name": "Chương trình Khoa học dữ liệu", | |
| "degree": "", | |
| "level": "Đại học/Undergraduate", | |
| # "major_name": "Khoa học dữ liệu trong Tài chính và thương mại điện tử/ of Data Science in Finance and E-commerce", | |
| "major_name": "", | |
| "major_code": "7460108", | |
| "file_path": "syllabus_nct_word_format/Trường Công nghệ/Chương trình Khoa học dữ liệu/22.5.1.CTĐT_ngành KHDL_cử nhân.docx" | |
| } | |
| } | |
| def extract_text_from_docx(self, file_path): | |
| """Extract text from .docx file using Docling and return chunks""" | |
| try: | |
| # Initialize DoclingLoader | |
| loader = DoclingLoader( | |
| file_path=file_path, | |
| export_type=ExportType.MARKDOWN, | |
| ) | |
| # Load and process document | |
| docs = loader.load() | |
| if docs: | |
| # Combine all text first | |
| full_text = "\n".join([doc.page_content for doc in docs]) | |
| # Split into chunks | |
| chunks = self.text_splitter.split_text(full_text) | |
| # Validate each chunk against token limit | |
| valid_chunks = [] | |
| for chunk in chunks: | |
| tokens = self.tokenizer.encode(chunk) | |
| if len(tokens) <= 10000: | |
| valid_chunks.append(chunk) | |
| else: | |
| # Further split this chunk | |
| smaller_splitter = RecursiveCharacterTextSplitter( | |
| chunk_size=len(chunk) // 2, # Split in half | |
| chunk_overlap=2000, | |
| ) | |
| smaller_chunks = smaller_splitter.split_text(chunk) | |
| valid_chunks.extend(smaller_chunks) | |
| return valid_chunks | |
| return [] | |
| except Exception as e: | |
| print(f"Error processing DOCX {file_path}: {e}") | |
| return [] | |
| def get_faculty_program_from_path(self, file_path): | |
| """Get faculty and program based on folder structure""" | |
| path_parts = Path(file_path).parts | |
| # Look for program folder in path | |
| for part in path_parts: | |
| if part in self.folder_mappings: | |
| return self.folder_mappings[part] | |
| return { | |
| "department_brief": "Unknown", | |
| "department_name": "Unknown", | |
| "program_brief": "Unknown", | |
| "program_name": "Unknown", | |
| "degree": "Unknown", | |
| "level": "Unknown", | |
| "major_name": "Unknown", | |
| "major_code": "Unknown", | |
| "file_path": "Unknown" | |
| } | |
| def process_document(self, file_path): | |
| """Process a single document and return its metadata""" | |
| file_path = Path(file_path) | |
| file_ext = file_path.suffix.lower() | |
| file_name = file_path.name.lower() | |
| # Extract text chunks based on file type | |
| if file_ext in ['.docx']: | |
| chunks = self.extract_text_from_docx(file_path) | |
| else: | |
| print(f"Unsupported file type: {file_ext}") | |
| return None | |
| # Get faculty and program info | |
| faculty_program_info = self.get_faculty_program_from_path(file_path) | |
| # Determine degree type | |
| if "kỹ sư" in file_name: | |
| degree_prefix = "Kỹ sư" | |
| eng_prefix = "Engineer" | |
| else: | |
| degree_prefix = "Cử nhân" | |
| eng_prefix = "Bachelor" | |
| # Create documents list with chunks | |
| documents = [] | |
| for chunk in chunks: | |
| # Determine major_name based on program | |
| if faculty_program_info["program_name"] == "Chương trình Khoa học dữ liệu": | |
| major_name = f"{degree_prefix} {faculty_program_info['program_name']}/{eng_prefix} of Data Science in Finance and E-commerce" | |
| degree = f"{degree_prefix}/{eng_prefix}" | |
| elif faculty_program_info["program_name"] == "Chương trình Trí tuệ nhân tạo": | |
| major_name = f"{degree_prefix} {faculty_program_info['program_name']}/{eng_prefix} of Artificial Intelligence" | |
| degree = f"{degree_prefix}/{eng_prefix}" | |
| else: | |
| major_name = faculty_program_info["major_name"] | |
| degree = faculty_program_info["degree"] | |
| doc = { | |
| "content": chunk, | |
| "department_brief": faculty_program_info["department_brief"], | |
| "department_name": faculty_program_info["department_name"], | |
| "program_brief": faculty_program_info["program_brief"], | |
| "program_name": faculty_program_info["program_name"], | |
| "degree": degree, | |
| "file_name": file_path.name, | |
| "file_path": str(file_path), | |
| "level": "Đại học/Undergraduate", | |
| "major_name": major_name, | |
| "major_code": faculty_program_info["major_code"] | |
| } | |
| documents.append(doc) | |
| return documents | |
| def process_directory(self, directory_path, output_file): | |
| """Process all documents in a directory and save to JSON""" | |
| directory = Path(directory_path) | |
| all_documents = [] | |
| # Get all supported files | |
| # files = list(directory.glob("**/*.docx")) | |
| files = list(directory.glob("**/*.docx")) | |
| print(f"Found {len(files)} documents to process") | |
| # Process each file | |
| for file_path in tqdm(files, desc="Processing documents"): | |
| doc_metadata = self.process_document(file_path) | |
| if doc_metadata: | |
| all_documents.append(doc_metadata) | |
| # Save to JSON file | |
| print(f"Saving {len(all_documents)} documents to {output_file}") | |
| with open(output_file, 'w', encoding='utf-8') as f: | |
| json.dump(all_documents, f, ensure_ascii=False, indent=2) | |
| if __name__ == "__main__": | |
| # Initialize processor | |
| processor = DocumentProcessor() | |
| # Process documents | |
| # Change this to your documents directory | |
| input_directory = "syllabus_nct_docx_format/" | |
| output_file = "processed_documents_docx_v3.json" | |
| processor.process_directory(input_directory, output_file) | |