nb-cli - CLI สำหรับระบบอัตโนมัติของโน้ตบุ๊กและ AI เอเจนต์
(blog.jupyter.org)- เครื่องมือ CLI โอเพนซอร์สเชิงทดลองที่ออกแบบมาเพื่อให้ AI coding agent จัดการ Jupyter โน้ตบุ๊กในฐานะอาร์ติแฟกต์ได้ โดยพัฒนาด้วย Rust เพื่อรองรับการจัดการโน้ตบุ๊กที่รวดเร็วและเสถียร
- เพื่อแก้ปัญหาที่โครงสร้าง JSON ของ
.ipynbไม่เหมาะกับงานอัตโนมัติและการประมวลผลโดย LLM จึงมีการให้ความสามารถอ่าน เขียน รัน และค้นหาผ่านบรรทัดคำสั่ง โดยยังคงเป็นไปตาม สเปก nbformat - ทำงานได้โดยไม่ต้องมี Jupyter server และหากเชื่อมต่อกับเซิร์ฟเวอร์ ก็รองรับการแก้ไขแบบร่วมมือกันแบบเรียลไทม์ด้วย โปรโตคอล Y.js CRDT แบบเดียวกับที่ JupyterLab ใช้
- เพื่อเพิ่มประสิทธิภาพการใช้คอนเท็กซ์ของ LLM จึงออกแบบ Markdown ฟอร์แมตที่ปรับให้เหมาะกับ AI โดยอิง sentinel เช่น
@@cell,@@outputขึ้นใหม่ - รวม ความสามารถที่ออกแบบมาให้เหมาะกับ workflow ของเอเจนต์ เช่น การประกอบคำสั่งแบบ Unix, การอ้างอิงเซลล์อย่างเสถียร, การค้นหาทรงพลัง, การจัดการหลายเซลล์แบบเป็นชุด และการรันที่รับรู้สภาพแวดล้อม
เบื้องหลัง: ปัญหา “กล่องดำ” ของโน้ตบุ๊ก
- เมื่อ AI coding agent เริ่มมีบทบาทมากขึ้น นิยามของเครื่องมือสำหรับนักพัฒนาก็กำลังเปลี่ยนไป และ LLM อย่าง Claude หรือ GPT ก็ถูกฝึกจากกรณีการใช้งาน CLI จำนวนมหาศาลจากเอกสาร, Stack Overflow และ GitHub จึง เชี่ยวชาญการใช้งาน command-line interface มาก
- เครื่องมือเดิมมักเน้นการรันเอเจนต์ภายในโน้ตบุ๊ก แต่ยังขาดเครื่องมือสำหรับ เอเจนต์ที่ต้องจัดการตัวโน้ตบุ๊กเองในฐานะอาร์ติแฟกต์
- โครงสร้าง JSON ของไฟล์
.ipynbใน Jupyter notebook กลายเป็น จุดเสียดทานที่ทำให้สคริปต์เชลล์และ LLM ประมวลผลแบบโปรแกรมได้ยาก - อินเทอร์เฟซเดิมยังไม่เพียงพอสำหรับสถานการณ์ต่อไปนี้ที่ต้องการงานอัตโนมัติและการวิเคราะห์ด้วย AI
- การวิเคราะห์อัตโนมัติ: AI agent ที่ตรวจสอบ data science workflow ต้องเข้าใจ pipeline ในระดับเซลล์
- การตรวจสอบอัตโนมัติ: ระบบ CI/CD ต้องรันโน้ตบุ๊ก ตรวจสอบผลลัพธ์ และจับข้อผิดพลาดล่วงหน้า
- การจัดทำเอกสารในวงกว้าง: ต้องแปลงเนื้อหาในโน้ตบุ๊กเป็นเอกสารที่เรียบร้อยโดยอัตโนมัติ
- การดีบักในสภาพแวดล้อมจริง: ต้องวินิจฉัยความล้มเหลวของการรันโน้ตบุ๊กในสภาพแวดล้อมแบบ headless โดยไม่ต้องแทรกแซงด้วยมือ
- โน้ตบุ๊กในฐานะข้อมูล: จัดการโน้ตบุ๊กเหมือนฐานข้อมูลแบบมีโครงสร้างเพื่อสร้างรายงาน สรุป และภาพแสดงผล
- ก่อนหน้านี้ วิธีที่ใช้กันทั่วไปคือควบคุม JupyterLab UI ด้วยมือ, เขียน Python สคริปต์ที่เปราะบาง เพื่อ parse JSON ที่ซับซ้อน, หรือใช้เครื่องมือรันที่ไม่มีการรวมแบบเรียลไทม์
- nb-cli ใช้ อินเทอร์เฟซที่ยึด CLI เป็นหลัก และความสามารถในการประกอบคำสั่งแบบ Unix เพื่อทำให้โน้ตบุ๊กกลายเป็นพลเมืองชั้นหนึ่งของ software stack
ความสามารถหลัก
-
ทำงานได้ทั้งมีและไม่มี Jupyter server
- โดยค่าเริ่มต้นจะอ่านและเขียนไฟล์
.ipynbโดยตรง และรันผ่าน การสื่อสารกับ kernel โดยตรงด้วย ZeroMQ - เหมาะกับสคริปต์และ CI pipeline ที่ไม่ต้องเปิดเซิร์ฟเวอร์
- สร้างโน้ตบุ๊กโดยไม่ต้องมีเซิร์ฟเวอร์ด้วย
nb create analysis.ipynb - เพิ่มเซลล์ รัน และดูผลลัพธ์ได้ด้วยคำสั่ง
nb cell add,nb execute,nb read
- สร้างโน้ตบุ๊กโดยไม่ต้องมีเซิร์ฟเวอร์ด้วย
- เมื่อต้องให้ผู้ใช้หรือเอเจนต์หลายตัวแก้ไขโน้ตบุ๊กเดียวกันพร้อมกัน การเชื่อมต่อเซิร์ฟเวอร์จะมีประโยชน์ โดยรองรับการซิงก์แบบเรียลไทม์โดยไม่มีความขัดแย้งผ่าน โปรโตคอล Y.js CRDT แบบเดียวกับที่ JupyterLab ใช้ภายใน
- ใช้
nb connectเพื่อตรวจหา local server อัตโนมัติ และสามารถระบุเซิร์ฟเวอร์หรือโทเค็นเฉพาะได้ด้วยออปชัน--server - รองรับการรันแบบรีสตาร์ตเคอร์เนลด้วยออปชัน
--restart-kernelเพื่อตรวจสอบความสามารถในการทำซ้ำ
- ใช้
- เมื่อเชื่อมต่อเซิร์ฟเวอร์ จะตรวจได้ว่าโน้ตบุ๊กถูกเปิดอยู่ใน JupyterLab หรือไม่ และหากไม่ได้เปิดก็จะ fallback ไปใช้การทำงานแบบไฟล์ได้อย่างเป็นธรรมชาติ
- โดยค่าเริ่มต้นจะอ่านและเขียนไฟล์
-
Markdown ฟอร์แมตที่ปรับให้เหมาะกับ AI
- โมเดลภาษานั้นไม่ได้ parse JSON แต่ ทำนายโทเค็น ดังนั้น JSON ของ Jupyter ที่ซ้อนลึกจึงไม่มีประสิทธิภาพใน context window
- ฟอร์แมตมาตรฐานของ Jupyter เก็บ source เป็นอาร์เรย์ของสตริง, output เป็น base64 blob และ metadata เป็นโครงสร้างซ้อนหลายชั้น ทำให้ในมุมของ LLM โทเค็น 30~40% ถูกใช้ไปกับอักขระโครงสร้างอย่างวงเล็บปีกกา วงเล็บเหลี่ยม และ escape โดยแทบไม่มีความหมาย
- Markdown ทั่วไปแม้จะมีประสิทธิภาพด้านโทเค็น แต่ก็คลุมเครือมาก
- แยกไม่ออกว่า
#เป็น Markdown heading หรือ Python comment - แยกไม่ออกว่า code fence เป็นเซลล์ของโน้ตบุ๊กหรือตัวอย่างในเอกสาร
- หากบอกว่า "ช่วยแก้ error ในเซลล์ที่ 7" ก็ไม่มีตัวบ่งชี้เชิงโครงสร้างที่ใช้ระบุตำแหน่งเซลล์ได้อย่างเสถียร
- แยกไม่ออกว่า
- เพื่อแก้ปัญหานี้จึงออกแบบ ฟอร์แมต sentinel แบบรายบรรทัด
- ใช้ sentinel เช่น
@@notebook,@@cell,@@outputเพื่อกำหนดขอบเขตของโครงสร้างอย่างชัดเจน - ในบรรทัด sentinel จะระบุ metadata แบบ inline JSON เช่น ประเภทเซลล์ ดัชนี และจำนวนครั้งที่รัน เพื่อให้สอดคล้องกับวิธีที่กลไก attention ค้นหาข้อมูล
- ใช้ code fence ที่มี language hint เพื่อกระตุ้นการเรียนรู้ syntax ของโมเดล
- แต่ละบล็อกเซลล์เป็นหน่วยสมบูรณ์ในตัวเอง จึง เสียหายแบบค่อยเป็นค่อยไปเมื่อถูกตัด ต่างจาก JSON ที่หากขาดตรงจุดเดียวโครงสร้างทั้งหมดอาจพัง
- ใช้ sentinel เช่น
-
การออกแบบที่ประกอบกันได้
- ตามแนวทาง Unix โดยรองรับ plain text output, stdin และ exit code ที่คาดเดาได้
- สำหรับเอเจนต์ คำสั่งเชลล์เพียงครั้งเดียวสามารถแทนการเรียกเครื่องมือหลายรอบและการ parse ระหว่างทางได้
- งานอย่าง “เพิ่มส่วนสรุปลงในโน้ตบุ๊กแล้วรัน” สามารถทำการเพิ่มเซลล์ รัน และอ่านผลลัพธ์ ได้ภายในการเรียกเชลล์ครั้งเดียว
- เชื่อมคำสั่งในรูปแบบ
nb cell add ... && nb execute ... && nb read ... - เอเจนต์จึงรับเฉพาะผลลัพธ์ที่ต้องการ โดยไม่ต้องอ่านทั้งโน้ตบุ๊กใหม่ทั้งหมด
- เชื่อมคำสั่งในรูปแบบ
- หลักการเดียวกันนี้ยังใช้กับการดีบักด้วย
nb search analysis.ipynb --with-errorsเพียงครั้งเดียวจะคืนเฉพาะเซลล์ที่มีข้อผิดพลาด โดยไม่สิ้นเปลืองโทเค็นกับเซลล์ที่รันสำเร็จ
-
การอ้างอิงเซลล์อย่างเสถียร
- รองรับการอ้างอิงเซลล์ 2 แบบ
- อิงดัชนี
--cell-index 0(รองรับ negative indexing โดย-1หมายถึงเซลล์สุดท้าย) - อิง ID
--cell f68t57(ไม่เปลี่ยนแม้เซลล์จะถูกย้ายตำแหน่ง)
- อิงดัชนี
- สามารถอ้างอิงตามตำแหน่งได้เช่น
nb cell update ... --cell-index 0 --source "x = 42" - หรืออ้างอิงด้วย stable ID เช่น
nb cell update ... --cell ce456 --source "print('Done')"ซึ่งปลอดภัยแม้มีการจัดลำดับเซลล์ใหม่
- รองรับการอ้างอิงเซลล์ 2 แบบ
-
ความสามารถในการค้นหาที่ทรงพลัง
- ค้นหาตำแหน่งได้อย่างรวดเร็วจากเนื้อหา ประเภทเซลล์ และข้อผิดพลาดตอนรัน
- ค่าเริ่มต้นจะจับคู่กับ source code ของเซลล์ และสามารถขยายไปยัง output ที่รันได้ด้วย scope filter
- ค้นหารูปแบบด้วย
nb search analysis.ipynb "import pandas" - ดึงเฉพาะเซลล์ที่มีข้อผิดพลาดด้วย
nb search analysis.ipynb --with-errors - ค้นหาใน output ด้วย
nb search analysis.ipynb "KeyError" --scope output - กรองตามประเภทเซลล์ด้วย
nb search analysis.ipynb "TODO" --cell-type markdown
- ค้นหารูปแบบด้วย
- เอเจนต์สามารถใช้
--with-errorsเพื่อ รับและประมวลผลเฉพาะเซลล์ที่ล้มเหลว และผสานกับ--scope outputเพื่อค้นหา error traceback ได้โดยตรง - มนุษย์ก็สามารถใช้เพื่อตรวจสอบ deprecated API, ค้นหาตำแหน่งฟังก์ชันในโน้ตบุ๊กขนาดใหญ่ หรือดึง pattern ก่อน refactor ได้เช่นกัน
-
การจัดการหลายเซลล์แบบเป็นชุด
- การเพิ่มลำดับเซลล์อย่างหัวข้อ Markdown → โค้ดตั้งค่า → การวิเคราะห์ เป็น pattern ที่พบบ่อย และหากต้องเพิ่มทีละเซลล์จะทำให้จำนวนรอบโต้ตอบและภาระในการจัดการดัชนีเพิ่มขึ้น
- รองรับ การเพิ่มหลายเซลล์ในการเรียกครั้งเดียวด้วย sentinel format
- สามารถรวมบล็อก
@@markdown,@@codeไว้ใน heredoc แล้วส่งครั้งเดียว - รองรับฟอร์แมต JSON เต็มรูปแบบในลักษณะ
@@cell {"cell_type": "..."}ด้วย
- สามารถรวมบล็อก
- ใช้งานร่วมกับ stdin ได้ จึงจัดองค์ประกอบเซลล์ในสคริปต์และ pipeline ได้ง่าย
printf '@@markdown\n## Summary\n\n@@code\ndf.describe()\n' | nb cell add report.ipynb --source -
- แนวคิดการประมวลผลแบบเป็นชุดเดียวกันนี้ยังใช้กับการรันและการลบด้วย
- รันเป็นช่วงด้วย
nb execute analysis.ipynb --start 2 --end 5 - ลบเซลล์ที่กำหนดด้วย
nb cell delete analysis.ipynb -i 0 -i 2 - ลบตามช่วงด้วย
nb cell delete analysis.ipynb --range 0:3
- รันเป็นช่วงด้วย
-
การรันที่รับรู้สภาพแวดล้อม
nb connect,nb execute,nb createรองรับแฟลก--uv,--pixiเพื่อค้นหา Jupyter server และ kernel ผ่าน environment manager ที่ระบุnb status --pythonจะคืนค่า command prefix สำหรับรัน Python ใน environment เดียวกับ kernel ที่เชื่อมต่ออยู่- ตัวอย่างค่าที่คืน:
"uv run","pixi run"และในกรณีของ system Python จะเป็นค่าว่าง - สามารถใช้ใน pipeline ในรูปแบบ
$(nb status --python) python -c "..."
- ตัวอย่างค่าที่คืน:
กรณีใช้งานจริง
-
AI agent workflow
- สามารถเชื่อมคำสั่งค้นหาเซลล์ที่ล้มเหลว → แก้โค้ด → รันซ้ำ เพื่อ จัดการโน้ตบุ๊กเป็นส่วนหนึ่งของ workflow การวิเคราะห์
nb search data_analysis.ipynb --with-errorsnb cell update data_analysis.ipynb --cell-index 3 --source "df = pd.read_csv('data.csv', encoding='utf-8')"nb execute data_analysis.ipynb --cell-index 3
- สามารถเชื่อมคำสั่งค้นหาเซลล์ที่ล้มเหลว → แก้โค้ด → รันซ้ำ เพื่อ จัดการโน้ตบุ๊กเป็นส่วนหนึ่งของ workflow การวิเคราะห์
-
การผสานกับ CI/CD
- ใช้ทำ การทดสอบและตรวจสอบโน้ตบุ๊กแบบอัตโนมัติ ใน continuous integration pipeline
- รันด้วย
nb execute pipeline.ipynb --allow-errorsแล้วตรวจข้อผิดพลาดด้วยnb search ... --with-errorsเพื่อให้คืน exit code 1 เมื่อพบปัญหา - ล้าง output ก่อนคอมมิตด้วย
nb output clear
- รันด้วย
- ใช้ทำ การทดสอบและตรวจสอบโน้ตบุ๊กแบบอัตโนมัติ ใน continuous integration pipeline
-
การสร้างโน้ตบุ๊กแบบโปรแกรม
- สร้างเอกสาร รายงาน และการวิเคราะห์โดยอัตโนมัติ
- สร้าง report notebook ด้วย
nb create report.ipynb - เพิ่มชื่อเรื่อง บทนำ และโค้ดวิเคราะห์พร้อมกันด้วยคำสั่ง multi-cell แล้วเติม output ด้วย
nb execute
- สร้าง report notebook ด้วย
- สร้างเอกสาร รายงาน และการวิเคราะห์โดยอัตโนมัติ
-
การดีบักโน้ตบุ๊กในสภาพแวดล้อมจริง
- วินิจฉัยปัญหาในโน้ตบุ๊กที่ deploy แล้วได้อย่างรวดเร็ว
- ดึงเซลล์ที่มีข้อผิดพลาดด้วย
nb search failing_notebook.ipynb --with-errors - ค้นหาการใช้ deprecated API ด้วย
nb search analysis.ipynb "pandas.np" - ค้นหา pattern ที่อาจเสี่ยงด้านความปลอดภัยด้วย
nb search notebook.ipynb "eval(" - ตรวจดู output ทั้งหมดของเซลล์เฉพาะด้วย
nb read failing_notebook.ipynb --cell-index 5 - ตรวจสอบความสามารถในการทำซ้ำในสภาพสะอาดด้วย
nb execute failing_notebook.ipynb --restart-kernel
- ดึงเซลล์ที่มีข้อผิดพลาดด้วย
- วินิจฉัยปัญหาในโน้ตบุ๊กที่ deploy แล้วได้อย่างรวดเร็ว
ตัวอย่างการทำงานจริง
-
Example 1: สร้างโน้ตบุ๊กสอน reinforcement learning สำหรับ LLM ด้วย Claude
- พรอมป์ต์ของผู้ใช้: ให้สร้างโน้ตบุ๊กที่ครอบคลุมแนวคิดหลักอย่าง policy model, reward model, KL divergence penalty, PPO, GRPO และอธิบายกลไกการทำงานในแต่ละเซลล์
- ใช้ โมเดลของเล่นขนาดเล็ก ที่อิงคำศัพท์ขนาดเล็กและ GRU เพื่อให้รันครบทั้งหมดบน CPU ได้โดยไม่ต้องใช้ API key
-
Example 2: แก้หลายบั๊กในโน้ตบุ๊กด้วย Codex
- พรอมป์ต์ของผู้ใช้: แก้
churn_analysis.ipynbซึ่งไม่ได้อัปเดตมาตั้งแต่หลังปี 2023 ให้รันได้จนจบอย่างเรียบร้อย โดยระบุ แก้ไข และตรวจสอบแต่ละเซลล์ที่ล้มเหลว พร้อมเพิ่มโน้ต Markdown เหนือเซลล์ที่แก้เพื่ออธิบายว่าปัญหาคืออะไรและแก้อย่างไร - บั๊ก 4 รายการที่ Codex แก้ไข
- path ไฟล์ที่ hardcode ไว้
DataFrame.append()ที่ ถูกลบออกใน pandas 2.0sklearn.cross_validationที่ถูกลบออกใน sklearn 0.20plot_confusion_matrixที่ถูกลบออกใน sklearn 1.2
- หลังแก้ไขแล้วมีการยืนยันว่าโน้ตบุ๊กรันได้ครบแบบ end-to-end
- พรอมป์ต์ของผู้ใช้: แก้
เริ่มต้นใช้งาน
- มี 3 วิธีติดตั้ง: สคริปต์ติดตั้ง,
cargo install nb-cliและการ build จากซอร์ส (cargo build --release) - เมื่อ build แล้ว ไบนารีจะถูกสร้างที่
target/release/nb - หากต้องการให้ AI agent ใช้ nb กับทุกงานที่เกี่ยวกับโน้ตบุ๊ก รองรับ คำสั่งติดตั้ง skill
npx skills install jupyter-ai-contrib/nb-cli
นักพัฒนาและการมีส่วนร่วม
- มีผู้ร่วมพัฒนา 3 คนซึ่งเป็นผู้มีส่วนร่วมในโปรเจกต์ Jupyter จาก AWS
- Andrii Ieroshenko: AWS Software Development Engineer, ผู้มีส่วนร่วมระยะยาวกับ JupyterLab และ Jupyter AI, สมาชิก Jupyter Media Strategy Working Group
- Brian Granger: AWS Senior Principal Technologist, ผู้ร่วมก่อตั้ง Project Jupyter, สมาชิกบอร์ดของ Jupyter และ PyTorch Foundation
- Piyush Jain: AWS Principal Engineer, ดูแลด้าน Jupyter และ Agentic AI, สมาชิก Jupyter Server Council
- nb-cli ยังอยู่ในระยะเริ่มต้น และขอให้ผู้ใช้ช่วยติดตั้งและทดลองใช้งาน จากนั้นเปิด GitHub issue, เข้าร่วมดิสคัสชันใน
jupyter-ai-contribและร่วมส่ง bug report, feature request หรือ PR
1 ความคิดเห็น
เขียนโดยเน้นกรณีตัวอย่าง เลยมีอะไรให้อ้างอิงเยอะมากครับ!