📗 บทที่ 1 — Second Brain แรกของคุณใน 20 บรรทัด¶
คู่กับ: หนังสือบทที่ 1 · สไลด์ Artifact "เห็น Vector Search ด้วยตา"
รันจากบนลงล่าง — จบ notebook นี้คุณจะมี second brain ที่ค้นด้วย ความหมาย ได้จริง และเจอ "ปริศนา" ที่จะพาไปบทที่ 2
ติดตั้ง (เซลล์เดียว)¶
In [1]:
import sys
IN_COLAB = 'google.colab' in sys.modules
if IN_COLAB:
%pip -q install chromadb sentence-transformers
import chromadb
print('chromadb', chromadb.__version__, '· พร้อม ✓ (เครื่องเรา: ใช้ kernel vector-book)')
chromadb 1.5.9 · พร้อม ✓ (เครื่องเรา: ใช้ kernel vector-book)
1) เปิดสมองที่สอง — ข้อมูลอยู่ในโฟลเดอร์ ไม่มี server¶
In [2]:
client = chromadb.PersistentClient(path='./chroma_db')
col = client.get_or_create_collection('second_brain_en')
print('collection พร้อม:', col.name)
collection พร้อม: second_brain_en
2) ใส่โน้ต (เริ่มด้วยอังกฤษ — เดี๋ยวรู้ว่าทำไม) · upsert = รันซ้ำไม่ duplicate¶
In [3]:
col.upsert(
ids=['e1', 'e2', 'e3'],
documents=[
'How to teach students vector search: start with cosine similarity',
'Cold brew recipe: 100g coffee, 1L water, steep 18 hours',
'Meeting with Professor Fon about the workshop on July 26',
],
metadatas=[{'folder': 'teaching'}, {'folder': 'recipes'}, {'folder': 'meetings'}],
)
print('โน้ตในสมอง:', col.count(), 'ชิ้น')
โน้ตในสมอง: 3 ชิ้น
3) ค้นด้วยความหมาย — ไม่มีคำตรงกันก็เจอ¶
โน้ตเขียนว่า Meeting แต่เราค้นว่า appointment — คนละคำ ความหมายเดียวกัน
In [4]:
res = col.query(query_texts=['who do I have an appointment with?'], n_results=1)
print('เจอ:', res['documents'][0][0])
เจอ: Meeting with Professor Fon about the workshop on July 26
✅ วัดผลตัวเอง #1¶
รันเซลล์ล่าง — ผ่าน = เข้าใจ upsert/query แล้ว
In [5]:
res = col.query(query_texts=['who do I have an appointment with?'], n_results=1)
assert 'Meeting' in res['documents'][0][0], 'ควรเจอโน้ต Meeting!'
assert col.count() == 3, 'ควรมี 3 ชิ้น (upsert ซ้ำต้องไม่เพิ่ม)'
print('✅ ผ่าน! "appointment" เจอ "Meeting" — ไม่มีคำตรงกันเลยสักตัว')
✅ ผ่าน! "appointment" เจอ "Meeting" — ไม่มีคำตรงกันเลยสักตัว
🔍 ปริศนาก่อนจบบท — ทีนี้ลองภาษาไทยบ้าง¶
ใส่โน้ตไทยชุดเดียวกัน แล้วค้นไทย — สังเกตผลให้ดี
In [6]:
col_th = client.get_or_create_collection('second_brain_th')
col_th.upsert(
ids=['n1', 'n2', 'n3', 'n4', 'n5'],
documents=[
'วิธีสอนนักศึกษาให้เข้าใจ vector search: เริ่มจาก cosine similarity ก่อน',
'สูตรกาแฟ cold brew: กาแฟ 100g น้ำ 1L แช่ 18 ชั่วโมง',
'ประชุมกับอาจารย์ฝน เรื่อง workshop วันที่ 26 กรกฎาคม ที่มหาวิทยาลัย',
'Embedding คือการแปลงข้อความเป็นตัวเลขหลายมิติที่เก็บความหมาย',
'รายการซื้อของ: นม ไข่ ขนมปัง กาแฟดริป',
],
metadatas=[{'folder': 'teaching'}, {'folder': 'recipes'}, {'folder': 'meetings'},
{'folder': 'teaching'}, {'folder': 'personal'}],
)
for q in ['นัดหมายกับใครบ้าง', 'อยากสอนเรื่อง AI ค้นหา', 'เครื่องดื่ม']:
res = col_th.query(query_texts=[q], n_results=1)
print(f'Q: {q}')
print(f' คะแนน {1-res["distances"][0][0]:+.3f} {res["documents"][0][0][:55]}')
print()
print('❓ อังกฤษเวิร์กสวยงาม แต่ไทยจับคู่เพี้ยน + คะแนนติดลบ — ทำไม?!')
print('→ คำตอบ + วิธีแก้ 30 บรรทัด อยู่ ch02_fix_thai_bge_m3.ipynb')
Q: นัดหมายกับใครบ้าง คะแนน -0.130 รายการซื้อของ: นม ไข่ ขนมปัง กาแฟดริป Q: อยากสอนเรื่อง AI ค้นหา คะแนน +0.531 ประชุมกับอาจารย์ฝน เรื่อง workshop วันที่ 26 กรกฎาคม ที
Q: เครื่องดื่ม คะแนน -0.130 รายการซื้อของ: นม ไข่ ขนมปัง กาแฟดริป ❓ อังกฤษเวิร์กสวยงาม แต่ไทยจับคู่เพี้ยน + คะแนนติดลบ — ทำไม?! → คำตอบ + วิธีแก้ 30 บรรทัด อยู่ ch02_fix_thai_bge_m3.ipynb
📊 เห็นภาพ — query ไทยยังอ่อน (ปริศนาของบทนี้)¶
In [7]:
# @@VIZ@@
import matplotlib, matplotlib.pyplot as plt
from matplotlib import font_manager as _fm
_av={f.name for f in _fm.fontManager.ttflist}
for _f in ['Thonburi','Loma','Sarabun','Noto Sans Thai','TH Sarabun New']:
if _f in _av: matplotlib.rcParams['font.family']=_f; break
matplotlib.rcParams['axes.unicode_minus']=False
qs=['นัดหมายกับใครบ้าง','อยากสอนเรื่อง AI ค้นหา','เครื่องดื่ม']
sc=[1-col_th.query(query_texts=[q],n_results=1)['distances'][0][0] for q in qs]
plt.figure(figsize=(7,3.4))
c=['#1baf7a' if s>0.3 else '#e34948' for s in sc]
plt.barh(qs[::-1],sc[::-1],color=c[::-1]); plt.axvline(0,color='#888',lw=1)
plt.title('บทที่ 1 — คะแนน top-1 ของ query ไทย (default embedder)')
plt.xlabel('cosine · แดง = ต่ำ/ติดลบ = ปัญหา → บทที่ 2 แก้'); plt.tight_layout(); plt.show()
/var/folders/lf/s98q6y892sl__0brv1tyn0ch0000gn/T/ipykernel_98636/3228679908.py:14: UserWarning: Glyph 8594 (\N{RIGHTWARDS ARROW}) missing from font(s) Thonburi.
plt.xlabel('cosine · แดง = ต่ำ/ติดลบ = ปัญหา → บทที่ 2 แก้'); plt.tight_layout(); plt.show()
/opt/Code/github.com/nat-build-with-oracle/ajfon-oracle/book/.venv/lib/python3.12/site-packages/IPython/core/pylabtools.py:170: UserWarning: Glyph 8594 (\N{RIGHTWARDS ARROW}) missing from font(s) Thonburi.
fig.canvas.print_figure(bytes_io, **kw)
🏋️ แบบฝึก¶
- เพิ่มโน้ตอังกฤษของคุณ 3 ชิ้น แล้วค้นด้วยคำที่ไม่อยู่ในโน้ตแต่ความหมายใกล้
- ลอง query ไทยกับ collection ไทยอีก 2-3 คำ — เพี้ยนแบบเดียวกันไหม? จดไว้เทียบกับบทที่ 2
บทต่อไป: ch02_fix_thai_bge_m3.ipynb — แก้ปริศนาภาษาไทย