Octobrain 0.9.0: ความรู้เข้าสู่โหมด Multiplayer
ทีมของคุณเขียนเอกสารไว้แล้ว ทั้ง deploy runbook, กฎ "ห้ามแตะสิ่งนี้โดยไม่มี migration", โน้ตที่ได้มาอย่างยากลำบากว่าทำไม payments service ถึง retry แบบที่มันทำ ทั้งหมดนั้นอยู่ใน wiki ที่ไม่มีใครอ่าน, ข้อความ Slack ที่ปักหมุดไว้ และในหัวของคนสามคน ทุก session ของ agent ใหม่ — และเพื่อนร่วมทีมใหม่ทุกคน — เริ่มจากศูนย์และเรียนรู้มันใหม่แบบยากลำบาก
0.7.0 ทำให้ความจำของ agent แต่ละตัวดูแลตัวเองได้ — sleep consolidation, decay, goal-anchored folding นั่นคือเรื่องของความจำหนึ่งอันที่ฉลาดขึ้นด้วยตัวมันเอง
0.9.0 เกี่ยวกับอีกครึ่งหนึ่งของปัญหา: ความรู้ที่ไม่ควรต้องเรียนรู้ใหม่ในทุกเครื่อง มันทำให้ knowledge layer ของ Octobrain แชร์กันได้ — เก็บเวอร์ชันใน git, scope ด้วยชื่อ, sync อัตโนมัติ — และทำให้ recall คมขึ้นเพื่อให้ fact ที่ถูกต้องชนะบ่อยขึ้น (เราพับงานพื้นฐานของ 0.8.0 รวมไว้ในนี้ด้วย)
Git-Backed Knowledge Boxes — ส่งความรู้แบบเดียวกับโค้ด
นี่คือพระเอก knowledge box คือ git repository ที่เต็มไปด้วย markdown — rules, docs, playbooks, โน้ตสถาปัตยกรรม — ที่ Octobrain clone, index และคอย sync ให้ จัดระเบียบมันครั้งเดียว เก็บเวอร์ชันมันเหมือนโค้ด แล้ว agent ทุกตัวบนทุกเครื่องที่ subscribe จะได้ความรู้ที่ค้นหาได้ชุดเดียวกัน
มีอยู่สองแบบ และมันครอบคลุมสองกรณีจริง:
Project-local — แค่ commit ไดเรกทอรี .box/ วางความรู้ที่มีชีวิตของโปรเจกต์คุณลงใน .box/ ที่ root ของ repo ใครก็ตามที่ clone repo แล้วรัน Octobrain จะได้มัน index อัตโนมัติ — ไม่ต้องมีคำสั่งเพิ่ม ไม่ต้อง config remote มันเดินทางไปพร้อมกับโค้ดเพราะมัน_อยู่ใน_โค้ด
Remote — subscribe กล่องที่แชร์กัน ชี้ Octobrain ไปที่ git URL แล้วมันจะ shallow-clone กล่องนั้นและ index มันภายใต้ scope หนึ่ง:
# Subscribe to your org's shared knowledge box
octobrain box import https://github.com/acme/engineering-knowledge
# Index it at the global scope — visible in every project on this machine
octobrain box import https://github.com/acme/conventions --global
# Pull + smart-reindex every subscribed box and the local .box/
octobrain box sync
# See what you're subscribed to, or drop one
octobrain box list
octobrain box remove github.com/acme/engineering-knowledge
ทุก chunk ที่มาจากกล่องจะได้ source URI แบบ box://<host>/<org>/<repo>/... ที่คงที่ ดังนั้นมันถูกจัดกลุ่ม ระบุที่มาได้ และลบออกได้สะอาด — ดึงกล่องออกแล้วทุก row ของมันก็ไปด้วย การ re-sync เป็นแบบ อิงแฮชและฉลาด: เฉพาะไฟล์ที่เปลี่ยนเท่านั้นที่ถูก re-embed ดังนั้น sync บนกล่องที่ไม่มีอะไรเปลี่ยนแทบไม่มีต้นทุนเลย
และภายใต้ MCP คุณไม่ต้องเรียก sync ด้วยซ้ำ — server จะค้นพบ .box/ ของแต่ละโปรเจกต์, ตรวจหา org box และรีเฟรช remote ที่ subscribe ไว้ ในเบื้องหลัง ครั้งเดียวต่อ session แบบ single-flight ดังนั้นมันไม่เคยบล็อก request agent ของคุณก็แค่เริ่มเจอความรู้ของทีมในการค้นหาของมัน
[knowledge]
chunk_size = 1200 # boxes index through the same chunker as everything else
ประเด็นคือ: runbook เลิกอยู่ในหัวของใครบางคน มันอยู่ใน repo, ค้นหาได้ด้วยความหมาย และโผล่ขึ้นมาใน context ของ agent คุณทันทีที่มันเกี่ยวข้อง — สำหรับทุกคน
Scopes แทนที่ Project Hashes — ความจำที่มีชื่อ
ที่ผ่านมา Octobrain แยกความจำต่อโปรเจกต์ด้วยการแฮช Git remote URL ของคุณให้เป็นไดเรกทอรี SHA-256 ที่อ่านไม่ออก มันใช้งานได้ แต่คุณอ่านมันไม่ได้ เล็งไปที่มันไม่ได้ และแชร์มันไม่ได้
0.9.0 แทนที่สิ่งนั้นด้วย scopes: สตริงที่มนุษย์อ่านออก, ได้มาอัตโนมัติจาก Git remote ของคุณ (หรือ local path เป็น fallback) ที่คุณมองเห็นและเล็งไปหาได้จริง
# Auto-detected from the git remote — nothing to configure
octobrain memory remember "rate limiting approach"
# Or target a scope explicitly
octobrain memory remember "rate limiting approach" --scope acme/payments
# Store something that should be visible everywhere, not just this project
octobrain memory memorize --title "Team convention: trunk-based, no long-lived branches" \
--content "..." --global
Scopes คือสิ่งที่ทำให้ box เป็นอันหนึ่งอันเดียวกัน: remote box ผูกกับ scope ระดับ org โดยค่าเริ่มต้น, .box/ ผูกกับ scope ของโปรเจกต์ของมัน และ --global วางความรู้หรือความจำไว้ต่อหน้าทุกโปรเจกต์บนเครื่อง ระบบตั้งชื่อเดียว ใช้ทุกที่ — storage path, search filter, stats และ log ตอนนี้อ่านเป็นภาษาธรรมดาแล้วแทนที่จะเป็นแฮช
นี่คือ breaking change อันเดียวที่กระทบคุณ: flag --project และพารามิเตอร์เครื่องมือ project ตอนนี้กลายเป็น --scope พฤติกรรมเดิม ชื่ออ่านได้ ดู การอัปเกรด
Multi-Query Recall ที่ได้ผลจริง — RRF Fusion
Octobrain รองรับการค้นหาแบบ multi-query มานานแล้ว — แตกคำถามคลุมเครือออกเป็นหลายคำถามที่คมกว่าแล้วค้นหาพวกมันพร้อมกัน:
octobrain memory remember "authentication" "session security" "jwt expiry"
ปัญหาอยู่ที่การ merge ตรรกะเดิมเก็บคะแนนเดี่ยวที่ดีที่สุดของแต่ละความจำไว้ แล้วบวกเพิ่มแบบคงที่ 10% ต่อ match เพิ่มเติม — ผสมคะแนนต่อ query ที่คำนวณบน สเกลที่เทียบกันไม่ได้ ความจำที่ติดอันดับมั่นคงทั้งสาม query อาจแพ้ให้กับผลอันดับต้นแบบครั้งเดียวบน query เดียวได้ การ decompose ไม่ได้ช่วยจริงๆ บางครั้งมันทำให้แย่ลงด้วยซ้ำ
0.9.0 แทนที่สิ่งนั้นด้วย Reciprocal Rank Fusion — การ fusion อิงอันดับแบบ k=60 เดียวกับที่ Octobrain ใช้รวม BM25 และ vector search ใน store อยู่แล้ว RRF อิงอันดับและไม่ขึ้นกับสเกล: ความจำที่ติดอันดับดีในหลาย query เอาชนะอันที่พุ่งสูงบน query เดียวได้ ตอนนี้การ decompose query ได้ผลแบบที่มันควรจะเป็น มันเป็นคณิตศาสตร์ล้วน — ไม่ต้องใช้ LLM ไม่ต้อง config เพิ่ม — และ rrf_fuse เป็นฟังก์ชันเล็กๆ ที่ผ่าน unit-test ที่คุณเชื่อใจได้
Recall รู้ว่าอะไรคือปัจจุบัน — การจัดอันดับที่รู้จัก Supersedes
Fact หมดอายุ คุณตัดสินใจใช้ Postgres แล้วหกสัปดาห์ต่อมาย้ายไป SQLite โน้ตทั้งสองอันอยู่ในความจำ ทั้งคู่ match กับ "เราใช้ database อะไรอยู่" — และคำตอบเก่าก็ไม่ควรมีสิทธิ์ชนะ
Octobrain มีความสัมพันธ์ชนิด Supersedes มาตลอด แต่มันถูกนิยาม, parse และจัดเก็บ — แล้วก็ไม่เคยถูกอ่านตอน retrieval ความสามารถที่สร้างไว้แล้ว นั่งตายอยู่เฉยๆ
0.9.0 ต่อสายมันเข้ามา เมื่อ edge X Supersedes M ที่ active มาร์กผลลัพธ์หนึ่งว่าล้าสมัย retrieval จะ soft-down-rank อันเก่านั้น (×0.1 — ไม่เคยถูกลบ) ดังนั้น fact ปัจจุบันจึงลอยขึ้นด้านบนขณะที่ประวัติยัง query ได้ มีราวกันสองอย่างที่จงใจไว้:
- Edge ถูกเคารพ ไม่เคยถูกสร้างอัตโนมัติ การตรวจจับความขัดแย้งที่แท้จริงต้องใช้การตัดสินเชิงความหมาย และ Octobrain จงใจเก็บมันออกจาก hot path คุณ (หรือ agent ของคุณ) มาร์ก supersede; retrieval เคารพมัน ผ่าน MCP ตอนนี้เครื่องมือ
knowledgeชี้นำ agent อย่างจริงจังให้สร้างลิงก์ supersedes เมื่อพวกมันอัปเดต fact - Best-effort ความล้มเหลวในการ lookup ความสัมพันธ์จะปล่อยผลลัพธ์ไว้ตามเดิมแทนที่จะทิ้งมัน กรณีแย่ที่สุดคือคุณกลับไปที่พฤติกรรมเดิม ไม่เคยแย่กว่านั้น
การตัดสินใจปัจจุบันชนะ; เส้นทางย้อนกลับไปยังอันเก่ายังรอด
Recall แบบจำกัดเวลา — ตัวกรอง Temporal และ Relevance
"สัปดาห์ที่แล้วฉันตัดสินใจอะไรไป?" เป็นคำถามที่มนุษย์ถามตลอดเวลา และ semantic search เพียงอย่างเดียวตอบมันได้แย่ — relevance ไม่รู้เรื่องเวลา
MemoryQuery รองรับ created_after / created_before (ส่งตรงลงไปที่ index created_at) และ min_relevance อยู่แล้ว — แต่เครื่องมือ MCP remember ไม่เคยใส่ค่าให้พวกมัน อีกหนึ่งความสามารถที่สร้างไว้แต่ตายอยู่ 0.9.0 เปิดเผยทั้งคู่:
created_after/created_before— วันที่แบบ ISO-8601 (2026-06-01) หรือ timestamp แบบ RFC3339 เต็ม วันที่เปล่าๆ หมายถึงเที่ยงคืน UTC; อะไรก็ตามที่ parse ไม่ได้จะข้ามตัวกรองไปเฉยๆ แทนที่จะ errormin_relevance— พื้นคุณภาพผลลัพธ์ต่อการเรียกหนึ่งครั้ง ที่ override ค่าเริ่มต้นระดับ global
เครื่องมือบอกให้ agent คำนวณช่วงเวลาเอง — มันรู้วันที่วันนี้อยู่แล้ว — ดังนั้นจึงไม่มีการ parse วันที่จากภาษาธรรมชาติที่เปราะบางฝังอยู่ในเครื่องมือ "สัปดาห์ที่แล้วฉันตัดสินใจอะไร" กลายเป็นการ scan ช่วงบน index ที่สะอาด ซึ่งเป็นคำถามแบบยึดกับเวลาแบบที่ LongMemEval วัดพอดี
เราใส่ตัวเลขให้มันแล้ว — BEIR Retrieval Benchmarks
0.7.0 เพิ่ม LongMemEval สำหรับความจำระยะยาว 0.9.0 เพิ่ม harness สำหรับ retrieval ของ BEIR เพื่อให้เราให้คะแนน ranking layer — embedding + BM25 fusion + reranking — บน dataset มาตรฐานที่มี qrels จริง ทำงานในเครื่องทั้งหมด ไม่ใช้ LLM judge
ใช้ embedder local ค่าเริ่มต้น (bge-small-en-v1.5, 384-dim, 33M params) วัดเป็น nDCG@10:
| ชุดข้อมูล | Octobrain vector | Octobrain hybrid | BM25 | bge-small-en-v1.5 |
|---|---|---|---|---|
| SciFact (5.2K docs, 300 q) | 0.722 | 0.742 | 0.665 | 0.713 |
| NFCorpus (3.6K docs, 323 q) | 0.341 | 0.363 | 0.325 | 0.343 |
คอลัมน์ dense-only ทำซ้ำตัวเลข BEIR ที่ embedder เผยแพร่ไว้ได้ — นั่นคือ harness ตรวจสอบตัวเอง คอลัมน์ hybrid (BM25 + vector ที่ fuse ด้วย RRF, ค่าเริ่มต้นของ Octobrain) เพิ่ม +2 nDCG@10 เหนือ embedding เปล่าๆ และเอาชนะ BM25 แบบคลาสสิกได้บนทั้งสอง dataset ทำซ้ำเองได้: cd benches && bash scripts/run_retrieval.sh ข้ออ้างเรื่อง recall ข้างบนเป็นข้ออ้างที่เรายืนยันได้
เบื้องหลัง
การเปลี่ยนแปลงเงียบๆ ที่ทำให้ทุกอย่างเร็วและคาดเดาได้ขณะที่ corpus โตขึ้น:
ปุ่มปรับ search ใหม่สองตัว ใน config
search.similarity_threshold(ค่าเริ่มต้น0.3) คือพื้น relevance ระดับ global สำหรับ semantic query;search.max_results(ค่าเริ่มต้น50) คือเพดานแข็งที่ผู้เรียกไม่มีทางเกินได้ ตอนนี้ทั้งคู่ถูกต่อสายแบบ end-to-end แล้วแทนที่จะโฆษณาไว้แต่ถูกเพิกเฉย[search] similarity_threshold = 0.3 # min relevance for semantic queries (0.0–1.0) max_results = 50 # hard ceiling on results from any searchTimeout สำหรับ embeddings และ reranker การเรียก provider ที่ช้าหรือค้างจะไม่ทำให้การค้นหาหยุดชะงักอีกต่อไป —
timeout_secs(ค่าเริ่มต้น30) จำกัดทั้งคู่ พร้อมตัวอย่างใน config ของ rerankerการ initialize ในเบื้องหลัง งานเริ่มต้นที่หนักถูก spawn ออกจาก hot path ดังนั้น request แรกหลังเปิดตัวจึงไม่ต้องจ่ายค่า warm-up ของ index
การค้นพบ scope อัตโนมัติ และการ override config (จาก 0.8.0) Octobrain ดึง scope ของคุณจาก working directory โดยอัตโนมัติ และ
OCTOBRAIN_CONFIG_PATHให้คุณชี้ไปที่ไฟล์ config ที่กำหนดเองได้ — สะดวกสำหรับ CI, container และการตั้งค่าแบบ multi-tenant การล็อก project และ role ถูกแยกออกจากกันเพื่อให้ session ที่ไม่เกี่ยวข้องเลิกแย่งกันDocker แบบ multi-arch ตอนนี้ release build และ push image แบบ multi-arch ดังนั้น
arm64(Apple Silicon, Graviton) และamd64ต่างก็เป็น first-class ทั้งคู่คณิตศาสตร์การจัดอันดับที่ harden แล้ว การแก้ไข reranker candidate limit, การ normalize RRF, การกัน archived-memory และ PRF guard ช่วยอุดช่อง edge case ใน retrieval path ใหม่ การค้นหา knowledge ตอนนี้ยังคืน parent section เต็มด้วย ไม่ใช่เศษเสี้ยวที่ถูกตัด
คุณจะไม่ไปแตะส่วนใหญ่ของพวกนี้โดยตรง นั่นแหละคือจุดประสงค์
0.9.0 เป็นอย่างไรในทางปฏิบัติ
วิศวกรใหม่เข้าร่วมทีม payments:
- เขา clone repo ไดเรกทอรี
.box/ของมัน — deploy runbook, กฎ "อย่า bypass idempotency layer", โน้ตว่าทำไมเราถึง retry — ถูก index อัตโนมัติในครั้งแรกที่ agent ของเขารัน ไม่ต้องตั้งค่าอะไรเลย - เครื่องของเขา subscribe org box (
octobrain box import …) ดังนั้น convention ระดับทั้งบริษัทจึงโผล่ขึ้นมาภายใต้ global scope ในทุกโปรเจกต์ - เขาถาม agent ด้วยคำถามคลุมเครือ — "เราจัดการ webhook failures ที่นี่ยังไง?" การ decompose แบบ multi-query กระจายมันออก, RRF fuse อันดับเข้าด้วยกัน และรายการ runbook ของทีมก็มาอยู่ด้านบนสุด
- การตัดสินใจหนึ่งเปลี่ยนไปเมื่อเดือนที่แล้ว — ทีมย้ายออกจาก queue ที่เคยแนะนำกัน โน้ตเก่าถูกมาร์กว่า superseded ดังนั้นวิธีปัจจุบันชนะ และประวัติก็ยังห่างออกไปแค่ query เดียว
- เขาถาม "สัปดาห์ที่แล้วเราเปลี่ยนอะไรไป?" — ตัวกรอง temporal, ช่วง index ที่สะอาด, ไม่มี noise จากหกเดือนก่อน
ไม่มีใครต้องอธิบายระบบใหม่ ความรู้ถูกเขียนไว้แล้ว — Octobrain แค่ทำให้มันค้นเจอได้ เป็นปัจจุบัน และถูกแชร์
การอัปเกรด
จาก 0.7.x หรือ 0.8.x การ migrate เล็กน้อย
Config — --project กลายเป็น --scope นี่คือ breaking change อันเดียว ที่ไหนก็ตามที่คุณส่ง --project <id> บน CLI หรือพารามิเตอร์ project ให้เครื่องมือ MCP ให้ใช้ --scope <name> แทน อัปเกรดใหญ่: ตอนนี้ค่าเป็นสตริงที่มนุษย์อ่านออก (ได้มาอัตโนมัติจาก Git remote ของคุณ) ไม่ใช่แฮช — ดังนั้นส่วนใหญ่คุณทิ้ง flag ไปทั้งหมดได้เลยและปล่อยให้ discovery จัดการ
octobrain memory remember "api design" --scope acme/web # was: --project <hash>
Storage — ไม่ต้องทำอะไร คอลัมน์ scope และ index ของมันถูกเพิ่มในการรันครั้งแรก และความจำที่มีอยู่ migrate ในที่ ไม่มีขั้นตอนด้วยมือ ไม่มี downtime
Config ใหม่เป็นแบบเพิ่มเข้ามา search.similarity_threshold, search.max_results และ timeout_secs ของ embedding/reranker ทั้งหมดมาพร้อมค่าเริ่มต้นที่ใช้งานได้ เพิ่มมันเฉพาะเมื่อคุณอยากปรับจูนเท่านั้น
Knowledge box เป็นแบบ opt-in ไม่มีอะไรเปลี่ยนจนกว่าคุณจะ commit ไดเรกทอรี .box/ หรือรัน octobrain box import แหล่งที่ index ไว้อยู่แล้วไม่ถูกแตะต้อง
MCP clients — รีเฟรช tool list ของคุณ remember ตอนนี้รับ created_after, created_before และ min_relevance; memorize รับ --global ไม่มีการเปลี่ยนชื่อเครื่องมือหลักห้าตัว — แค่ field ตัวเลือกใหม่ที่ agent ของคุณใช้ได้
Source, binaries และ Docker image ที่ github.com/muvon/octobrain ถ้าพบอะไรพัง เปิด issue — เราอ่าน



