Vector Search Theoritical Notes With Keywords
Vector Search Theoritical Notes With Keywords
=========================
Vector Embeddings
=========================
Oracle AI Vector Search stores vector embeddings, which are mathematical vector
representations of data points.
These vector embeddings describe the semantic meaning behind content such as words,
documents, audio tracks, or images. As an example, while doing text based searches,
vector search is often considered better than keyword search as vector search is
based on the meaning and context behind the words and not the actual words
themselves.
Vector embeddings are a way of representing almost any kind of data, such as text,
images, videos, users, or music as points in a multidimensional space where the
locations of those points in space, and proximity to others, are semantically
meaningful.
=========================
Similarity Search
=========================
Example:
~~~~~~~
The distance between dog and wolf in this vector space is shorter than the distance
between dog and kitten.
In this space, a dog is more similar to a wolf than it is to a kitten.
Vector data tends to be unevenly distributed and clustered into groups that are
semantically related.
Doing a similarity search based on a given query vector is equivalent to retrieving
the K-nearest vectors to your query vector in your vector space.
Basically, you need to find an ordered list of vectors by ranking them, where the
first row in the list is the closest or most similar vector to the query vector,
the second row in the list is the second closest vector to the query vector, and so
on.
When doing a similarity search, the relative order of distances is what really
matters rather than the actual distance.
Approximate searches using vector indexes can limit the searches to specific
clusters, whereas exact searches visit vectors across all clusters.
=========================
Vector Embedding Models
=========================
Depending on the type of your data, you can use different pretrained, open-source
models to create vector embeddings.
For example:
~~~~~~~~~~~
For textual data --> "sentence transformers" transform words, sentences, or
paragraphs into vector embeddings.
For visual data --> you can use Residual Network (ResNet) to generate vector
embeddings.
For audio data --> you can use the visual spectrogram representation of the audio
data to fall back into the visual data case.
Each model also determines the number of dimensions for your vectors.
For example:
~~~~~~~~~~~~
Cohere's embedding model 'embed-english-v3.0' has 1024 dimensions.
OpenAI's embedding model 'text-embedding-3-large' has 3072 dimensions.
Hugging Face's embedding model 'all-MiniLM-L6-v2' has 384 dimensions.
Of course, you can always create your own model that is trained with your own data
set.
==================================================
Import Embedding Models into Oracle Database
==================================================
You can generate vector embeddings outside the Oracle Database using pretrained
open-source embeddings models or your own embeddings models.
you also have the option to import those models directly into the Oracle Database
if they are compatible with the Open Neural Network Exchange (ONNX) standard.
Oracle Database implements an ONNX runtime directly within the database. This
allows you to generate vector embeddings directly within the Oracle Database using
SQL.
==================================================
Why Use Oracle AI Vector Search?
==================================================
One of the biggest benefits of Oracle AI Vector Search is that semantic search on
unstructured data can be combined with relational search on business data in one
single system.
This is not only powerful but also significantly more effective because you don't
need to add a specialized vector database, eliminating the pain of data
fragmentation between multiple systems.
==================================================
Oracle AI Vector Search Workflow
==================================================
With the query vector, you can perform similarity searches against the vectors that
are already stored in the database,
in combination with relational queries if desired.
==================================================
Generate Vector Embeddings
==================================================
You must generate vector embeddings from your unstructured data either outside or
within Oracle Database.
To get vector embeddings, you can either use ONNX embedding machine learning models
or access third-party REST APIs.
Put differently, You can generate vectors by calling services outside the database
or generate vectors directly from within the database after you have imported
pretrained embedding models.
***********************************************************************************
*
Import Pretrained Models in ONNX Format for Vector Generation Within the Database:
***********************************************************************************
*
You can download pretrained embedding machine learning models and then convert them
into ONNX format, if they are not already in ONNX format, and then import the ONNX
format models into the Oracle Database and then generate vector embeddings from
your data within the database.
-------------------------------------------
Import ONNX Models and Generate Embeddings
-------------------------------------------
If the pretrained model is in ONNX format already, then simply import it and
generate vector embeddings.
(or) Alternately, you can load the ONNX embedding model by specifying the JSON
metadata.
4. Generate Embeddings:
```````````````````````
SELECT TO_VECTOR(VECTOR_EMBEDDING(doc_model USING 'hello' as data)) AS embedding;
Alternatively, using DBMS_DATA_MINING package also, you can import the Models.
CONN dmuser/<password>@<pdbname>;
DECLARE
m_blob BLOB default empty_blob();
m_src_loc BFILE ;
BEGIN
DBMS_LOB.createtemporary (m_blob, FALSE);
m_src_loc := BFILENAME('DM_DUMP', 'my_embedding_model.onnx');
DBMS_LOB.fileopen (m_src_loc, DBMS_LOB.file_readonly);
DBMS_LOB.loadfromfile (m_blob, m_src_loc, DBMS_LOB.getlength (m_src_loc));
DBMS_LOB.CLOSE(m_src_loc);
DBMS_DATA_MINING.import_onnx_model ('doc_model', m_blob, JSON('{"function" :
"embedding", "embeddingOutput" : "embedding", "input": {"input": ["DATA"]}}'));
DBMS_LOB.freetemporary (m_blob);
END;
/
(or)
DECLARE
model_source BLOB := NULL;
BEGIN
-- get BLOB holding onnx model
model_source := DBMS_CLOUD.GET_OBJECT(
credential_name => 'myCredential',
object_uri => 'https://objectstorage.us-phoenix -1.oraclecloud.com/' ||
'n/namespace -string/b/bucketname/o/myONNXmodel.onnx');
DBMS_DATA_MINING.IMPORT_ONNX_MODEL(
"myonnxmodel",
model_source,
JSON('{ function : "embedding" })
);
END;
/
-------------------------------------------
Convert Pretrained Models to ONNX Format
-------------------------------------------
If the pretrained model is NOT in ONNX format, then convert it to ONNX format so
that SQL understands it.
OML4Py enables the use of text transformers from Hugging Face by converting the
pretrained models into ONNX format models.
OML4Py also adds the necessary tokenization and post-processing.
The resulting ONNX pipeline is then imported into the database and can be used to
generate embeddings for AI Vector Search.
Note: This feature will only work on OML4Py client. It is not supported on the
OML4Py server.
At a high level, the Python utility package performs the following tasks:
1. Downloads the pretrained model from external source to your system
2. Augments the model with pre-processing and post-processing steps and creates a
new ONNX model
3. Validates the augmented ONNX model
4. Loads into the database as a mining model or optionally exports to a file
The Python utility can take any of the models in the preconfigured list as input.
Alternatively, you can use the built-in template that contains common
configurations for certain groups of models such as text-based models.
Currently, the Python package supports only the Text Transformers and the Model
size should be less than 1GB. If it is more than 1 GB, then try Quantization to
reduce the size. And, the Tokenizers must be either BERT, GPT2, SENTENCEPIECE, or
ROBERTA.
Preconfigured list of models are common models from external resource repositories
that are provided with the Python utility. The preconfigured models have an
existing specification. Users can create their own specification using the text
template as a starting point. To get a list of all model names in the preconfigured
list, you can use the show_preconfigured function.
The Python utility package provides built-in text template for you to configure the
pretrained models with pre-processing and post-processing operations. The template
has a default specification for the pretrained models. This specification can be
changed or augmented to create custom configurations. The text template uses Mean
Pooling and Normalization as post-processing operations by default.
To use the Python utility, ensure that you have the following:
1. OML4Py Client running on Linux X64 for On-Premises Databases
2. Python 3.12 (the earlier versions are not compatible)
Note:ONNX files are only created when export2file is used. If export2db is used, no
ONNX files will be generated.
Note: The Python utility package validates the embedding text model before you can
run them using ONNX Runtime. Oracle supports ONNX embedding models that conform to
string as input and float32 [<vector dimension>] as output.
--------------------------------------------------------------
Python Classes to Convert Pretrained Models to ONNX Models
--------------------------------------------------------------
The EmbeddingModelConfig class contains the properties required for the package to
perform downloading, exporting, augmenting, validation, and storing of an ONNX
model. The class provides access to configuration properties using the dot
operator. As a convenience, well-known configurations are provided as templates.
This example illustrates the preconfigured embedding model that comes with the
Python package. You can use this model without any additional configurations.
"sentence-transformers/distiluse-base-multilingual-cased-v2": {
"max_seq_length": 128,
"do_lower_case": false,
"post_processors":[{"name":"Pooling","type":"mean"},
{"name":"Dense","in_features":768, "out_features":512, "bias":true,
"activation_function":"Tanh"}],
"quantize_model":true,
"distance_metrics": ["COSINE"],
"languages": ["ar", "bg", "ca", "cs", "dk", "d", "us", "el", "et", "fa",
"sf", "f", "frc", "gu", "iw", "hi", "hr", "hu", "hy", "in", "i", "ja", "ko", "lt",
"lv", "mk", "mr", "ms", "n", "nl", "pl", "pt", "ptb", "ro", "ru", "sk", "sl", "sq",
"lsr", "s", "th", "tr", "uk", "ur", "vn", "zhs", "zht"]
}
***********************************************************************************
*
Generate Vector Embeddings Using Vector Utilities Leveraging Third-Party REST APIs:
***********************************************************************************
*
Oracle AI Vector Search offers vector utilities (SQL and PL/SQL tools) to
automatically generate vector embeddings from your unstructured data.
You can call either Vector Utility SQL functions or Vector Utility PL/SQL packages
to transform unstructured data into vector embeddings.
--------------------------------------------------------------
Understand the Stages of Data Transformations
--------------------------------------------------------------
Your input data may travel through different stages before turning into a vector
For example, you may first transform textual data (such as a PDF document) into
plain text, then break the resulting text into smaller pieces of text (chunks) to
finally create vector embeddings on each chunk.
To prepare large unstructured textual data (for example, a PDF or Word document),
you first transform the data into plain text and then pass the resulting text
through Chunker. The chunker then splits the text into smaller chunks using a
process known as chunking. A single document may be split into many chunks, each
transformed into a vector.
Chunks are pieces of words (to capture specific words or word pieces), sentences
(to capture a specific meaning), or paragraphs (to capture broader themes). Later,
you will learn about several chunking parameters and techniques to define so that
each chunk contains relevant and meaningful context.
The chunks are first passed through Tokenizer of the model to split into words or
word pieces, known as tokens. The model then embeds each token into a vector
representation.
Tokenizers used by embedding models frequently have limits on the size of the input
text they can deal with, so chunking is needed to avoid loss of text when
generating embeddings. If input text is larger than the maximum input limit imposed
by the model, then the text gets truncated unless it is split up into appropriate-
sized segments or chunks. Chunking is not needed for smaller documents, text
strings, or summarized texts that meet this maximum input limit.
The chunker must select a text size that approximates the maximum input limit of
your model. The actual number of tokens depends on the specified tokenizer for the
model, which typically uses a vocabulary list of words, numbers, punctuations, and
pieces of tokens.
as the following eight tokens and also includes ## (number signs) to indicate non-
initial pieces of words:
Em ##bedd ##ing use ##case for chunk ##ing
Vocabulary files are included as part of a model's distribution. You can supply a
vocabulary file (recognized by your model's tokenizer) to the chunker beforehand,
so that it can correctly estimate the token count of your input data when chunking.
--------------------------------------------------------------
Use SQL Functions to Generate Embeddings
--------------------------------------------------------------
Choose to implement Vector Utility SQL functions to perform parallel or on-the-fly
chunking and embedding operations, within Oracle Database.
Vector Utility SQL functions are intended for a direct and quick interaction with
data, within pure SQL.
To get chunks, this function uses the in-house implementation with Oracle Database.
To get an embedding, this function uses ONNX embedding models that you load into
the database (and not third-party REST providers).
VECTOR_CHUNKS
~~~~~~~~~~~~~
Use the VECTOR_CHUNKS SQL function if you want to split plain text into chunks
(pieces of words, sentences, or paragraphs) in preparation for the generation of
embeddings, to be used with a vector index.
For example, you can use this function to build a standalone Text Chunking system
that lets you break down a large amount of text into smaller yet semantically
meaningful chunks. You can experiment with your chunks by inspecting and
accordingly amending the chunking results and then proceed further.
VECTOR_EMBEDDING
~~~~~~~~~~~~~~~~~
Use the VECTOR_EMBEDDING function if you want to generate a single vector embedding
for different data types.
Vector Utility PL/SQL APIs work with both the ONNX embedding models (loaded into
the database) and third-party REST providers, such as Cohere, Google AI, Hugging
Face, Oracle Cloud Infrastructure (OCI) Generative AI, OpenAI, or Vertex AI.
You can combine a set of chainable utility (UTL) functions together in an end-to-
end pipeline.
Each chainable utility function performs a specific task of transforming data into
other representations, such as converting data to text, converting text to chunks,
or converting the extracted chunks to embeddings.
Chainable utility functions are designed to be flexible and modular. You can create
transformation chains in various sequences, depending on your use case.
For example, you can directly extract vectors from a PDF file by creating a chain
of the UTL_TO_TEXT, UTL_TO_CHUNKS, and UTL_TO_EMBEDDINGS chainable utility
functions.
After generating the summary, you can either generate a single vector (using
UTL_TO_EMBEDDING) or chunk it and then generate multiple vectors (using
UTL_TO_EMBEDDINGS).
You can convert the document to plain text, summarize the text into a concise gist
to finally create a single embedding on the summarized text, in a file-to-text-to-
summary-to-embedding chain.
You can convert the document to plain text, summarize the text into a gist, split
the gist into chunks to finally create multiple embeddings on each summarized
chunk, in a file-to-text-to-summary-to-chunks-to-embeddings chain.
While both the chunking and summarization techniques make text smaller, they do so
in different ways. Chunking just breaks the text into smaller pieces, whereas
summarization extracts a salient meaning and context of that text into free-form
paragraphs or bullet points.
By summarizing the entire document and appending the summary to each chunk, you get
the best of both worlds, that is, an individual piece that also has a high-level
understanding of the overall document.
Prompt to text:
^^^^^^^^^^^^^^
You can generate a response directly based on a prompt.
A prompt can be an input string, such as a question that you ask a Large Language
Model (LLM). For example, "What is Oracle Text?".
A prompt can also be a command, such as "Summarize the following ...", "Draft an
email asking for ...", or "Rewrite the following ...", and can include results from
a search.
Other usecases are Text to vector (text-to-embedding chain), Text to chunks (text-
to-chunks chain), Text to summary (text-to-summary chain).
Chunker helper procedures to manage custom vocabulary and language data, which are
used when chunking user data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CREATE_VOCABULARY --> Loads your own vocabulary file into the database.
DROP_VOCABULARY --> Removes the specified vocabulary data from the
database.
CREATE_LANG_DATA --> Loads your own language data file (abbreviation tokens) into
the database.
DROP_LANG_DATA --> Removes abbreviation data for a given language from the
database.
DBMS_VECTOR:
This package simplifies common operations with Oracle AI Vector Search, such as
chunking text into smaller segments, extracting vector embeddings from user data,
or generating text for a given prompt.
Refer the Table Chart to see what can be called within Database and outside
Database.
https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/supplied-
vector-utility-pl-sql-packages.html
DBMS_VECTOR_CHAIN:
This package provides chunking and embedding functions along with some text
generation and summarization capabilities. It is more suitable for text processing
with similarity search, using functionality that can be pipelined together for an
end-to-end search.
This package requires you to install the CONTEXT component of Oracle Text, an
Oracle Database technology that provides indexing, term extraction, text analysis,
text summarization, word and theme searching, and other utilities.
Refer the Table Chart to see what can be called within Database and outside
Database.
https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/supplied-
vector-utility-pl-sql-packages.html
---------------------------------------
Validate JSON Input Parameters
---------------------------------------
You can optionally validate the structure of your JSON input to the DBMS_VECTOR.UTL
and DBMS_VECTOR_CHAIN.UTL functions, which use JSON to define their input
parameters.
The JSON data is schemaless, so the amount of validation that Vector Utility
package APIs do at runtime is minimal for better performance. The APIs validate
only the mandatory JSON parameters, that is, the parameters that you supply for the
APIs to run (not optional JSON parameters and attributes).
Before calling an API, you can use subprograms in the DBMS_JSON_SCHEMA package to
test whether the input data to be specified in the PARAMS clause is valid with
respect to a given JSON schema. This offers more flexibility and also ensures that
only schema-valid data is inserted in a JSON column.
==================================================
Generate Vector Embeddings (Examples)
==================================================
If you want to access a third-party embedding model, then you can use
UTL_TO_EMBEDDING from either the DBMS_VECTOR or DBMS_VECTOR_CHAIN package.
If you are using an ONNX format embedding model, then you can use both
UTL_TO_EMBEDDING and VECTOR_EMBEDDING functions.
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('connect'),
principal_name => 'docuser',
principal_type => xs_acl.ptype_db));
END;
/
Using Cohere, Google AI, Hugging Face, OpenAI, and Vertex AI:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Run DBMS_VECTOR.CREATE_CREDENTIAL to create and store a credential.
-- Cohere, Google AI, Hugging Face, OpenAI, and Vertex AI require the following
authentication parameters/syntax:
-- { "access_token": "<access token>" }
(or)
declare
input clob;
params clob;
v vector;
begin
input := 'hello';
params := '
{
"provider": "<REST provider>",
"credential_name": "<credential name>",
"url": "<REST endpoint URL for embedding service>",
"model": "<embedding model name>"
}';
v := dbms_vector.utl_to_embedding(input, json(params));
dbms_output.put_line(vector_serialize(v));
exception
when OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
end;
/
exec dbms_vector.drop_credential('OCI_CRED');
declare
jo json_object_t;
begin
jo := json_object_t();
jo.put('user_ocid','<user ocid>');
jo.put('tenancy_ocid','<tenancy ocid>');
jo.put('compartment_ocid','<compartment ocid>');
jo.put('private_key','<private key>');
jo.put('fingerprint','<fingerprint>');
dbms_output.put_line(jo.to_string);
dbms_vector.create_credential(
credential_name => 'OCI_CRED',
params => json(jo.to_string));
end;
/
Note: Replace the url and model values. Optionally, you can specify additional REST
provider-specific parameters
If you are using a declared embedding model, then call either VECTOR_EMBEDDING or
UTL_TO_EMBEDDING
a. Load your ONNX model into Oracle Database.
b. Call VECTOR_EMBEDDING or UTL_TO_EMBEDDING:
SELECT TO_VECTOR(VECTOR_EMBEDDING(doc_model USING 'hello' as data)) AS
embedding;
(or)
var params clob; exec :params := '{"provider":"database", "model":"doc_model"}';
select dbms_vector.utl_to_embedding('hello', json(:params)) from dual;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
conn sys/password@CDB_PDB as sysdba
conn docuser/password@CDB_PDB;
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 10000
SET LONG 10000
desc doc_chunks;
set linesize 100
set long 1000
col id for 999
col chunk_id for 99999
col chunk_offset for 99999
col chunk_length for 99999
col chunk for a30
col vector for a100
select id, chunk_id, chunk_offset, chunk_length, chunk from doc_chunks;
select vector from doc_chunks where rownum <= 1;
==================================================
Perform Text Processing: PL/SQL Examples
==================================================
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
conn sys/password@CDB_PDB as sysdba
CONN docuser/password@CDB_PDB
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 10000
SET LONG 10000
EXEC UTL_HTTP.SET_PROXY('<proxy-hostname>:<proxy-port>');
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('connect'),
principal_name => 'docuser',
principal_type => xs_acl.ptype_db));
END;
/
declare
jo json_object_t;
begin
jo := json_object_t();
jo.put('access_token', 'AbabA1B123aBc123AbabAb123a1a2ab');
dbms_vector_chain.create_credential(
credential_name => 'HF_CRED',
params => json(jo.to_string));
end;
/
-- select example
select dbms_vector_chain.utl_to_summary(
'A transaction is a logical, atomic unit of work that contains one or more SQL
statements.
An RDBMS must be able to group SQL statements so that they are either all
committed, which means they are applied to the database, or all rolled back,
which
means they are undone.
An illustration of the need for transactions is a funds transfer from a savings
account to
a checking account. The transfer consists of the following separate operations:
1. Decrease the savings account.
2. Increase the checking account.
3. Record the transaction in the transaction journal.
Oracle Database guarantees that all three operations succeed or fail as a unit.
For
example, if a hardware failure prevents a statement in the transaction from
executing,
then the other statements must be rolled back.
Transactions set Oracle Database apart from a file system. If you
perform an atomic operation that updates several files, and if the system fails
halfway
through, then the files will not be consistent. In contrast, a transaction
moves an
Oracle database from one consistent state to another. The basic principle of a
transaction is "all or nothing": an atomic operation succeeds or fails as a
whole.',
json(:params)) from dual;
-- PL/SQL example
declare
input clob;
params clob;
output clob;
begin
input := 'A transaction is a logical, atomic unit of work that contains one or
more SQL
statements.
An RDBMS must be able to group SQL statements so that they are either all
committed, which means they are applied to the database, or all rolled back,
which
means they are undone.
An illustration of the need for transactions is a funds transfer from a savings
account to
a checking account. The transfer consists of the following separate operations:
1. Decrease the savings account.
2. Increase the checking account.
3. Record the transaction in the transaction journal.
Oracle Database guarantees that all three operations succeed or fail as a unit.
For
example, if a hardware failure prevents a statement in the transaction from
executing,
then the other statements must be rolled back.
Transactions set Oracle Database apart from a file system. If you
perform an atomic operation that updates several files, and if the system fails
halfway
through, then the files will not be consistent. In contrast, a transaction
moves an
Oracle database from one consistent state to another. The basic principle of a
transaction is "all or nothing": an atomic operation succeeds or fails as a
whole.';
params := '
{
"provider": "<REST provider>",
"credential_name": "<credential name>",
"url": "<REST endpoint URL for text summarization service>",
"model": "<REST provider text summarization model name>"
}';
output := dbms_vector_chain.utl_to_summary(input, json(params));
dbms_output.put_line(output);
if output is not null then
dbms_lob.freetemporary(output);
end if;
exception
when OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
end;
/
Note: Replace the provider, credential_name, url, and model values as per your
Provider like Cohere, Google AI, Hugging Face, OpenAI, Vertex AI
{
"user_ocid": "<user ocid>",
"tenancy_ocid": "<tenancy ocid>",
"compartment_ocid": "<compartment ocid>",
"private_key": "<private key>",
"fingerprint": "<fingerprint>"
}
exec dbms_vector_chain.drop_credential('OCI_CRED');
declare
jo json_object_t;
begin
jo := json_object_t();
jo.put('user_ocid','<user ocid>');
jo.put('tenancy_ocid','<tenancy ocid>');
jo.put('compartment_ocid','<compartment ocid>');
jo.put('private_key','<private key>');
jo.put('fingerprint','<fingerprint>');
dbms_output.put_line(jo.to_string);
dbms_vector_chain.create_credential(
credential_name => 'OCI_CRED',
params => json(jo.to_string));
end;
/
declare
jo json_object_t;
begin
jo := json_object_t();
jo.put('user_ocid','ocid1.user.oc1..aabbalbbaa1112233aabbaabb1111222aa1111bb');
jo.put('tenancy_ocid','ocid1.tenancy.oc1..aaaaalbbbb1112233aaaabbaa1111222aaa111a')
;
jo.put('compartment_ocid','ocid1.compartment.oc1..ababalabab1112233abababab1111222a
ba11ab');
jo.put('private_key','AAAaaaBBB11112222333...AAA111AAABBB222aaa1a/+');
jo.put('fingerprint','01:1a:a1:aa:12:a1:12:1a:ab:12:01:ab:a1:12:ab:1a');
dbms_output.put_line(jo.to_string);
dbms_vector_chain.create_credential(
credential_name => 'OCI_CRED',
params => json(jo.to_string));
end;
/
-- select example
select dbms_vector_chain.utl_to_summary(
'A transaction is a logical, atomic unit of work that contains one or more SQL
statements.
An RDBMS must be able to group SQL statements so that they are either all
committed, which means they are applied to the database, or all rolled back,
which
means they are undone.
An illustration of the need for transactions is a funds transfer from a savings
account to
a checking account. The transfer consists of the following separate operations:
1. Decrease the savings account.
2. Increase the checking account.
3. Record the transaction in the transaction journal.
Oracle Database guarantees that all three operations succeed or fail as a unit.
For
example, if a hardware failure prevents a statement in the transaction from
executing,
then the other statements must be rolled back.
Transactions set Oracle Database apart from a file system. If you
perform an atomic operation that updates several files, and if the system fails
halfway
through, then the files will not be consistent. In contrast, a transaction
moves an
Oracle database from one consistent state to another. The basic principle of a
transaction is all or nothing: an atomic operation succeeds or fails as a
whole.',
json(:params)) from dual;
-- PL/SQL example
declare
input clob;
params clob;
output clob;
begin
input := 'A transaction is a logical, atomic unit of work that contains one or
more SQL
statements.
An RDBMS must be able to group SQL statements so that they are either all
committed, which means they are applied to the database, or all rolled back,
which
means they are undone.
An illustration of the need for transactions is a funds transfer from a savings
account to
a checking account. The transfer consists of the following separate operations:
1. Decrease the savings account.
2. Increase the checking account.
3. Record the transaction in the transaction journal.
Oracle Database guarantees that all three operations succeed or fail as a unit.
For
example, if a hardware failure prevents a statement in the transaction from
executing,
then the other statements must be rolled back.
Transactions set Oracle Database apart from a file system. If you
perform an atomic operation that updates several files, and if the system fails
halfway
through, then the files will not be consistent. In contrast, a transaction
moves an
Oracle database from one consistent state to another. The basic principle of a
transaction is all or nothing: an atomic operation succeeds or fails as a
whole.';
params := '
{
"provider": "ocigenai",
"credential_name": "OCI_CRED",
"url": "<REST endpoint URL for text summarization service>",
"model": "<REST provider text summarization model name>"
}';
output := dbms_vector_chain.utl_to_summary(input, json(params));
dbms_output.put_line(output);
if output is not null then
dbms_lob.freetemporary(output);
end if;
exception
when OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
end;
/
Replace the url and model values. Optionally, you can specify additional REST
provider-specific parameters.
{
"provider": "ocigenai",
"credential_name": "OCI_CRED",
"url": "https://generativeai.oci.example.com/summarizeText",
"model": "summarize.modelname",
"length": "MEDIUM",
"format": "PARAGRAPH",
"temperature": 1.0
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
conn sys/password@CDB_PDB as sysdba
Transfer the vocabulary file for your required model to the VEC_DUMP directory.
For example, if using WordPiece tokenization, you can download and transfer the
vocab.txt vocabulary file for "bert-base-uncased".
conn docuser/password@CDB_PDB;
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 10000
SET LONG 10000
DECLARE
vocab_params clob := '{"table_name" : "doc_vocabtab",
"column_name" : "token",
"vocabulary_name" : "doc_vocab",
"format" : "bert",
"cased" : false}';
BEGIN
dbms_vector_chain.create_vocabulary(json(vocab_params));
END;
/
After loading the token vocabulary, you can now use the BY VOCABULARY chunking mode
(with VECTOR_CHUNKS or UTL_TO_CHUNKS) to split data by counting the number of
tokens.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Here, you use the chunker helper function CREATE_LANG_DATA from the
DBMS_VECTOR_CHAIN package to load the data file for Simplified Chinese. This data
file contains abbreviation tokens for your chosen language.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
conn sys/password@CDB_PDB as sysdba
conn docuser/password@CDB_PDB;
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 10000
SET LONG 10000
DECLARE
lang_params clob := '{"table_name" : "doc_langtab",
"column_name" : "token",
"language" : "simplified chinese",
"preference_name" : "doc_lang_data"}';
BEGIN
dbms_vector_chain.create_lang_data(json(lang_params));
END;
/
After loading the language data, you can now use language-specific chunking by
specifying the LANGUAGE chunking parameter with VECTOR_CHUNKS or UTL_TO_CHUNKS.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Here, you use the VECTOR_CHUNKS SQL function or the UTL_TO_CHUNKS() PL/SQL function
from the DBMS_VECTOR_CHAIN package.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
conn sys/password@CDB_PDB as sysdba
CONN docuser/password@CDB_PDB
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 10000
SET LONG 10000
COMMIT;
-- Call the VECTOR_CHUNKS SQL function and specify the following custom chunking
parameters:
SELECT D.id doc, C.chunk_offset pos, C.chunk_length siz, C.chunk_text txt
FROM documentation_tab D, VECTOR_CHUNKS(D.text
BY words
MAX 50
OVERLAP 0
SPLIT BY recursively
LANGUAGE american
NORMALIZE all) C;
-- To call the same operation using the UTL_TO_CHUNKS function from the
DBMS_VECTOR_CHAIN package, run:
SELECT D.id doc,
JSON_VALUE(C.column_value, '$.chunk_id' RETURNING NUMBER) AS id,
JSON_VALUE(C.column_value, '$.chunk_offset' RETURNING NUMBER) AS pos,
JSON_VALUE(C.column_value, '$.chunk_length' RETURNING NUMBER) AS siz,
JSON_VALUE(C.column_value, '$.chunk_data') AS txt
FROM documentation_tab D,
dbms_vector_chain.utl_to_chunks(D.text,
JSON('{"by":"words",
"max":"50",
"overlap":"0",
"split":"recursively",
"language":"american",
"normalize":"all"}')) C;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- create a relational table
-- create a local directory and store the document into the table
dbms_lob.open(v_bfile, dbms_lob.lob_readonly);
dbms_lob.loadClobFromFile(
dest_loc,
v_bfile,
dbms_lob.lobmaxsize,
v_dest_offset,
v_src_offset,
873,
v_lang_context,
v_warning);
dbms_lob.close(v_bfile);
END my_clob_from_file;
/
show errors;
In this example, you can see how to generate text for a given prompt by accessing
third-party text generation models.
A prompt can be an input string (such as a question that you ask an LLM or a
command), and can include results from a search.
You can use the described functions either from the DBMS_VECTOR or
DBMS_VECTOR_CHAIN package, depending on your use case.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
conn sys/password@CDB_PDB as sysdba
CONN docuser/password@CDB_PDB
SET ECHO ON
SET FEEDBACK 1
SET NUMWIDTH 10
SET LINESIZE 80
SET TRIMSPOOL ON
SET TAB OFF
SET PAGESIZE 10000
SET LONG 10000
EXEC UTL_HTTP.SET_PROXY('<proxy-hostname>:<proxy-port>');
BEGIN
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => '*',
ace => xs$ace_type(privilege_list => xs$name_list('connect'),
principal_name => 'docuser',
principal_type => xs_acl.ptype_db));
END;
/
declare
jo json_object_t;
begin
jo := json_object_t();
jo.put('access_token', 'AbabA1B123aBc123AbabAb123a1a2ab');
dbms_vector_chain.create_credential(
credential_name => 'HF_CRED',
params => json(jo.to_string));
end;
/
-- select example
select dbms_vector_chain.utl_to_generate_text(
'What is Oracle Text?',json(:params)) from dual;
-- PL/SQL example
declare
input clob;
params clob;
output clob;
begin
input := 'What is Oracle Text?';
params := '
{
"provider": "<REST provider>",
"credential_name": "<credential name>",
"url": "<REST endpoint URL for text generation service>",
"model": "<REST provider text generation model name>"
}';
output := dbms_vector_chain.utl_to_generate_text(input, json(params));
dbms_output.put_line(output);
if output is not null then
dbms_lob.freetemporary(output);
end if;
exception
when OTHERS THEN
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
end;
/
Refer to the below link for the JSON syntax for various providers.
https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/generate-text-
prompt-pl-sql-example.html
###########################################################
Vector Indexes
###########################################################
The distance function used to create and search the index should be the one
recommended by the embedding model used to create the vectors.
You can specify this distance function at the time of index creation or when you
perform a similarity search using the VECTOR_DISTANCE() function.
If you use a different distance function than the one used to create the index, an
exact match is triggered because you cannot use the index in this case.
Oracle AI Vector Search indexes supports the same distance metrics as the
VECTOR_DISTANCE() function.
COSINE is the default metric if you do not specify any metric at the time of index
creation or during a similarity search
using the VECTOR_DISTANCE() function.
You should always define the distance metric in an index based on the distance
metric used by the embedding model you are using
, EFCONSTRUCTION max_candidates_to_consider
|
IVF , { NEIGHBOR PARTITIONS number_of_partitions
| SAMPLE_PER_PARTITION number_of_samples
| MIN_VECTORS_PER_PARTITION
min_number_of_vectors_per_partition }
}
]
[ PARALLEL degree_of_parallelism ]
The default type of index created for a Neighbor Partition vector index is Inverted
File Flat (IVF) vector index. The IVF index is a technique designed to enhance
search efficiency by narrowing the search area through the use of neighbor
partitions or clusters.
###########################################################
Work with Retrieval Augmented Generation
###########################################################
Oracle AI Vector Search supports Retrieval Augmented Generation (RAG) to enable
sophisticated queries that can combine vectors
with relational data, graph data, spatial data, and JSON collections. By
communicating with LLMs through the implementation of RAG,
the knowledge of LLMs is increased with business data found through AI Vector
Search.
Using Retrieval Augmented Generation (RAG) can mitigate the inaccuracies and
hallucinations faced when using Large Language Models (LLMs).
Oracle AI Vector Search enables RAG through the use of popular frameworks and
PL/SQL APIs.
The primary problem with Large Language Models (LLMs) like GPT (Generative
Pretrained Transformer) is that they generate responses
based solely on the patterns and data they were trained on up to the point of their
last update.
This means that they inherently lack the ability to access or incorporate new,
real-time information after their training is cut off,
potentially limiting their responses to outdated or incomplete information.
By providing your LLM with up-to-date facts from your company, you can minimize the
probability that an LLM will make up answers (hallucinate).
RAG combines the strengths of pretrained language models with the ability to
retrieve recent and accurate information from a dataset or
database in real-time during the generation of responses.
Here is how RAG improves upon the issues with traditional LLMs:
Oracle AI Vector Search enables RAG within Oracle Database using the
DBMS_VECTOR_CHAIN PL/SQL package.
You can also implement RAG externally by using popular frameworks such as
LangChain.
LangChain is a popular open source framework that encapsulates popular LLMs, vector
databases, document stores, and embedding models.
DBMS_VECTOR_CHAIN is a PL/SQL package that provides the ability to create RAG
solutions, all within the database. With DBMS_VECTOR_CHAIN, your
data never needs to leave the security of Oracle Database.
>>>>>>>>>>>>>>>>>>>>>>>>>>
From Chapter4, I am going through Online. Later, I will take notes and update
here.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@
Vector Keywords
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@
Important Points for Speech
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@
One of the biggest benefits of Oracle AI Vector Search is that semantic search on
unstructured data can be combined with relational search on business data in one
single system.
This is not only powerful but also significantly more effective because you don't
need to add a specialized vector database, eliminating the pain of data
fragmentation between multiple systems.