ผู้เขียน: @hi_im_isaac_, @learnwdaniel, @gaozenghao
หมายเหตุ: เวอร์ชันอินเทอร์แอคทีฟของบล็อกเทคนิคแบบเต็มมีให้ดูที่: https://www.cerebras.ai/blog/how-we-built-our-knowledge-base
พนักงานถามคำถามกับฐานความรู้ภายในของเรามากกว่า 15,000 คำถามทุกวัน มันกลายเป็นหนึ่งในเครื่องมือภายในที่ถูกนำไปใช้อย่างกว้างขวางที่สุดในบริษัทนับตั้งแต่เปิดตัวเมื่อ 3 เดือนที่แล้ว ถูกใช้โดยมนุษย์ ระบบอัตโนมัติ และเอเจนต์
ที่ Cerebras ทีมของเราทำงานครอบคลุมทั้งการดำเนินงานศูนย์ข้อมูล การออกแบบชิป ฮาร์ดแวร์ การฝึกสอน (training) การอนุมาน (inference) แพลตฟอร์มคลาวด์ และอื่นๆ ด้วยพนักงานใหม่หลายร้อยคนที่เข้าร่วมทุกปี ช่องทางการสื่อสารของเราเต็มไปด้วยคำถามซ้ำๆ กัน:
- “ฉันจะหา X ได้ที่ไหน?”
- “ใครคือผู้เชี่ยวชาญด้าน Y?”
- “Z คืออะไร?”

เราสร้าง Cerebras Knowledge เพื่อช่วยให้ผู้คนเชื่อมต่อผู้คนและระบบกับข้อมูลที่เป็นประโยชน์
พบข้อมูล ณ ที่ที่มันอยู่
การค้นหาข้อมูลภายในองค์กรเป็นเรื่องยาก ข้อมูลกระจายอยู่ทั่วเครื่องมือต่างๆ และทุกๆ ไตรมาสก็จะมีคนเสนอวิธีแก้ปัญหาที่ 'ยอดเยี่ยม' เหมือนเดิม: มาเก็บทุกอย่างไว้ในแพลตฟอร์มเดียวเพื่อให้ข้อมูลทั้งหมดอยู่ในที่เดียว ความฝันของแหล่งความจริงเดียว (single source of truth) แน่นอนว่าไม่ค่อยได้ผลในทางปฏิบัติ
ข้อมูลถูกสร้างขึ้นในที่ที่สะดวกและเหมาะสมตามหลักการยศาสตร์: ข้อเสนอแนะการแก้ไขในเอกสาร, เธรดใน Slack, การอ้างอิงโค้ดใน GitHub, และเมทาดาทาสถานะใน Jira แพลตฟอร์มเหล่านี้ถูกออกแบบมาเฉพาะสำหรับโดเมนของตัวเอง ได้รับการปรับให้เหมาะสมผ่านการพัฒนาผลิตภัณฑ์และการวิเคราะห์หลายปี การอภิปราย pull request ใน Google Docs คงเป็นประสบการณ์ที่แย่มาก
ดังนั้นเราจึงออกแบบระบบที่ต้องการการเปลี่ยนแปลงพฤติกรรมที่มีอยู่เพียงเล็กน้อย ในด้านการรวบรวมข้อมูล นั่นหมายถึงการดึงข้อมูลจากแต่ละแพลตฟอร์มโดยตรง
กายวิภาคของฐานความรู้
ฐานความรู้ของเรามีสามสิ่ง:
- แพลตฟอร์มสำหรับรวบรวมและจัดเก็บข้อมูลภายใน
- แพลตฟอร์มสำหรับสอบถามข้อมูลนั้น
- ชั้นที่บังคับใช้การตรวจสอบสิทธิ์และการอนุญาต พร้อมการตรวจสอบและการวิเคราะห์
แกนกลางคือตาราง Postgres เดียวที่เก็บ embeddings, สรุปข้อมูลดิบ, และเมทาดาทาจากหลายแหล่ง ระบบจะรับข้อมูลจากทั่วทั้งบริษัทอย่างต่อเนื่องและคงไว้ซึ่งดาต้าสโตร์ที่พร้อมสำหรับการสอบถาม
เราต้องการอินเทอร์เฟซข้อมูลที่เรียบง่ายแต่สามารถทำงานกับข้อมูลได้หลายรูปแบบ เรายังต้องการให้นักพัฒนาคนอื่นๆ ที่ Cerebras สามารถสร้างคอนเนกเตอร์แบบกำหนดเองได้ ผลลัพธ์ที่ได้นั้นตั้งใจให้เรียบง่าย: ทุกแหล่งข้อมูล ตั้งแต่เธรด Slack ไปจนถึง netlist ต่างก็ลงในตาราง embeddings เดียวกัน และทุกอย่างในตารางนั้นสามารถสอบถามได้ทันทีผ่านอินเทอร์เฟซเดียวกัน:

