การโหลดเอกสารและการดึงข้อความ
โหลด PDF เอกสาร Word และไฟล์ข้อความธรรมดาด้วยไลบรารี Python ทำความสะอาดข้อความที่ดึงได้ และเตรียมข้อความสำหรับแบ่งส่วนและสร้างเวกเตอร์ฝังตัว
การโหลดเอกสารและการดึงข้อความ เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดการโหลดเอกสารจึงไม่ใช่เรื่องง่าย
ขั้นแรกของกระบวนการ RAG ใด ๆ คือการนำข้อความดิบออกจากเอกสารของคุณ ฟังดูเหมือนง่าย แต่ในทางปฏิบัติกลับซับซ้อนกว่าที่คาดไว้ ไฟล์ PDF อาจฝังข้อความเป็นอักขระ เป็นรูปภาพ หรือเป็นทั้งสองแบบผสมกัน เอกสาร Word มีมาร์กอัปการจัดรูปแบบที่คุณต้องลบออก หน้า HTML มีเมนูนำทางและโฆษณาอยู่ร่วมกับเนื้อหาจริง ตัวโหลดที่มีประสิทธิภาพต้องรองรับทุกกรณีเหล่านี้ และสร้างข้อความที่สะอาดและต่อเนื่องสำหรับการแบ่งเป็นชิ้นข้อมูล
การโหลด PDF ด้วย pypdf
pypdf เป็นไลบรารี Python มาตรฐานสำหรับอ่านไฟล์ PDF ที่มีข้อความฝังอยู่ ไลบรารีนี้ดึงข้อความทีละหน้า โดยรักษาขอบเขตเดิมของแต่ละหน้าไว้ ซึ่งเป็นเมทาดาทาที่มีประโยชน์ อย่างไรก็ตาม pypdf ไม่สามารถอ่าน PDF ที่สแกนมา (รูปภาพของข้อความ) ได้ เพราะไฟล์เหล่านั้นต้องใช้ OCR ควรดึงหมายเลขหน้ามาพร้อมกับข้อความเสมอ เพื่อให้คุณอ้างอิงหน้าที่แน่นอนได้ในการอ้างอิงแหล่งที่มาของ RAG
from pypdf import PdfReader
def load_pdf(file_path):
reader = PdfReader(file_path)
pages = []
for page_num, page in enumerate(reader.pages, start=1):
text = page.extract_text()
if text and text.strip(): # skip blank pages
pages.append({
'text': text,
'metadata': {
'source': file_path,
'page': page_num,
'doc_type': 'pdf'
}
})
return pages
docs = load_pdf('annual_report.pdf')
print(f'Loaded {len(docs)} non-empty pages')การโหลดเอกสาร Word ด้วย python-docx
ไฟล์ Microsoft Word (.docx) จัดเก็บเนื้อหาในรูปแบบ XML ไลบรารี python-docx จะวิเคราะห์ XML นี้และเปิดให้เข้าถึงย่อหน้า ตาราง และหัวข้อในรูปออบเจ็กต์ Python ดึงข้อความของย่อหน้าตามลำดับ และเก็บระดับของหัวข้อไว้เพื่อรักษาโครงสร้างเอกสาร หัวข้อส่วนต่าง ๆ เป็นบริบทที่มีประโยชน์ ซึ่งช่วยปรับปรุงคุณภาพการแบ่งและการค้นคืนเมื่อใส่หัวข้อเหล่านั้นไว้ร่วมกับข้อความที่หัวข้อเริ่มต้น
from docx import Document
def load_docx(file_path):
doc = Document(file_path)
sections = []
current_section = {'heading': '', 'text': ''}
for para in doc.paragraphs:
if para.style.name.startswith('Heading'):
if current_section['text'].strip():
sections.append(current_section.copy())
current_section = {'heading': para.text, 'text': ''}
else:
current_section['text'] += para.text + '\n'
if current_section['text'].strip():
sections.append(current_section)
return [{'text': f"{s['heading']}\n{s['text']}",
'metadata': {'source': file_path, 'section': s['heading']}}
for s in sections]การโหลดหน้าเว็บและ HTML
หน้า HTML มี เนื้อหาส่วนเกิน อยู่มาก เช่น แถบนำทาง ส่วนท้าย แบนเนอร์คุกกี้ และบล็อกโฆษณา ใช้ BeautifulSoup เพื่อวิเคราะห์ HTML และดึงเฉพาะพื้นที่เนื้อหาหลัก เลือกองค์ประกอบอย่าง <article>, <main> หรือคลาส CSS ที่เจาะจงกับเนื้อหา ลบแท็กสคริปต์ สไตล์ และการนำทางก่อนดึงข้อความ เพื่อไม่ให้ชิ้นข้อมูลของคุณปนเปื้อนด้วยโค้ด JavaScript หรือรายการเมนู
import requests
from bs4 import BeautifulSoup
def load_url(url):
response = requests.get(url, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# Remove noise elements
for tag in soup(['script', 'style', 'nav', 'footer', 'header', 'aside']):
tag.decompose()
# Try to find main content
main = soup.find('article') or soup.find('main') or soup.find('body')
text = main.get_text(separator='\n', strip=True)
return [{'text': text, 'metadata': {'source': url, 'doc_type': 'html'}}]การจัดการ PDF ที่สแกนด้วย OCR
ไฟล์ PDF ที่สแกนจะจัดเก็บแต่ละหน้าเป็นรูปภาพโดยไม่มีข้อความฝังอยู่ หากต้องการดึงข้อความออกมา คุณต้องใช้ การรู้จำอักขระด้วยแสง (OCR) ไลบรารี pytesseract เป็นตัวห่อหุ้มเอนจิน Tesseract OCR ของ Google โดย OCR ทำงานช้ากว่าและมีความแม่นยำน้อยกว่าการดึงข้อความ (มีความแม่นยำระดับอักขระ 80-95% สำหรับการสแกนคุณภาพดี) ดังนั้นควรเลือกใช้ไฟล์ PDF ดิจิทัลเสมอเมื่อมีให้ใช้ ระบุในข้อมูลเมทาดาทาว่าใช้ OCR เพื่อให้คุณตรวจสอบข้อความที่ดึงออกมาและมีความเชื่อมั่นต่ำได้
import pytesseract
from pdf2image import convert_from_path
def load_scanned_pdf(file_path):
# Convert PDF pages to PIL images
pages_as_images = convert_from_path(file_path, dpi=300)
results = []
for page_num, img in enumerate(pages_as_images, start=1):
text = pytesseract.image_to_string(img, lang='eng')
results.append({
'text': text,
'metadata': {
'source': file_path,
'page': page_num,
'ocr': True # flag for quality review
}
})
return resultsการใช้ Unstructured กับทุกรูปแบบ
ไลบรารี unstructured เป็นเครื่องมืออเนกประสงค์สำหรับโหลดเอกสาร โดยรองรับ PDF, Word, Excel, PowerPoint, HTML อีเมล และรูปแบบอื่น ๆ ผ่านส่วนติดต่อ API แบบรวมเป็นหนึ่งเดียว ไลบรารีนี้ใช้หลักการวิเคราะห์แบบฮิวริสติกเพื่อระบุองค์ประกอบของเอกสาร (ชื่อเรื่อง ข้อความบรรยาย ตาราง ส่วนหัว) แล้วส่งคืนเป็นออบเจ็กต์ที่มีโครงสร้าง วิธีนี้มีประโยชน์เป็นพิเศษเมื่อคลังเอกสารของคุณมี เอกสารหลายประเภทปะปนกัน และคุณต้องการเมทาดาทาในระดับองค์ประกอบโดยไม่ต้องเขียนตัวแยกวิเคราะห์เฉพาะรูปแบบ
from unstructured.partition.auto import partition
def load_any_document(file_path):
elements = partition(filename=file_path)
docs = []
for element in elements:
docs.append({
'text': str(element),
'metadata': {
'source': file_path,
'element_type': type(element).__name__,
'category': element.category
}
})
return docs
# Works on .pdf, .docx, .pptx, .html, .eml, .xlsx
docs = load_any_document('presentation.pptx')การทำความสะอาดข้อความหลังการดึงข้อมูล
ข้อความดิบที่ดึงออกมาแทบไม่เคยสะอาดเรียบร้อย การดึงข้อความจาก PDF มักทำให้เกิด การตัดบรรทัดตรงยัติภังค์จากการจัดวางแบบหลายคอลัมน์ ช่องว่างส่วนเกิน ส่วนหัวหน้าที่ซ้ำกันทุกหน้า และอักขระพิเศษที่ผิดเพี้ยน ให้ใช้กระบวนการทำความสะอาด โดยลบช่องว่างที่มากเกินไป เชื่อมคำที่ถูกตัดด้วยยัติภังค์ข้ามการขึ้นบรรทัดใหม่ ลบส่วนหัวและท้ายหน้าที่ระบุได้จากการจับคู่รูปแบบ และทำอักขระ Unicode ให้เป็นรูปแบบมาตรฐาน ข้อความที่สะอาดช่วยให้ชิ้นข้อความมีความต่อเนื่องสอดคล้องกันดีขึ้นอย่างมาก
import re
def clean_text(text):
# Rejoin hyphenated line breaks (PDF column artifacts)
text = re.sub(r'-(\n)([a-z])', r'\2', text)
# Normalize whitespace
text = re.sub(r' +', ' ', text)
text = re.sub(r'\n{3,}', '\n\n', text)
# Remove page numbers standing alone on a line
text = re.sub(r'^\d+$', '', text, flags=re.MULTILINE)
# Strip leading/trailing whitespace from each line
lines = [line.strip() for line in text.split('\n')]
return '\n'.join(lines).strip()การโหลดจากฐานข้อมูลและ API
แหล่งความรู้ไม่ได้อยู่ในไฟล์ทั้งหมด ฐานข้อมูลภายใน ระบบ CRM เครื่องมือจัดการบัตรแจ้งปัญหา และ REST API ก็เป็นแหล่งข้อมูลเช่นกัน ให้โหลดแถวข้อมูลที่มีโครงสร้างจากฐานข้อมูลโดยเชื่อมตารางที่เกี่ยวข้อง แล้วนำค่าของฟิลด์มาต่อกันเป็นย่อหน้าภาษาธรรมชาติที่โมเดลการฝังเวกเตอร์เข้าใจได้ สำหรับ API ให้ดึงผลลัพธ์แบบแบ่งหน้า แล้วแปลงข้อมูลแต่ละระเบียนเป็นเอกสารข้อความที่มีคู่คีย์-ค่า
import psycopg2
def load_from_database(conn_string, query):
conn = psycopg2.connect(conn_string)
cursor = conn.cursor()
cursor.execute(query)
columns = [desc[0] for desc in cursor.description]
docs = []
for row in cursor.fetchall():
# Convert row to natural language text
parts = [f'{col}: {val}' for col, val in zip(columns, row) if val]
text = '\n'.join(parts)
docs.append({'text': text, 'metadata': {'source': 'database'}})
conn.close()
return docsการติดตามแหล่งที่มาของเอกสาร
เอกสารทุกฉบับที่โหลดเข้ามาควรมี เมทาดาทาแหล่งที่มา ติดไปตลอดกระบวนการทั้งหมด ได้แก่ URL ต้นทางหรือเส้นทางไฟล์ ชื่อเอกสาร ผู้เขียน วันที่สร้าง และวันที่แก้ไขล่าสุด เมทาดาทานี้จะติดไปกับชิ้นข้อความแต่ละชิ้นเข้าสู่ที่จัดเก็บเวกเตอร์ และปรากฏในข้อมูลอ้างอิงของ LLM หากไม่มีแหล่งที่มา คุณจะบอกผู้ใช้ไม่ได้ว่าคำตอบมาจากที่ใด ไม่สามารถอัปเดตเอกสารเฉพาะรายการในดัชนี และไม่สามารถกรองการค้นคืนตามคุณลักษณะของแหล่งที่มาได้
import os
from datetime import datetime
def load_pdf_with_provenance(file_path):
from pypdf import PdfReader
reader = PdfReader(file_path)
stat = os.stat(file_path)
base_metadata = {
'source': file_path,
'title': reader.metadata.get('/Title', os.path.basename(file_path)),
'author': reader.metadata.get('/Author', 'Unknown'),
'doc_type': 'pdf',
'file_size_kb': stat.st_size // 1024,
'loaded_at': datetime.utcnow().isoformat()
}
pages = []
for i, page in enumerate(reader.pages, 1):
text = page.extract_text()
if text and text.strip():
pages.append({'text': text, 'metadata': {**base_metadata, 'page': i}})
return pagesการโหลดชุดเอกสารขนาดใหญ่เป็นชุด
เมื่อสร้างดัชนีเอกสารหลายพันฉบับ ให้โหลดเอกสารเหล่านั้น แบบขนาน โดยใช้ concurrent.futures เพื่อใช้ทรัพยากร I/O และ CPU ได้เต็มประสิทธิภาพ จัดทำตัวติดตามความคืบหน้าและบันทึกข้อผิดพลาด เพื่อไม่ให้เอกสารที่โหลดไม่สำเร็จหายไปจากดัชนีโดยไม่มีการแจ้งเตือน อย่าปล่อยให้ไฟล์ที่เสียหายเพียงไฟล์เดียวทำให้งานโหลดทั้งหมดหยุดทำงาน — ดักจับข้อยกเว้นแยกตามเอกสาร แล้วดำเนินการกับเอกสารถัดไป
from concurrent.futures import ThreadPoolExecutor, as_completed
def batch_load_documents(file_paths, max_workers=8):
all_docs = []
errors = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
future_to_path = {
executor.submit(load_pdf_with_provenance, p): p
for p in file_paths
}
for future in as_completed(future_to_path):
path = future_to_path[future]
try:
docs = future.result()
all_docs.extend(docs)
print(f'Loaded {len(docs)} pages from {path}')
except Exception as e:
errors.append({'path': path, 'error': str(e)})
return all_docs, errorsการตรวจสอบคุณภาพเนื้อหาที่โหลด
หลังจากโหลดแล้ว ให้ตรวจสอบว่าคุณดึงเนื้อหาที่มีความหมายออกมาได้ ให้ตรวจสอบสิ่งต่อไปนี้: ความยาวข้อความขั้นต่ำ (ข้ามชิ้นข้อความที่มีอักขระน้อยกว่า 50 ตัว) การตรวจจับภาษา (หาก RAG ของคุณรองรับเฉพาะภาษาอังกฤษ ให้กรองหน้าที่ไม่ใช่ภาษาอังกฤษออก) และ การตรวจจับข้อความที่ผิดเพี้ยน (อัตราส่วนอักขระที่ไม่ใช่ ASCII สูงอาจบ่งชี้ว่า OCR ล้มเหลวหรือเกิดปัญหาการเข้ารหัส) บันทึกสถิติต่าง ๆ เช่น จำนวนหน้าที่โหลด ความยาวหน้าโดยเฉลี่ย และอัตราข้อผิดพลาด เพื่อให้ตรวจพบปัญหาการโหลดได้ตั้งแต่เนิ่น ๆ
def validate_documents(docs, min_length=100):
valid = []
skipped = 0
for doc in docs:
text = doc['text']
if len(text) < min_length:
skipped += 1
continue
# Check for high non-ASCII ratio (garbled OCR)
non_ascii = sum(1 for c in text if ord(c) > 127)
if non_ascii / max(len(text), 1) > 0.3:
skipped += 1
continue
valid.append(doc)
print(f'Valid: {len(valid)}, Skipped: {skipped}')
return validตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจแนวคิดวิศวกรรม AI จากบทเรียนนี้
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้เกี่ยวกับ ตัวโหลดเฉพาะรูปแบบสำหรับ PDF ด้วย pypdf เอกสาร Word ด้วย python-docx, HTML ด้วย BeautifulSoup และเอกสารที่สแกนด้วย OCR รวมถึง ไลบรารี unstructured ในฐานะตัวโหลดเอกสารหลายรูปแบบแบบรวมเป็นหนึ่งเดียว และ แนวปฏิบัติที่ดีสำหรับระบบจริง ซึ่งครอบคลุมการทำความสะอาดข้อความ เมทาดาทาแหล่งที่มา การโหลดเป็นชุดแบบขนาน และการตรวจสอบเนื้อหา บทถัดไปเราจะจัดการกลยุทธ์การแบ่งชิ้นข้อความ ซึ่งเป็นตัวกำหนดว่าข้อความที่ค้นคืนมาจะเชื่อมโยงกับบริบทของโมเดลอย่างไร
คำถามที่พบบ่อย
บทเรียน “การโหลดเอกสารและการดึงข้อความ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การโหลดเอกสารและการดึงข้อความ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การโหลดเอกสารและการดึงข้อความ”
โหลด PDF เอกสาร Word และไฟล์ข้อความธรรมดาด้วยไลบรารี Python ทำความสะอาดข้อความที่ดึงได้ และเตรียมข้อความสำหรับแบ่งส่วนและสร้างเวกเตอร์ฝังตัว คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การโหลดเอกสารและการดึงข้อความ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การโหลดเอกสารและการดึงข้อความ
- กลยุทธ์การแบ่งส่วน: ขนาดคงที่ เทียบกับประโยค เทียบกับแบบเรียกซ้ำ
- การทำดัชนี: การสร้างและจัดเก็บส่วนข้อความ
- ค้นคำค้น คืนข้อมูล และสร้างคำตอบ