AI Engineering Academy · Oppitunti

Hybridihaku Pineconessa ja pgvectorissa

Määritä hybridihaku Pineconessa sparse-dense-indeksitilalla ja pgvectorissa rinnakkaisilla kyselyillä sekä RRF-yhdistämisellä. Arvioi haun laatua aineistollasi.

Oppitunti 4/413 vaihetta

Hybridihaku Pineconessa ja pgvectorissa on ilmainen AI Engineering Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu AI Engineering Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. AI Engineering Academy-kurssilla on yhteensä 4 oppituntia.

Natiivi hybrid haku vektoritietokannoissa

Voitte toteuttaa hybrid haun itse käyttämällä kahta erillistä indeksiä ja RRF-yhdistämistä, mutta tuotantokäyttöön tarkoitetut vektoritietokannat tarjoavat yhä useammin sisäänrakennetun hybrid haun, joka käsittelee harvan ja tiheän haun yhdellä kyselyllä. Sekä Pinecone että pgvector tukevat hybriditiloja, mutta niiden arkkitehtuurivalinnat ja kompromissit ovat erilaisia. Molempien vaihtoehtojen ymmärtäminen auttaa valitsemaan infrastruktuuriinne sopivan työkalun.

Pineconen harva-tiheä-indeksitila

Pinecone tukee harva-tiheää indeksiä, jossa jokainen vektoritietue sisältää sekä tiheän upotuksen (liukulukutaulukkona) että harvan vektorin (sanaketunnisteen ja painon sisältävänä sanakirjana). Kyselyissä voidaan määrittää sekä tiheä kyselyvektori että harva kyselyvektori, ja Pinecone yhdistää tulokset painotetulla lineaarisella yhdistelmällä. Tämä eroaa RRF:stä: Pinecone käyttää raakapisteiden yhdistämistä, jossa määritettävissä olevia painoja kutsutaan nimellä 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')

Harvojen vektorien luominen SPLADElla

Jotta voitte käyttää Pineconen harva-tiheää tilaa, teidän on luotava harvat vektorit jokaista dokumenttia varten. Tehokkain lähestymistapa on SPLADE (Sparse Lexical and Expansion), neuroverkkomalli, joka tuottaa laajennettuja opittuja harvoja esityksiä — se lisää harvaan vektoriin semanttisesti toisiinsa liittyviä termejä, vaikka niitä ei esiintyisi tekstissä kirjaimellisesti. Vaihtoehtoisesti voitte käyttää yksinkertaisia BM25-termpainoja harmoina vektoreina.

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}

Hybridivektorien upsertointi Pineconeen

Jokainen hybridihakemiston Pinecone-tietue sisältää id-tunnisteen, tiheän values-taulukon, indices- ja values-kentät sisältävän sparse_values-sanakirjan sekä valinnaisen metadata-kentän. Upsertoikaa tietueet 100 tietueen erissä, jotta läpimeno olisi mahdollisimman suuri ja Pineconen pyyntöjen kokorajat eivät ylittyisi.

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}')

Pineconen hybridihakemiston kysely

Hybridikysely välittää Pineconen kysely-API:lle sekä tiheän vector-vektorin että sparse_vector-vektorin. alpha-parametri (0–1) määrittää painotuksen: alpha=1.0 tarkoittaa puhtaasti tiheää hakua, alpha=0.0 puhtaasti harvaa hakua ja alpha=0.5 antaa kummallekin yhtä suuren painon. Säätäkää alpha-arvoa validointiaineiston avulla — tyypilliset optimaaliset arvot ovat välillä 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.matches

pgvector: vektorihaku PostgreSQL:ssä

pgvector-laajennus lisää PostgreSQL:ään vector-saraketyypin ja etäisyysoperaattorit. Hybridihakua varten suoritatte kaksi kyselyä rinnakkain: likimääräisen lähimmän naapurin haun vektorisarakkeesta ja kokotekstihaun PostgreSQL:n sisäisillä tsvector- ja tsquery-tyypeillä. Tämän jälkeen yhdistätte tulokset sovelluskoodissa RRF:n avulla.

-- 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);

Tiheiden ja harvojen kyselyjen suorittaminen pgvectorissa

Suorittakaa pgvectorissa tiheä kysely <=>-kosinusetäisyysoperaattorilla löytääksenne kyselyupotuksen lähimmät naapurit. Suorittakaa harva kysely ts_rank_cd-funktiolla tsvector-saraketta vasten avainsanaosumien pisteyttämiseksi. Noutakaa molemmat tulosjoukot erikseen ja yhdistäkää ne sitten RRF:n avulla Pythonissa.

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:n soveltaminen pgvectorin tuloksiin