แต่ละแหล่งข้อมูลกำหนดว่าข้อมูลคืออะไร วิธีเชื่อมต่อ และควรดึงข้อมูลบ่อยแค่ไหน แต่ละแถว embeddings ที่ได้จะเป็นไปตามอินเทอร์เฟซเดียวกัน ไม่ว่าจะมาจาก Slack, โค้ดรีโพสิทอรี, ระบบเอกสาร หรือฐานข้อมูลที่กำหนดเอง
เราประมวลผลการสนทนาแบบไม่มีโครงสร้างใน Slack อย่างไร
Slack คือแหล่งข้อมูลที่สำคัญที่สุดที่เราต้องออกแบบ มันคือที่ที่การอภิปรายทางวิศวกรรมที่ทันสมัยที่สุดเกิดขึ้นทั่วทั้งบริษัท

เราเริ่มต้นทดสอบว่าแค่ embeddings ธรรมดาบนข้อความดิบทำงานได้ดีหรือไม่ เราพบอย่างรวดเร็วว่าการค้นหาแบบเวกเตอร์เพียงอย่างเดียวนั้นไม่เพียงพอที่จะจับคู่ข้อมูลที่เกี่ยวข้องทั้งหมด
ข้อความใน Slack มีความท้าทายหลายประการ:
- ความหนาแน่นของข้อมูลแตกต่างกันมาก: "เฮ้ ใช่ แน่นอน ไมค์" กับคำอธิบายเคอร์เนลโดยละเอียด ล้วนเป็นข้อความ
- ความยาวข้อความแตกต่างกัน และข้อความสั้นมักจะชนะข้อความที่ยาวและละเอียดกว่าในการเปรียบเทียบ cosine similarity
- ความหมายของข้อความมักขึ้นอยู่กับบทสนทนารอบข้าง
เราจึงต้องการแนวทางแบบไฮบริด เราสร้างการดึงข้อมูล Slack ทุกเธรดสามารถค้นหาได้ผ่านเทคนิคการค้นหาหลายแบบพร้อมกัน โดยแต่ละเทคนิคจะชดเชยจุดอ่อนของเทคนิคอื่น:
- การค้นหาข้อความแบบเต็มจะจับโทเค็นที่แน่นอนซึ่ง embeddings ทำให้เบลอ: สตริงข้อผิดพลาด, ชื่อแฟล็ก, ชื่อโฮสต์ เมื่อวิศวกรวางข้อความข้อผิดพลาดตามตัวอักษร การจับคู่คำศัพท์ที่แน่นอนมักจะเป็นหลักฐานที่ดีที่สุด และไม่ควรถูกแทนที่ด้วยความคล้ายคลึงทางความหมาย
- การค้นหาแบบ embedding จับการถอดความ คนที่ถามว่า "restore hangs after manifest load" กับคนที่ตอบว่า "checkpoint stalls on the NFS mount" อาจไม่ใช้คำศัพท์ร่วมกัน ความคล้ายคลึงของเวกเตอร์คือสิ่งที่เชื่อมโยงคำถามกับคำตอบที่เขียนด้วยคำต่างกัน(1)
- ความถี่เอกสารผกผัน (IDF) แยกสัญญาณออกจากเสียง ข้อความสั้นที่สร้างจากโทเค็นหายาก เช่น แฟล็กการกำหนดค่าที่ไม่ชัดเจน สมควรได้รับการจัดอันดับ "sounds good, thanks!" นั้นใกล้เคียงกับหลายๆ คำถามในพื้นที่ embedding แต่ได้คะแนนเกือบเป็นศูนย์เมื่อพิจารณาความหายากของคำศัพท์
- การเสื่อมค่าตามอายุ (Age decay) สะท้อนว่าคำตอบใน Slack หมดอายุ สองเธรดสามารถตอบคำถามเดียวกันได้ และเธรดจากหกเดือนก่อนอาจอธิบายโครงสร้างพื้นฐานที่ไม่มีอยู่อีกต่อไป เมื่อความเกี่ยวข้องเท่ากัน เธรดที่ใหม่กว่าจะชนะ

