[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"academy-blogs-th-1-1-all-golang-the-series-ep152-intro-to-vector-embeddings-go-all--*":3,"academy-blog-translations-j8rehtbpflwmsyv":87},{"data":4,"page":73,"perPage":73,"totalItems":73,"totalPages":73},[5],{"alt":6,"collectionId":7,"collectionName":8,"content":9,"cover_image":10,"cover_image_path":11,"created":12,"created_by":13,"expand":14,"id":81,"keywords":82,"locale":53,"published_at":83,"scheduled_at":69,"school_blog":77,"short_description":84,"status":75,"title":85,"updated":86,"updated_by":13,"slug":78,"views":80},"การเขียนโค้ด Go แปลงข้อความเป็นเวกเตอร์ด้วย OpenAI Embedding API","sclblg987654321","school_blog_translations","\u003Cp>ยินดีต้อนรับเข้าสู่ EP.152 ครับ! ในตอนที่แล้วเราคุยกันถึงคอนเซปต์ RAG ว่ามันคือการให้ AI เปิดหนังสือสอบ แต่คำถามสำคัญที่สาย Backend อย่างเราต้องคิดต่อคือ \u003Cstrong>\"เราจะค้นหาข้อมูลในหนังสือเล่มนั้นอย่างไร ให้เจอประโยคที่มีความหมายตรงกับคำถามของ User มากที่สุด?\"\u003C\u002Fstrong>\u003C\u002Fp>\u003Cp>ถ้าเราใช้คำสั่ง SQL แบบเดิมๆ อย่าง \u003Ccode>WHERE content LIKE '%ชำระเงิน%'\u003C\u002Fcode> แล้วเจอ User สายอินดี้ถามว่า \u003Cem>\"จ่ายตังค์ยังไง?\"\u003C\u002Fem> ระบบของเราจะควานหาเอกสารไม่เจอทันที เพราะคำว่า \"ชำระเงิน\" กับ \"จ่ายตังค์\" สะกดไม่เหมือนกันเลยสักตัวเดียว\u003C\u002Fp>\u003Cp>เพื่อแก้ปัญหานี้ โลกของ AI จึงสร้างสิ่งที่เรียกว่า Embeddings ขึ้นมา มันคือการแปลง \"ข้อความภาษาคน\" ให้กลายเป็น \"ชุดตัวเลข (Vectors)\" เพื่อให้คอมพิวเตอร์สามารถคำนวณและวัด \"ความหมาย\" ของคำได้อย่างแม่นยำ วันนี้เราจะมาเขียน Go จัดการสิ่งนี้กันครับ\u003C\u002Fp>\u003Ch2>Vector Embeddings คืออะไร?\u003C\u002Fh2>\u003Cp>\u003Cstrong>Embedding\u003C\u002Fstrong> คือการนำข้อความ (ไม่ว่าจะเป็นคำ ประโยค หรือทั้งบทความ) วิ่งผ่าน AI Model สำหรับถอดรหัสความหมายโดยเฉพาะ (เช่น \u003Ccode>text-embedding-3-small\u003C\u002Fcode> ของ OpenAI) เพื่อแปลงข้อความนั้นให้ออกมาเป็น Array ของตัวเลขทศนิยม (\u003Ccode>[]float32\u003C\u002Fcode>) ที่มีความยาวคงที่ เช่น 1,536 มิติ\u003C\u002Fp>\u003Cp>ความเจ๋งของมันคือ:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>คำที่ความหมายคล้ายกัน\u003C\u002Fstrong> เช่น \"แมว\" กับ \"ลูกแมว\" หรือ \"ชำระเงิน\" กับ \"จ่ายตังค์\" จะได้ชุดตัวเลขที่อยู่ใกล้กัน ในพิกัดมิติเชิงความหมาย\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>เปลี่ยนภาษาคนให้เป็นคณิตศาสตร์\u003C\u002Fstrong> คอมพิวเตอร์ไม่เข้าใจภาษาเรา แต่เข้าใจตัวเลข มันจึงสามารถนำตัวเลขเหล่านี้ไปคำนวณหาค่าระยะห่าง (เช่น Cosine Similarity) เพื่อบอกได้ทันทีว่าสองประโยคนี้คุยเรื่องเดียวกันหรือไม่\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>เขียน Go เรียกใช้งาน Embedding API\u003C\u002Fh2>\u003Cp>เราจะใช้คลังไลบรารี \u003Ccode>go-openai\u003C\u002Fcode> เจ้าเก่า ในการส่งข้อความไปแปลงเป็น Vector ครับ\u003C\u002Fp>\u003Cp>Go\u003C\u002Fp>\u003Cpre>\u003Ccode>package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com\u002Fsashabaranov\u002Fgo-openai\"\n)\n\nfunc main() {\n\t\u002F\u002F ดึง API Key จาก Environment Variable\n\tapiKey := os.Getenv(\"OPENAI_API_KEY\")\n\tif apiKey == \"\" {\n\t\tlog.Fatal(\"Embedding API Key is required\")\n\t}\n\n\tclient := openai.NewClient(apiKey)\n\n\t\u002F\u002F ข้อความที่เราต้องการแปลงความหมาย\n\tinputText := \"ฉันต้องการจ่ายเงินด้วยบัตรเครดิต\"\n\n\t\u002F\u002F 1. สร้าง Request สำหรับ Embedding\n\treq := openai.EmbeddingRequest{\n\t\tInput: []string{inputText},\n\t\tModel: openai.SmallEmbedding3Small, \u002F\u002F โมเดลยอดนิยม 1,536 มิติ ประหยัดและเร็วมาก\n\t}\n\n\t\u002F\u002F 2. ส่งข้อมูลไปแปลงที่ OpenAI API\n\tresp, err := client.CreateEmbeddings(context.Background(), req)\n\tif err != nil {\n\t\tlog.Fatalf(\"Embedding failed: %v\", err)\n\t}\n\n\t\u002F\u002F 3. ดึงผลลัพธ์ Vector ออกมา (Array of float32)\n\tvector := resp.Data[0].Embedding\n\n\tfmt.Printf(\"ข้อความ: '%s'\\n\", inputText)\n\tfmt.Printf(\"ขนาดของมิติ Vector (Dimensions): %d\\n\", len(vector))\n\tfmt.Printf(\"ตัวอย่างเลข 5 มิติแรก: %v\\n\", vector[:5])\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2>โครงสร้างข้อมูลเมื่อนำไปใช้งานจริง\u003C\u002Fh2>\u003Cp>ในระบบ RAG หลังจากที่เราได้ Vector ออกมาแล้ว เรามักจะเก็บมันไว้คู่กับข้อความต้นฉบับในรูปแบบ Struct เพื่อเตรียมเอาไปคำนวณเปรียบเทียบตอนที่ User พิมพ์ถามเข้ามา:\u003C\u002Fp>\u003Cp>Go\u003C\u002Fp>\u003Cpre>\u003Ccode>type DocumentChunk struct {\n\tID        string    `json:\"id\"`\n\tContent   string    `json:\"content\"`   \u002F\u002F ข้อความดิบ เช่น \"คู่มือการคืนสินค้าใน 7 วัน\"\n\tEmbedding []float32 `json:\"embedding\"` \u002F\u002F ตัวเลข 1,536 มิติที่ได้จาก API\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2>จุดเด่นของ Go ในงานทำ Data Embedding Pipeline\u003C\u002Fh2>\u003Cp>ถ้าคุณต้องทำระบบ RAG ขนาดใหญ่ขององค์กร คุณอาจต้องแปลงเอกสารนับแสนหน้าให้กลายเป็น Vector งานนี้จะกลายเป็นทั้ง I\u002FO Bound (ยิง API) และ Compute Bound (จัดการข้อมูล) พร้อมกัน ซึ่ง Go กินขาดในเรื่องนี้:\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>Goroutine Worker Pool:\u003C\u002Fstrong> เราสามารถใช้ Go แยกอ่านเอกสาร ทำการตัดแบ่งชิ้นส่วนข้อความ (Chunking) และสั่งยิงไปแปลง Embedding พร้อมกันหลายร้อยลูปได้แบบ Concurrent ช่วยย่นเวลาจากหลายชั่วโมงให้เหลือไม่กี่นาที\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>Memory Efficiency:\u003C\u002Fstrong> ข้อมูลประเภท \u003Ccode>[]float32\u003C\u002Fcode> จำนวนมหาศาลถ้าจัดการไม่ดี แรมของ Server จะเต็มไวมาก แต่การจัดการหน่วยความจำที่ต่ำและเสถียรของ Go ช่วยให้คุม Resource ได้อยู่หมัด\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>🎯 ท้าให้ลอง (Daily Mission)\u003C\u002Fh2>\u003Cp>ลองสร้างข้อความขึ้นมา 3 ประโยคในโค้ด Go ของคุณ:\u003C\u002Fp>\u003Col>\u003Cli>\u003Cp>\u003Cem>\"วิธีเปลี่ยนรหัสผ่านใหม่ทำอย่างไร\"\u003C\u002Fem>\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cem>\"ขั้นตอนการรีเซ็ตพาสเวิร์ด\"\u003C\u002Fem>\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cem>\"วันนี้ฝนตกหนักมากที่กรุงเทพ\"\u003C\u002Fem>\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Fol>\u003Cp>\u003Cstrong>การบ้าน:\u003C\u002Fstrong> ปรับโค้ดของคุณให้นำทั้ง 3 ประโยคนี้ไปแปลงเป็น Embedding พร้อมกัน จากนั้นลองเขียนฟังก์ชันลูปเพื่อสังเกตค่าตัวเลขดู หรือหากใครต้องการท้าทายตัวเอง ลองเขียนสูตรคำนวณหาค่าระยะห่างแบบง่ายๆ (เช่น Dot Product) ระหว่างข้อความที่ [1 กับ 2] และ [1 กับ 3] ดูครับว่า... คู่ไหนได้ตัวเลขที่ใกล้เคียงกันมากกว่ากัน?\u003C\u002Fp>\u003Ch2>❓ FAQ: คำถามที่พบบ่อยเกี่ยวกับ Embeddings\u003C\u002Fh2>\u003Ch3>ตัวเลข 1,536 มิติ (Dimensions) หมายความว่าอย่างไร?\u003C\u002Fh3>\u003Cp>เปรียบเหมือนการมองวัตถุในระบบพิกัด ถ้ากราฟ 2 มิติมีค่า (X, Y) โมเดล AI ก็จะสร้างกราฟ 1,536 มิติขึ้นมาเพื่อสับย่อยคุณลักษณะของความหมายคำ เช่น มิติความเป็นทางการ, มิติเกี่ยวกับสัตว์, มิติเกี่ยวกับการเงิน ยิ่งมิติตัวเลขเยอะ ยิ่งเก็บความละเอียดของความหมายได้ลึกขึ้นครับ\u003C\u002Fp>\u003Ch3>ถ้าส่งประโยคภาษาไทย กับภาษาอังกฤษที่ความหมายเดียวกัน ตัวเลขจะใกล้กันไหม?\u003C\u002Fh3>\u003Cp>ใกล้กันครับ! โมเดลยุคใหม่อย่าง \u003Ccode>text-embedding-3-small\u003C\u002Fcode> เป็นแบบ Multilingual มันเข้าใจบริบทข้ามภาษา ดังนั้นคำว่า \"แมว\" กับ \"Cat\" จะถูกจัดวางให้อยู่ในพิกัดที่ใกล้กันมากๆ บนโลกของ Vector\u003C\u002Fp>\u003Cdiv data-type=\"horizontalRule\">\u003Chr>\u003C\u002Fdiv>\u003Ch2>📌 บทสรุป (Conclusion)\u003C\u002Fh2>\u003Cp>\u003Cstrong>Vector Embeddings\u003C\u002Fstrong> คือสะพานเชื่อมที่เปลี่ยนภาษาพูดของมนุษย์ให้กลายเป็นภาษาคณิตศาสตร์ที่คอมพิวเตอร์เข้าใจ ช่วยให้เราก้าวข้ามขีดจำกัดของการค้นหาด้วย Keyword แบบเดิมๆ ไปสู่การค้นหาด้วย \u003Cstrong>\"ความเข้าใจในบริบท\"\u003C\u002Fstrong> และเมื่อผสานพลังเข้ากับความเร็วและความประหยัดทรัพยากรของ \u003Cstrong>ภาษา Go\u003C\u002Fstrong> การทำ Data Pipeline เพื่อแปลงข้อมูลระดับล้านเรคคอร์ดก็ไม่ใช่เรื่องที่น่ากังวลอีกต่อไปครับ\u003C\u002Fp>\u003Cp>\u003Cstrong>ในตอนต่อไป (EP.153):\u003C\u002Fstrong> เมื่อเรามี Array ของ \u003Ccode>[]float32\u003C\u002Fcode> นับล้านตัวลอยอยู่ในระบบ คำถามคือเราจะเอาตัวเลขเหล่านี้ไปเก็บไว้ที่ไหนให้ค้นหาและเปรียบเทียบได้เร็วในระดับมิลลิวินาที? ตอนหน้าเราจะก้าวเข้าสู่โลกของ \u003Cstrong>\"Vector Databases 101: ทำความรู้จัก Pinecone, Weaviate และ Milvus\"\u003C\u002Fstrong> เตรียมตัวอัปเกรด Stack ของคุณขึ้นไปอีกขั้น ห้ามพลาดครับ!\u003C\u002Fp>\u003Cp>\u003Cstrong>ฝากกดติดตามพวกเราได้ที่ Superdev Academy\u003C\u002Fstrong> ในทุกช่องทางนะครับ!\u003C\u002Fp>\u003Cul>\u003Cli>\u003Cp>\u003Cstrong>🔵 Facebook: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener\" class=\"ng-star-inserted\" href=\"https:\u002F\u002Fwww.facebook.com\u002Fsuperdev.academy.th\">\u003Cstrong>Superdev Academy Thailand\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> \u003C\u002Fstrong>(อัปเดตข่าวสารและบทความใหม่)\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>🎬 YouTube: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener\" class=\"ng-star-inserted\" href=\"https:\u002F\u002Fwww.youtube.com\u002F@SuperdevAcademy\">\u003Cstrong>Superdev Academy Channel\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> \u003C\u002Fstrong>(ติวเข้มแบบวิดีโอ)\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>📸 Instagram: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener\" class=\"ng-star-inserted\" href=\"https:\u002F\u002Fwww.instagram.com\u002Fsuperdevacademy\u002F\">\u003Cstrong>@superdevacademy\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> \u003C\u002Fstrong>(เกร็ดความรู้สั้นๆ และเบื้องหลังการทำงาน)\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>🎬 TikTok: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener\" class=\"ng-star-inserted\" href=\"https:\u002F\u002Fwww.tiktok.com\u002F@superdevacademy?lang=th-TH\">\u003Cstrong>@superdevacademy\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> \u003C\u002Fstrong>(Tips &amp; Tricks ฉบับย่อยง่าย)\u003C\u002Fp>\u003C\u002Fli>\u003Cli>\u003Cp>\u003Cstrong>🌐 Website: \u003C\u002Fstrong>\u003Ca target=\"_blank\" rel=\"noopener noreferrer\" href=\"http:\u002F\u002Fsuperdevacademy.com\">\u003Cstrong>superdevacademy.com\u003C\u002Fstrong>\u003C\u002Fa>\u003Cstrong> \u003C\u002Fstrong>(คลังบทความและคอร์สเรียนฉบับเต็ม)\u003C\u002Fp>\u003C\u002Fli>\u003C\u002Ful>\u003Cp>\u003C\u002Fp>","23t6ihv8f23v_2de832us2c.png","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclblg987654321\u002Fxd49351t8ivfdj9\u002F23t6ihv8f23v_2de832us2c.png","2026-06-11 16:31:45.236Z","76qprkevbgfdps8",{"keywords":15,"locale":47,"school_blog":57},[16,22,26,31,35,39,43],{"collectionId":17,"collectionName":18,"created":19,"created_by":13,"id":20,"name":21,"updated":19,"updated_by":13},"sclkey987654321","school_keywords","2026-06-11 16:25:16.987Z","n7490lhschwfwmx","Vector Embeddings",{"collectionId":17,"collectionName":18,"created":23,"created_by":13,"id":24,"name":25,"updated":23,"updated_by":13},"2026-06-11 16:25:22.867Z","0umxsfrwhw7w81k","Go OpenAI",{"collectionId":17,"collectionName":18,"created":27,"created_by":13,"id":28,"name":29,"updated":30,"updated_by":13},"2026-03-04 08:20:11.547Z","ey3puyme01a9bsw","Go","2026-06-07 06:45:07.798Z",{"collectionId":17,"collectionName":18,"created":32,"created_by":13,"id":33,"name":34,"updated":32,"updated_by":13},"2026-06-11 16:25:34.988Z","fslp7pvjf16upiv","Text Embedding",{"collectionId":17,"collectionName":18,"created":36,"created_by":13,"id":37,"name":38,"updated":36,"updated_by":13},"2026-06-11 16:25:43.052Z","0e3t6eerwk8xl3u","Go Concurrency",{"collectionId":17,"collectionName":18,"created":40,"created_by":13,"id":41,"name":42,"updated":40,"updated_by":13},"2026-06-11 16:25:49.118Z","8gdef2395f0aey9","Data Pipeline",{"collectionId":17,"collectionName":18,"created":44,"created_by":13,"id":45,"name":46,"updated":44,"updated_by":13},"2026-06-11 16:25:53.881Z","jzb7gzyrenusyyy","RAG Backend",{"code":48,"collectionId":49,"collectionName":50,"created":51,"flag":52,"id":53,"is_default":54,"label":55,"updated":56},"th","pbc_1989393366","locales","2026-01-22 10:59:55.832Z","twemoji:flag-thailand","s8wri3bt4vgg2ji",true,"Thai","2026-04-10 15:42:46.614Z",{"category":58,"collectionId":59,"collectionName":60,"created":61,"expand":62,"id":77,"slug":78,"updated":79,"views":80},"wqxt7ag2gn7xcmk","pbc_2105096300","school_blogs","2026-06-11 16:31:45.024Z",{"category":63},{"blogIds":64,"collectionId":65,"collectionName":66,"created":67,"created_by":13,"id":58,"image":68,"image_alt":69,"image_path":70,"label":71,"name":72,"priority":73,"publish_at":74,"scheduled_at":69,"status":75,"updated":76,"updated_by":13},[],"sclcatblg987654321","school_category_blogs","2026-03-04 08:33:53.210Z","59ty92ns80w_15oc1implw.png","","https:\u002F\u002Ftwsme-r2.tumwebsme.com\u002Fsclcatblg987654321\u002Fwqxt7ag2gn7xcmk\u002F59ty92ns80w_15oc1implw.png",{"en":72,"th":72},"Golang The Series",1,"2026-03-16 04:39:38.440Z","published","2026-06-07 06:45:03.856Z","j8rehtbpflwmsyv","golang-the-series-ep152-intro-to-vector-embeddings-go","2026-06-16 06:29:02.666Z",109,"xd49351t8ivfdj9",[20,24,28,33,37,41,45],"2026-06-16 04:00:00.000Z","บอกลาการค้นหาแบบเดิมๆ! เรียนรู้แนวคิด Vector Embeddings วิธีเปลี่ยนข้อความภาษาคนให้เป็นตัวเลขเพื่อวัดความหมาย พร้อมโค้ด Go ต่อสายตรง OpenAI API","Golang The Series EP.152: Intro to Embeddings - เปลี่ยนข้อความให้เป็นตัวเลขด้วย Go","2026-06-16 04:00:00.066Z",{"th":78,"en":78}]