ถาม Claude เกี่ยวกับบริษัทของคุณ โน้ตของคุณ หรือไฟล์ของคุณ แล้วมันจะตอบไม่ได้เพราะมันไม่เคยเห็นข้อมูลเหล่านั้นมาก่อน มันรู้แค่สิ่งที่เรียนรู้จากข้อมูลฝึกฝน และข้อมูลของคุณไม่ได้อยู่ในนั้น
ระบบ RAG แก้ปัญหานี้ แทนที่จะตอบจากความจำ Claude จะค้นหาข้อมูลในเอกสารของคุณก่อน ดึงส่วนที่เกี่ยวข้องมา แล้วตอบจากสิ่งที่มันเจอจริงๆ ข้อมูลของคุณ เป็นแหล่งของมัน ไม่มีการเดาสุ่ม
ทำไมมันถึงดีกว่าการวางไฟล์ลงในแชทเฉยๆ:
ปรับขนาดได้ ฐานความรู้ทั้งหมดของคุณใส่ในแชทเดียวไม่พอ RAG เก็บทุกอย่างและดึงเฉพาะสิ่งที่แต่ละคำถามต้องการ
ถูกกว่า การวางไฟล์หมายความว่า Claude จะอ่านทั้งไฟล์ใหม่ทุกครั้งที่มีคำถาม RAG อ่านครั้งเดียว แล้วดึงเฉพาะส่วนที่เกี่ยวข้อง แทนที่จะส่งคู่มือขนาด 10,000 โทเค็นทุกครั้ง มันอาจส่งแค่ 500 โทเค็นของส่วนที่คุณต้องการ ระบบจริงลดการใช้โทเค็นได้ 80% หรือมากกว่า
แม่นยำกว่า ป้อนข้อความยาวๆ ให้โมเดล มันจะสูญเสียรายละเอียดตรงกลาง แต่ถ้าให้เฉพาะส่วนที่เกี่ยวข้อง คำตอบจะแม่นยำขึ้น
เป็นปัจจุบัน อัปเดตไฟล์ของคุณครั้งเดียว ระบบก็จะใช้เวอร์ชันล่าสุด ไม่ต้องวางไฟล์ใหม่
เมื่ออ่านคู่มือนี้จบ คุณจะได้ระบบ RAG ที่ทำงานกับไฟล์ของคุณเอง ทีละขั้นตอน โดยไม่ต้องมีปริญญาเอก
สิ่งที่คุณต้องมี
ก่อนจะแตะโค้ดใดๆ นี่คือรายการทั้งหมด ข่าวดี: เวอร์ชันนี้ใช้คีย์ API แค่หนึ่งอัน และทุกอย่างอื่นทำงานฟรีบนเครื่องของคุณ
1. Python 3.9 หรือใหม่กว่า เช็คว่ามีหรือไม่โดยเปิด Terminal (Terminal บน Mac, Command Prompt บน Windows) แล้วพิมพ์ python --version ถ้าเห็นเลขเช่น 3.11 ก็ใช้ได้ ถ้าไม่มี ให้ดาวน์โหลดจาก python.org แล้วติดตั้ง บน Windows ให้ติ๊ก "Add Python to PATH" ระหว่างติดตั้ง ไม่เช่นนั้นคำสั่งด้านล่างจะใช้ไม่ได้
2. Claude API key หนึ่งอัน พร้อมเครดิตเล็กน้อย นี่คือคีย์เดียวและเงินเดียวที่คู่มือนี้ต้องการ วิธีทำทีละขั้นตอน:
ไปที่ platform.claude.com แล้วล็อกอิน (หรือสมัคร) ที่นั่น
API ต้องมีเครดิตเป็นบวกจึงจะทำงานได้ ดังนั้นเติมเงินก่อน เมื่อระบบถาม ให้เลือกว่าเครดิตสำหรับตัวคุณหรือบริษัท จากนั้นคุณจะไปที่หน้าชำระเงิน เลือกตัวเลือก $5 "Starting out" นั้นเพียงพอแล้ว: ทุกอย่างอื่นในคู่มือนี้ฟรีและทำงานบนเครื่องของคุณ Claude จึงเป็นสิ่งเดียวที่เสียเงิน และแต่ละคำถามเสียเงินแค่เศษเสี้ยวเซนต์ เครดิตหมดอายุหลังจากซื้อ 1 ปี
หลังจากชำระเงิน คุณจะไปที่หน้า Console Dashboard คุณควรเห็นยอดเครดิต (เช่น $5.00) ที่มุมซ้ายบนใต้ "Organization credits"
จากนั้นรับคีย์ คลิก Get API key (มุมขวาบน) แล้ว Create Key ตั้งชื่ออะไรก็ได้ (เช่น my-rag-key) แล้วปล่อย workspace เป็น Default คลิก create แล้วคัดลอกสตริงที่แสดงขึ้นมา มันขึ้นต้นด้วย sk-ant- และคุณจะเห็นมันแค่ครั้งเดียว ดังนั้นวางไว้ที่ปลอดภัยสักครู่
นั่นคือการตั้งค่าทั้งหมด
ขั้นตอนที่ 1: เพิ่มคีย์และโหลดไฟล์ของคุณ
1. สร้างโฟลเดอร์โปรเจกต์ สร้างโฟลเดอร์ใหม่บน Desktop ชื่อ rag-project ทุกอย่างจะอยู่ที่นี่
2. เปิดเทอร์มินัล บน Mac: Cmd+Space, พิมพ์ Terminal, Enter บน Windows: ปุ่ม Start, พิมพ์ cmd, Enter
3. ชี้เทอร์มินัลไปที่โฟลเดอร์ของคุณ พิมพ์ cd แล้วเว้นวรรค จากนั้นลากโฟลเดอร์ rag-project ไปที่หน้าต่างเทอร์มินัลแล้วกด Enter ทุกคำสั่งด้านล่างจะรันจากในโฟลเดอร์นี้
1cd Desktop/rag-project
4. ติดตั้งเครื่องมือ วางคำสั่งนี้ในเทอร์มินัลแล้วกด Enter (ครั้งแรกอาจใช้เวลาสักครู่):
1pip install anthropic chromadb sentence-transformers pypdf python-dotenv
ถ้าเจอ pip: command not found ให้ใช้ pip3 แทน pip เมื่อเทอร์มินัลแสดงบรรทัดใหม่โดยไม่มีข้อผิดพลาดสีแดง แสดงว่าเสร็จ
5. สร้างไฟล์โค้ดของคุณ ใน rag-project สร้างไฟล์ว่างชื่อ rag.py เปิดด้วยโปรแกรมแก้ไขข้อความใดก็ได้
6. สร้างไฟล์คีย์ของคุณ ในโฟลเดอร์เดียวกัน สร้างไฟล์ชื่อ .env (ขึ้นต้นด้วยจุด ไม่มีชื่อข้างหน้า) วางข้อความนี้ลงไป โดยใส่คีย์จริงที่คุณสร้างตอนตั้งค่าไว้หลังเครื่องหมาย = ไม่มีช่องว่าง ไม่มีเครื่องหมายคำพูด:
1ANTHROPIC_API_KEY=sk-ant-paste-your-real-key-here
การเก็บคีย์ไว้ใน .env แทนที่จะใส่ในโค้ดจะป้องกันไม่ให้คีย์รั่วไหลถ้าคุณแชร์สคริปต์หรืออัปโหลดขึ้น GitHub
7. โหลดคีย์ ใส่โค้ดนี้ไว้ที่ด้านบนของ rag.py:
1import os2from dotenv import load_dotenv34load_dotenv() # อ่านไฟล์ .env ของคุณ5api_key = os.getenv("ANTHROPIC_API_KEY")
8. สร้างฐานความรู้ของคุณ ใน rag-project สร้างโฟลเดอร์ชื่อ documents วางไฟล์ .txt, .md, หรือ .pdf ลงไป: โน้ตของคุณ, เอกสารผลิตภัณฑ์, บันทึกการประชุม, อะไรก็ได้
8.1. ถ้าคุณยังไม่มีไฟล์ ให้ใช้ไฟล์ทดสอบนี้ สร้างไฟล์ notes.txt ในโฟลเดอร์ documents แล้ววางข้อความนี้:
Project Northstar คือเครื่องมือภายในของเราสำหรับติดตามความคิดเห็นของลูกค้า เปิดตัวในเดือนมีนาคม 2026 และดูแลโดยทีมแพลตฟอร์ม วิศวกรนำคือ Dana Reyes ความคิดเห็นจะถูกตรวจสอบทุกวันศุกร์ Northstar แทนที่ระบบสเปรดชีตแบบเก่าที่เราใช้จนถึงปี 2025
ในตอนท้าย คุณจะถาม Claude เกี่ยวกับ Northstar และดูมันตอบจากไฟล์นี้โดยตรง
9. เพิ่มโค้ดที่อ่านไฟล์ของคุณ ใต้โค้ดจากขั้นตอนที่ 7 ใน rag.py:
1from pathlib import Path2from pypdf import PdfReader34def load_documents(folder="documents"):5 docs = []6 for file in Path(folder).iterdir():7 if file.suffix in [".txt", ".md"]:8 text = file.read_text(encoding="utf-8")9 docs.append({"source": file.name, "text": text})10 elif file.suffix == ".pdf":11 reader = PdfReader(str(file))12 text = "\n".join(page.extract_text() or "" for page in reader.pages)13 docs.append({"source": file.name, "text": text})14 return docs1516documents = load_documents()17print(f"Loaded {len(documents)} document(s).")
10. รันมัน บันทึก rag.py จากนั้นในเทอร์มินัล:
1python rag.py
คุณควรเห็น:
Loaded 1 document(s)
ถ้าคุณเห็น Loaded 0 document(s) แสดงว่าโฟลเดอร์ documents ว่างหรืออยู่ในตำแหน่งผิด มันต้องอยู่ภายใน rag-project โดยตรง ข้างๆ rag.py
ขั้นตอนที่ 2: แบ่งไฟล์ของคุณเป็น chunks
ตอนนี้แต่ละไฟล์เป็นข้อความก้อนใหญ่一塊 ก่อนที่เราจะค้นหามันได้ เราต้องตัดมันเป็นชิ้นเล็กๆ ที่เรียกว่า chunks นี่คือเหตุผล: เมื่อมีคนถามคำถาม ระบบจะหา chunks ที่ตรงกันและส่งเฉพาะส่วนนั้นไปให้ Claude ถ้า chunks ของคุณเป็นเอกสารทั้ง 50 หน้า คุณก็ส่งข้อมูลมากเกินไป ถ้าเป็นประโยคเดี่ยวๆ มันจะขาดบริบท ย่อหน้าสั้นๆ คือจุดที่เหมาะสม
1. เพิ่มโค้ดการแบ่ง chunk ใต้โค้ดจากขั้นตอนที่ 10 ใน rag.py:
1def chunk_text(text, chunk_size=500, overlap=100):2 words = text.split()3 chunks = []4 start = 05 while start < len(words):6 end = start + chunk_size7 chunk = " ".join(words[start:end])8 chunks.append(chunk)9 start = end - overlap # ถอยหลังเล็กน้อยเพื่อให้ chunks ซ้อนทับกัน10 return chunks
ตัวเลขสองตัวที่ต้องเข้าใจในภาษาธรรมดา:
- chunk_size=500 หมายถึงแต่ละ chunk มีประมาณ 500 คำ ใหญ่พอที่จะเก็บแนวคิดหนึ่งๆ ได้ เล็กพอที่จะคงความแม่นยำ
- overlap=100 หมายถึงแต่ละ chunk ซ้ำ 100 คำสุดท้ายของ chunk ก่อนหน้า สิ่งนี้สำคัญเพราะคำตอบอาจอยู่ตรงรอยต่อของสอง chunks พอดี ถ้าไม่มีการซ้อนทับ ประโยคที่ถูกแบ่งครึ่งอาจหายไป การซ้อนทับทำให้ไม่มีแนวคิดใดตกหล่น
2. แปลงทุกเอกสารเป็น chunks เพิ่มโค้ดนี้ด้านล่าง:
1all_chunks = []2for doc in documents:3 for chunk in chunk_text(doc["text"]):4 all_chunks.append({"source": doc["source"], "text": chunk})56print(f"Created {len(all_chunks)} chunk(s) from {len(documents)} document(s).")
สังเกตว่าแต่ละ chunk ติด source (ชื่อไฟล์ที่มันมา) มาด้วย เราจะเก็บสิ่งนี้ไว้ตลอดทาง เพื่อที่เมื่อ Claude ตอบในภายหลัง มันจะบอกคุณได้ว่าคำตอบมาจากไฟล์ไหน
3. รันมัน บันทึก rag.py จากนั้นในเทอร์มินัล:
1python rag.py
คุณควรเห็นอะไรทำนองนี้:
Loaded 1 document(s).
Created 1 chunk(s) from 1 document(s).
ไฟล์ทดสอบเล็กๆ กลายเป็นแค่ chunk เดียวเพราะมันสั้น เอกสารจริงจะสร้างหลาย chunk ถ้าคุณวาง PDF ยาวๆ ในโฟลเดอร์ คุณอาจเห็นหลายสิบหรือหลายร้อย chunks ซึ่งเป็นสิ่งที่คุณต้องการ
ขั้นตอนที่ 3: เปลี่ยน chunks ของคุณเป็น embeddings
นี่คือขั้นตอนที่ทำให้คอมพิวเตอร์ค้นหาด้วยความหมายแทนคำที่ตรงกัน แต่ละ chunk จะถูกแปลงเป็นชุดตัวเลข (embedding) ที่จับความหมายของมัน Chunks ที่มีความหมายคล้ายกันจะมีตัวเลขที่คล้ายกัน ต่อมาเมื่อมีคำถามเข้ามา เราจะเปลี่ยนคำถามเป็นตัวเลขเช่นกันและหา chunks ที่ใกล้เคียงที่สุด
โมเดลที่ทำสิ่งนี้ทำงานบนเครื่องของคุณในเครื่อง本地 มันดาวน์โหลดครั้งเดียว จากนั้นทำงานออฟไลน์และฟรี และไฟล์ของคุณไม่เคยออกจากเครื่องของคุณ
1. โหลดโมเดล embedding ใต้โค้ดจากขั้นตอนที่ 2 ใน rag.py:
1from sentence_transformers import SentenceTransformer23print("Loading the embedding model (first run downloads it, about 90 MB)...")4embedder = SentenceTransformer("all-MiniLM-L6-v2")
ครั้งแรกที่รัน มันจะดาวน์โหลดโมเดล ดังนั้นรอสักครู่ ครั้งต่อๆ ไปจะทันทีเพราะมันอยู่ในเครื่องของคุณแล้ว
2. แปลงทุก chunk เป็น embedding เพิ่มโค้ดนี้ด้านล่าง:
1chunk_texts = [chunk["text"] for chunk in all_chunks]2embeddings = embedder.encode(chunk_texts)34print(f"Created {len(embeddings)} embedding(s).")5print(f"Each embedding is a list of {len(embeddings[0])} numbers.")
embedder.encode(...) รับ list ของข้อความ chunk แล้วคืนค่า embedding หนึ่งตัวต่อ chunk เท่านั้นเอง
3. รันมัน บันทึก rag.py จากนั้นในเทอร์มินัล:
1python rag.py
ครั้งแรกจะหยุดชั่วคราวขณะดาวน์โหลดโมเดล จากนั้นคุณควรเห็นอะไรทำนองนี้:
Loaded 1 document(s).
Created 1 chunk(s) from 1 document(s).
Loading the embedding model (first run downloads it, about 90 MB)...
Created 1 embedding(s).
Each embedding is a list of 384 numbers.
บรรทัด "384 ตัวเลข" นั้นทำให้แนวคิดทั้งหมดเห็นภาพ: ข้อความของคุณกลายเป็นแถวตัวเลขที่คอมพิวเตอร์สามารถเปรียบเทียบได้ คุณไม่จำเป็นต้องอ่านหรือเข้าใจตัวเลขเหล่านั้นด้วยตนเอง ฐานข้อมูลในขั้นตอนต่อไปจะจัดการการเปรียบเทียบทั้งหมดให้คุณ
ถ้าการดาวน์โหลดล้มเหลวเนื่องจากข้อผิดพลาดการเชื่อมต่อ ให้รันคำสั่งอีกครั้ง มันจะเริ่มต่อจากจุดที่ค้างไว้
ขั้นตอนที่ 4: เก็บทุกอย่างในฐานข้อมูลเวกเตอร์ของคุณ
ตอนนี้เราจะใส่ chunks และ embeddings ของพวกมันลงใน Chroma ซึ่งเป็นฐานข้อมูลในเครื่องของคุณ นี่คือสิ่งที่ทำให้การค้นหาเร็ว: แทนที่จะเปรียบเทียบคำถามของคุณกับทุก chunk ด้วยมือทุกครั้ง Chroma เก็บพวกมันไว้พร้อมใช้งานและทำการจับคู่ให้คุณ มันบันทึกลงในโฟลเดอร์บนเครื่องของคุณ ดังนั้นคุณจึงสร้างมันเพียงครั้งเดียว
1. ตั้งค่าฐานข้อมูล ใต้โค้ดจากขั้นตอนที่ 3 ใน rag.py:
1import chromadb23client = chromadb.PersistentClient(path="chroma_db")4collection = client.get_or_create_collection("my_documents")
PersistentClient(path="chroma_db") บอกให้ Chroma บันทึกลงในโฟลเดอร์ชื่อ chroma_db (มันสร้างโดยอัตโนมัติ ข้างๆ สคริปต์ของคุณ) เนื่องจากบันทึกลงดิสก์ ข้อมูลของคุณจึงอยู่รอดหลังจากสคริปต์ทำงานเสร็จ collection คือกล่องที่มีชื่อที่ chunks ของคุณอาศัยอยู่
2. เพิ่ม chunks ของคุณลงในฐานข้อมูล เพิ่มโค้ดนี้ด้านล่าง:
1collection.add(2 ids=[str(i) for i in range(len(all_chunks))],3 embeddings=[emb.tolist() for emb in embeddings],4 documents=[chunk["text"] for chunk in all_chunks],5 metadatas=[{"source": chunk["source"]} for chunk in all_chunks],6)78print(f"Stored {collection.count()} chunk(s) in the database.")
นี่คือสิ่งที่แต่ละบรรทัดส่งให้ Chroma ในภาษาธรรมดา: ids ให้ป้ายชื่อเฉพาะกับทุก chunk (0, 1, 2...), embeddings คือตัวเลขจากขั้นตอนที่ 3, documents คือข้อความ chunk จริงๆ, และ metadatas ติดชื่อไฟล์ไปด้วยเพื่อให้เราสามารถแสดงแหล่งที่มาได้ในภายหลัง Chroma เก็บทั้งสี่สิ่งนี้ไว้ด้วยกัน
3. รันมัน บันทึก rag.py จากนั้นในเทอร์มินัล:
1python rag.py
คุณควรเห็น:
Stored 1 chunk(s) in the database.
สิ่งหนึ่งที่ควรรู้สำหรับภายหลัง ทุกครั้งที่คุณรันสคริปต์ตอนนี้ มันจะเพิ่ม chunks อีกครั้ง ดังนั้นจำนวนอาจเพิ่มขึ้น (1, แล้ว 2, แล้ว 3...) ในการรันซ้ำ ซึ่งไม่เป็นไรระหว่างที่เรากำลังสร้าง ถ้าต้องการเริ่มใหม่ ให้ลบโฟลเดอร์ chroma_db แล้วรันอีกครั้ง ในเวอร์ชันสุดท้ายเราจะจัดการอย่างถูกต้องเพื่อไม่ให้ซ้ำซ้อน
ขั้นตอนที่ 5: ค้นหาเอกสารของคุณ
นี่คือส่วน "retrieval" ของ RAG ตัว R ในชื่อ เราจะนำคำถาม เปลี่ยนเป็น embedding ด้วยวิธีเดียวกับที่ทำกับ chunks แล้วถาม Chroma ว่า chunks ไหนที่มีความหมายใกล้เคียงที่สุด chunks ที่ตรงกันเหล่านั้นคือสิ่งที่เราจะส่งให้ Claude ในขั้นตอนถัดไป
1. เพิ่มฟังก์ชันค้นหา ใต้โค้ดจากขั้นตอนที่ 4 ใน rag.py:
1def search(question, n_results=3):2 question_embedding = embedder.encode([question])[0]3 results = collection.query(4 query_embeddings=[question_embedding.tolist()],5 n_results=n_results,6 )7 return results
สิ่งที่ฟังก์ชันนี้ทำ ทีละบรรทัดในภาษาธรรมดา: มันเปลี่ยนคำถามเป็นตัวเลขด้วยโมเดลเดียวกับที่คุณใช้กับ chunks (สำคัญ เพราะทั้งคู่ต้องใช้ "ภาษาตัวเลข" เดียวกัน) จากนั้นถาม Chroma หา chunks ที่ใกล้เคียงที่สุด n_results=3 หมายถึง "ให้ chunks ที่เกี่ยวข้องมากที่สุด 3 อันมา" สามเป็นค่าเริ่มต้นที่ดี: มีบริบทเพียงพอ ไม่มากเกินไปจนเสียโทเค็น
2. ทดลองค้นหา เพิ่มโค้ดนี้ด้านล่างเพื่อทดสอบ:
1question = "Who runs Northstar and when is feedback reviewed?"2results = search(question)34for i, doc in enumerate(results["documents"][0]):5 source = results["metadatas"][0][i]["source"]6 print(f"\n--- Match {i+1} (from {source}) ---")7 print(doc)
นี่จะรันคำถามจริงกับฐานข้อมูลของคุณและพิมพ์ chunks ที่พบ พร้อมชื่อไฟล์ที่มา
3. รันมัน บันทึก rag.py จากนั้นในเทอร์มินัล:
1python rag.py
ด้วยไฟล์ทดสอบ Northstar คุณควรเห็นมันดึง chunk ที่ตรงกันกลับมา ประมาณนี้:
--- Match 1 (from notes.txt) ---
Project Northstar คือเครื่องมือภายในของเราสำหรับติดตามความคิดเห็นของลูกค้า เปิดตัวในเดือนมีนาคม 2026 และดูแลโดยทีมแพลตฟอร์ม วิศวกรนำคือ Dana Reyes ความคิดเห็นจะถูกตรวจสอบทุกวันศุกร์ Northstar แทนที่ระบบสเปรดชีตแบบเก่าที่เราใช้จนถึงปี 2025
สังเกตสิ่งที่เกิดขึ้น: คำถามของคุณใช้คำว่า "who runs" และ "reviewed" แต่ไฟล์บอกว่า "lead engineer" และ "reviewed every Friday" มันก็จับคู่ได้เพราะการค้นหาทำงานด้วยความหมาย ไม่ใช่คำที่ตรงกัน นั่นคือจุดรวมของ embeddings และนี่คือสาเหตุที่มันดีกว่าการค้นหาคำหลัก (Ctrl+F) ทั่วไปในไฟล์ของคุณ
ถ้าคุณมีไฟล์มากกว่านี้ คุณจะเห็น 3 chunks อันดับต้นๆ จากทั้งหมด เรียงตามความใกล้เคียง
ขั้นตอนที่ 6: ให้ Claude ตอบจากสิ่งที่มันพบ
นี่คือส่วน "generation" ตัว G ใน RAG เราจะนำ chunks จากขั้นตอนที่ 5 ส่งให้ Claude Opus 4.8 พร้อมกับคำถาม และบอกให้มันตอบโดยใช้เฉพาะบริบทนั้นเท่านั้น นี่คือสิ่งที่หยุดไม่ให้มันเดา: Claude ตอบจากไฟล์ของคุณ ไม่ใช่จากความจำของมันเอง และบอกคุณว่ามันใช้ไฟล์ไหน
1. เพิ่มฟังก์ชันตอบคำถาม ใต้โค้ดจากขั้นตอนที่ 5 ใน rag.py:
1import anthropic23claude = anthropic.Anthropic(api_key=api_key)45def answer(question):6 results = search(question)7 chunks = results["documents"][0]8 sources = [m["source"] for m in results["metadatas"][0]]910 context = ""11 for i, chunk in enumerate(chunks):12 context += f"[From {sources[i]}]\n{chunk}\n\n"1314 message = claude.messages.create(15 model="claude-opus-4-8",16 max_tokens=1024,17 system=(18 "You answer questions using only the context provided. "19 "If the answer is not in the context, say you don't know. "20 "Always mention which file your answer came from."21 ),22 messages=[23 {24 "role": "user",25 "content": f"Context:\n{context}\nQuestion: {question}",26 }27 ],28 )29 return message.content[0].text
สิ่งที่เกิดขึ้นที่นี่ ในภาษาธรรมดา: เราค้นหา chunks ที่เกี่ยวข้อง รวม它们ไว้เป็นก้อน context เดียว (แต่ละส่วนมีป้ายชื่อไฟล์) จากนั้นส่งก้อนนั้นพร้อมกับคำถามไปยัง Claude คำสั่ง system คือส่วนสำคัญ มันบอก Claude สามอย่าง: ตอบจากบริบทเท่านั้น ยอมรับเมื่อไม่มีคำตอบอยู่ในนั้น และบอกชื่อไฟล์ต้นทาง สามกฎนี้คือสิ่งที่ทำให้คำตอบน่าเชื่อถือแทนที่จะถูกสร้างขึ้นมา
model="claude-opus-4-8" คือชื่อโมเดลที่แน่นอน (ใช้ขีดกลาง ไม่ใช่จุด) max_tokens=1024 จำกัดความยาวของคำตอบ
2. ถามคำถาม เพิ่มโค้ดนี้ด้านล่าง:
1question = "Who runs Northstar and when is feedback reviewed?"2print(answer(question))
3. รันมัน บันทึก rag.py จากนั้นในเทอร์มินัล:
1python rag.py
คุณควรได้คำตอบจริงที่สร้างจากไฟล์ของคุณ ประมาณนี้:
Dana Reyes เป็นวิศวกรนำที่ดูแล Project Northstar และความคิดเห็นจะถูกตรวจสอบทุกวันศุกร์ (ที่มา: notes.txt)
นั่นคือระบบ RAG ที่สมบูรณ์ทำงาน Claude ไม่เคยเห็นไฟล์นี้ระหว่างการฝึก มันไม่สามารถรู้ว่า Dana Reyes คือใคร แต่มันตอบถูกต้องและบอกคุณอย่างชัดเจนว่าคำตอบมาจากไหน ถามสิ่งที่ไม่มีในไฟล์ของคุณ มันจะบอกว่าไม่รู้ แทนที่จะสร้างคำตอบขึ้นมา การพูดว่า "ไม่รู้" นั้นเป็นคุณสมบัติ ไม่ใช่ความล้มเหลว: มันคือความแตกต่างระหว่างเครื่องมือที่คุณไว้ใจได้กับเครื่องมือที่เดาสุ่ม
ขั้นตอนที่ 7: ทำให้เป็นสิ่งที่คุณสามารถใช้ได้จริง
ตอนนี้คุณต้องแก้ไขโค้ดและรันสคริปต์ทั้งหมดใหม่ทุกครั้งที่ต้องการถามอะไร แย่กว่านั้น ทุกครั้งที่รัน มันจะอ่านไฟล์ของคุณใหม่และเพิ่ม它们ลงในฐานข้อมูลอีกครั้ง ทำให้ chunks สะสม มาลองแก้ไขทั้งสองอย่าง: สร้างฐานข้อมูลเพียงครั้งเดียว จากนั้นให้คุณถามคำถามเป็น loop โดยพิมพ์ลงในเทอร์มินัลโดยตรง
1. แก้ปัญหาการเพิ่มซ้ำ หาบล็อกจากขั้นตอนที่ 4 ที่เพิ่ม chunks (ส่วน collection.add(...)) แล้วแทนที่ด้วยเวอร์ชันนี้ ซึ่งจะสร้างฐานข้อมูลก็ต่อเมื่อมันว่างเปล่า:
1if collection.count() == 0:2 collection.add(3 ids=[str(i) for i in range(len(all_chunks))],4 embeddings=[emb.tolist() for emb in embeddings],5 documents=[chunk["text"] for chunk in all_chunks],6 metadatas=[{"source": chunk["source"]} for chunk in all_chunks],7 )8 print(f"Stored {collection.count()} chunk(s) in the database.")9else:10 print(f"Database already has {collection.count()} chunk(s), skipping rebuild.")
ตอนนี้งานหนัก (อ่านไฟล์, สร้าง embeddings, เติมฐานข้อมูล) จะเกิดขึ้นเฉพาะครั้งแรกเท่านั้น การรันครั้งต่อๆ ไปจะข้ามไปยังการตอบคำถามโดยตรง
2. เพิ่ม loop คำถาม ที่ด้านล่างสุดของ rag.py ให้แทนที่คำถามทดสอบเดี่ยวจากขั้นตอนที่ 6 ด้วยโค้ดนี้:
1print("\nAsk a question about your documents (or type 'quit' to exit).\n")23while True:4 question = input("You: ")5 if question.lower() in ["quit", "exit"]:6 break7 print("\nClaude: " + answer(question) + "\n")
input("You: ") รอให้คุณพิมพ์คำถามแล้วกด Enter while True ให้มันทำงานต่อไปเพื่อให้คุณถามได้มากเท่าที่ต้องการ พิมพ์ quit เพื่อหยุด
3. รันมัน บันทึก rag.py จากนั้นในเทอร์มินัล:
1python rag.py
ตอนนี้คุณสามารถพูดคุยกับไฟล์ของคุณได้:
Ask a question about your documents (or type 'quit' to exit).
You: ใครเป็นวิศวกรนำของ Northstar?
Claude: วิศวกรนำของ Project Northstar คือ Dana Reyes (ที่มา: notes.txt)
You: มันแทนที่อะไร?
Claude: Northstar แทนที่ระบบสเปรดชีตแบบเก่าที่ใช้จนถึงปี 2025 (ที่มา: notes.txt)
You: quit
นั่นคือระบบ RAG ที่เสร็จสมบูรณ์ของคุณ มันอ่านไฟล์ของคุณครั้งเดียว จดจำ它们 และตอบคำถามเกี่ยวกับ它们ตามต้องการ พร้อมแหล่งที่มาทุกครั้ง
สิ่งหนึ่งที่ควรรู้เมื่อคุณเพิ่มไฟล์ใหม่ เนื่องจากตอนนี้ฐานข้อมูลถูกสร้างเพียงครั้งเดียว การวางไฟล์ใหม่ใน documents จะไม่แสดงผลโดยอัตโนมัติ ในการโหลดไฟล์ใหม่ ให้ลบโฟลเดอร์ chroma_db แล้วรันสคริปต์หนึ่งครั้ง มันจะสร้างใหม่ทั้งหมดจากทุกอย่างในโฟลเดอร์
เสริม: ทำให้มีหน้าต่างแชทในเบราว์เซอร์ของคุณ
เทอร์มินัลใช้งานได้ แต่ถ้าคุณต้องการหน้าต่างแชทจริงๆ Streamlit จะเพิ่มให้ด้วยโค้ดประมาณ 20 บรรทัด
1. ติดตั้งมัน ในเทอร์มินัลของคุณ:
1pip install streamlit
2. สร้าง app.py ในโฟลเดอร์เดียวกันแล้ววางโค้ดนี้ลงไป มันจะใช้ฟังก์ชัน answer จาก rag.py ของคุณซ้ำ:
1import streamlit as st2from rag import answer34st.title("Chat with your documents")56if "history" not in st.session_state:7 st.session_state.history = []89question = st.chat_input("Ask about your files...")1011if question:12 reply = answer(question)13 st.session_state.history.append((question, reply))1415for q, a in st.session_state.history:16 st.chat_message("user").write(q)17 st.chat_message("assistant").write(a)
3. รันมัน ในเทอร์มินัลของคุณ (หมายเหตุ: ใช้ streamlit run ไม่ใช่ python):
1streamlit run app.py
มันจะเปิดหน้าต่างแชทในเบราว์เซอร์ของคุณโดยอัตโนมัติ พิมพ์คำถาม ได้รับคำตอบพร้อมแหล่งที่มา เหมือนกับเทอร์มินัลแต่ดูดีกว่า
ข้อควรทราบ: เพื่อให้สิ่งนี้ทำงานได้ loop คำถามจากขั้นตอนที่ 7 ต้องไม่ทำงานเมื่อ import ให้ห่อ loop นั้นที่ด้านล่างของ rag.py ด้วย if __name__ == "__main__": เพื่อให้มันทำงานก็ต่อเมื่อคุณรัน rag.py โดยตรง ไม่ใช่ตอนที่ app.py import มัน
การให้มันตอบคำถามทั่วไปด้วย
ถ้าคุณต้องการให้มันตอบคำถามทั่วไปด้วย ตอนนี้ระบบตอบจากไฟล์ของคุณเท่านั้น ดังนั้นคำถามเช่น "เมืองหลวงของเวเนซุเอลาคืออะไร" จะได้คำตอบว่า "ไม่มีในเอกสาร" ทั้งที่ Claude รู้คำตอบ ถ้าคุณต้องการให้มันใช้ความรู้ของตัวเองเป็นตัวเลือกสำรอง ให้เปิด rag.py หาบล็อก system=(...) ในขั้นตอนที่ 6 แล้วสลับบรรทัดนี้:
1"ถ้าคำตอบไม่อยู่ในบริบท ให้บอกว่าคุณไม่รู้"
สำหรับอันนี้:
1"ถ้าคำตอบไม่อยู่ในบริบท ให้ตอบจากความรู้ทั่วไปของคุณ แต่ให้บอกว่าคุณกำลังทำเช่นนั้น"
บันทึกแล้วรันใหม่ ตอนนี้มันจะตอบจากไฟล์ของคุณก่อน และถ้าไฟล์ไม่ครอบคลุม ก็จะใช้ความรู้ทั่วไปแทน พร้อมบอกคุณว่ามันใช้ข้อมูลจากไหน
สรุป
คุณเพิ่งสร้างระบบ RAG ที่ใช้งานได้จริง มันอ่านไฟล์ของคุณเอง ค้นหาส่วนที่เกี่ยวข้อง และให้ Claude ตอบโดยอ้างอิงแหล่งที่มาที่แน่นอนทุกครั้ง โครงสร้างเดียวกันนี้ปรับขนาดได้จากโน้ตไม่กี่อันไปจนถึงฐานความรู้ทั้งหมดของคุณ
จากตรงนี้ คุณสามารถชี้ไปที่ไหนก็ได้: คลัง Obsidian ของคุณ, เอกสารงานของคุณ, งานวิจัยที่คุณบันทึกไว้ วางไฟล์ลงไป, สร้างใหม่ครั้งเดียว, แล้วเริ่มถาม ทุกสิ่งที่คุณเรียนรู้ที่นี่ — การแบ่งเป็นส่วน, การสร้าง embeddings, การค้นหา, การตอบ — คือแกนหลักเดียวกันกับเครื่องมือ "แชทกับเอกสารของคุณ" ทุกตัวที่คุณเคยเห็น
ถ้าสิ่งนี้มีประโยชน์ ไปที่โปรไฟล์ของฉันแล้วกดติดตาม ฉันเขียนเกี่ยวกับเทคโนโลยี, AI, และระบบที่ทำงานได้จริง
Ciao,
[@undefinedKi](https://x.com/@undefinedKi)





![[บันทึก] หัวหน้าของคุณทำงานเร็วกว่าคุณถึง 3 เท่า](/cdn-cgi/image/width=1920,quality=90,format=auto,metadata=none/https%3A%2F%2Fcms-assets.youmind.com%2Fmedia%2F1783963982361_vdddap_HNDtsxJbcAAoE0q.jpg)