ไม่มีตัวให้คะแนนใดถูกเชื่อถือเพียงลำพัง แต่ละเทคนิคสร้างมุมมองการจัดอันดับของตัวเองบนคลังข้อมูลเดียวกัน และมุมมองเหล่านั้นถูกหลอมรวมในเวลาสืบค้น (ดู การจัดอันดับใหม่)
Socket Mode
เพื่อรวบรวมข้อมูลแบบเรียลไทม์ เราติดตั้งบอท Slack ในพื้นที่ทำงานของเราและรันใน Socket Mode Slack จะส่งทุกอีเวนต์ข้อความถึงเราผ่าน WebSocket แบบถาวร ดังนั้นเราจึงได้รับการอัปเดตแบบเรียลไทม์โดยไม่ต้องเรียก Web API และหมดขีดจำกัดอัตรา
เมื่ออีเวนต์มาถึง เราจะยอมรับทันที กำจัดรายการซ้ำโดยใช้ stable event ID และทำเครื่องหมายข้อความสำหรับ ingest consumer
ingest consumer ไม่ได้บันทึกข้อความใหม่เพียงลำพัง มันจะแก้ไขเธรดที่ข้อความนั้นอยู่ และดึงข้อมูลการสนทนาทั้งหมดอีกครั้ง รวมถึงข้อความหลักและทุกคำตอบ จาก Slack API จากนั้นเขียนทั้งเธรดกลับเป็นหนึ่งแถว การตอบกลับเธรดที่มีอยู่จึงดึงข้อความหลักและพี่น้องทั้งหมดอีกครั้ง ดังนั้นเนื้อหาที่เก็บ รายชื่อผู้เข้าร่วม และการประทับเวลากิจกรรมล่าสุดจะสะท้อนการสนทนาที่สมบูรณ์เสมอ
ทุกช่อง Slack ในระบบของเรามีแหล่งข้อมูลของตัวเอง ซึ่งช่วยให้ปรับแต่งความสดของข้อมูลได้ละเอียด ทีมอาจเลือกดึงข้อมูลช่องเหตุการณ์ที่ยุ่งบ่อยขึ้น
เธรดและข้อความ
ข้อความ Slack ดิบสามารถค้นหาด้วยคำสำคัญได้ทันทีที่มาถึง เพราะเรามีดัชนีข้อความแบบเต็ม (GIN) ของ Postgres บนเนื้อหาดิบ อย่างไรก็ตาม เพื่อให้การค้นหาแบบเวกเตอร์มีประโยชน์ เราจึงทำการประมวลผลเพิ่มเติม(8)
ในระหว่างการกลั่น (distillation) LLM จะดึงข้อมูลที่มีโครงสร้างจากเธรดทั้งหมด:
- คำถามหนึ่งบรรทัดที่วิศวกรจะค้นหาจริง
- สรุปสั้นๆ
- วิธีแก้ไข
- ระบบและการอ้างอิงโค้ดที่กล่าวถึง