Kun olette koonneet järjestetyt rivit molemmista PostgreSQL-kyselyistä, soveltakaa RRF:ää poimimalla dokumenttitunnisteet kunkin tulosjoukon sijoitusjärjestyksessä ja suorittamalla yhdistämisalgoritmi. Lopullinen yhdistetty luettelo sisältää top-K-dokumentit, jotka ovat merkityksellisimpiä sekä semanttisen merkityksen että avainsanojen päällekkäisyyden kannalta.

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]]

Haun laadun vertailu

Kun olette toteuttaneet hybrid haun, vertailkaa sitä perusteellisesti lähtötasona olevaan pelkkään tiheään hakuun. Käyttäkää vähintään 100 kyselyn kultaista testijoukkoa, jonka relevantit dokumentit tunnetaan. Mitatkaa NDCG@5, MRR ja hit rate@3. Hybrid haun tyypilliset parannukset ovat NDCG@5-mittarilla 5–20 prosenttia, ja suurimmat hyödyt saavutetaan kyselyillä, jotka sisältävät täsmällisiä teknisiä termejä, joita tiheät mallit eivät löydä.

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),
    }

Alphan säätäminen Pineconen hybriditilassa

Pineconen hybridikyselyn alpha-parametri vaatii järjestelmällistä säätämistä. Kyselytyyppien osittaminen on hyödyllinen lähestymistapa: luokitelkaa testikyselyt pääasiassa semanttisiksi (parafraasit ja käsitteelliset kyselyt) tai pääasiassa leksikaalisiksi (täsmälliset termit ja koodit) ja mitatkaa optimaalinen alpha erikseen kummallekin ryhmälle. Joissakin tuotantojärjestelmissä käytetään dynaamista alphan valintaa, jossa kysely luokitellaan ajonaikaisesti ja sille valitaan automaattisesti sopiva alpha-arvo.

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

Pineconen ja pgvectorin hybridin välillä valitseminen

Käyttäkää Pinecone-hybridiä, kun tarvitsette hallittua infrastruktuuria ja automaattista skaalausta ja haluatte ulkoistaa harvojen vektorien luomisen monimutkaisuuden yhdelle API:lle. Käyttäkää pgvector-hybridiä, kun teillä on jo PostgreSQL-infrastruktuuri, tarvitsette dokumenttien ja niiden metatietojen transaktionaalista yhdenmukaisuutta, haluatte täydet SQL-suodatuksen mahdollisuudet tai haluatte välttää toimittajalukkiutumisen. Molemmat lähestymistavat tuottavat oikein säädettyinä erinomaisen hybridihakulaadun.

Pikatesti

Testatkaa tässä oppitunnissa oppimaanne hybrid haun toteuttamisesta.

Oppitunnin kertaus

Tässä oppitunnissa opitte, että Pineconen harva-tiheä tila tallentaa jokaiseen tietueeseen sekä tiheät että harvat vektorit ja yhdistää ne määritettävissä olevan alpha-parametrin avulla, pgvectorin hybrid haku yhdistää SQL-kokotekstihaun vektorikyselyihin, jotka yhdistetään sovelluskoodissa RRF:n avulla, ja alphan säätäminen validointiaineiston avulla on välttämätöntä kyselyjakauman optimaalisen tasapainon löytämiseksi. Seuraavaksi tutustumme kaksivaiheiseen hakuun ja uudelleenjärjestämiseen.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Hybridihaku Pineconessa ja pgvectorissa” ilmainen?

Kyllä – oppitunnin ”Hybridihaku Pineconessa ja pgvectorissa” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko AI Engineering Academy-kurssin, päivitä CoddyKit PROhon. AI Engineering Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Hybridihaku Pineconessa ja pgvectorissa”?

Määritä hybridihaku Pineconessa sparse-dense-indeksitilalla ja pgvectorissa rinnakkaisilla kyselyillä sekä RRF-yhdistämisellä. Arvioi haun laatua aineistollasi. Harjoittelet AI Engineering Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni AI Engineering Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin AI Engineering Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Hybridihaku Pineconessa ja pgvectorissa”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä AI Engineering Academy-oppitunnilla?

Kyllä. Jokainen AI Engineering Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Tiheä ja harva haku: kompromissit
  2. BM25-avainsanahaun toteuttaminen
  3. Reciprocal rank fusion -menetelmä pisteiden yhdistämiseen
  4. Hybridihaku Pineconessa ja pgvectorissa
← Takaisin: AI Engineering Academy