Valkey: Vektorinė paieška ir RAG
Semantinė paieška, rekomendacijos ir retrieval-augmented generation su Valkey
👋 Sveiki atvykę į Stackhero dokumentaciją!
Stackhero siūlo paruoštą naudoti Valkey cloud sprendimą, kuris suteikia daugybę privalumų, įskaitant:
- Įtrauktą
Valkey Adminweb UI.- Neribotas žinučių dydis ir perdavimas.
- Paprasti atnaujinimai vienu paspaudimu.
- Optimali veikla ir stipri saugumo apsauga, užtikrinama naudojant privačią, dedikuotą infrastruktūrą.
Taupykite laiką ir supaprastinkite savo darbą: išbandyti Stackhero Valkey cloud hosting sprendimą užtrunka tik 5 minutes!
Jei kuriate semantinę paiešką, rekomendacijų variklį arba retrieval-augmented generation (RAG) procesą, jums reikia saugoti embedding'us ir greitai rasti artimiausius atitikmenis užklausai. Stackhero for Valkey tai palaiko natūraliai: paieškos modulis indeksuoja vektorius ir atsako į panašumo užklausas per milisekundes. Jums nereikia diegti atskiros vektorinės duomenų bazės šalia jau naudojamos Valkey paslaugos.
Šį sprendimą praktišku ir efektyviu daro dvi savybės:
- Hibridinės užklausos. Galite atlikti vektorinės panašumo paieškas ir taikyti įprastus filtrus (pvz., skaitmeninius intervalus, žymas ar tekstą) vienoje užklausoje. Pavyzdžiui, galite gauti „5 fragmentus, artimiausius šiam klausimui, bet tik iš dokumentų, kuriuos šis naudotojas gali skaityti“ su viena užklausa, o ne dviem.
- Mažiau komponentų. Jūsų embedding'ai saugomi kartu su cache ir sesijos duomenimis, naudojant tuos pačius prisijungimo duomenis, atsargines kopijas ir stebėsenos įrankius. Tai supaprastina jūsų infrastruktūrą ir palengvina valdymą.
Prieš pradedant
Įjunkite Search modulį (ir JSON, jei norite dokumentus saugoti JSON formatu) savo paslaugos konfigūracijos Modules skiltyje Stackhero valdymo pulte. Daugiau informacijos rasite search ir JSON gide.
Vektoriaus indekso kūrimas
Deklaruokite vektoriaus lauką nurodydami jo dimensiją ir atstumo metriką. Dimensija turi atitikti jūsų modelį: pavyzdžiui, 1536 OpenAI text-embedding-3-small, arba 768 daugeliui atviro kodo modelių.
FT.CREATE chunksIndex
ON HASH
PREFIX 1 chunk:
SCHEMA
content TEXT
documentId TAG
embedding VECTOR HNSW 6
TYPE FLOAT32
DIM 1536
DISTANCE_METRIC COSINE
HNSW sukuria grafų indeksą, leidžiantį greitai atlikti apytiksles paieškas net ir didėjant kolekcijai. Tai rekomenduojama, jei turite daugiau nei kelis tūkstančius vektorių. Mažoms kolekcijoms galite naudoti FLAT tiksliai, brute-force paieškai.
COSINE dažniausiai yra geriausia atstumo metrika tekstiniams embedding'ams. Taip pat palaikomos L2 ir IP metrikos.
Užklausos
K artimiausių kaimynų (KNN) užklausa perduoda vektorių kaip parametrą, naudodama žalius little-endian float32 baitus:
FT.SEARCH chunksIndex "*=>[KNN 5 @embedding $queryVector]"
PARAMS 2 queryVector "<rawBytes>"
Norėdami derinti vektorinę paiešką su filtrais, tiesiog pakeiskite * savo filtro išraiška:
FT.SEARCH chunksIndex "@documentId:{doc42}=>[KNN 5 @embedding $queryVector]"
PARAMS 2 queryVector "<rawBytes>"
RAG pipeline Node.js aplinkoje
Valkey naudoja tą pačią protokolą kaip Redis, todėl galite naudoti bet kurį Redis suderinamą klientą.
import { createClient, SCHEMA_FIELD_TYPE, SCHEMA_VECTOR_FIELD_ALGORITHM } from 'redis';
const client = createClient({ url: process.env.STACKHERO_VALKEY_URL_TLS });
await client.connect();
const DIMENSIONS = 1536;
const toBytes = embedding => Buffer.from(new Float32Array(embedding).buffer);
// 1. Sukurkite indeksą vieną kartą, paleidžiant programą
try {
await client.ft.create(
'chunksIndex',
{
content: SCHEMA_FIELD_TYPE.TEXT,
documentId: SCHEMA_FIELD_TYPE.TAG,
embedding: {
type: SCHEMA_FIELD_TYPE.VECTOR,
ALGORITHM: SCHEMA_VECTOR_FIELD_ALGORITHM.HNSW,
TYPE: 'FLOAT32',
DIM: DIMENSIONS,
DISTANCE_METRIC: 'COSINE'
}
},
{ ON: 'HASH', PREFIX: 'chunk:' }
);
}
catch (error) {
if (!error.message.includes('Index already exists')) {
throw error;
}
}
// 2. Indeksuokite savo fragmentus (embedding'ą pateikia jūsų modelio tiekėjas)
async function indexChunk({ id, documentId, content, embedding }) {
await client.hSet(`chunk:${id}`, {
content,
documentId,
embedding: toBytes(embedding)
});
}
// 3. Gaukite fragmentus, artimiausius klausimui, apribojant pagal dokumentą
async function retrieve({ questionEmbedding, documentId, count = 5 }) {
const results = await client.ft.search(
'chunksIndex',
`@documentId:{${documentId}}=>[KNN ${count} @embedding $queryVector]`,
{ PARAMS: { queryVector: toBytes(questionEmbedding) } }
);
return results.documents.map(({ value }) => value.content);
}
// 4. Pateikite juos savo modeliui kaip kontekstą
const context = await retrieve({ questionEmbedding, documentId: 'doc42' });
const prompt = `Atsakykite naudodami tik šį kontekstą:\n\n${context.join('\n\n')}\n\nKlausimas: ${question}`;
Tas pats Python kalba
import os
import numpy as np
import redis
from redis.commands.search.field import TextField, TagField, VectorField
from redis.commands.search.index_definition import IndexDefinition, IndexType
from redis.commands.search.query import Query
DIMENSIONS = 1536
r = redis.from_url(os.environ['STACKHERO_VALKEY_URL_TLS'])
# Sukurkite indeksą vieną kartą, paleidžiant programą
try:
r.ft('chunksIndex').create_index(
(
TextField('content'),
TagField('documentId'),
VectorField(
'embedding',
'HNSW',
{'TYPE': 'FLOAT32', 'DIM': DIMENSIONS, 'DISTANCE_METRIC': 'COSINE'},
),
),
definition=IndexDefinition(prefix=['chunk:'], index_type=IndexType.HASH),
)
except redis.ResponseError as error:
if 'Index already exists' not in str(error):
raise
def index_chunk(chunk_id, document_id, content, embedding):
r.hset(
f'chunk:{chunk_id}',
mapping={
'content': content,
'documentId': document_id,
'embedding': np.array(embedding, dtype=np.float32).tobytes(),
},
)
def retrieve(question_embedding, document_id, count=5):
query = Query(f'@documentId:{{{document_id}}}=>[KNN {count} @embedding $queryVector]')
results = r.ft('chunksIndex').search(
query,
query_params={'queryVector': np.array(question_embedding, dtype=np.float32).tobytes()},
)
return [document.content for document in results.docs]
Paslaugos dydžio planavimas
Vektoriai saugomi atmintyje, todėl svarbu įvertinti jų užimamą vietą. Apytikslis float32 vektorių skaičiavimas:
numberOfVectors x dimensions x 4 bytes, plius apie 30–50 procentų papildomai HNSW grafui.
Pavyzdžiui, milijonas 1536-dimensijų vektorių užims apie 6 GB žaliems vektoriams. 20 GB planas yra patogus startui. Atminties naudojimą galite sumažinti pasirinkę modelį su mažesniu dimensijų skaičiumi: 768-dimensijų modelis naudoja tik pusę 1536-dimensijų modelio atminties.
Tikslų atminties naudojimą galite patikrinti su FT.INFO chunksIndex ir su used_memory metrika savo Prometheus stebėsenos sistemoje. Jei reikia daugiau atminties, planą galite bet kada padidinti valdymo pulte.
Svarbu žinoti
- Egzistuojančių raktų indeksavimas vyksta fone. Progresą galite stebėti su
FT.INFO. Paieškos grąžins dalinius rezultatus, kol užpildymas bus baigtas. - Paieškos modulis įgyvendina pagrindines
FT.*komandas. Vektorinės paieškos atveju palaikomos visos esminės funkcijos: HNSW ir tiksli KNN, hibridinis filtravimas irFT.AGGREGATE.
Išsamią informaciją rasite Valkey search dokumentacijoje.