เราสร้าง embeddings สำหรับข้อมูลเหล่านี้และเขียนลงในตาราง embeddings ที่ใช้ร่วมกัน เราไม่ได้ทำ embedding กับข้อความถอดเสียงต้นฉบับโดยตรง จากการทดลองของเรา ความแม่นยำเพิ่มขึ้นอย่างมีนัยสำคัญเมื่อเธรดถูกทำให้เป็นรูปแบบที่สอดคล้องกัน(7,9) เมทาดาทาเพิ่มเติมยังให้สัญญาณที่มีประโยชน์มากขึ้นสำหรับการจับคู่ความหมาย
การกระจาย (Bursting)
เมื่อถึงจุดนี้การค้นหา Slack ก็ดีแล้ว แต่เรายังคงพบปัญหาเดิม: ข้อความสำคัญภายในเธรดยาวไม่ได้แสดงในสรุปในระดับเธรดเสมอไป
เพื่อเพิ่มสัญญาณจากข้อความแต่ละข้อความ เราใช้การกระจาย (bursting) burst คือชุดข้อความต่อเนื่องจากผู้เขียนคนเดียวกัน เราสร้าง embedding สำหรับแต่ละ burst โดยมีหัวข้อเธรดเป็นบริบทนำ(2) เพราะบางครั้งคำตอบอยู่ในข้อความแยกที่คำศัพท์ไม่เคยปรากฏในสรุปเธรด Burst embeddings ทำให้ข้อความนั้นค้นหาได้ด้วยตัวเอง
เพื่อป้องกันไม่ให้ข้อมูลสัญญาณต่ำเข้าสู่ฐานข้อมูล แต่ละ burst จะถูกให้คะแนนเทียบกับสัญญาณที่ถ่วงน้ำหนัก และต้องผ่านเกณฑ์ก่อนที่จะถูกทำ embedding:
- มีโทเค็นที่ค่อนข้างหายากในคลังข้อมูล โดยมี IDF อย่างน้อย 4.0
- burst รวมมีความยาวอย่างน้อย 200 ตัวอักษร
- ข้อความหนึ่งข้อความขึ้นไปใน burst มีรีแอคชั่น (reactions) ซึ่งให้การสนับสนุนทางสังคม

หลังจากการกลั่น burst ที่มีคุณสมบัติจะถูกทำ embedding และเก็บในตาราง embeddings พร้อมกับบันทึกระดับเธรด
คลังโค้ด (Code repositories)
ตอนแรกเราถกเถียงกันว่าจำเป็นต้องทำ embedding สำหรับคลังโค้ดหรือไม่ ด้วยการเพิ่มขึ้นของ Claude Code และเครื่องมือบรรทัดคำสั่งอื่นๆ การสร้าง code embeddings ดูขัดกับสัญชาตญาณเมื่อดูเหมือนว่า "grep is all you need" หลังจากพูดคุยกับคนอื่นในอุตสาหกรรมและอ่านผลการค้นพบของ Cursor เกี่ยวกับการค้นหาความหมายในคลังโค้ดขนาดใหญ่ เราจึงตัดสินใจลอง
เรามีคลังที่เก็บข้อมูลภายในหลายแห่ง บางแห่งมีขนาดใหญ่กว่า 40 GB ความกังวลหลักของเราคือจะทำให้มันทันสมัยอย่างมีประสิทธิภาพได้อย่างไร
ใช้ @cocoindex_io เพื่อรักษา code embeddings
หลังจากการทดลองหลายครั้ง เราก็ลงเอยที่ CocoIndex ซึ่งเป็นเฟรมเวิร์ก open-source สำหรับทำ embedding เอกสารที่เชี่ยวชาญในการแปลงคลังโค้ดเป็นเวกเตอร์
สำหรับแต่ละคลังที่เก็บข้อมูล เราแบ่งโค้ดโดยใช้ขอบเขต regex ที่เฉพาะภาษา เรียงจากหยาบไปละเอียด ตัวแบ่งจะลองขอบเขตระดับสูงก่อน เช่น class ถ้าส่วนย่อย (chunk) ที่ได้ยังใหญ่เกินไป ก็จะถอยไปใช้ขอบเขต method และบล็อกย่อยลงไปอีก เราสร้าง embedding สำหรับส่วนย่อยที่ได้และเขียนเวกเตอร์ลงใน Postgres ไฟล์เดียวอาจสร้าง embeddings หลายตัวในระดับความเฉพาะเจาะจงที่แตกต่างกัน เช่น บันทึกระดับไฟล์และระดับฟังก์ชัน

