ตรวจสอบการสะกดคำด้วย NHunspell (.Net Framework Library)

สำหรับแอปพลิเคชันที่มีส่วนค้นหาแล้วนั้น หนีไม่พ้นคำถามจากผู้ใช้ว่า ถ้าสะกดคำผิดจะค้นเจอมั้ย (ก็ไม่เจอซิครับ) พร้อมยกตัวอย่างความสามารถในการแก้คำผิดของ Google, Bing ให้ฟัง สำหรับนักพัฒนาตัวคนเดียว หรือทีมงานเล็กๆ ที่ไม่สามารถใช้แนวทาง API แบบต้องมีค่าใช้จ่าย หรือ Machine Learning ที่ต้องใช้ความรู้เฉพาะด้าน ผมก็มี Library ขนาดเล็กที่อาศัยวิธีการทางสถิติ และไฟล์คลังคำศัพท์ (Dictionary) มาใช้งานไปก่อนครับ โดยได้ทำการทดสอบประสิทธิภาพเปรียบเทียบกับ PyThaiNLP, WeCantSpell.Hunspell มาแล้วทั้งในด้านความเร็ว และความถูกต้อง พบว่าดีที่สุด นั้นคือ NHunspell

ขั้นตอนการนำมาใช้งาน

ในตัวอย่าง เป็นการนำมาใช้งานร่วมกับ Console Application

1.เปิด Nuget Manager ด้วยการ คลิกขวาที่ชื่อโปรเจค เลือก Manage Nuget Packages

2.ค้นหา NHunspell เลือก Install

3.สร้างโฟลเดอร์สำหรับเก็บไฟล์ Dictionary โดยสามารถดาวส์โหลดได้จาก https://github.com/LibreOffice/dictionaries นำไปวางไว้ที่ [ProjectPath]/bin/Debug

4.สร้างโฟลเดอร์สำหรับเก็บไฟล์คำตัวอย่าง sentense_list.txt โดยมีบรรทัดละ 1 คำ เพื่อทำการโหลดข้อมูลเข้ามาให้ Library ประมวลผล และเก็บไฟล์ผลลัพธ์ไว้ที่ suggest_result.txt นำไปวางไว้ที่ [ProjectPath]/bin/Debug

5. จากนั้นก็เขียนโค้ดในไฟล์ Program.cs ดังนี้

using System;
using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using NHunspell;

namespace SpellCheckTest
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (var sr = new StreamReader("example_data/sentense_list.txt"))
                {
                    //อ่านรายการคำ
                    string searchterm = sr.ReadToEnd();
                    string[] searchtermArray = searchterm.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                    Console.WriteLine("Processing...");

                    using (var sw = new StreamWriter("example_data/suggest_result.txt"))
                    {
                        foreach (string sentense in searchtermArray)
                        {
                            string result = string.Empty;
                            var startTime = System.DateTime.Now.Ticks;

                            //ส่งคำให้ NHunspell ประมวลผล
                            result = SuggestNHunSpell(sentense);

                            var endTime = System.DateTime.Now.Ticks - startTime;
                            TimeSpan elapsedSpan = new TimeSpan(endTime);

                            //เขียนผลการตรวจสอบ และเวลาที่ใช้ลงในไฟล์ผลลัพธ์
                            sw.WriteLine(result);
                            sw.WriteLine(string.Format("{0}", elapsedSpan.TotalSeconds));
                            sw.WriteLine();
                            sw.Flush();
                        }
                    }

                    Console.WriteLine("Process Complete.");
                    Console.ReadKey();
                }
            }
            catch (IOException e)
            {
                Console.WriteLine("The file could not be read:");
                Console.WriteLine(e.Message);
                Console.ReadKey();
            }
        }

        /// <summary>
        /// NHunSpell
        /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        private static string SuggestNHunSpell(string sentence)
        {
            //ตรวจสอบว่าเป็นภาษาอังกฤษ หรือภาษาไทย
            bool IsEnglish = Regex.IsMatch(sentence.Replace(" ", string.Empty), "[a-zA-Z]");

            string dictPath = IsEnglish ? "dict/en_US.dic" : "dict/th_TH.dic";
            string affixPath = IsEnglish ? "dict/en_US.aff" : "dict/th_TH.aff";
            
            //โหลดไฟล์ Dict และ Affix 
            using (Hunspell hunspell = new Hunspell(affixPath, dictPath))
            {
                //ตรวจสอบว่าสะกดถูกหรือไม่
                if (!hunspell.Spell(sentence))
                {
                    List<string> suggestions = hunspell.Suggest(sentence);
                    if (suggestions.Count > 0)
                    {
                        //คืนค่า รายการคำที่น่าจะเป็นคำสะกดที่ถูกต้อง
                        return sentence + " : " + string.Join(",", suggestions);
                    }
                }
            }

            //หากตรวจสอบว่าสะกดถูกแล้ว บันทึกผลว่า Correct
            return sentence + ": Correct";
        }
    }
}

6.จากนั้นทำการ Run แบบ Debug จะปรากฎหน้าจอ Command Line แสดงข้อความ Processing… รอจนเห็นคำว่า Process Complete. แสดงว่าทำการประมวลผลเสร็จแล้ว

7.ผลลัพธ์จะถูกบันทึกลงในไฟล์ suggest_list.txt ดังรูป

ในตัวอย่างนี้ เป็นเพียงโปรเจคสำหรับทดสอบการเรียกใช้งาน และดูผลลัพธ์ของ Library เท่านั้น การนำไปใช้งานร่วมกับระบบยังต้องการ การประยุกต์ให้เหมาะสมกับแต่ละระบบ แต่ก็หวังว่าจะเป็นประโยชน์กับคนที่กำลังหาเครื่องมือที่ใช้ตรวจสอบการสะกดคำให้กับระบบของตัวเองอยู่ไม่มาก ก็น้อยครับ