set long 999999 set pages 1000 set lines 200 /* -------------------------------- HNSW INDEX -------------------------------- */ -- crear indice HNSW para busquedas vectoriales aproximadas DROP INDEX IF EXISTS markdown_chunks_hnsw_idx; CREATE VECTOR INDEX markdown_chunks_hnsw_idx ON markdown_chunks (embedding) ORGANIZATION INMEMORY NEIGHBOR GRAPH DISTANCE COSINE WITH TARGET ACCURACY 90 PARAMETERS ( TYPE HNSW, NEIGHBORS 32, EFCONSTRUCTION 200 ); /* -------------------------------- IVF INDEX -------------------------------- */ -- crear indice IVF con DOC_ID incluido para filtros por documento DROP INDEX IF EXISTS markdown_chunks_ivf_idx; CREATE VECTOR INDEX markdown_chunks_ivf_idx ON markdown_chunks (embedding) INCLUDE (doc_id) ORGANIZATION NEIGHBOR PARTITIONS DISTANCE COSINE WITH TARGET ACCURACY 90 PARAMETERS ( TYPE IVF, NEIGHBOR PARTITIONS 4, MIN_VECTORS_PER_PARTITION 1 ); /* -------------------------------- TEXT INDEX + VECTOR SEARCH -------------------------------- */ -- hybrid indexes / text indexes para busquedas textuales y combinadas DROP INDEX IF EXISTS markdown_chunks_text_idx; CREATE SEARCH INDEX markdown_chunks_text_idx ON markdown_chunks (chunk_text) FOR TEXT; select doc_id, chunk_id, SCORE(1) as text_score, VECTOR_DISTANCE(embedding, VECTOR_EMBEDDING(MULTILINGUAL_E5_BASE USING 'estaciones de servicio' as DATA ) ) as vector_distance, chunk_text from markdown_chunks where contains(chunk_text, 'Beneficio AND FUZZY(Benefcio) AND ABOUT(estaciones) AND (Visa accum Mastercard) AND (Clásica OR Oro) AND (crédito NOT débito) AND NEAR((POS, Infonet), 5) AND NEAR((App, Premmia, Petrobras), 1) AND (consumo AND personal)', 1) > 0 order by vector_distance fetch first 3 rows only; /* -------------------------------- HYBRID VECTOR INDEX -------------------------------- */ -- crear indice hibrido para combinar busqueda textual y semantica DROP INDEX IF EXISTS markdown_chunks_hybrid_idx; CREATE HYBRID VECTOR INDEX markdown_chunks_hybrid_idx ON markdown_chunks (chunk_text) PARAMETERS ('MODEL MULTILINGUAL_E5_BASE VECTOR_IDXTYPE HNSW MEMORY 128M') PARALLEL 2; -- ejemplo de consulta usando el indice hibrido SELECT JSON_SERIALIZE( DBMS_HYBRID_VECTOR.SEARCH( JSON('{ "hybrid_index_name" : "markdown_chunks_hybrid_idx", "search_fusion" : "UNION", "vector" : { "search_text" : "beneficios en estaciones de servicio", "search_mode" : "CHUNK" }, "text" : { "contains" : "estaciones AND Petrobras" }, "return" : { "values" : [ "chunk_id", "chunk_text", "score", "vector_score", "text_score" ], "topN" : 5 } }') ) RETURNING CLOB PRETTY ) AS hybrid_results; SELECT jt.* FROM JSON_TABLE( dbms_hybrid_vector.search( json_object( 'hybrid_index_name' VALUE 'markdown_chunks_hybrid_idx', 'search_fusion' VALUE 'INTERSECT', 'search_scorer' VALUE 'rsf', 'vector' VALUE json_object('search_text' VALUE 'beneficios en estaciones de servicio'), 'text' VALUE json_object('contains' VALUE 'estaciones AND Petrobras'), 'return' VALUE json_object( 'values' VALUE json_array('rowid', 'score', 'vector_score', 'vector_rank', 'text_score', 'text_rank', 'chunk_text'), 'topN' VALUE 3 ) RETURNING JSON ) ), '$[*]' COLUMNS idx for ORDINALITY, score NUMBER PATH '$.score', vector_score NUMBER PATH '$.vector_score', vector_rank NUMBER PATH '$.vector_rank', text_score NUMBER PATH '$.text_score', text_rank NUMBER PATH '$.text_rank', chunk_text VARCHAR2(4000) PATH '$.chunk_text' ) jt;