CocoIndex ติดตามเมทาดาทาการซิงค์ใน Postgres ในแต่ละ commit มันจะทำ embedding และส่งออกเฉพาะส่วนของโค้ดที่เปลี่ยนแปลงอีกครั้ง แทนที่จะคำนวณทั้งคลังใหม่ วิธีนี้ใช้ได้ดีเป็นพิเศษสำหรับเราเพราะสถานะการซิงค์และที่เก็บ embedding อยู่ในฐานข้อมูลเดียวกัน
เมื่อจำนวนคลังโค้ดเพิ่มมากขึ้น เราได้ย้ายการเริ่มต้นใช้งานคลังไปเป็นไฟล์คอนฟิกที่ทีมสามารถส่งได้เอง รวมถึง allowlists และ denylists ในระดับพาธของไฟล์
แหล่งข้อมูลที่กำหนดเอง (Custom data sources)
บางทีมมีฐานข้อมูลของตัวเองอยู่แล้ว และไม่ต้องการย้ายข้อมูลไปยัง Slack หรือระบบเอกสารเพียงเพื่อเข้าร่วมฐานความรู้ พวกเขาต้องการพื้นผิวการค้นหาเดียวกันบนตารางที่มีอยู่ของพวกเขา
เพื่อรองรับสิ่งนี้ เราถือว่าแหล่งข้อมูลที่กำหนดเองเป็นสคริปต์ปลั๊กอิน ทีมจะเปิด pull request พร้อมโมดูล Python ขนาดเล็กที่รู้วิธีอ่านจากระบบของตนและส่งออกแถวที่มีรูปร่างเหมือนตาราง embeddings ของเรา พร้อมกับรายการแหล่งข้อมูลที่ตรงกัน
ตราบใดที่สคริปต์เขียนลงในฐานข้อมูลที่ใช้ร่วมกันโดยใช้สคีมาเดียวกันกับทุกแถว embeddings อื่นๆ สแต็กที่เหลือก็ทำงานได้โดยไม่เปลี่ยนแปลง ข้อมูลจะกลายเป็นสิ่งที่ค้นหาได้พร้อมกับ Slack, โค้ด และเอกสาร โดยไม่ต้องจัดการพิเศษอื่นๆ ในระบบ
การวางแผนและการกระจายเครื่องมือ (Planning and tool fan-out)
สำหรับทุกคำสั่งค้นหา อันดับแรกเราจะทำการวางแผนสั้นๆ โดย LLM ตัดสินใจว่าเครื่องมือและแหล่งข้อมูลใดน่าจะเกี่ยวข้อง เครื่องมือหลักๆ มีดังนี้:
- subsystem_index: สรุป LLM ต่อไฟล์
- search: ไพพ์ไลน์เวกเตอร์แบบรวมผ่าน Slack, wiki, โค้ด และแหล่งที่ถูกทำดัชนีอื่นๆ ** รวมและจัดอันดับใหม่ภายใน
- search_slack: การดึงข้อมูล Slack โดยตรง
- search_code: ripgrep ในคลังโค้ดต้นทาง
- recent_prs: pull requests ล่าสุดที่เกี่ยวข้องกับคำถาม
- who_knows: ผู้ที่มีความเชี่ยวชาญที่พิสูจน์แล้วในหัวข้อนั้น
ผู้วางแผนทำงานบนคำอธิบายที่กระชับเกี่ยวกับสิ่งที่เราได้ทำดัชนีไว้: โปรเจกต์ใดบ้างที่มี แหล่งข้อมูลใดบ้างในแต่ละโปรเจกต์ และแต่ละแหล่งข้อมูลถนัดตอบคำถามอะไร เมื่อรับคำถามของผู้ใช้และขอบเขตที่ใช้งานอยู่ มันจะส่งออกการเลือกเครื่องมือที่ผู้ดำเนินการ (executor) แจกจ่ายแบบขนาน ทำให้เป็นรูปแบบหลักฐานร่วม และส่งต่อไปยัง LLM สังเคราะห์ขั้นสุดท้าย(4)

