การค้นหาแบบผสมใน Pinecone และ pgvector
กำหนดค่าการค้นหาแบบผสมใน Pinecone ด้วยโหมดดัชนีแบบเบาบาง-หนาแน่น และใน pgvector ด้วยคำสั่งค้นหาแบบขนานที่ผสานด้วย RRF พร้อมทดสอบเปรียบเทียบคุณภาพการดึงข้อมูลบนชุดข้อมูลของคุณ
การค้นหาแบบผสมใน Pinecone และ pgvector เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
การค้นหาแบบไฮบริดดั้งเดิมในฐานข้อมูลเวกเตอร์
แม้ว่าคุณจะสร้างการค้นหาแบบไฮบริดด้วยตนเองได้โดยใช้ดัชนีสองชุดแยกกันและการผสานแบบ RRF แต่ฐานข้อมูลเวกเตอร์สำหรับใช้งานจริงจำนวนมากขึ้นเรื่อย ๆ ก็นำเสนอ การค้นหาแบบไฮบริดในตัว ซึ่งจัดการการดึงข้อมูลแบบเบาบางและแบบหนาแน่นภายในการค้นหาเดียว Pinecone และ pgvector ต่างรองรับโหมดไฮบริด แต่ใช้สถาปัตยกรรมและมีข้อแลกเปลี่ยนแตกต่างกัน การเข้าใจทั้งสองทางเลือกจะช่วยให้คุณเลือกเครื่องมือที่เหมาะกับโครงสร้างพื้นฐานของคุณได้
โหมดดัชนีแบบเบาบาง-หนาแน่นของ Pinecone
Pinecone รองรับ ดัชนีแบบเบาบาง-หนาแน่น ซึ่งระเบียนเวกเตอร์แต่ละรายการจะเก็บทั้งเวกเตอร์ฝังตัวแบบหนาแน่น (เป็นอาร์เรย์จำนวนทศนิยม) และเวกเตอร์แบบเบาบาง (เป็นพจนานุกรมของ ID โทเค็นกับน้ำหนัก) คำค้นสามารถระบุทั้งเวกเตอร์คำค้นแบบหนาแน่นและเวกเตอร์คำค้นแบบเบาบางได้ จากนั้น Pinecone จะผสานผลลัพธ์ด้วยการรวมเชิงเส้นแบบถ่วงน้ำหนัก วิธีนี้แตกต่างจาก RRF เพราะ Pinecone ใช้การผสานคะแนนดิบด้วยน้ำหนักที่กำหนดค่าได้ ซึ่งเรียกว่า alpha
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key='YOUR_API_KEY')
# Create a sparse-dense index
pc.create_index(
name='hybrid-index',
dimension=1536, # dense vector dimension
metric='dotproduct', # must use dotproduct for hybrid
spec=ServerlessSpec(cloud='aws', region='us-east-1'),
)
index = pc.Index('hybrid-index')การสร้างเวกเตอร์แบบเบาบางด้วย SPLADE
หากต้องการใช้โหมดแบบเบาบาง-หนาแน่นของ Pinecone คุณต้องสร้าง เวกเตอร์แบบเบาบาง สำหรับเอกสารแต่ละรายการ แนวทางที่มีประสิทธิภาพสูงสุดคือ SPLADE (Sparse Lexical and Expansion) ซึ่งเป็นแบบจำลองประสาทเทียมที่สร้างตัวแทนแบบเบาบางที่เรียนรู้ได้พร้อมการขยายความหมาย โดยจะเพิ่มคำที่เกี่ยวข้องเชิงความหมายลงในเวกเตอร์แบบเบาบาง นอกเหนือจากคำที่ปรากฏอยู่ในข้อความตามตัวอักษร อีกทางเลือกหนึ่งคือใช้ค่าน้ำหนักคำแบบ BM25 อย่างง่ายเป็นเวกเตอร์แบบเบาบาง
from transformers import AutoTokenizer, AutoModelForMaskedLM
import torch
# Load SPLADE model
tokenizer = AutoTokenizer.from_pretrained('naver/splade-cocondenser-ensembledistil')
model = AutoModelForMaskedLM.from_pretrained('naver/splade-cocondenser-ensembledistil')
def generate_sparse_vector(text: str) -> dict:
tokens = tokenizer(text, return_tensors='pt', truncation=True, max_length=512)
with torch.no_grad():
output = model(**tokens)
logits = output.logits
# Max-pool over sequence length and apply log1p activation
sparse = torch.max(torch.log1p(torch.relu(logits)), dim=1).values.squeeze()
# Return non-zero indices and values as a sparse dict
nz_indices = sparse.nonzero().squeeze().tolist()
nz_values = sparse[nz_indices].tolist()
return {'indices': nz_indices, 'values': nz_values}การเพิ่มเวกเตอร์ไฮบริดลงใน Pinecone
ระเบียน Pinecone แต่ละรายการในดัชนีไฮบริดจะเก็บ id อาร์เรย์ values แบบหนาแน่น พจนานุกรม sparse_values ที่มี indices และ values รวมถึง metadata ซึ่งเป็นข้อมูลเสริมที่ไม่จำเป็นต้องมี เพิ่มระเบียนเป็นชุด ชุดละ 100 รายการ เพื่อให้มีอัตราการประมวลผลสูงสุดและยังอยู่ภายในขีดจำกัดขนาดคำขอของ Pinecone
def upsert_hybrid_docs(index, documents: list[dict], batch_size: int = 100):
records = []
for doc in documents:
dense_vec = embed(doc['text']) # OpenAI embedding
sparse_vec = generate_sparse_vector(doc['text']) # SPLADE
records.append({
'id': doc['id'],
'values': dense_vec,
'sparse_values': sparse_vec,
'metadata': {'text': doc['text'], 'source': doc['source']},
})
for i in range(0, len(records), batch_size):
batch = records[i:i + batch_size]
index.upsert(vectors=batch)
print(f'Upserted batch {i//batch_size + 1}')การค้นหาดัชนีไฮบริดของ Pinecone
คำค้นแบบไฮบริดจะส่งทั้ง vector แบบหนาแน่นและ sparse_vector ไปยัง API การค้นหาของ Pinecone พารามิเตอร์ alpha (0 ถึง 1) ควบคุมสัดส่วนดังกล่าว: alpha=1.0 คือแบบหนาแน่นล้วน alpha=0.0 คือแบบเบาบางล้วน และ alpha=0.5 ให้น้ำหนักทั้งสองแบบเท่ากัน ปรับค่า alpha ด้วยชุดตรวจสอบ โดยค่าที่เหมาะสมมักอยู่ระหว่าง 0.3 ถึง 0.7
def hybrid_query_pinecone(index, query: str, alpha: float = 0.5, top_k: int = 5):
dense_vec = embed(query)
sparse_vec = generate_sparse_vector(query)
# Scale vectors by alpha for weighted fusion
scaled_dense = [v * alpha for v in dense_vec]
scaled_sparse = {
'indices': sparse_vec['indices'],
'values': [v * (1 - alpha) for v in sparse_vec['values']],
}
results = index.query(
vector=scaled_dense,
sparse_vector=scaled_sparse,
top_k=top_k,
include_metadata=True,
)
return results.matchespgvector: การค้นหาเวกเตอร์ใน PostgreSQL
ส่วนขยาย pgvector เพิ่มชนิดคอลัมน์ vector และตัวดำเนินการวัดระยะทางให้กับ PostgreSQL สำหรับการค้นหาแบบไฮบริด คุณจะเรียกใช้คำค้นสองรายการพร้อมกัน ได้แก่ คำค้นเพื่อนบ้านใกล้เคียงโดยประมาณบนคอลัมน์เวกเตอร์ และคำค้นข้อความเต็มรูปแบบโดยใช้ tsvector และ tsquery ในตัวของ PostgreSQL จากนั้นจึงผสานผลลัพธ์ด้วย RRF ในโค้ดแอปพลิเคชัน
-- Setup: enable extensions
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- Create hybrid-capable table
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL,
embedding vector(1536),
content_tsv tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED
);
-- Indexes for both search modes
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
CREATE INDEX ON documents USING GIN (content_tsv);การเรียกใช้คำค้นแบบหนาแน่นและแบบเบาบางใน pgvector
ใน pgvector ให้เรียกใช้ คำค้นแบบหนาแน่น โดยใช้ตัวดำเนินการวัดระยะโคไซน์ <=> เพื่อค้นหาเพื่อนบ้านที่ใกล้กับเวกเตอร์ฝังตัวของคำค้นที่สุด และใช้ คำค้นแบบเบาบาง โดยใช้ ts_rank_cd กับคอลัมน์ tsvector เพื่อให้คะแนนการจับคู่คำสำคัญ ดึงชุดผลลัพธ์ทั้งสองชุดแยกจากกัน แล้วผสานผลลัพธ์ด้วย RRF ใน Python
import psycopg2
import json
def pgvector_hybrid_search(conn, query: str, top_k: int = 5):
dense_vec = embed(query)
tsquery = ' & '.join(query.split()) # simple AND query
# Dense query
dense_sql = '''
SELECT id, content, 1 - (embedding <=> %s::vector) AS score
FROM documents
ORDER BY embedding <=> %s::vector
LIMIT 20
'''
# Sparse query
sparse_sql = '''
SELECT id, content, ts_rank_cd(content_tsv, to_tsquery('english', %s)) AS score
FROM documents
WHERE content_tsv @@ to_tsquery('english', %s)
ORDER BY score DESC
LIMIT 20
'''
with conn.cursor() as cur:
cur.execute(dense_sql, [json.dumps(dense_vec), json.dumps(dense_vec)])
dense_rows = cur.fetchall()
cur.execute(sparse_sql, [tsquery, tsquery])
sparse_rows = cur.fetchall()
return fuse_with_rrf(dense_rows, sparse_rows, top_k)การใช้ RRF กับผลลัพธ์จาก pgvector
หลังจากรวบรวมแถวที่จัดอันดับจากคำค้น PostgreSQL ทั้งสองรายการแล้ว ให้ใช้ RRF โดยดึง ID เอกสารตามลำดับอันดับจากชุดผลลัพธ์แต่ละชุด แล้วเรียกใช้อัลกอริทึมการผสาน รายการสุดท้ายที่ผสานแล้วจะให้เอกสารอันดับต้น ๆ จำนวน K รายการ ซึ่งเกี่ยวข้องมากที่สุดทั้งในด้านความหมายเชิงความหมายและการทับซ้อนของคำสำคัญ
def fuse_with_rrf(dense_rows, sparse_rows, top_k: int = 5, k: int = 60):
from collections import defaultdict
doc_texts = {}
scores = defaultdict(float)
for rank, row in enumerate(dense_rows, start=1):
doc_id, text, _ = row
scores[doc_id] += 1.0 / (k + rank)
doc_texts[doc_id] = text
for rank, row in enumerate(sparse_rows, start=1):
doc_id, text, _ = row
scores[doc_id] += 1.0 / (k + rank)
doc_texts[doc_id] = text
ranked = sorted(scores.items(), key=lambda x: x[1], reverse=True)
return [{'id': doc_id, 'text': doc_texts[doc_id], 'rrf_score': s}
for doc_id, s in ranked[:top_k]]การวัดประสิทธิภาพคุณภาพการดึงข้อมูล
หลังจากนำการค้นหาแบบไฮบริดมาใช้แล้ว ให้ ทดสอบประสิทธิภาพอย่างเคร่งครัด โดยเปรียบเทียบกับการดึงข้อมูลแบบหนาแน่นเท่านั้นซึ่งเป็นค่าพื้นฐาน ใช้ชุดทดสอบมาตรฐานที่มีคำค้นอย่างน้อย 100 รายการและมีเอกสารที่เกี่ยวข้องระบุไว้แล้ว วัดค่า NDCG@5, MRR และอัตราการพบผลลัพธ์@3 โดยทั่วไป การค้นหาแบบไฮบริดช่วยเพิ่มค่า NDCG@5 ได้ประมาณ 5 ถึง 20 เปอร์เซ็นต์ และให้ผลดีขึ้นมากที่สุดกับคำค้นที่มีคำศัพท์ทางเทคนิคตรงตัวซึ่งแบบจำลองหนาแน่นมักพลาด
def evaluate_retrieval(search_fn, test_queries, golden_relevant, k=5):
ndcg_scores = []
hit_count = 0
for query, relevant_ids in zip(test_queries, golden_relevant):
results = search_fn(query, top_k=k)
retrieved_ids = [r['id'] for r in results]
# Hit rate
if any(rid in relevant_ids for rid in retrieved_ids):
hit_count += 1
# Simplified NDCG (binary relevance)
dcg = sum(
1.0 / (i + 1)
for i, rid in enumerate(retrieved_ids)
if rid in relevant_ids
)
idcg = sum(1.0 / (i + 1) for i in range(min(len(relevant_ids), k)))
ndcg_scores.append(dcg / idcg if idcg > 0 else 0)
return {
'hit_rate': hit_count / len(test_queries),
'ndcg': sum(ndcg_scores) / len(ndcg_scores),
}การปรับค่า Alpha ในโหมดไฮบริดของ Pinecone
พารามิเตอร์ alpha ในคำค้นแบบไฮบริดของ Pinecone ต้องปรับอย่างเป็นระบบ การแบ่งกลุ่มตามประเภทคำค้น เป็นแนวทางที่มีประโยชน์ โดยจัดประเภทคำค้นสำหรับทดสอบว่าเน้นความหมายเป็นหลัก (การถอดความหรือแนวคิด) หรือเน้นคำศัพท์เป็นหลัก (คำตรงตัวหรือรหัส) แล้ววัดค่า alpha ที่เหมาะสมแยกกันสำหรับแต่ละกลุ่ม ระบบสำหรับใช้งานจริงบางระบบใช้ การเลือกค่า alpha แบบไดนามิก ซึ่งจัดประเภทคำค้นขณะทำงานและเลือกค่า alpha ที่เหมาะสมให้อัตโนมัติ
def find_optimal_alpha(index, test_queries, golden_relevant, alphas=None):
if alphas is None:
alphas = [0.0, 0.2, 0.4, 0.5, 0.6, 0.8, 1.0]
best_alpha, best_score = 0.5, 0
for alpha in alphas:
hits = 0
for query, relevant in zip(test_queries, golden_relevant):
results = hybrid_query_pinecone(index, query, alpha=alpha, top_k=5)
if any(r['id'] in relevant for r in results):
hits += 1
hit_rate = hits / len(test_queries)
print(f'alpha={alpha}: hit_rate={hit_rate:.3f}')
if hit_rate > best_score:
best_score, best_alpha = hit_rate, alpha
return best_alphaการเลือกระหว่าง Pinecone และ pgvector แบบไฮบริด
ใช้ Pinecone แบบไฮบริด เมื่อคุณต้องการโครงสร้างพื้นฐานที่มีผู้ดูแล การปรับขนาดอัตโนมัติ และต้องการย้ายความซับซ้อนของการสร้างเวกเตอร์แบบเบาบางไปให้ API เดียวจัดการ ใช้ pgvector แบบไฮบริด เมื่อคุณมีโครงสร้างพื้นฐาน PostgreSQL อยู่แล้ว ต้องการความสอดคล้องเชิงธุรกรรมระหว่างเอกสารกับข้อมูลเมตา ต้องการความยืดหยุ่นเต็มรูปแบบในการใช้ SQL สำหรับการกรอง หรือต้องการหลีกเลี่ยงการผูกติดกับผู้ให้บริการ ทั้งสองแนวทางให้คุณภาพการดึงข้อมูลแบบไฮบริดที่ยอดเยี่ยมได้เมื่อปรับค่าอย่างเหมาะสม
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจเกี่ยวกับการนำการค้นหาแบบไฮบริดมาใช้จากบทเรียนนี้
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า โหมดแบบเบาบาง-หนาแน่นของ Pinecone เก็บเวกเตอร์ทั้งแบบหนาแน่นและแบบเบาบางต่อระเบียน แล้วผสานเวกเตอร์เหล่านั้นด้วยพารามิเตอร์ alpha ที่กำหนดค่าได้ การค้นหาแบบไฮบริดของ pgvector รวมการค้นหาข้อความเต็มรูปแบบด้วย SQL เข้ากับคำค้นเวกเตอร์ แล้วผสานผลลัพธ์ด้วย RRF ในโค้ดแอปพลิเคชัน และ การปรับค่า alpha บนชุดตรวจสอบเป็นสิ่งสำคัญในการหาสมดุลที่เหมาะสมกับการกระจายของคำค้นของคุณ บทถัดไป เราจะสำรวจการดึงข้อมูลแบบสองขั้นตอนพร้อมการจัดอันดับใหม่
คำถามที่พบบ่อย
บทเรียน “การค้นหาแบบผสมใน Pinecone และ pgvector” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การค้นหาแบบผสมใน Pinecone และ pgvector” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การค้นหาแบบผสมใน Pinecone และ pgvector”
กำหนดค่าการค้นหาแบบผสมใน Pinecone ด้วยโหมดดัชนีแบบเบาบาง-หนาแน่น และใน pgvector ด้วยคำสั่งค้นหาแบบขนานที่ผสานด้วย RRF พร้อมทดสอบเปรียบเทียบคุณภาพการดึงข้อมูลบนชุดข้อมูลของคุณ คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “การค้นหาแบบผสมใน Pinecone และ pgvector” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การดึงข้อมูลแบบหนาแน่นเทียบกับแบบเบาบาง: จุดแลกเปลี่ยน
- การสร้างการค้นหาด้วยคำสำคัญ BM25
- การรวมอันดับแบบผกผันเพื่อผสานคะแนน
- การค้นหาแบบผสมใน Pinecone และ pgvector