반응형

Oracle Ai Vector 개념

벡터 하나를 '설문지 응답'이라고 생각해보면 세 가지 저장 방식의 차이있음

  • Dense (밀집) 벡터 
    • 문항 100개짜리 설문지에서 응답자가 모든 문항에 빠짐없이 답한 경우
    • 답이 0이어도 그 자리에 0이 물리적으로 저장
    • 텍스트 임베딩이 바로 이 형태임
  • Sparse (희소) 벡터
    • 문항 10000개짜리 설문지인데 응답자가 어차피 대부분 "해당 없음"이라서 답한 문항 몇 개만 기록하는 경우
    • '3번 문항=7점, 158번 문항=2점'처럼 (위치, 값) 쌍만 저장하니 공간이 훨씬 절약
    • 키워드 검색(BM25, TF-IDF류)에서 주로 사용
  • Binary (이진) 벡터 
    • 문항 하나하나가 그냥 'Yes/No(0/1)'인 체크리스트
    • 숫자 하나에 8개 문항(비트)을 사용하여 저장공간이 극도로 작고, 비교 연산(해밍 거리)도 매우빠름
    • 그러나 정밀도는 가장 낮으며 정확도보다 일단 후보를 확 걸러내는 1차 필터링 용도로 사용
[oracle@rhel10nm ~]$ id
uid=5001(oracle) gid=500(dba) groups=500(dba) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[oracle@rhel10nm ~]$ env | grep SID
ORACLE_SID=CDB1
[oracle@rhel10nm ~]$
[oracle@rhel10nm ~]$ sqlplus "/as sysdba"
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
SQL>
SQL> --PDB1 접속
SQL> ALTER SESSION SET CONTAINER = PDB1;
Session altered.
SQL> --PDB1 접속 확인
SQL> show con_name
CON_NAME
------------------------------
PDB1
SQL>
SQL> --Dense vector
SQL> --DROP TABLE vec_lab_dense PURGE;
SQL> CREATE TABLE vec_lab_dense (
  2  id  NUMBER,
  3  v32 VECTOR(3, FLOAT32),  -- 32bit float: 실제 임베딩 모델이 가장 흔히 쓰는 포맷
  4  v64 VECTOR(3, FLOAT64),  -- 64bit float: 정밀도,저장공간 2배
  5  v8  VECTOR(3, INT8)      -- 8bit 정수: 저장공간 최소, 정밀도 최저
  6  );
Table created.
SQL> desc vec_lab_dense
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER
 V32                                                VECTOR(3, FLOAT32, DENSE)
 V64                                                VECTOR(3, FLOAT64, DENSE)
 V8                                                 VECTOR(3, INT8, DENSE)
SQL>
SQL> INSERT INTO vec_lab_dense
  2  VALUES (1, '[1.625, 1.5, 1.0]', '[11.25, 11.75, 11.5]', '[10, 20, 30]');
1 row created.
SQL> commit;
Commit complete.
SQL> set linesize 120
SQL> col V32 for a30
SQL> col V64 for a40
SQL> col v8 for a30
SQL> --입력한 세 벡터가 그대로 조회돼야 함
SQL> SELECT * FROM vec_lab_dense;
        ID V32                            V64                                      V8
---------- ------------------------------ ---------------------------------------- ------------------------------
         1 [1.625E+000,1.5E+000,1.0E+000] [1.125E+001,1.175E+001,1.15E+001]        [10,20,30]
SQL>
SQL> --1.625E+000은 1.625를 지수 표기법(E+000 = ×10⁰ = ×1)
SQL> --입력:[11.25, 11.75, 11.5] -> 출력:[1.125E+001, 1.175E+001, 1.15E+001] (11.25 = 1.125×10¹)
SQL>
SQL> -- Sparse vector
SQL> -- DROP TABLE vec_lab_sparse PURGE;
SQL>
SQL> CREATE TABLE vec_lab_sparse (
  2  id   NUMBER,
  3  v_sp VECTOR(25, FLOAT32, SPARSE)
  4  );
Table created.
SQL>
SQL> desc vec_lab_sparse
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 ID                                                                         NUMBER
 V_SP                                                                       VECTOR(25, FLOAT32, SPARSE)
SQL>
SQL> -- 전체 25차원 중 5, 8, 11번 위치에만 값이 있고 나머지 22개는 0
SQL> INSERT INTO vec_lab_sparse VALUES (1, '[25,[5,8,11],[25.25,6.125,8.25]]');
1 row created.
SQL> commit;
Commit complete.
SQL>
SQL> col V_SP for a50
SQL> SELECT id, v_sp FROM vec_lab_sparse;
        ID V_SP
---------- --------------------------------------------------
         1 [25,[5,8,11],[2.525E+001,6.125E+000,8.25E+000]]