การจัดอันดับใหม่ (Reranking)
เอกสารอาจปรากฏใกล้ด้านบนเพียงเพราะใช้คำศัพท์ร่วมกับคำถามแต่ตอบคำถามคนละอย่าง ก่อนการจัดอันดับใหม่ เรารวมรายการผลลัพธ์ที่เข้ากันไม่ได้ของตัวดึงข้อมูลด้วย reciprocal rank fusion (RRF) สำหรับทุกเอกสาร เราเพิ่ม weight / (60 + rank) สำหรับแต่ละรายการที่ปรากฏ โดยมีค่า weight เริ่มต้น 1.0 และ smoothing constant 60

ค่าคงที่ปรับเรียบทำให้ฉันทามติสำคัญกว่าเสียงเดียวที่แข็งแรง: เอกสารที่ปรากฏใกล้ด้านบนในหลายตัวดึงข้อมูลสามารถเอาชนะเอกสารที่จัดอันดับหนึ่งในเพียงตัวเดียว จากนั้นเรารวมส่วนที่ซ้ำกันกลับเป็นแหล่งเดียว จำกัดจำนวนผลลัพธ์ที่แต่ละไฟล์สามารถมีส่วนร่วม และจบลงด้วยยี่สิบอันดับแรกที่หลากหลายมากขึ้น
เราส่งคำถามต้นฉบับและผู้สมัครเหล่านั้นไปยังโมเดล reranker ขนาดเล็ก มันให้คะแนนเอกสารแต่ละฉบับตั้งแต่ศูนย์ถึงสิบ และเราเก็บสิบอันดับแรก(6)
เมื่อการจัดอันดับเสร็จสิ้น เราเพิ่มบริบทกลับไปยังผู้ชนะ ตัวอย่างเช่น ถ้าเราจับคู่ส่วน wiki เราเพิ่มสองส่วนข้างเคียงเพื่อไม่ให้หัวข้อ ข้อกำหนดเบื้องต้น และข้อแม้ที่การแบ่งชิ้นส่วนแยกจากกันหายไป สิ่งนี้ทำให้ผู้อ่านเห็นตัวอย่างที่สมบูรณ์แทนที่จะเป็นย่อหน้าเดี่ยวที่ขาดบริบทสำคัญ
ดังนั้นผลลัพธ์ของการค้นหาคือแพ็กเก็ตหลักฐานที่สมบูรณ์: ผลลัพธ์จากตัวดึงข้อมูลต่างๆ ที่หลอมรวม กำจัดรายการซ้ำในระดับแหล่งที่มา จัดอันดับใหม่เทียบกับคำถามจริง และจากนั้นขยายด้วยบริบทรอบข้างเท่านั้น
MCP
ในการรวม MCP เราเปิดเผยบล็อกการดึงข้อมูลเป็นเครื่องมือโดยตรงแทนที่จะซ่อนไว้หลัง endpoint "ตอบคำถามนี้" เครื่องมือเหล่านี้มีความตั้งใจให้เรียบง่ายและปราศจาก LLM เท่าที่เป็นไปได้ เพื่อให้ลูกค้าสามารถสืบค้นได้รวดเร็วและราคาถูก(5)
MCP tool แต่ละตัวสอดคล้องกับ primitive การดึงข้อมูลพื้นฐานหนึ่งตัว เช่น search_slack, search_code, search หรือ who_knows อินพุตและเอาต์พุตของเครื่องมือนั้นแคบ มีโครงสร้าง และเสถียร ทำให้ง่ายต่อการเรียกใช้จากไคลเอนต์หรือเอเจนต์ใดๆ โดยไม่ต้องฝังตรรกะการจัดระเบียบเพิ่มเติมภายในเครื่องมือเอง
เครื่องมือส่วนใหญ่เรียกใช้ไพพ์ไลน์การสืบค้นหนึ่งไพพ์ไลน์ เช่น การค้นหาเวกเตอร์, การค้นหาคำศัพท์ หรือ ripgrep ใช้ฮิวริสติกการให้คะแนนแบบเบา และส่งคืนแถวหลักฐานดิบ
Claude Code หรือเอเจนต์ที่เข้ากันได้กับ MCP ใดๆ จะกลายเป็นเครื่องมือจัดระเบียบ (orchestration engine) มันตัดสินใจว่าจะเรียกใช้เครื่องมือใด ตามลำดับใด และจะประกอบผลลัพธ์เป็นคำตอบสุดท้ายหรือการแก้ไขโค้ดอย่างไร ชั้นการดึงข้อมูลไม่ได้ขึ้นอยู่กับการตัดสินใจของ LLM เหล่านั้นเพื่อให้บริการคำขอ
เว็บ UI
ในเว็บ UI เครื่องมือเดียวกันนี้มีอยู่ แต่เชื่อมต่อกับไพพ์ไลน์การสืบค้นที่สมบูรณ์ซึ่งทำงานตั้งแต่ต้นจนจบสำหรับทุกคำถามของผู้ใช้ เอเจนต์ UI เป็นเจ้าของขั้นตอนผู้วางแผนและผู้ดำเนินการ
- ผู้วางแผน (Planner): LLM น้ำหนักเบาจะตรวจสอบคำถามและโปรเจกต์ที่ใช้งาน แล้วเลือกเครื่องมือดึงข้อมูลที่จะเรียกใช้ เช่น search, search_slack และ subsystem_index
- ผู้ดำเนินการ (Executor): ระบบกระจายการเรียกใช้เครื่องมือเหล่านั้นแบบขนาน รวบรวมผลลัพธ์ และทำให้เป็นมาตรฐานเป็นสคีมาหลักฐานร่วมที่มีคะแนน ความใหม่ และคำแนะนำแหล่งที่มา
- การสังเคราะห์ (Synthesis): LLM รอบสุดท้ายใช้ชุดหลักฐานที่มีประเภทและคำถามเดิม แล้วสร้างคำตอบที่แสดงใน UI รวมถึงการอ้างอิง ข้อแม้ และการสังเคราะห์ข้ามแหล่งที่มา
จากมุมมองของผู้ใช้ เว็บ UI ก็คือ "ถามคำถามแล้วรับคำตอบ" เบื้องหลัง มันรันรูปแบบ planner → executor → synthesizer เดียวกันกับที่ MCP clients สามารถสร้างขึ้นใหม่ได้อย่างชัดเจน

