Công nghệ đang ngày càng phát triển qua từng năm, dẫn đến việc tra cứu thông tin của con người cũng thay đổi theo, từ những phương pháp tra cứu dữ liệu đơn giản bằng cách tìm kiếm theo các từ trong câu cho đến những phương pháp phức tạp như áp dụng học máy để trích xuất dữ liệu chính xác hơn dựa trên ngữ nghĩa của các từ đó. Sự đột phá trong lĩnh vực tra cứu thông tin được tái định nghĩa lại sau sự ra đời của ChatGPT một mô hình ngôn ngữ được OpenAI phát triển đã làm cách mạng hoá việc tìm kiếm, làm cho việc tìm kiếm thông tin được biểu diễn dưới dạng một chatbot hỏi đáp, nhờ vậy mô hình này đã giúp giải đáp các thông tin theo một cách thức giống con người hơn. Tuy nhiên ChatGPT cũng tồn tại những hạn chế của một mô hình ngôn ngữ, nhất là khả năng bị lỗi thời thông tin (outdated information), dẫn chứng là thời điểm ra mắt mô hình này chỉ cập nhật kiến thức đến năm 2021. Hiện nay, tất cả những vấn đề này đã được khắc phục nhờ phương pháp mở miền dữ liệu, giúp mô hình có thể cập nhật thông tin từ nhiều nguồn theo thời gian thực. Ở đề tài này ta sẽ mô phỏng lại hệ thống đó, bằng việc xây dựng một hệ thống hỏi đáp có thể truy cập dữ liệu từ nội quy học vụ được liệt kê trong sổ tay sinh viên của trường Đại học Nguyễn Tất Thành và nguồn thông tin từ Bách Khoa toàn thư Wikipedia. Để xây dựng được hệ thống này ta cần tìm hiểu về cách các mô hình ngôn ngữ lớn hoạt động, các phương pháp trích xuất thông tin liên quan, xử lý dữ liệu, cách triển khai mô hình trên server và làm thế nào để đánh giá hiệu quả của một hệ thống hỏi đáp. Bằng việc đón đầu xu thế chung về công nghệ AI tạo sinh, đề tài cũng đánh mạnh vào quá trình xử lý dữ liệu, một thứ cốt lõi quyết định độ hiệu quả của mô hình ngôn ngữ trong việc trích xuất thông tin và trả lời câu hỏi, từ đó có thể áp dụng kỹ thuật này trong nhiều lĩnh vực khác nhau có thể là việc tạo một hệ thống tra cứu tài liệu nội bộ, hỗ trợ tư vấn bán hàng hoặc là một trợ thủ đắc lực giúp việc học tập hiệu quả hơn.
Giới thiệu chung về đề tài
Giới thiệu để tài mục tiêu
Trong thời đại công nghệ thông tin phát triển mạnh mẽ, nhu cầu truy vấn thông tin ngày càng tăng cao Đặc biệt, với sự phát triển của trí tuệ nhân tạo (AI), các hệ thống trả lời câu hỏi (question answering - QA) đang trở nên phổ biến và được ứng dụng trong nhiều lĩnh vực khác nhau như giáo dục, y tế, kinh doanh,v.v Đón đầu xu thế đó đề tài này tập trung nghiên cứu phát triển hệ thống được trình bày như sau
Tên đề tài : Xây dựng hệ thống và mô hình trả lời câu hỏi miền mở trên Tiếng Việt
Mục tiêu đề tài : Xây dựng được một hệ thống có khả năng trả lời các câu hỏi dựa trên những thông tin trích xuất được từ tài liệu và văn bản được lưu trữ trong hệ thống cơ sở dữ liệu Có thể triển khai thành một ứng dụng chatbot có khả năng tương tác thông qua giao diện và có khả năng thêm dữ liệu từ người dùng.
Phương pháp đề tài
Đề tài sử dụng những kiến thức đã học trong lĩnh vực học máy và học sâu để xây dựng, đào tạo và áp dụng một số phương pháp thống kê nhằm kiểm thử, đánh giá mức độ hiệu quả của mô hình Đồng thời cũng áp dụng những công nghệ bao gồm: Đề tài sử dụng các công nghệ như sau:
Thư viện học máy, học sâu: Pytorch, Hugging Face, Langchain
Triển khai Back-end: vLLM, FastAPI
Triển khai Front-end: ReactJS, TailwindCSS, HTML.
Lý do chọn đề tài
Trong tiếng Việt, sử dụng mô hình ngôn ngữ làm hệ thống trả lời câu hỏi là một lĩnh vực nghiên cứu còn khá mới mẻ Các hệ thống trả lời câu hỏi trên tiếng Việt hiện nay vẫn còn gặp nhiều hạn chế, đặc biệt là về độ chính xác và khả năng đáp ứng các câu hỏi mở, mang tính suy luận, sáng tạo
Do đó, việc nghiên cứu và xây dựng hệ thống QA trên tiếng Việt là một vấn đề cấp thiết, có ý nghĩa quan trọng trong việc đáp ứng nhu cầu truy vấn thông tin của người dùng tiếng Việt Giải quyết vấn đề tổng hợp thông tin từ nhiều nguồn một cách nhanh chóng, hỗ trợ con người trong các tác vụ tìm kiếm thông tin, giải đáp thắc mắc và kiểm tra kiến thức Giúp con người đưa ra quyết định một cách dễ dàng nhờ những gợi ý của hệ thống Đón đầu xu hướng trí tuệ nhân tạo và xử lý dữ liệu trong thời đại ngày nay.
Mục tiêu nghiên cứu
Một số mục tiêu bao gồm việc tìm hiểu và đánh giá được độ hiệu quả của các mô hình học sâu trong lĩnh vực xử lý chuỗi dữ liệu liên tục và xử lý ngôn ngữ tự nhiên, cách huấn luyện và triển khai mô hình trong thực tiễn Mục tiêu chính của đề tài này là xây dựng một hệ thống trả lời câu hỏi miền mở trên tiếng Việt có độ chính xác cao, khả năng đáp ứng tốt các câu hỏi mở, mang tính suy luận, sáng tạo Cụ thể, hệ thống này cần đạt được các mục tiêu bao gồm:
• Hệ thống có thể trả lời được các câu hỏi mở, mang tính suy luận, sáng tạo một cách chính xác, đầy đủ và hữu ích
• Hệ thống có khả năng xử lý được nhiều loại câu hỏi mở khác nhau, bao gồm câu hỏi về sự kiện, câu hỏi về khái niệm, câu hỏi về mối quan hệ, câu hỏi về ý kiến,
Đối tượng nghiên cứu
Đối tượng nghiên cứu của đề tài này bao gồm:
• Các phương pháp và kỹ thuật xử lý ngôn ngữ tự nhiên (NLP) hiện đại,
• Các mạng học sâu phục vụ các tác vụ NLP như Transformer, BERT, GPT
• Các công nghệ tối ưu, lượng tử hoá mô hình và triển khai mô hình lên môi trường server cloud
• Dữ liệu cần trích xuất, phương pháp tìm kiếm văn bản tương tự
• Các phương pháp đánh giá mô hình ngôn ngữ lớn
Bố cục đề tài
Đề tài bao gồm 5 chương:
• Chương 1: Giới thiệu chung về đề tài
• Chương 2: Cơ sở lý luận về vấn đề nghiên cứu
• Chương 3: Xây dựng hệ thống trình bày
• Chương 4: Thực nghiệm và đánh giá
• Chương 5: Kết luận và hướng phát triển
Cơ sở lý luận về vấn đề nghiên cứu
Giới thiệu về Hệ thống Trả lời câu hỏi
Từ lâu con người luôn tìm cách trả lời những câu hỏi xung quanh mình, từ thực nghiệm đến kết luận chúng ta đã đúc kết những tri thức ấy qua nhiều năm và tạo nên một kho tàng đồ sộ những thông tin được lưu trữ dưới dạng giấy bút và ngày nay chúng được số hóa và lưu trữ gọn nhẹ trên những thiết bị phần cứng hiện đại
Hình 2.1: Minh họa cho Hệ thống Trả lời câu hỏi
Do sự đồ sộ của nguồn thông tin được tăng dần theo cấp số nhân qua từng năm, một hệ thống tổng hợp thông tin và trả lời câu hỏi là vô cùng cần thiết Sơ khai nhất có lẽ là sự xuất hiện của Google hoặc gần đây là ChatGPT đã làm cách mạng hóa việc tìm kiếm thông tin, giúp việc tìm kiếm thông tin trở nên đơn giản và dễ dàng hơn Vì vậy ta có thể hiểu tác vụ này có định nghĩa như sau:
Trả lời câu hỏi (Question-Answering) là một tác vụ nhằm hiểu ngôn ngữ tự nhiên, trích xuất và truy xuất thông tin, mục tiêu là tạo ra một hệ thống trả lời câu hỏi tự động dựa trên khả năng đọc hiểu của máy tính (machine reading comprehension), cho phép người dùng đặt câu hỏi bất kỳ và nhận được câu trả lời phù hợp từ một tập dữ liệu lớn và đa dạng [1] Đây là một lĩnh vực thu hút nhiều nhà nghiên cứu trong lĩnh vực trí tuệ nhân tạo trong những năm gần đây bởi sự phát triển mạnh mẽ của các mô hình dữ liệu lớn dựa trên khả năng đọc hiểu của máy tính, được ứng dụng trong nhiều lĩnh vực từ y tế, giáo dục, tài chính,.v.v
Hệ thống trả lời câu hỏi thường có 2 loại bao gồm : trả lời câu hỏi miền đóng (closed domain) và trả lời câu hỏi miền mở (open domain)
Hệ thống Trả lời câu hỏi miền mở là gì?
Khác với một hệ thống Trả lời câu hỏi miền đóng chỉ cho phép trả lời câu hỏi trong một lĩnh vực nhất định ví dụ như luật pháp hoặc tài chính thì hệ thống Trả lời câu hỏi miền mở có thể trả lời câu hỏi ở bất kỳ lĩnh vực nào miễn là trong hệ thống dữ liệu có lưu trữ về nó
Về định nghĩa ta có thể hiểu như sau: Trả lời câu hỏi miền mở (Open-Domain Question
Answering) là một tác vụ giúp trả lời câu hỏi đầu vào dựa trên cơ chế Truy xuất thông tin
(Information Retrieval - IR) với cơ sở dữ liệu có sẵn, hệ thống IR này sẽ tổng hợp và lựa chọn ra những tài liệu thông tin văn bản có mức độ liên quan cao trong hệ thống lưu trữ
(cơ sở dữ liệu) và trả về với sắp xếp theo mức độ liên quan đó Từ những thông tin có được mô hình sẽ dùng một số kỹ thuật Xử lý ngôn ngữ tự nhiên (NLP) để trích xuất ra một phần thông tin khả năng cao là câu trả lời cho câu hỏi [2].
Cơ chế hoạt động của Open-Domain Question Answering
Như ta đã tìm hiểu thì một hệ thống trả lời câu hỏi miền mở sẽ bao gồm 2 thành phần chính:
Retriever (Người tha mồi) và Reader (Người chắt lọc)
Hình 2.2: Cơ chế hoạt động của một hệ thống Information Retrieval
● Thành phần Retriever sẽ có nhiệm vụ trích xuất những tài liệu có liên quan (theo top-K) trong hệ thống lưu trữ và sắp xếp nó theo mức độ liên quan từ cao đến thấp
Thông thường phương pháp được dùng để tìm kiếm theo mức độ tương tự văn bản (text similarity) sẽ dựa trên TF-IDF, MB25 hoặc dense vector
● Thành phần Reader trích xuất những thông tin văn bản lấy được từ Retriever để lấy ra đoạn hoặc câu có khả năng cao là đáp án cho câu hỏi Thông thường sẽ là 2 biến giá trị số index của điểm bắt đầu và kết thúc của đáp án trong văn bản Lúc này thông tin văn bản sẽ gọi là ngữ cảnh (context) để mô hình Reader dựa vào Mô hình thường được dùng cho Reader là BERT, RoBERTa, DeBERTa, XLM,.v.v Ngoài ra, thay vì dùng Reader một số hệ thống hiện đại sẽ thay thế Reader bằng một Generator như GPT-2, BLOOM hoặc LLaMA [3] Giúp câu trả lời mang tính chất con người hơn kết hợp với những thông tin mà mô hình đã được huấn luyện trước đó Trong đề tài này, một Generator sẽ được sử dụng thay cho Reader.
Tìm kiếm mức độ tương tự văn bản
Để có thể tạo ra một Retriever phục vụ tìm kiếm những tài liệu (document) có liên quan đến câu truy vấn (query) ở đầu vào Ta cần một thuật toán có thể đánh giá mức độ tương tự văn bản (text similarity), thuật toán này sẽ dò xem những tài liệu và văn bản nào có khả năng cao chứa đựng nội dung liên quan truy vấn đó Phổ biến nhất có lẽ là 2 thuật toán TF- IDF và BM25
Trong truy xuất thông tin, TF-IDF (term frequency–inverse document frequency) là một kỹ thuật giúp đánh giá, phản ánh mức độ quan trọng của một từ trong văn bản [8]
Trong đó TF (term frequency) được tính là tần suất xuất hiện của một từ trong văn bản Được tính theo công thức
● f(t,d): là số lần xuất hiện từ t trong văn bản d
● max{f(w,d): w∈d}: là tổng số từ t trong văn bản d
Tiếp tục ta có IDF (inverse document frequency) Là tần số nghịch của một từ trong tập văn bản (corpus)
● |𝐷|: là tổng số văn bản trong tập mẫu D
● |𝑑 𝜖 𝐷 ∶ 𝑡 𝜖 𝑑|: là số lượng văn bản có chứa từ t
Từ 2 chỉ số TF và IDF tính được, nhân lại sẽ cho ra được giá trị của TF-IDF như sau
Một từ có giá trị TF-IDF cao chứng tỏ sự xuất hiện của từ đó trong tài liệu được bù đắp bởi số lượng những tài liệu có chứa từ đó, có nghĩa là từ có giá trị này cao sẽ xuất hiện nhiều trong văn bản này và xuất hiện ít hơn trong văn bản khác Giúp việc lọc ra văn bản có liên quan đến từ khóa tìm kiếm trở nên chính xác hơn
BM25 (hay Okapi BM25 (BM – best match)) thường được sử dụng để xếp hạng các tài liệu dựa trên việc kiểm tra liệu chúng có khớp với một truy vấn (query) cụ thể Hàm xếp hạng này dựa trên mô hình xác suất từng từ của truy vấn xuất hiện trong tài liệu Tương tự TF- IDF, BM25 cũng được sử dụng rộng rãi trong tìm kiếm
Ví dụ cho đầu vào một truy vấn 𝑸 bao gồm những từ 𝒒 𝒊 , , 𝒒 𝒏 , thuật toán BM25 sẽ đưa ra đánh giá xem văn bản 𝑫 có phù hợp với truy vấn 𝑸 hay không [7]
● 𝑓(𝑞 𝑖 , 𝐷) là tần suất xuất hiện của từ 𝒒 𝒊 với văn bản 𝑫
● |𝐷| là số lượng từ của 𝑫
● 𝑎𝑣𝑔𝑑𝑙 là độ dài trung bình của văn bản trong tập
● 𝑘 1 và 𝑏 là hệ số độc lập mặc định là 𝑘 1 ∈ [1.2, 2.0] và 𝑏 = 0.75
● 𝐼𝐷𝐹(𝑞 𝑖 ) là tần số nghịch của từ 𝑞 𝑖
8 Để tính 𝐼𝐷𝐹(𝑞 𝑖 ) ta dựa theo công thức sau:
● 𝑁 là tổng số lượng văn bản
● 𝑛(𝑞 𝑖 ) là số lượng văn bản chứa từ 𝑞 𝑖
Tuy nhiên phương pháp tính này có một nhược điểm đó là đối với những từ vựng phổ biến ví dụ như: là, và, hoặc, nhưng, của,.v.v Nếu nó xuất hiện nhiều hơn một nửa số văn bản trong tập, giá trị của 𝐼𝐷𝐹(𝑞 𝑖 ) sẽ âm, vì vậy trong thực tế chúng ta cần đưa những từ phổ biến này vào một danh sách loại trừ để có thể lược bỏ, điều này tương tự việc loại bỏ 𝐼𝐷𝐹 có giá trị âm hoặc ta sẽ quy định một số 𝜀 nào đó đại diện cho mức 𝐼𝐷𝐹 thấp nhất có thể chấp nhận được để so sánh, tức là chỉ lấy nếu giá trị 𝐼𝐷𝐹 lớn hơn 𝜀, còn lại sẽ bằng 𝜀 Tuy nhiên BM25 cũng có những hạn chế của nó khi chỉ tìm kiếm theo xác suất xuất hiện nhưng không thể tìm dựa trên ý nghĩa của nó, vì vậy người ta đã sử dụng học sâu để tăng khả năng tìm kiếm thông qua một phương pháp tìm kiếm tương tự bằng cách nhúng từ
2.4.3 Tìm kiếm tương đồng dựa trên vector nhúng từ
Bằng cách trích xuất đặc trưng của từ vựng hoặc một câu thành các vector embedding, nếu biểu diễn vector này trên không gian nhiều chiều ta có thể tính toán được khoảng cách giữa vector của câu tìm kiếm với các vector nội dung trong database từ đó có thể truy xuất được tài liệu có khoảng cách ngắn nhất, tức mức độ liên quan cao nhất Việc tính toán khoảng cách giữa 2 vector có thể dùng công thức toán cấp 3 như cosine để thực hiện Tuy nhiên vấn đề ở chỗ ta phải tìm được một mô hình có khả năng trích xuất đặc trưng đủ tốt để chuyển đổi văn bản thành các vector có thể biểu diễn được ngữ nghĩa Thông thường một model BERT sử dụng cấu trúc Transformer Encoder sẽ là một lựa chọn phù hợp để sử dụng cho việc chuyển đổi này.
Lịch sử hình thành mô hình ngôn ngữ
Một mô hình ngôn ngữ (language model) là một mô hình có thể gán được xác suất, khả năng xuất hiện của một phần tử từ trong một câu Dưới góc nhìn toán học thì một câu được biểu diễn dưới dạng một chuỗi liên tục kèm theo những từ mà ở đó xác suất, khả năng một từ xuất hiện của từ đó trong một chuỗi biết trước Ta có thể hình dung một câu là một chuỗi
Ví dụ: 𝑃("𝐼 𝑙𝑜𝑣𝑒 𝑐𝑎𝑡") = 𝑃(𝐼) × 𝑃(𝑙𝑜𝑣𝑒|𝐼) × 𝑃(𝑐𝑎𝑡|𝐼 𝑙𝑜𝑣𝑒) Để tính được xác xuất các từ được sinh ra ta cần biểu diễn chuỗi văn bản đầu vào sang dạng số, việc chuyển văn bản thành số gọi là encode (mã hóa) hay còn gọi là nhúng từ (word embedding)
Máy tính không thể hiểu được ngôn ngữ của con người, để máy tính có thể hiểu được một từ trong câu, ta cần một hệ thống có khả năng ánh xạ từ ngôn ngữ thông thường sang số để biểu diễn từ đó Kỹ thuật này được gọi là nhúng từ (word embedding) giúp ta có thể chuyển đổi từ vựng sang vector đặc trưng (vector embedding) của nó
Hình 2.3: Minh họa về kỹ thuật nhúng từ Trong quá khứ, việc chuyển văn bản thành vector (tokenizer) sẽ thông qua các phương pháp mang tính chất đơn giản như phương pháp túi từ (Bag-of-Words - BOW), chỉ việc
10 trích xuất sự xuất hiện của các từ trong văn bản để lấy làm đặc trưng hoặc phương pháp
TF-IDF chỉ việc lấy tần suất xuất hiện của từ trong câu làm đặc trưng của từ đó Tuy nhiên, hiện tại hai phương pháp này không còn hiệu quả và người ta dần thay thế nó bằng các mô hình phức tạp hơn áp dụng học sâu để có thể biểu diễn nhiều thông tin trong một từ hơn, từ đó kỹ thuật nhúng từ ra đời, một phương pháp nhúng từ hiệu quả cần phải thỏa mãn 2 điều kiện:
● Nếu hai từ có sự liên quan về ngữ nghĩa thì khoảng cách hai từ này khi biểu diễn cũng sẽ gần nhau hơn trong không gian được biểu diễn
● Với mỗi một từ chỉ tồn tại một cách biểu diễn duy nhất, hai từ khác nhau sẽ được biểu diễn khác nhau, không có sự trùng lặp
Một đại diện tiêu biểu của kỹ thuật nhúng từ được sử dụng phổ biến là word2vec ra đời
2013 bởi Tomas Mikolov với mục tiêu biểu diễn embedding từ xuống một không gian tối ưu hơn rất nhiều so với số lượng từ có trong từ điển Mô hình word2vec là một mạng nơ- ron có 3 tầng, mô hình sẽ lấy từ mục tiêu và các từ ngữ cảnh của từ đó để làm đầu vào và đầu ra, tùy thuộc vào cách ta sử dụng thông thường sẽ có 2 kiểu mô hình word2vec:
● Skip-gram: Lấy từ mục tiêu làm đầu vào và các từ xung quanh nó (từ ngữ cảnh) làm đầu ra mong muốn để huấn luyện mạng nơ ron
● CBOW (Continuous Bag of Words): Lấy từ mục tiêu làm đầu ra dự đoán từ đầu vào là các từ xung quanh nó để huấn luyện mạng
Mục tiêu cuối cùng của mô hình word2vec là lấy đầu ra biểu diễn của một từ để làm đầu vào cho một mô hình ngôn ngữ, một mô hình xử lý chuỗi dữ liệu liên tục
Ví dụ để encode được câu: "𝐼 𝑙𝑜𝑣𝑒 𝑐𝑎𝑡" có 3 từ ta cần đưa qua một vector embedding (véc- tơ nhúng từ), một vector embedding có chiều dài là số lượng từ trong câu tối đa mà ta muốn đưa vào mô hình ví dụ 1024 làm tiêu chuẩn, thì lúc này đầu ra sau khi encode sẽ là
3 × 1024 = 3072 tham số, đó là chỉ với 3 từ Trong thực tế số lượng từ đầu vào có thể là hàng trăm hoặc thậm chí hàng nghìn gần với độ dài vector embedding Để một mô hình học các đặc trưng với số lượng tham số lớn như vậy với ngôn ngữ thì mạng nơ ron truyền thống là không khả thi Do đó ta cần mô mô hình có khả năng chia sẻ tham số lẫn nhau trong việc xử lý chuỗi liên tục Để xây dựng một mô hình ngôn ngữ lớn (LLM) cho tác vụ
Sinh văn bản (Text generation) phục vụ cho việc xây dựng mô hình hỏi đáp, ta cần tìm hiểu
11 về khởi nguồn của các mạng xử lý chuỗi liên tục, từ đó làm tiền đề cho việc phát triển mô hình này
2.5.2 Mạng Nơ-ron Hồi tiếp truyền thống (RNN)
Mạng nơ-ron Hồi tiếp (Recurrent Neural Network (RNN)) là một họ các mạng có khả năng xử lý dữ liệu dạng chuỗi bao gồm một chuỗi các giá trị 𝑥 (1) , , 𝑥 (𝑡) với thời gian 𝒕 Ý tưởng của mạng này là sử dụng cách thức dùng chung tham số (parameter sharing) giữa các phần khác nhau của mô hình đơn cử là việc lưu lại thông tin thông qua biến tiềm ẩn
(hidden state), nơi kết nối giữa các nút để tạo thành đồ thị có hướng dọc theo một trình tự thời gian[4]
Hình 2.4: Cấu trúc một tế bào RNN
Một tế bào (cell) của RNN sẽ nhận 2 tham số đầu vào tại thời điểm t hiện tại là 𝑥 (𝑡) và
ℎ (𝑡−1) Tham số ℎ ở đây chính là trạng thái ẩn (hidden state) mà chúng ta đã nhắc đến phía trên, tế bào sẽ duy trì bộ nhớ thông qua trạng thái ẩn này, sau đó sẽ nhân vô hướng với trọng số (weight) và hàm kích hoạt ϕ (activation) để cho ra đầu ra ℎ (𝑡) Công thức lan truyền thuận ở đây là:
⇔ ℎ (𝑡) = 𝑡𝑎𝑛ℎ (𝑏 + 𝑊 ℎ (𝑡−1) + 𝑈𝑥 (𝑡) ) Trong đó U, W là ma trận trọng số và b là hệ số tự do (bias) Ta có thể giả định 𝜙 1 là một hàm 𝑡𝑎𝑛ℎ(𝑥) Lúc này ta đã có một mạng nơ-ron hồi duy đơn giản (SimpleRNN) với đầu
Activation yt ht ht-1 xt
12 ra 𝑦 (𝑡) và ℎ (𝑡) là tương đương nhau Tuy vậy, giả sử bài toán toán là dự đoán từ hoặc ký tự, giá trị đầu ra là rời rạc, để cho ra được 𝑦 (𝑡) ta cần thêm một bước là nhân ℎ (𝑡) với một ma trận trọng số V rồi đưa qua một hàm kích hoạt 𝜙 2
⇔ 𝑦 (𝑡) = 𝑠𝑜𝑓𝑡𝑚𝑎𝑥 (𝑐 + 𝑉 ℎ (𝑡) ) Tại đây, c cũng là một hệ số bias khác Lúc này 𝜙 2 là một hàm 𝑠𝑜𝑓𝑡𝑚𝑎𝑥(𝑥)
Hình 2.5: Cấu trúc một tế bào RNN đầu ra rời rạc
Cứ như vậy, nhân này sẽ tiếp tục theo quá trình đó xuyên suốt độ dài chuỗi Tế bào nhân này được dàn trải (unfolding) ra, ta sẽ có một mạng có hình dáng như sau
Hình 2.6: Cấu trúc mạng RNN [5]
Activation yt ht ht-1 xt
Lượng tử hóa mô hình (Quantization model)
Điểm yếu của các mô hình ngôn ngữ lớn đó chính là tốn nhiều tài nguyên lưu trữ và tính toán, một mô hình được coi là có thể sử dụng được thường ở mức từ 3 hoặc 7 tỉ tham số trở lên Để tăng tốc độ xử lý Inference khi triển khai lên môi trường server ra cần sử dụng kỹ thuật lượng tử hóa để làm nhẹ kích thước của mô hình gốc bằng cách cắt đi các bit lưu trữ của trọng số (weight), độ chính xác sẽ giữ nguyên hoặc sẽ giảm nhưng không đáng kể, đổi lại tốc độ phản hồi có thể tăng gấp đôi hoặc gấp 3 lần
Hình 2.22: Minh họa việc cắt float-32 thành float-16 Một số thư viện phổ biến để lượng tử hóa mô hình như Bitsandbytes để cắt hoàn toàn hay với GPT-Q sử dụng post-training với một dataset thứ 2 trong quá trình lượng tử để giảm mất mát độ chính xác sau khi lượng tử, tuy nhiên hai phương pháp này gần như đã cũ và không tối ưu khi việc cắt hoàn toàn hoặc train lại mô hình trong khi tối ưu có thể dẫn đến giảm độ chính xác hoặc hiện tượng quá khớp (overfitting) xảy ra Gần đây có một phương pháp mới nổi lên là AWQ (Activation-aware Weight Quantization) với nghiên cứu chỉ ra rằng không phải trọng số nào trong mô hình cũng quan trọng như nhau, do đó thay vì lượng tử hóa tất cả, việc chỉ giữ lại từ 0.1% đến 1% trọng số quan trọng nhất thì sau khi lượng tử hóa cũng sẽ không làm giảm độ chính xác mô hình Những trọng số quan trọng được nói đến được lấy như thế nào? Trọng số này cung cấp bởi activation Ví dụ như hình dưới đây phía bên trái chỉ việc lượng tử hóa cắt hoàn toàn đơn thuần từ số thập phân FP16 (bfloat16) xuống số nguyên INT3 sẽ làm giảm độ chính xác khi chỉ số Perplexity (PPL) tăng tới 43.2 điểm [17] (Perplexity PPL - chỉ số đánh giá độ phân bố xác suất của một mô hình xác suất trên mẫu, PPL càng thấp sẽ càng tốt)
Hình 2.23: So sánh việc ép kiểu bit hoàn toàn và giữ lại 1% tham số quan trọng
Từ hình trên ta thấy rằng chỉ việc giữ lại 1% những tham số quan trọng nhất đã cải thiện PPL từ 43.2 xuống còn 13.0 Tuy nhiên một ma trận trọng số khi được biểu diễn trên phần cứng máy tính chỉ có thể là 1 kiểu dữ liệu duy nhất cho toàn bộ ma trận, hoặc là FP16 hoặc là INT3 gần như không khả thi khi kết hợp nhiều kiểu chính xác của số trong ma trận đó
Vì vậy, nhóm tác giả của AWQ đã thực hiện một bước scale trên trọng số trước khi thực hiện lượng tử hóa mô hình
Hình 2.24: Scale trọng số trước khi lượng tử hóa
Nhờ việc thực hiện per-channel scaling này giúp giải quyết vấn đề kém hiệu quả về mặt phần cứng nhưng vẫn giữ được độ chính xác của mô hình Ta có kết quả so sánh như sau với các phương pháp lượng tử hoá khác
Bảng 2.2: So sánh kết quả lượng tử trên độ đo Perplexity (PPL)
Vậy là ta đã có những kiến thức cần thiết để có thể xây dựng nên một hệ thống hỏi đáp Tiếp theo ta sẽ tiến hành áp dụng những kiến thức ở chương lý thuyết để xây dựng nên hệ thống này
Xây dựng hệ thống trình bày
Tổng quan về ý tưởng hệ thống
Ở đề tài này ta sẽ lựa chọn một phạm vi cho hệ thống hỏi đáp, tức là hệ thống sẽ không thể trả lời được mọi câu hỏi ở mọi lĩnh vực một cách toàn năng như ChatGPT mà thay vào đó sẽ chỉ phục vụ trả lời câu hỏi trong một phạm vi chủ đề nhất định Giống như một chiến lược đánh du kích, khi chia nhỏ chủ đề ra sẽ giúp mô hình có thể trả lời tốt ở lĩnh vực được giao, việc này sẽ giúp ta tận dụng được lượng dữ liệu và tài nguyên hạn chế trong phạm vi nghiên cứu của đề tài
Mô tả chung: Hệ thống sẽ là một chatbot có khả năng trả lời thắc mắc cho sinh viên trường đại học Nguyễn Tất Thành với dữ liệu được truy xuất từ Sổ tay Sinh viên năm học 2023 -
2024 soạn bởi phòng Công tác Sinh Viên NTTU Hệ thống có thể trả lời các câu hỏi về học vụ, quy định của trường trong việc đào tạo đại học và các câu hỏi liên quan đến kiến thức trong bách khoa toàn thư Wikipedia Hệ thống được người dùng sử dụng thông qua một website có giao diện hoàn chỉnh, có liệt kê phần tài liệu tham khảo để kiểm chứng thông tin
Thiết kế hệ thống: Hệ thống sẽ bao gồm 3 phần chính bao gồm: Front-end, Backend và
Hình 3.1: Kiến trúc của hệ thống hỏi đáp
Cơ chế hoạt động: Người dùng sẽ tương tác gửi câu hỏi từ front-end sau đó câu hỏi sẽ được chuyển qua backend thông qua FastAPI Tại backend hệ thống sẽ dùng một Retriever để tìm những văn bản được lưu trong vector database mà có liên quan nhất đến câu hỏi đầu vào, sau đó Retriever trả về top-k các văn bản dựa trên điểm số liên quan đó Cuối cùng văn bản liên quan kèm câu hỏi sẽ được đưa vào ngữ cảnh (context) đầu vào của một mô hình ngôn ngữ (Generator) được triển khai trên một server GPU riêng Tại đây mô hình ngôn ngữ sẽ sinh ra câu trả lời dựa trên ngữ cảnh được cung cấp rồi trả về cho người dùng thông qua front-end
Tại sao lại là vector database?
Vì vector database được sinh ra là để tối ưu cho việc tìm kiếm tương tự (similarity search), ví dụ như văn bản, hình ảnh hoặc âm thanh với khả năng mở rộng linh hoạt và tốc độ cao Việc tìm kiếm văn bản tương tự trong cơ sở dữ liệu có cấu trúc truyền thống (SQL) sẽ trở nên khó khăn hơn bao giờ hết.
Chuẩn bị dữ liệu
Dữ liệu ta sử dụng sẽ bao gồm 3 bộ chính bao gồm:
+ Dữ liệu văn bản của Sổ Tay Sinh Viên 2023 để lưu trữ trên vector database làm nguồn dữ liệu cho mô hình sử dụng phục vụ việc hỏi đáp
+ Bộ gồm 100+ câu hỏi thường gặp của sinh viên kèm câu trả lời làm dữ liệu đánh giá độ chính xác hệ thống
+ Bộ dữ liệu hỏi đáp vilm/OpenOrca-Viet được trích xuất từ các mô hình ngôn ngữ lớn như GPT-4, PaLM-2 và Claude dùng để tinh chỉnh mô hình Generator
Hình 3.2: Sổ tay sinh viên 2023 - 2024
3.2.1 Làm sạch dữ liệu Để chuẩn bị dữ liệu văn bản của Sổ Tay Sinh Viên 2023 ta sẽ tiến hành tiền xử lý, khác với dữ liệu có cấu trúc ở dạng bảng thì dữ liệu văn bản (text) không có cấu trúc do đó ta cần xử lý một cách thủ công như sau:
Bước 1: Tiền xử lý bằng cách chuyển đổi tệp gốc ở định dạng pdf thành dạng text ở định dạng docx
Bước 2: Loại bỏ những phần không cần thiết như mục lục, hình ảnh, các mục hướng dẫn dựa trên hình ảnh, ký tự đặc biệt
Bước 3: Loại bỏ hầu hết các bảng vì mô hình ngôn ngữ vẫn chưa thể xử lý được dữ liệu dạng bảng biểu Những bảng quan trọng như điểm xếp loại học bổng hoặc xếp loại điểm rèn luyện sẽ được viết lại thủ công với diễn giải bằng ngôn từ Sau đó lưu lại dữ liệu đã làm sạch dưới dạng txt
Bước 4: Tiến hành cắt văn bản trong txt này thành các phần nhỏ (chunk) với mỗi phần là
800 ký tự (chunk_size) và số lượng ký tự trùng lặp với phần trước đó là 400 ký tự (chunk_overlap) Tức là mỗi đoạn 800 chữ cái được cắt ra sẽ dính 400 chữ cái với đoạn đã cắt trước đó nhằm hạn chế việc cắt bị thiếu thông tin Từ việc đưa 1000 ký tự vào làm ngữ cảnh thì phần còn lại cũng sẽ đủ dư để chứa câu hỏi và đoạn hướng dẫn (instruction) cho đầu vào mô hình Tổng cộng sẽ có 184 mẫu nhỏ như vậy
Bước 5: Cuối cùng, ta sẽ tiến hành encode các phần nhỏ này thành vector embedding để lưu trữ trên vector database Ta sẽ sử dụng mô hình Sentence Similarity để thực hiện encode, sau khi thử nghiệm nhiều loại mô hình encode thì mô hình sentence- transformers/paraphrase-multilingual-mpnet-base-v2 là lựa chọn tối ưu khi có hỗ trợ
Tiếng Việt và đạt độ chính xác tương đối cao trên mặt bằng chung là 53.7% trên 14 dataset đa lĩnh vực theo [12] Sau khi đã thực hiện encode ta sẽ lưu nó trên vector database, quá trình lưu trữ database này sẽ được trình bày ở phần xây dựng back-end phía dưới
Hình 3.3: Ví dụ về một mẩu dữ liệu trong database Tiếp theo sẽ chuẩn bị dữ liệu gồm 100+ câu hỏi thường gặp kèm câu trả lời của sinh viên , để có được dữ liệu này không phải là khó nhưng sẽ cần một chút kiên trì Cụ thể những câu hỏi này phải đáp ứng yêu cầu là nó phải có đáp án nằm trong dữ liệu trong cơ sở dữ liệu mà chúng ta đã chuẩn bị phía bên trên Việc đánh nhãn thủ công là không thể tránh khỏi tuy nhiên có một hướng tiếp cận tối ưu hơn đang nổi lên gần đây là ta sẽ tận dụng sức mạnh của ChatGPT để làm điều đó, tăng cường dữ liệu (data augmentation) Cụ thể ta sẽ cắt từng mục trong sổ tay sinh viên để đưa vào ChatGPT giúp ta sinh ra câu hỏi kèm câu trả lời mà ta cần
Hình 3.4: Sử dụng ChatGPT để tăng cường dữ liệu (Câu hỏi)
Hình 3.5: Sử dụng ChatGPT để tăng cường dữ liệu (Trả lời) Nhờ công cụ này việc chỉnh sửa thủ công trên dữ liệu trở nên nhẹ nhàng hơn, nhưng dữ liệu mà ChatGPT sinh ra cũng sẽ có những khuyết điểm như đôi lúc sẽ có những câu hỏi mặc dù có tồn tại trong ngữ cảnh văn bản nhưng lại không có nhiều ý nghĩa cho sinh viên nên ta cũng sẽ loại bỏ bớt đi hoặc những câu hỏi không đúng trọng tâm của văn bản mà ta phải nhập thủ công thêm vào
Hình 3.6: Mô tả cấu trúc dữ liệu 146 câu hỏi đáp sinh viên Tổng cộng ta sẽ có 146 câu hỏi tất cả Việc đánh nhãn dữ liệu tốn gần như phần lớn thời gian nhưng cũng là một trải nghiệm thú vị giúp ta hiểu hơn về quá trình này Đối với dữ liệu Wikipedia sẽ có một lớp Wikipedia Retriever trong Langchain giúp ta thực hiện việc truy xuất dữ liệu tự động cho nên việc tích hợp lớp này song song với dữ liệu NTTU vô cũng dễ dàng
Bộ dữ liệu vilm/OpenOrca-Viet là một bộ bao gồm hơn 100.000 câu hỏi đáp kèm ngữ cảnh đã được làm sạch từ tước, do đó ta chỉ cần thực hiện gộp nội dung, cắt giới hạn và vector hoá mà thôi Bộ dữ liệu có cấu trúc như sau:
Hình 3.7: Mô tả dữ liệu vilm/OpenOrca-Viet
Trong bộ này ta sẽ chỉ cắt ra 10.000 mẫu để sử dụng, bởi vì ở đây ta chỉ thực hiện tinh chỉnh, chi tiết sẽ được giải thích ở phần lựa chọn mô hình phía dưới Từng mẫu của dữ liệu sẽ được gộp lại thành một cấu trúc hỏi đáp như sau:
Hình 3.8: Mô tả việc gộp dữ liệu thành cấu trúc hỏi đáp
Do đầu vào khi huấn luyện mô hình là một đoạn văn bản, đối với mô hình ngôn ngữ cho trả lời câu hỏi, việc định cấu trúc hỏi đáp đầu vào là bắt buộc, điều này sẽ giúp mô hình có thể hiểu được đâu là ngữ cảnh, đâu là câu hỏi và câu trả lời sẽ được bố trí như thế nào Giúp đầu ra chặt chẽ đồng thời sẽ dễ xử lý khi trích xuất câu trả lời về sau Sau khi đã tái cấu trúc ta sẽ tiến hành dùng tokenizer để vector hoá các đoạn văn bản này sang số Ta sẽ dùng tokenizer đi kèm với mô hình ta sử dụng để chuyển đổi, chi tiết mô hình sẽ được trình bày ở phần sau Ta cũng sẽ thực hiện cắt dữ liệu cho việc kiểm tra đánh giá trong quá trình training, dữ liệu sẽ được chia theo tỉ lệ 99/1 với 99% dùng để training và 1% dùng để test, sở dĩ ta chia như vậy vì khác với mô hình học máy khác, mô hình ngôn ngữ có đặc thù là cần dữ liệu huấn luyện lớn nên thường sẽ được chia ở tập test khoảng 10%, 1% hoặc 0.1%, với lại từ 100 mẫu trở nên là quá đủ cho việc đánh giá mô hình Vậy là dữ liệu đã sẵn sàng, tiếp theo ta sẽ tiến hành khám phá một số thông tin về dữ liệu trước khi lựa chọn và huấn luyện mô hình
Việc phân tích dữ liệu sẽ giúp ta có thể hiểu được dữ liệu nhiều hơn qua những góc nhìn khác nhau
Phân tích trên dữ liệu Sổ Tay Sinh Viên 2023
Thử tiến hành phân tích dữ liệu sổ tay sinh viên, ta thu được một số thống kê thú vị như sau:
41 Hình 3.9: Top 20 từ vựng có tần suất xuất hiện cao nhất
Hình 3.10: Top 20 cặp từ vựng (bigram) có tần suất xuất hiện cao nhất
Hình 3.11: Top 20 bộ ba từ vựng (trigram) có tần suất xuất hiện cao nhất
Dữ liệu trên bộ câu hỏi đáp là dữ liệu sinh nên ta sẽ không phân tích trên dữ liệu này Vậy là việc chuẩn bị dữ liệu đã xong ta sẽ tiến hành lựa chọn mô hình và xây dựng lõi hệ thống hỏi đáp.
Xây dựng lõi back-end
Ở phần này sẽ đề cập đến việc xây dựng lõi cho ứng dụng bao gồm từ việc xây dựng vector database, truy xuất dữ liệu, hệ thống API, mô hình ngôn ngữ lớn Cơ chế hoạt động ở phía server Đối với backend ta sẽ cần thiết kế 2 module chính là Langchain RAG để xử lý tác vụ hỏi đáp và FastAPI để tương tác với người dùng ở giao diện website front-end Từ câu hỏi người dùng sẽ được đi qua lớp embedding rồi đưa qua retriever để tìm tài liệu liên quan Tại phía website của người dùng sẽ có một tùy chọn tài liệu tham khảo cung cấp 2 lựa chọn là “Bách khoa toàn thư Wikipedia” và “Trường đại học Nguyễn Tất Thành” Người dùng sẽ chọn nguồn từ trường thì phía backend sẽ dùng retriever Qdrant để tìm kiếm và ngược lại thì sẽ dùng retriever Wikipedia được cung cấp sẵn bởi Langchain để truy xuất từ Internet Cụ thể sẽ có sơ đồ như sau:
Hình 3.12: : Sơ đồ hoạt động của backend
Ta sẽ tiến hành đi vào chi tiết cách xây dựng các phần của hệ thống này Bắt đầu từ việc xây dựng vector database trước
Bên cạnh các công nghệ vector database đang nổi như Weaviate, Chroma và FAISS thì Qdrant là một công nghệ mã nguồn mở tuyệt vời khi có thể triển khai dễ dàng trên môi trường Docker chỉ với 1 dòng lệnh và quan trọng hơn hết là đội ngũ phát triển cung cấp cloud miễn phí 1GB lưu trữ vĩnh viễn cho database, một con số quá dư dả cho việc lưu trữ dữ liệu văn bản
Công nghệ này được viết bằng Rust, cho phép tìm kiếm liên quan thông qua vector embedding và model dùng để tạo ra các embedding này có thể được tích hợp thông qua kho mô hình khổng lồ của Huggingface, việc kết nối và cài đặt vô cùng đơn giản như việc thực hiện setup một server non-SQL, khi setup trên cloud ta sẽ cần lưu ý 2 giá trị quan trọng đó chính là Endpoint URL và API Key của để truy cập vào clusters
Hình 3.14: Cấu hình Qdrant Vector Database Một cluster giống như một table trong SQL, ta cần lưu lại 2 cấu hình này để có thể truy cập vào thực hiện CRUD (Create – Read – Update - Delete) trên cluster thông qua Qdrant
Client Library được tích hợp trong Langchain Cuối cùng ta sẽ tạo một file Jupyter Notebook trên Google Colab tên VECTOR_DATABASE_CREATE.ipynb để thực hiện việc đẩy toàn bộ các chunks của sổ tay sinh viên đã xử lý và encode thông qua model embedding mã đã đề cập trước đó là sentence-transformers/paraphrase-multilingual- mpnet-base-v2 lên cluster Lúc này ta đã có thể thực hiện truy xuất theo mức độ liên quan trên dữ liệu database như một Retriver, tuy nhiên nếu dừng lại ở đây mô hình sẽ gặp hiện tượng đôi lúc sẽ không lấy được đúng nội dung cần tìm vì sự phân tán quá lớn của dữ liệu
Ta sẽ cần áp dụng một số kĩ thuật Retriver nâng cao để đảm bảo hệ thống luôn lấy ra được đoạn chunk liên quan nhất
45 Để tạo ra một Retriever có khả năng trích xuất được phần văn bản có liên quan nhất đến câu hỏi truy vấn ta cần thực hiện nó qua một bộ lọc bao gồm 2 lớp tìm kiếm có cấu trúc như sau:
Hình 3.15: Cấu trúc Retriver nâng cao kèm bộ lọc Rerank
Bộ lọc này sẽ áp dụng trên cả 2 miền là NTTU và miền Wikipedia Đầu tiên, ở bộ lọc đầu sẽ lọc ra top-k các văn bản liên quan nhất (ở đây top-k = 15) Tiếp tục, các văn bản liên quan nhất này sẽ được tái xếp hạng (re-rank) lại bằng một mô hình phân loại văn bản (text classification) khác Mô hình này sẽ tính toán điểm số tương đồng lại một lần nữa để đảm bảo rằng văn bản lấy ra là có điểm khác biệt thấp nhất đến câu truy vấn, đầu ra của re- ranker là một văn bản duy nhất Việc dùng một mô hình thứ 2 để kiểm chứng lại sẽ giúp tăng độ chính xác của hệ thống tìm kiếm thông tin, nó giống như việc kiểm chứng thông tin từ nhiều nguồn, việc này trong thực tế chứng minh rằng nó có hiệu quả trong hầu hết các trường hợp Và mô hình ta sử dụng ở đây làm re-ranker là amberoad/bert- multilingual-passage-reranking-msmarco, đây là một mô hình có hỗ trợ tiếng Việt và đạt được đánh giá tốt trên HuggingFace
Hình 3.16: Mô hình BERT Re-ranker
Trong thực tế có một số phương pháp được áp dụng phổ biến như kết hợp điểm số BM25 hoặc TF-IDF song song với việc tính toán qua embedding rồi nhập bảng xếp hạng lại làm một, nhưng sau khi kiểm nghiệm thực tế tôi nhận thấy rằng phương pháp bộ lọc qua 2 mô hình ngôn ngữ lớn sẽ có hiệu quả vượt trội hơn, theo suy đoán có lẽ vì nếu tính độ liên quan theo tần suất xuất hiện của từ vựng thì sẽ không hiệu quả bằng việc tính toán dựa trên vector đặc trưng, thứ vốn biểu diễn về mặt ngữ nghĩa cho từ và đoạn văn đó Phương pháp này sẽ tốn nhiều tài nguyên tính toán hơn tuy nhiên bù lại kết quả truy xuất sẽ cải thiện đáng kể Để có thể tích hợp được lớp re-ranker này trên Langchain ta cần viết thêm một lớp Custom Retriever kế thừa lớp RetrieverVectorStore để có thể nhúng vào retriever của 2 miền data NTTU và Wikipedia Vậy là chúng ta đã xong việc xây dựng hệ thống truy xuất thông tin từ truy vấn, tiếp theo ta sẽ tiến hành lựa chọn pretrained model cho mô hình ngôn ngữ.
Lựa chọn mô hình ngôn ngữ lớn
Ở đề tài này sẽ huấn luyện một mô hình ngôn ngữ rồi sẽ so sánh với 2 mô hình ngôn ngữ lớn trên Tiếng Việt khác được đánh giá là tốt ngay tại thời điểm hiện tại, thời điểm bài báo cáo này được viết Dựa trên bảng so sánh mới nhất của paper PhoGPT (PhởGPT) [15] ta có bảng so sánh performance như sau:
Hình 3.17: Bảng đánh giá các LLM Tiếng Việt dựa trên các task bằng con người
Hai mô hình ta sẽ lấy ra để so sánh là vilm/vietcuna-7b-v3 (7 tỉ tham số) và vinai/PhoGPT-
7B5-Instruct (7,5 tỉ tham số) đây là các pretrained model được huấn luyện và tinh chỉnh trên Tiếng Việt dựa trên mô hình BLOOMZ [13], cả ba mô hình này sử dụng kiến trúc GPT-2 để làm lõi chính sau đó được huấn luyện trên tập dữ liệu đa ngôn ngữ, mô hình còn lại như URA-LLaMa và vietcuna-3b-v2 có độ chính xác không cao nên ta sẽ không dùng để so sánh Các mô hình này đều không quá lớn và cũng không quá nhỏ rất phù hợp để thực hiện nghiên cứu sau khi cân nhắc các điều kiện về phần cứng và chi phí trong phạm vi đề tài
Hình 3.18: Mô hình vilm/vietcuna-7b-v3 trên HuggingFace
Hình 3.19: Mô hình vilm/PhoGPT-7B5-Instruct trên HuggingFace
Ta sẽ không thực hiện huấn luyện (training) hay tinh chỉnh (fine-tuning) các mô hình này trên dữ liệu sổ tay sinh viên mà sẽ sử dụng trực tiếp nó để làm một Generator Lý do là vì một hệ thống hỏi đáp mà ta đang xây dựng là một hệ thống Tăng cường sinh nội dung thông qua truy xuất (Retrieval Augmented Generation - RAG) với mục tiêu tạo ra một hệ thống không cần qua bước huấn luyện nhưng vẫn cho ra câu trả lời dựa trên kho tri thức đã cung cấp, ta có thể hiểu đơn giản thay vì cứ có dữ liệu tri thức mới lại cho mô hình training thì sẽ rất tốn kém tài nguyên, thì với RAG ta chỉ cần cập nhật database của nó là xong, hệ thống sẽ tự truy cập database rồi đưa ra tài liệu liên quan làm đầu vào kèm theo câu hỏi cho mô hình ngôn ngữ lớn rồi đưa ra câu trả lời, hệ thống này đánh mạnh vào khả năng one-shot learning của mô hình dựa trên ngữ cảnh của nó, hay nói cách khác là mô hình sẽ cố gắng đưa ra câu trả lời dựa trên ngữ cảnh input đầu vào thay vì dựa trên xác suất của các từ Với lại việc huấn luyện trên một dữ liệu riêng biệt có khả năng mô hình sẽ bị hiện tượng quá khớp xảy ra nếu dữ liệu không đủ lượng data cần thiết (trung bình cần 100.000 mẫu để huấn luyện được một mô hình ngôn ngữ tốt từ đầu) và tại đây ta có khoảng một trăm mẫu thì thật sự không đủ để thực hiện huấn luyện mô hình và chúng ta cũng không cần thiết để thực hiện bước fine-tuning này
Thay vào đó chiến lược đặt ra ở đây là ta sẽ thực hiện fine-tuining một mô hình đã tốt sẵn trên Tiếng Anh trên một bộ data hỏi đáp chung chung khác trên Tiếng Việt và mô hình mà ta lựa chọn ở đây có tên là HuggingFaceH4/zephyr-7b-beta (với 7 tỉ tham số) mô hình này đã đánh bại Llama-2-70b-chat (với 70 tỉ tham số) của Facebook trong tác vụ hỏi đáp [19]
Hình 3.20: Hiệu năng mô hình Zephyr-7b-beta
Bởi vì ta chỉ tinh chỉnh và không phải training lại từ đầu nên ta chỉ cần lấy mức 10% trong
100.000 mẫu dữ liệu cần thiết, do đó ở đây sẽ lấy 10.000 mẫu phục vụ cho quá trình huấn luyện tinh chỉnh Mô hình mới này ta sẽ đặt tên là vietzephyr-7b
Việc tự training một mô hình ngôn ngữ 7 tỷ tham số rồi so sánh nó với 2 mô hình ngôn ngữ khác được coi là tốt nhất trên Tiếng Việt hiện tại là một thách thức to lớn khi tốn kém chi phí (phải thuê GPU vì phiên bản miễn phí của Google Colab không đủ lượng tài nguyên cần thiết để huấn luyện) và đầy rủi ro bởi vì khả năng cao mô hình ta xây dựng sẽ không thể đánh bại những mô hình được các tập đoàn tiềm lực dồi dào như VinAI và FPT Do đó ta sẽ không cứng nhắc trong việc bắt buộc phải sử dụng mô hình tự huấn luyện cho sản phẩm đầu cuối, ta sẽ lựa ra mô hình tốt nhất qua đánh giá để sử dụng Ngoài ra, việc sử dụng một mô hình tốt trên thế giới cho Tiếng Anh để thử nghiệm cũng sẽ cho ta những góc nhìn thú vị nhất về quá trình huấn luyện mô hình này cho mục đích nghiên cứu đề tài
3.4.1 Lượng tử hóa mô hình
Nhằm tăng tốc quá trình inference mô hình sẽ được lượng tử hóa theo phương pháp AWQ đã được nêu ở phần trước Trong lập trình ta sẽ dùng thư viện AutoAWQ để thực hiện chuyển đổi vilm/vietcuna-7b-v3 xuống còn 4 bit với group_size8 Để tiện cho việc sử dụng sau này cũng như đóng góp cho cộng đồng, ta sẽ lưu mô hình lượng tử hóa trên Huggingface với tên phatjk/vietcuna-7b-v3-AWQ Sở dĩ ta chỉ lựa chọn lượng tử hoá mô hình này vì sau khi thực nghiệm qua đánh giá của con người mô hình vietcuna-7b-v3 có khả năng trả lời tốt hơn so với PhoGPT-7B5-Instruct mặc dù điểm số trên bản đánh giá cho thấy PhoGPT vượt trội, chi tiết các đánh giá này sẽ được trình bày ở phần cuối thực nghiệm Đây là bảng so sánh mô hình trước và sau khi lượng tử: vilm/vietcuna-7b-v3
(Model Gốc) phatjk/vietcuna-7b-v3-AWQ
Bảng 3.1: So sánh trước và sau khi lượng tử hoá vietcuna-7b-v3
Như ta thấy việc lượng tử hóa đã giúp cho mô hình nhẹ đi ~ 51.2% so với mô hình gốc Đối với mô hình vietzephyr-7b của chúng ta cũng sẽ lượng tử hoá, tuy nhiên sẽ dùng phương pháp cắt hoàn toàn bit từ 16 bit xuống 8 bit để tối ưu hoá thời gian training vì nguồn dữ liệu khá lớn Ta có kết quả lượng tử hoá như sau:
Bảng 3.2: So sánh trước và sau khi lượng tử hoá zephyr-7b-beta
Mô hình giảm đi 50% so với mô hình gốc, sau khi tối ưu ta sẽ tiếng hành training mô hình
Ta sẽ tiến hành training mô hình thông qua một Adapter bằng phương pháp LoRA, điều này có nghĩa là gì?
Nói về Adapter trước thì mô hình sẽ không thực hiện huấn luyện và cập nhật trọng số trực tiếp trên nó mà lúc này mô hình gốc sẽ đóng băng, các chỉnh sửa thay đổi sẽ được lưu vào một file riêng gọi là Adapter, file này chỉ chứa những sửa đổi trên mô hình gốc do đó nó sẽ nhẹ hơn rất nhiều, chỉ khoảng vài đến vài chục MB Khi cần sử dụng ta chỉ cần load mô hình gốc và kèm theo file adapter này ta sẽ có được mô hình mà ta đã huấn luyện trước đó Apdapter sẽ giúp nhanh chóng và tối ưu trong việc lưu trữ nhiều phiên bản của mô hình, nhất là khi tải về một phiên bản mô hình tinh chỉnh từ GPU hoạt động trên cloud
Còn về phía LoRA, đây là một phương pháp huấn luyện mô hình đi kèm Adapter thông qua việc phân rã ma trận trọng số của nó Thay vì thực hiện training trên ma trận trọng số
𝑾 𝒅×𝒌 thì ta sẽ thực hiện phân rã ma trận này thành 2 ma trận con nhỏ hơn của nó rồi cập nhật trọng số trên 2 ma trận con 𝑨 𝒅×𝒓 và 𝑩 𝒓×𝒌 này với 𝒓 < 𝐦𝐢𝐧 (𝒅, 𝒌) là hạng mà ta có thể cài đặt Chi tiết về phương pháp và công thức toán có thể tìm thấy tại [20] Ta sẽ thực hiện huấn luyện trên phần cứng là NVIDIA A6000 (48 GB VRAM) Các siêu tham số
(hyper-parameter) cài đặt cho huấn luyện được mô tả như sau:
51 batch-size 24 gradient-accumulation- steps
2 learning_rate 2e-4 (= 0.0002) lora_r 8 lora_alpha 16 lora_dropout 0.05
Bảng 3.3: Siêu tham số cài đặt cho training
Giải thích: Với thông số epochs ta sẽ chỉ lặp qua 10.000 điểm dữ liệu một lần duy nhất, batch-size là số lượng điểm dữ liệu được học trong một lần cặp nhật, việc học các đặc trưng của một tập các lô (batch) cập nhật gradient sẽ giúp mô hình tăng tốc độ huấn luyện và tận dụng được hết khả năng xử GPU, với NVIDIA A6000 thì 24 là lựa chọn hợp lý giúp chạy tối đa công suất thiết bị Gradient-accumulation-steps giúp khi huấn luyện sẽ cập nhật gradient mỗi 2 batch một lần thay vì cập nhật ở mỗi batch giúp hạn chế khả năng bị quá tải bộ nhớ và giảm chi phí tính toán khi cập nhật gradient Ta có learning_rate là tốc độ học để tham số thông dụng là 2e-4 Giá trị lora_r là hạng phân rã ma trận như đã đề cập ở trên, lora_alpha là hằng số của lora_r dùng để tinh chỉnh learning_rate thông thường phải lớn hơn hạng lora_r và thường đặt từ 16 đến 48 tại đây ta set số nhỏ nhất là 16 Drop-out sẽ là tỉ lệ ngẫu nhiên xoá mất các trọng số để tránh hiện tượng quá khớp (overfitting) khi huấn luyện mô hình, 5% trên toàn bộ mô hình là một con số hợp lý
Hình 3.22: Giá trị loss trên tập test trước khi huấn luyện
Quá trình huấn luyện: Mô hình đã giảm loss từ 1.4 xuống còn 0.92 sau khi training qua
1 epoch với thời gian là 2 tiếng 22 phút, ta có tham số loss ở các steps như sau:
Hình 3.23: Tham số loss tại các steps khi training
Hình 3.24: Biểu đồ về sự suy giảm loss của mô hình khi huấn luyện
Ta thấy rằng không có hiện tượng quá khớp diễn ra khi cả loss trên tập train và tập test luôn giảm đều theo thời gian, như vậy việc huấn luyện mô hình có hiệu quả Thử hỏi một câu đơn giản để xem khả năng trả lời của mô hình, có được kết quả như sau:
Hình 3.25: Test một câu hỏi nhỏ
Dựa trên kết quả ta thấy rằng, gần như ta đã thành công trong việc huấn luyện một mô hình tiếng Anh sang tiếng Việt, tuy nhiên để chắc chắn mô hình có hiệu quả ta sẽ cần một bước đánh giá, ta sẽ tiếp tục phần đánh giá kết quả này tại chương 4 Ta cũng sẽ lưu mô hình này lại trên Huggingface với tên phatjk/vietzephyr-7b-lora-8bit để sử dụng về sau
3.4.3 Triển khai mô hình Ở đây ta sẽ triển khai mô hình trên một server riêng có hỗ trợ phần cứng GPU Tesla T4, công nghệ triển khai mô hình là vLLM
Xây dựng front-end
Ta sẽ sử dụng ReactJS và TailwindCSS trên môi trường phát triển (development environment) của Vite để xây dựng một trang web hỏi đáp Chatbot có giao diện gồm 4 trang là: Trang Chủ, Trò chuyện, FAQs và Báo lỗi/Góp ý Website xây dựng được sẽ có thiết kế như sau:
Hình 3.27: Sơ đồ thiết kế giao diện front-end
Ta sẽ thiết kế một website tiêu chuẩn như trên với trang Trò chuyện sẽ dùng fetch Javascript đơn thuần để xử lý API ở phía back-end mà ta đã xây dựng trước đó Trang Góp ý/Báo lỗi ta sẽ dùng thư viện EmailJS để từ front-end sử dụng server của Google để thiết đặt một địa chỉ email mặc định, gửi trực tiếp góp ý của người dùng vào email đó Như vậy, quản trị viên (admin) sẽ thu được những góp ý của người dùng rồi cải thiện sản phẩm
Một số hình ảnh về website thiết kế:
55 Hình 3.28: Giao diện trang chủ NTTU Chatbot
Hình 3.29: Giao diện trò chuyện
Hình 3.31: Giao diện trang phản hồi góp ý
Tại trang FAQs và Trò chuyện ta sẽ giả định một số câu hỏi thường gặp của người dùng và kết hợp một số câu hỏi được lấy từ tập dữ liệu được sinh ra từ ChatGPT để làm gợi ý Vậy là gần như đã hoàn thành phần xây dựng hệ thống, tiếp theo ta sẽ tiến hành thực nghiệm, chạy thử hệ thống và đánh giá độ chính xác của hệ thống hỏi đáp này trên tập dữ liệu 100+ câu hỏi của sinh viên Toàn bộ mã nguồn sẽ được đính kèm ở cuối bài báo cáo này
Thực nghiệm và đánh giá
Phương pháp đánh giá
*Phương pháp BERT-Score Đối với một mô hình hỏi đáp, một câu trả lời đúng và chính xác có thể được biểu diễn theo nhiều cách khác nhau, nên việc dùng các phương pháp đánh giá, so sánh đòi hỏi câu trả lời phải trùng khớp hoàn toàn với nhãn sẽ là không phù hợp Để đánh giá hệ thống này ta sẽ dùng phương pháp đánh giá dựa trên điểm BERT (BERT Score) theo nghiên cứu
BERTScore: Evaluating Text Generation with BERT [14]
Hình 4.1: Mô tả phương pháp BERTScore
Phương pháp đánh giá được mô tả như sau: Giả sử ta có 2 câu đầu vào được xem như 2 chuỗi giá trị liên tục với một là câu nhãn 𝑥 = ⟨𝑥 1 , , 𝑥 𝑘 ⟩ với độ dài 𝑘 và câu dự đoán 𝑥̂ = ⟨𝑥̂ 1 , , 𝑥̂ 𝑚 ⟩ với độ dài 𝑚 Ta sẽ thực hiện embedding 2 câu qua model BERT thu được 2 vector embedding là ⟨x 𝟏 , … ,x 𝒌 ⟩ và ⟨x̂ 𝟏 , … ,x̂ 𝒎 ⟩ Tại đây các biểu diễn của từng từ sẽ được tính toán thông qua mô hình BERT (Transformer encoder) bằng cách liên tục áp dụng các phép biến đổi self-attention và phi tuyến tính theo kiểu luân phiên bên trong mô hình Việc chọn sử dụng BERT làm model embedding bởi vì nhiều nghiên cứu đã chứng minh rằng dùng BERT sẽ mang lại hiệu quả trong các nhiệm vụ NLP khác nhau, trong đó có thể thực hiện đo lường độ tương tự của các từ để tìm ra mức độ liên quan giữa chúng trên hệ trục toạ độ của không gian nhiều chiều Ví dụ, ta có thể đo lường độ tương tự giữa từ nhãn 𝑥 𝑖 và từ dự đoán 𝑥̂ 𝑗 bằng công thức cosine với 2 vector embedding của nó như sau cos(θ) = x 𝑖 ⊤ x̂ 𝑗
58 Đối với BERTScore việc tính toán 3 chỉ số Recall, Precision và F1 score trên 2 câu được thực hiện bằng cách so khớp (matching) từng token trong câu nhãn 𝑥 vào một token trong câu dự đoán 𝑥̂ để tính toán recall và ngược lại so khớp từng token trong câu 𝑥̂ vào một token trong câu 𝑥 để tính toán precision Rồi từ recall và precision ta sẽ tính được F1 score Tại đây sẽ sử dụng so khớp tham lam (greedy matching) để tối đa hoá điểm số tính toán tương đồng nhằm đảm bảo rằng mỗi token sẽ được so khớp với token mà chúng có mức độ tương đồng cao nhất
𝑃 𝐵𝐸𝑅𝑇 + 𝑅 𝐵𝐸𝑅𝑇 Ngoài ra, ta có thể tuỳ chọn tính thêm 𝑅 𝐵𝐸𝑅𝑇 (𝑖𝑑𝑓) bằng cách kết hợp với phương pháp tìm kiếm IDF mà đã trình bày ở trên để tính, việc này gọi là tính trọng số quan trọng
(importance weighting) Mặc dù việc kết hợp với IDF này có thể sẽ tạo mối tương quan về điểm số đánh giá gần hơn với mức độ đánh giá của con người Tuy nhiên, nếu câu nhãn quá nhỏ có thể điểm IDF sẽ trở nên không chính xác/không hợp lệ vì vậy ta sẽ không sử dụng nó trong trường hợp này mà chỉ sử dụng 3 công thức đã nêu trên để tính toán
*Phương pháp đánh giá chủ quan: Ở phương pháp này sẽ dùng bộ câu hỏi thường gặp để đánh giá câu trả lời thủ công qua góc nhìn của con người, bởi phương pháp BERT Score là chưa đủ để có thể chứng minh là hệ thống trả lời tốt, việc dùng con người để đánh giá thật sự có hiệu quả dẫn chứng là ở paper PhoGPT [15] họ cũng sử dụng con người để đánh giá khả năng của mô hình trên các tác vụ dựa trên thang điểm số từ 0 tới 5 Tại mô hình này ta cũng sẽ làm tương tự nhưng vì nguồn lực con người có hạn nên ta sẽ lọc ra khoảng 15 câu hỏi thường gặp nhất để test và so sánh kết quả
Kết quả thực nghiệm
*Phương pháp BERT Score: Để tính toán 3 độ đo là Precision, Recall và F1 Score ta sẽ sử dụng thư viện bert_score, thư viện này sử dụng một model BERT đa ngôn ngữ với 104 ngôn ngữ được huấn luyện có hỗ trợ Tiếng Việt (BERT-Base, Multilingual Cased: 104 languages, 12-layer, 768- hidden, 12-heads, 110M parameters) Ta sẽ tiến hành cho chạy đánh giá trên bộ data 100+ câu hỏi thường gặp kèm câu trả lời của sinh viên với 2 mô hình khác nhau thu được kết quả như sau:
Kết quả hệ thống chạy mô hình vietcuna-7b-v3-AWQ
Bảng 4.1: Kết quả hệ thống chạy mô hình vietcuna-7b-v3-AWQ
Hình 4.2: Biểu đồ Histogram sự phân bố Precision, Recall và F1 (vietcuna-7b-v3-AWQ)
Kết quả hệ thống chạy mô hình vietcuna-7b-v3
Bảng 4.2: Kết quả hệ thống chạy mô hình vietcuna-7b-v3
Hình 4.3: Biểu đồ Histogram sự phân bố Precision, Recall và F1 (vietcuna-7b-v3)
Kết quả hệ thống chạy mô hình PhoGPT-7B5-Instruct
Bảng 4.3: Kết quả hệ thống chạy mô hình PhoGPT-7B5-Instruct
Hình 4.4: Biểu đồ Histogram sự phân bố Precision, Recall và F1 (PhoGPT-7B5-Instruct)
Kết quả hệ thống chạy mô hình vietzephyr-7b-8bit-lora
Bảng 4.4: Kết quả hệ thống chạy mô hình vietzephyr-7b-8bit-lora
Hình 4.5: Biểu đồ Histogram sự phân bố Precision, Recall và F1 (vietzephyr-7b-8bit- lora)
*Phương pháp dùng con người đánh giá:
Ta thấy rằng điểm số BERT Score giữa mô hình vietcuna-7b-v3 đã lượng tử hoá AWQ với phiên bản gốc của nó không có sự khác biệt quá nhiều, chứng tỏ rằng phương pháp lượng tử hoá này thật sự có hiệu quả khi giảm được kích thước mô hình một nửa nhưng vẫn giữ được độ chính xác vốn có của nó Vì vậy tại phương pháp đánh giá con người ta sẽ sử dụng mô hình AWQ này để so sánh luôn với PhoGPT-7B5 và Vietzephyr-7b-8bit-lora để tiết kiệm chi phí thuê GPU Như đã nói ở trên vì nguồn lực con người có hạn ta sẽ sử dụng 15 câu hỏi thông dụng nhất để đánh giá độ hiệu quả của 2 mô hình này Điểm số đánh giá từ [0-5], để khách quan nhất mỗi câu sẽ được thử 5 lần trước khi chấm kết quả Toàn bộ câu trả lời và kết quả đánh giá sẽ được đính kèm trong mã nguồn phía cuối bài báo cáo này
STT Câu hỏi kiểm tra Vietcuna PhoGPT Vietzephyr
1 Điều kiện nhận học bổng? 4.5 4 4
2 Bao nhiêu điểm thì học lực Xuất sắc? 5 5 3.5
3 Bao nhiêu điểm thì học lực Giỏi? 5 5 3.5
4 Bao nhiêu điểm thì học lực Khá? 3.5 1 2.5
5 Điều kiện thực tập tốt nghiệp là gì? 5 3.5 1
6 Học phần đã đăng ký có trạng thái N* là gì?
7 Điều kiện nào để được xét chuyển trường? 5 5 5
8 Nếu điểm thi kết thúc học phần < 4 thì như thế nào?
9 Phí cấp lại thẻ sinh viên khi bị mất là bao nhiêu?
10 Để đạt loại xuất sắc điểm rèn luyện cần bao nhiêu điểm?
11 Để đạt loại tốt điểm rèn luyện cần bao nhiêu điểm?
12 Nếu sinh viên không đạt ở một học phần, phải làm gì?
13 Lớp trưởng được cấp bao nhiêu tiền? 5 5 5
14 Lớp phó được cấp bao nhiêu tiền? 5 5 4
15 Bao nhiêu điểm thì bị rớt? 3.5 5 3.5 Điểm trung bình 4.8 4.15 3.6
Bảng 4.5: Tính điểm theo đánh giá con người qua 15 câu hỏi trên 2 mô hình
Hình 4.6: Biểu đồ cột trực quan điểm số con người đánh giá
Đánh giá kết quả
Ta tổng hợp lại kết quả của cả 2 mô hình trên rồi đánh giá như sau:
Precision Recall F1 Score vietcuna-7b-v3-AWQ 0.734 0.784 0.756 vietcuna-7b-v3 0.729 0.787 0.755
PhoGPT-7B5-Instruct 0.745 0.790 0.766 vietzephyr-7b-8bit-lora 0.683 0.764 0.720
Bảng 4.6: Kết quả BERT Score
Nhận xét: Ta nhận thấy rằng kết quả không có sự chênh lệch nhiều trên cả 3 mô hình khi đánh giá trên BERT Score Tuy nhiên ta có thể thấy rõ trên điểm số F1 rằng mô hình lượng tử hoá của vietcuna gần như không sụt giảm độ chính xác so với phiên bản gốc của nó và ta cũng thấy rằng PhoGPT có kết quả tốt hơn đáng kể bởi vì số lượng tham số nó lớn hơn
Mô hình mà chúng ta training có điểm số thấp nhất trên cả 3 chỉ số đánh giá
*Phương pháp dùng con người đánh giá:
Ta có điểm số đánh giá như sau:
Mô hình sử dụng Điểm đánh giá dựa trên con người vietcuna-7b-v3-AWQ 4.8
PhoGPT-7B5-Instruct 4.1 vietzephyr-7b-8bit-lora 3.6
Bảng 4.7: Kết quả dùng con người đánh giá
Nhận xét: Ta nhận thấy mô hình vietcuna tốt hơn khi đứng dưới góc nhìn của con người, đưa ra thông tin chuẩn xác và có hiếm bị hiện tượng ảo giác (hallucination), là hiện tượng mô hình trả lời chung chung mà không tuân theo ngữ cảnh được cấp Mô hình mà chúng ta huấn luyện mặc dù trả lời đúng trong một số trường hợp tuy nhiên hiện tượng ảo giác vẫn xảy ra khi mô hình luôn đưa vào một số thông tin sai với ngữ cảnh Vì như đã nói ban đầu là chúng ta sẽ không cứng nhắc trong việc phải lựa chọn mô hình ta huấn luyện do đó mô hình vietcuna sẽ là một lựa chọn phù hợp ở hệ thống này