สร้าง AI Agent สกัด Flashcards จากโน้ตใน Obsidian: บูสต์พลังการเรียนรู้แบบ Active Recall ด้วย Python + Ollama
เปลี่ยนคลังโน้ตความรู้ใน Obsidian ให้เป็นบัตรคำถาม-คำตอบ (Flashcards) โดยอัตโนมัติด้วย AI Agent บนเครื่องคุณเอง ช่วยประหยัดเวลาและเพิ่มประสิทธิภาพในการเรียนรู้แบบออฟไลน์ 100%
สำหรับผู้ที่ใช้งานระบบ Second Brain หรือจดบันทึกความรู้ใน Obsidian เป็นประจำ สิ่งท้าทายที่สุดหลังจากจดโน้ตเสร็จแล้วคือ \"การทบทวนและจดจำ\" ข้อมูลเหล่านั้นเพื่อนำไปใช้งานจริง เทคนิคการเรียนรู้ที่ได้รับการยอมรับในระดับสากลว่ามีประสิทธิภาพสูงสุดคือ Active Recall (การทดสอบดึงความรู้จากสมอง) และ Spaced Repetition (การทบทวนซ้ำตามระยะเวลาที่กำหนด) ซึ่งส่วนใหญ่จะทำผ่านระบบบัตรคำถาม-คำตอบ หรือ Flashcards
อย่างไรก็ตาม การต้องมานั่งอ่านโน้ตของตัวเองทีละหน้า แล้วคิดตั้งคำถามพร้อมคำตอบเพื่อสร้างเป็น Flashcard แผ่นต่อแผ่น เป็นกระบวนการที่ใช้พลังงานสมองสูงมาก (High Cognitive Load) และน่าเบื่อหน่าย จนหลายคนถอดใจและเลิกทำไปในที่สุด
นี่คือหน้าที่สำคัญของ Cognitive Automation หรือการใช้โปรแกรมเข้ามาช่วยคิดและเตรียมงานแทนเรา ในบทความนี้ เราจะมาสร้าง AI Agent สกัด Flashcards ส่วนตัวที่ทำงานออฟไลน์ในเครื่อง 100% ด้วยภาษา Python และ Ollama เพื่อทำหน้าที่แปลงโน้ตดิบของคุณให้กลายเป็นระบบบัตรคำเพื่อใช้ทบทวนใน Obsidian ได้โดยอัตโนมัติ
ทำไมต้องเป็น Local AI ในการสร้าง Flashcards?
แม้ว่าในปัจจุบันจะมี AI บนคลาวด์คอยให้บริการอยู่มากมาย แต่การสกัดบัตรคำจากโน้ตส่วนตัวภายในเครื่องมีข้อดีเหนือกว่าอย่างสิ้นเชิงในด้าน:
- ความเป็นส่วนตัวสมบูรณ์แบบ (Absolute Privacy): โน้ตของคุณอาจมีความคิดส่วนตัว แผนธุรกิจ หรือเนื้อหาการวิจัยที่เป็นความลับ การประมวลผลผ่าน Ollama ในเครื่องทำให้ข้อมูลทุกอย่างปลอดภัยจากบุคคลภายนอกและไม่เสี่ยงต่อการรั่วไหล
- ปรับแต่งการตั้งคำถามได้เอง: คุณสามารถแก้ไขสคริปต์เพื่อควบคุมจำนวน ความยากง่าย หรือเน้นประเด็นประเภทใดประเภทหนึ่งในโน้ตตามสไตล์การเรียนรู้ของคุณเอง
- ลดอุปสรรคและไร้ค่าใช้จ่าย: ทำงานแบบออฟไลน์ได้ทุกที่ ไม่มีข้อจำกัดด้านเครือข่าย และไม่ต้องจ่ายค่าสมาชิก API รายเดือนใดๆ
โครงสร้างการทำงานของ Flashcard Agent
ระบบจะทำงานร่วมกันสามส่วนหลักผ่านการทำงานแบบอัตโนมัติ: 1. การคัดกรองโน้ต: สแกนหาไฟล์โน้ต Markdown ใน Obsidian Vault ที่ติดแท็ก #study หรือ #flashcard และตรวจสอบว่าโน้ตนั้นยังไม่มีหัวข้อ ## Flashcards เพื่อป้องกันการทำงานซ้ำซ้อน 2. การสกัดเนื้อหาด้วย LLM: ส่งเนื้อหาในโน้ตไปยัง Ollama เพื่อให้โมเดลภาษาช่วยวิเคราะห์แนวคิดหลักและตั้งคำถาม-คำตอบในรูปแบบที่เข้ากันได้กับปลั๊กอินยอดนิยมใน Obsidian 3. บันทึกข้อมูลกลับ: เขียนบัตรคำที่สร้างได้ต่อท้ายไฟล์โน้ตเดิมทันทีโดยไม่ต้องผ่านโปรแกรมอื่น
การเตรียมความพร้อมก่อนเริ่มต้น
โปรดตรวจสอบให้แน่ใจว่าคุณติดตั้งสิ่งเหล่านี้ในเครื่องคอมพิวเตอร์ของคุณแล้ว: * Python 3: สำหรับรันสคริปต์ * Ollama: ตัวขับเคลื่อนโมเดลออฟไลน์ (ดาวน์โหลดจาก ollama.com) * Obsidian: แอปจัดการโน้ตพร้อมติดตั้งปลั๊กอิน Obsidian Spaced Repetition (เลือกติดตั้งเพิ่มเติมผ่าน Community Plugins)
จากนั้นเปิด Terminal แล้วเรียกใช้โมเดลภาษาที่จะมาวิเคราะห์สรุปข้อมูล ในที่นี้ขอแนะนำ gemma2 (ขนาด 9B) ซึ่งฉลาดและเข้าใจบริบทภาษาไทยได้ดีเยี่ยม:
ollama pull gemma2
สคริปต์ Python สำหรับ AI Flashcard Agent
ให้สร้างไฟล์ชื่อ flashcard_generator.py ไว้ในคอมพิวเตอร์ของคุณและคัดลอกโค้ดด้านล่างนี้ไปใช้งาน สคริปต์นี้เขียนขึ้นโดยอ้างอิงจากไลบรารีมาตรฐานของ Python ทั้งหมด ทำให้คุณรันได้ทันทีโดยไม่ต้องพิมพ์ pip install เพิ่มเติม:
import urllib.request
import json
import os
import glob
# กำหนดโฟลเดอร์คลังโน้ต Obsidian ของคุณ (กรุณาปรับปรุงพาธให้ตรงกับเครื่องของคุณ)
OBSIDIAN_VAULT_PATH = "/home/linn/notes"
LLM_MODEL = "gemma2" # สามารถปรับเปลี่ยนเป็น llama3 หรือรุ่นที่เหมาะสมได้
def get_target_notes(vault_path):
"""ค้นหาไฟล์โน้ต Markdown ทั้งหมดในคลังที่ติดแท็กและยังไม่มี Flashcards"""
search_pattern = os.path.join(vault_path, "**", "*.md")
all_files = glob.glob(search_pattern, recursive=True)
target_files = []
for filepath in all_files:
if os.path.basename(filepath).startswith("."):
continue
try:
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
# ตรวจสอบหาแท็กทริกเกอร์การทบทวน
if "#study" in content or "#flashcard" in content:
# ตรวจสอบป้องกันการสร้างซ้ำซ้อน
if "## Flashcards" not in content:
target_files.append(filepath)
except Exception as e:
print(f"ไม่สามารถอ่านไฟล์ {filepath} ได้: {e}")
return target_files
def generate_flashcards(note_content):
"""ส่งเนื้อหาโน้ตให้ Ollama วิเคราะห์และจัดทำบัตรคำ"""
prompt = f"""
คุณคือ AI Agent ผู้เชี่ยวชาญด้านการเรียนรู้และเทคนิคการจำอัจฉริยะ (Active Recall & Spaced Repetition)
หน้าที่ของคุณคือการอ่านเนื้อหาในโน้ตด้านล่างนี้ และสร้างบัตรคำถาม-คำตอบ (Flashcards) คุณภาพสูงเพื่อใช้ในการทบทวนความรู้
เนื้อหาโน้ต:
{note_content}
---
คำสั่งและเงื่อนไขการทำงาน:
1. สร้างบัตรคำถาม-คำตอบ (Flashcards) จำนวน 3-7 ใบตามระดับปริมาณและความสำคัญของข้อมูลในโน้ต
2. คำถามต้องมุ่งเน้นไปที่นิยามสำคัญ แนวคิดหลัก เหตุและผล หรือสมมติฐานสำคัญ ไม่ควรถามเรื่องทั่วไปที่ง่ายเกินไป
3. ตอบกลับในรูปแบบของปลั๊กอิน Obsidian Spaced Repetition โดยใช้เครื่องหมายโคลอนสองตัว (::) คั่นระหว่างคำถามและคำตอบเท่านั้น เช่น:
คำถามเกี่ยวกับแนวคิด? :: คำตอบของแนวคิดนั้น
คำนิยามของหัวข้อ? :: คำอธิบายคำนิยามสั้นๆ
4. ตอบกลับเฉพาะคู่บัตรคำถาม-คำตอบเท่านั้น ห้ามเขียนเกริ่นนำ ห้ามพูดทักทาย หรือเขียนข้อความอธิบายขั้นตอนการทำงานเด็ดขาด
5. เขียนเป็นภาษาไทย
"""
url = "http://localhost:11434/api/generate"
payload = {
"model": LLM_MODEL,
"prompt": prompt,
"stream": False,
"options": {
"temperature": 0.3 # ใช้ค่าความสร้างสรรค์ต่ำ เพื่อรักษาความถูกต้องของข้อมูลความรู้
}
}
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
url,
data=data,
headers={"Content-Type": "application/json"},
method="POST"
)
try:
with urllib.request.urlopen(req) as response:
res_body = response.read().decode("utf-8")
res_json = json.loads(res_body)
return res_json.get("response", "").strip()
except Exception as e:
print(f"ล้มเหลวในการเชื่อมต่อกับ Ollama: {e}")
return None
def write_flashcards_to_note(filepath, flashcards):
"""เขียน Flashcards ต่อท้ายโน้ตเดิม"""
if not flashcards:
return False
try:
with open(filepath, "a", encoding="utf-8") as f:
f.write("\n\n---\n## Flashcards\n\n")
f.write(flashcards)
f.write("\n")
return True
except Exception as e:
print(f"ล้มเหลวในการเขียนไฟล์ {filepath}: {e}")
return False
def main():
print("เริ่มระบบ Cognitive Automation สำหรับสกัด Flashcards...")
target_notes = get_target_notes(OBSIDIAN_VAULT_PATH)
if not target_notes:
print("ไม่พบโน้ตที่มีแท็ก #study หรือ #flashcard และยังไม่ได้ประมวลผลเพิ่ม")
return
print(f"พบโน้ตเป้าหมายทั้งหมด {len(target_notes)} โน้ต")
for filepath in target_notes:
note_name = os.path.basename(filepath)
print(f"\nกำลังเริ่มทำงานกับโน้ต: {note_name}")
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
print("กำลังส่งประมวลผลผ่านโมเดล LLM...")
flashcards = generate_flashcards(content)
if flashcards:
print("สร้างคู่บัตรคำสำเร็จ! กำลังเขียนข้อมูลกลับเข้าโน้ต...")
if write_flashcards_to_note(filepath, flashcards):
print(f"อัปเดตโน้ต {note_name} เรียบร้อยแล้ว")
else:
print(f"ไม่สามารถบันทึกบัตรคำลงในโน้ต {note_name} ได้")
else:
print(f"ข้ามการทำงานกับ {note_name} เนื่องจากข้อผิดพลาดในการประมวลผล")
if __name__ == "__main__":
main()
วิธีการนำไปใช้งานในชีวิตประจำวัน
- การจดบันทึกปรกติ: เมื่อคุณเขียนโน้ตสรุปหรือเรียนรู้เรื่องใหม่ๆ ใน Obsidian (เช่น โน้ตวิชาคอมพิวเตอร์เน็ตเวิร์ก หรือสรุปคู่มือการใช้ Docker) ให้หยอดแท็ก
#studyหรือ#flashcardไว้ที่ส่วนใดส่วนหนึ่งของหน้าโน้ต - รันสคริปต์อัตโนมัติ: เมื่อจดโน้ตเสร็จเรียบร้อยในแต่ละวัน ให้รันคำสั่งใน Terminal:
bash python flashcard_generator.py - ผลลัพธ์ในหน้าโน้ต: สคริปต์จะเติมข้อมูลท้ายโน้ตให้คุณโดยอัตโนมัติ เช่น:
markdown ## Flashcards TCP คืออะไร? :: โปรโตคอลการรับส่งข้อมูลที่รับประกันความถูกต้องของข้อมูล (Connection-oriented) IP Address ทำหน้าที่อะไร? :: ระบุตำแหน่งของอุปกรณ์ที่เชื่อมต่อภายในระบบเครือข่าย - เปิดเล่นใน Obsidian: เมื่อคุณเปิดโปรแกรม Obsidian ขึ้นมา ปลั๊กอิน Spaced Repetition จะดึงบัตรคำเหล่านี้ไปทบทวนในโหมดทดสอบความจำ (Flashcard Review) อัตโนมัติ โดยสัญลักษณ์
::จะทำหน้าที่แบ่งด้านคำถามและด้านคำตอบให้พร้อมใช้งานทันที
บทสรุป
การสร้างสมองส่วนที่สอง (Second Brain) ไม่ใช่แค่การสะสมข้อมูลให้เยอะขึ้นเรื่อยๆ แต่คือการเปลี่ยนข้อมูลเหล่านั้นให้กลายเป็น \"ปัญญาความรู้\" ที่เราจดจำและเรียกใช้งานได้จริง การใช้ระบบ Cognitive Automation มาช่วยสกัด Flashcards อัตโนมัติช่วยลดภาระที่น่าเบื่อหน่ายในการคิดคำถาม-คำตอบลงไปได้มากกว่า 80% ปลดปล่อยให้สมองของคุณมีสมาธิอยู่กับสิ่งที่มีค่าที่สุด นั่นคือการคิด วิเคราะห์ และทำความเข้าใจข้อมูลครับ