องค์กร (Organization)
เมื่อคลังข้อมูลเติบโตขึ้น "ค้นหาทุกอย่างทุกที่" ก็หยุดมีประโยชน์อย่างรวดเร็ว วิศวกรในทีมคอมไพเลอร์ไม่ต้องการให้คู่มือโครงสร้างพื้นฐานปรากฏในผลลัพธ์ของพวกเขา และในทางกลับกัน โปรเจกต์คือวิธีที่เราทำให้การค้นหาเกี่ยวข้องโดยค่าเริ่มต้น
โปรเจกต์และการค้นหาแบบจำกัดขอบเขต (Scoped search)
เราแนะนำโปรเจกต์เป็นวิธีหลักในการจัดระเบียบพื้นที่ทำงานที่คำสั่งค้นหาทำงานบนนั้น โปรเจกต์คือชุดของแหล่งข้อมูลที่มีชื่อ: ช่อง Slack เฉพาะ, คลังที่เก็บโค้ด, ฐานข้อมูลภายใน และพื้นที่เอกสารที่เกี่ยวข้องกับทีมหรือโครงการริเริ่ม
โปรเจกต์มีจุดประสงค์ให้น้ำหนักเบา แหล่งข้อมูลเดียวกัน เช่น ช่องเหตุการณ์ที่ใช้ร่วมกันหรือคลังที่เก็บแพลตฟอร์มกลาง สามารถอ้างอิงโดยหลายโปรเจกต์แทนที่จะถูกทำซ้ำ

