Hybrid søgning i Pinecone og pgvector
Konfigurér hybrid søgning i Pinecone ved hjælp af sparse-dense-indekstilstand og i pgvector ved hjælp af parallelle forespørgsler med RRF-sammenlægning, og benchmark søgekvaliteten på Deres datasæt.
Hybrid søgning i Pinecone og pgvector er en gratis AI Engineering Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i AI Engineering Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. AI Engineering Academy-kurset indeholder 4 lektioner i alt.
Indbygget hybridsøgning i vektordatabaser
Selvom du selv kan implementere hybridsøgning ved hjælp af to separate indeks og RRF-fusion, tilbyder produktionsvektordatabaser i stigende grad indbygget hybridsøgning, der håndterer sparse og dense hentning i én forespørgsel. Pinecone og pgvector understøtter begge hybridtilstande, men med forskellige arkitekturvalg og afvejninger. Når du forstår begge muligheder, kan du vælge det rigtige værktøj til din infrastruktur.
Pinecones sparse-dense-indekstilstand
Pinecone understøtter et sparse-dense-indeks, hvor hver vektorpost gemmer både en dense embedding (som et float-array) og en sparse vektor (som en ordbog fra token-id til vægt). Forespørgsler kan angive både en dense forespørgselsvektor og en sparse forespørgselsvektor, hvorefter Pinecone fletter resultaterne ved hjælp af en vægtet lineær kombination. Dette adskiller sig fra RRF – Pinecone bruger rå scorefusion med konfigurerbare vægte kaldet 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')Generering af sparse vektorer med SPLADE
Hvis du vil bruge Pinecones sparse-dense-tilstand, skal du generere sparse vektorer for hvert dokument. Den mest effektive metode er SPLADE (Sparse Lexical and Expansion), en neural model, der producerer indlærte sparse-repræsentationer med udvidelse – den tilføjer semantisk relaterede termer til den sparse vektor ud over dem, der bogstaveligt forekommer i teksten. Alternativt kan du bruge simple BM25-termvægte som sparse vektorer.
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}Upserting af hybridvektorer til Pinecone
Hver Pinecone-post i et hybridindeks gemmer et id, et dense values-array, en sparse_values-ordbog med indices og values samt valgfri metadata. Upsert poster i batches på 100 for at maksimere gennemløbet, samtidig med at du holder dig inden for Pinecones grænser for forespørgselsstørrelse.
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}')Forespørgsler til Pinecones hybridindeks
En hybridforespørgsel sender både en dense vector og en sparse_vector til Pinecones forespørgsels-API. Alpha-parameteren (0 til 1) styrer balancen: alpha=1.0 er ren dense, alpha=0.0 er ren sparse, og alpha=0.5 giver begge samme vægt. Justér alpha på et valideringssæt – typiske optimale værdier ligger mellem 0.3 og 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: Vektorsøgning i PostgreSQL
Udvidelsen pgvector tilføjer en vector-kolonnetype og afstandsoperatorer til PostgreSQL. Ved hybridsøgning kører du to forespørgsler parallelt – en forespørgsel efter approksimale nærmeste naboer på vektorkolonnen og en fuldtekstsøgningsforespørgsel ved hjælp af PostgreSQLs indbyggede tsvector og tsquery – og fletter derefter resultaterne med RRF i din applikationskode.
-- 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);Kørsel af dense og sparse forespørgsler i pgvector
Med pgvector kører du den dense forespørgsel ved hjælp af cosine-afstandsoperatoren <=> for at finde de nærmeste naboer til forespørgslens embedding, og den sparse forespørgsel ved hjælp af ts_rank_cd mod tsvector-kolonnen for at score søgeordsmatch. Hent begge resultatsæt uafhængigt, og flet dem derefter med RRF i 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)Anvendelse af RRF på pgvector-resultater
Efter at have indsamlet rangordnede rækker fra begge PostgreSQL-forespørgsler anvender du RRF ved at udtrække dokument-id'er i rangorden fra hvert resultatsæt og køre fusionsalgoritmen. Den endelige flettede liste giver dig de top-K-dokumenter, der er mest relevante med hensyn til både semantisk betydning og overlap af søgeord.
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]]Benchmarking af hentningskvalitet
Efter implementering af hybridsøgning skal du benchmarke den grundigt mod din baseline for hentning, der kun bruger dense. Brug et gyldent testsæt med mindst 100 forespørgsler og kendte relevante dokumenter. Mål NDCG@5, MRR og hitrate@3. Typiske forbedringer fra hybridsøgning ligger på 5 til 20 procent for NDCG@5, med de største gevinster på forespørgsler, der indeholder eksakte tekniske termer, som dense-modeller overser.
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),
}Justering af Alpha i Pinecones hybridtilstand
Alpha-parameteren i Pinecones hybridforespørgsel kræver systematisk justering. Stratificering efter forespørgselstype er en nyttig metode: klassificér dine testforespørgsler som overvejende semantiske (omskrivninger, begreber) eller overvejende leksikalske (eksakte termer, koder), og mål den optimale alpha separat for hver gruppe. Nogle produktionssystemer implementerer dynamisk alpha-valg, der klassificerer forespørgslen under kørsel og automatisk vælger den passende 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_alphaValg mellem Pinecone- og pgvector-hybrid
Brug Pinecone-hybrid, når du har brug for administreret infrastruktur og automatisk skalering og ønsker at overlade kompleksiteten ved generering af sparse vektorer til én API. Brug pgvector-hybrid, når du allerede har PostgreSQL-infrastruktur, har brug for transaktionskonsistens mellem dokumenter og deres metadata, ønsker fuld SQL-fleksibilitet til filtrering eller vil undgå leverandørafhængighed. Begge metoder giver fremragende kvalitet ved hybrid hentning, når de er korrekt justeret.
Hurtigt tjek
Test din forståelse af implementering af hybridsøgning fra denne lektion.
Opsummering af lektionen
I denne lektion har du lært, at Pinecones sparse-dense-tilstand gemmer både dense og sparse vektorer pr. post og fletter dem med en konfigurerbar alpha-parameter, at pgvector-hybridsøgning kombinerer SQL-fuldtekstsøgning med vektorforespørgsler, der flettes med RRF i applikationskoden, og at justering af alpha på et valideringssæt er afgørende for at finde den optimale balance for din fordeling af forespørgsler. Nu går vi videre til hentning i to trin med omrangering.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “Hybrid søgning i Pinecone og pgvector” gratis?
Ja — hele teksten til “Hybrid søgning i Pinecone og pgvector” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af AI Engineering Academy-kurset, skal du opgradere til CoddyKit PRO. AI Engineering Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Hybrid søgning i Pinecone og pgvector”?
Konfigurér hybrid søgning i Pinecone ved hjælp af sparse-dense-indekstilstand og i pgvector ved hjælp af parallelle forespørgsler med RRF-sammenlægning, og benchmark søgekvaliteten på Deres datasæt. Du øver dig i AI Engineering Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på AI Engineering Academy?
Der kræves ingen tidligere erfaring. AI Engineering Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Hybrid søgning i Pinecone og pgvector”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne AI Engineering Academy-lektion?
Ja. Alle AI Engineering Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Tæt versus sparsom søgning: afvejninger
- Implementering af BM25-søgeordssøgning
- Reciprocal Rank Fusion til sammenlægning af scorer
- Hybrid søgning i Pinecone og pgvector