SQL> -- SELECT결과는 압축된 [25,[5,8,11],[25.25,6.125,8.25]] 형식으로 출력 되어야 함
SQL>
SQL> -- TO_VECTOR로 Dense 변환하여 25개 값을 확인
SQL> set linesize 120
SQL> col V_SP_AS_DENSE for a80
SQL> SELECT id, TO_VECTOR(v_sp, 25, FLOAT32, DENSE) AS v_sp_as_dense FROM vec_lab_sparse;
        ID V_SP_AS_DENSE
---------- --------------------------------------------------------------------------------
         1 [0,0,0,0,0,2.525E+001,0,0,6.125E+000,0,0,8.25E+000,0,0,0,0,0,0,
SQL> --SELECT결과는 25개 숫자가 다 출력되어야 하며 5, 8, 11번째 자리만 값이 있고 나머지는 0이어야 함
SQL> --위 2개의 Select 결과는 압축 형태와 실제 내용이 같은 데이터의 두 가지 표현 차이
SQL> 
SQL> -- Binary vector
SQL> -- DROP TABLE vec_lab_binary PURGE;
SQL>
SQL> CREATE TABLE vec_lab_binary (
  2  id    NUMBER,
  3  v_bin VECTOR(16, BINARY)   -- 16차원 = 2바이트
  4  );
Table created.
SQL>
SQL> desc vec_lab_binary
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 ID                                                                         NUMBER
 V_BIN                                                                      VECTOR(16, BINARY, DENSE)
SQL>
SQL> -- 201 = 이진수 11001001, 15 = 이진수 00001111
SQL> -- 이 두 바이트가 합쳐져서 16개의 개별 비트(차원)를 표현함
SQL> INSERT INTO vec_lab_binary VALUES (1, '[201, 15]');
1 row created.
SQL> commit;
Commit complete.
SQL> col V_BIN for a50
SQL> SELECT id, v_bin FROM vec_lab_binary;
        ID V_BIN
---------- --------------------------------------------------
         1 [201,15]
SQL>
SQL> -- 실습용 Sample Table 생성(문서 1000건 벡터 대량 적재)
SQL> -- lab_documents: a small "document + vector" table.
SQL> -- DROP TABLE lab_documents PURGE;
SQL>
SQL> CREATE TABLE lab_documents (
  2  doc_id    NUMBER,
  3  doc_title VARCHAR2(100),
  4  embedding VECTOR(8, FLOAT32)
  5  );
Table created.
SQL>
SQL> desc lab_documents
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 DOC_ID                                                                     NUMBER
 DOC_TITLE                                                                  VARCHAR2(100)
 EMBEDDING                                                                  VECTOR(8, FLOAT32, DENSE)
SQL>
SQL> INSERT INTO lab_documents (doc_id, doc_title, embedding)
  2  SELECT
  3      LEVEL,
  4      'Document ' || LEVEL,
  5      TO_VECTOR(
  6          '[' ||
  7          ROUND(DBMS_RANDOM.VALUE(0,1),3) || ',' ||
  8          ROUND(DBMS_RANDOM.VALUE(0,1),3) || ',' ||
  9          ROUND(DBMS_RANDOM.VALUE(0,1),3) || ',' ||
 10          ROUND(DBMS_RANDOM.VALUE(0,1),3) || ',' ||
 11          ROUND(DBMS_RANDOM.VALUE(0,1),3) || ',' ||
 12          ROUND(DBMS_RANDOM.VALUE(0,1),3) || ',' ||
 13          ROUND(DBMS_RANDOM.VALUE(0,1),3) || ',' ||
 14          ROUND(DBMS_RANDOM.VALUE(0,1),3) ||
 15          ']'
 16      )
 17  FROM dual
 18  CONNECT BY LEVEL <= 1000;
1000 rows created.
SQL> commit;
Commit complete.
SQL>
SQL> -- 전체 1000건 확인
SQL> SELECT COUNT(*) AS row_count FROM lab_documents;
 ROW_COUNT
----------
      1000
SQL>
SQL> -- 샘플 3건 확인 - 8개 숫자가 채워진 벡터가 보여야 함
SQL> col EMBEDDING for a80
SQL> col DOC_TITLE for a15
SQL> SELECT doc_id, doc_title, embedding FROM lab_documents WHERE doc_id <= 3;
    DOC_ID DOC_TITLE       EMBEDDING
---------- --------------- --------------------------------------------------------------------------------
         1 Document 1      [5.42999983E-001,3.81999999E-001,9.3900001E-001,6.14000022E-001,
         2 Document 2      [5.66999972E-001,9.60000008E-002,3.2100001E-001,6.74000025E-001,
         3 Document 3      [7.9400003E-001,3.31E-001,4.79999989E-001,2.56000012E-001,7.54999995E-001,
SQL> --ROW_COUNT가 1000, 샘플 조회에서 각 행마다 8개 실수로 채워진 벡터가 보이면 성공
SQL> exit
Disconnected from Oracle AI Database 26ai Enterprise Edition Release 23.26.2.0.0 - Production
Version 23.26.2.0.0
[oracle@rhel10nm ~]$

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

+ Recent posts