การเริ่มต้นใช้งานและค่าเริ่มต้น
ระหว่างการเริ่มต้นใช้งาน ผู้ใช้จะถูกขอให้เลือกหรือสร้างโปรเจกต์เริ่มต้นที่ตรงกับวิธีการทำงานของตน เช่น โครงสร้างพื้นฐานการฝึก ML, คอมไพเลอร์ หรือการดำเนินงานศูนย์ข้อมูล
โปรเจกต์เริ่มต้นนั้นถูกเก็บไว้ในโปรไฟล์ผู้ใช้และจำกัดขอบเขตการค้นหาโดยอัตโนมัติ วิศวกรใหม่จะได้รับคำตอบที่มีสัญญาณสูงโดยไม่ต้องเรียนรู้ก่อนว่าช่อง Slack, คลังที่เก็บ หรือพื้นที่เอกสารใดสำคัญ
ข้อคิดสุดท้าย
ท้ายที่สุดแล้ว ฐานความรู้ทำงานได้เพราะมันพบผู้คนในที่ที่ข้อมูลมีอยู่แล้ว แทนที่จะบังคับทุกอย่างเข้าสู่ระบบที่ตายตัวเพียงระบบเดียว ด้วยการรวมเทคนิคการค้นหาต่างๆ เราสามารถนำเสนอหลักฐานได้อย่างรวดเร็ว ผลลัพธ์คือประสบการณ์การค้นหาที่ยืดหยุ่นพอสำหรับข้อมูลบริษัทจริง แต่มีโครงสร้างพอที่จะมีประโยชน์ในขณะที่ Cerebras ยังคงเติบโต
ถ้าคุณอ่านมาถึงตรงนี้และน่าสนใจสำหรับคุณ ทีม ai/growth กำลังรับสมัคร ติดต่อได้ถ้าสนใจ @learnwdaniel
อ้างอิง
- Malkov และ Yashunin, Efficient and Robust Approximate Nearest Neighbor Search Using Hierarchical Navigable Small World Graphs, arXiv:1603.09320 / IEEE TPAMI 2018.
- Anthropic, Introducing Contextual Retrieval, 2024.
- Cormack, Clarke, และ Büttcher, Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods, SIGIR 2009.
- Li et al., Search-o1: Agentic Search-Enhanced Large Reasoning Models, arXiv:2501.05366, 2025.
- Anthropic, Code Execution with MCP, 2025.
- Liu et al., Lost in the Middle: How Language Models Use Long Contexts, arXiv:2307.03172, 2023.
- Anthropic, Use XML Tags.
- Salesforce/Slack Engineering, How Slack AI Processes Billions of Messages, 2024.
- Improving Agents, Best Nested Data Format.
- Cursor, Improving Agent with Semantic Search, 2025.





