SQL RAG Example
This scenario allows you to run a similarity search for specific documentation content based on a user query. Once documentation chunks are retrieved, they are concatenated and a prompt is generated to ask an LLM to answer the user question using retrieved chunks.
- Start SQL*Plus and connect to Oracle AI Database as a local test
user.
- Log in to SQL*Plus as the
sysuser, connecting assysdba:conn sys/password AS sysdbaSET SERVEROUTPUT ON; SET ECHO ON; SET LONG 100000; - Create a local test user (
vector) and grant necessary privileges:DROP USER vector cascade;CREATE USER vector identified by <my vector password>GRANT DB_DEVELOPER_ROLE, CREATE CREDENTIAL TO vector; - Set the proxy if one exists:
EXEC UTL_HTTP.SET_PROXY('<my proxy full name>:<my proxy port>'); - Grant connect privilege for a host using the
DBMS_NETWORK_ACL_ADMINprocedure. This example uses*to allow any host. However, you can explicitly specify each host that you want to connect to.BEGIN DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE( host => '*', ace => xs$ace_type(privilege_list => xs$name_list('connect'), principal_name => 'VECTOR', principal_type => xs_acl.ptype_db)); END; / - Connect to Oracle AI Database as the test user.
conn docuser/password;
- Log in to SQL*Plus as the
- Create a credential for Oracle Cloud Infrastructure Generative AI:
-
Run
DBMS_VECTOR_CHAIN.CREATE_CREDENTIALto create and store an OCI credential (OCI_CRED).OCIGenAI requires the following parameters:{ "user_ocid" : "<user ocid>", "tenancy_ocid" : "<tenancy ocid>", "compartment_ocid": "<compartment ocid>", "private_key" : "<private key>", "fingerprint" : "<fingerprint>" }Note:
The generated private key may appear as:
You pass the-----BEGIN RSA PRIVATE KEY----- <private key string> -----END RSA PRIVATE KEY-----<private key string>value (excluding theBEGINandENDlines), either as a single line or as multiple lines.BEGIN DBMS_VECTOR_CHAIN.DROP_CREDENTIAL(credential_name => 'OCI_CRED'); EXCEPTION WHEN OTHERS THEN NULL; END; /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_VECTOR_CHAIN.CREATE_CREDENTIAL( credential_name => 'OCID_CRED', params => json(jo.to_string)); END; / -
Check credential creation:
col owner format a15 col credential_name format a20 col username format a20SELECT owner, credential_name, username FROM all_credentials ORDER BY owner, credential_name, username;
-
- Generate a prompt using similarity search results:
Note:
For information about loading the ONNX format model into the database asdoc_model, see Import ONNX Models into Oracle AI Database End-to-End Example.SET SERVEROUTPUT ON; VAR prompt CLOB; VAR user_question CLOB; VAR context CLOB; BEGIN -- initialize the concatenated string :context := ''; -- read this question from the user :user_question := 'what are vector indexes?'; -- cursor to fetch chunks relevant to the user's query FOR rec IN (SELECT EMBED_DATA FROM doc_chunks WHERE DOC_ID = 'Vector User Guide' ORDER BY vector_distance(embed_vector, vector_embedding( doc_model using :user_question as data), COSINE) FETCH EXACT FIRST 10 ROWS ONLY) LOOP -- concatenate each value to the string :context := :context || rec.embed_data; END LOOP; -- concatenate strings and format it as an enhanced prompt to the LLM :prompt := 'Answer the following question using the supplied context assuming you are a subject matter expert. Question: ' || :user_question || ' Context: ' || :context; DBMS_OUTPUT.PUT_LINE('Generated prompt: ' || :prompt); END; / - Issue the GenAI call:
Note:
For a list of all supported REST endpoints, see Supported Third-Party Provider Operations and Endpoints.DECLARE input CLOB; params CLOB; output CLOB; BEGIN input := :prompt; params := '{ "provider" : "ocigenai", "credential_name" : "OCI_CRED", "url" : "https://inference.generativeai.us-chicago-1.oci. oraclecloud.com/20231130/actions/generateText", "model" : "cohere.command" }'; 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; /
Parent topic: Use Retrieval Augmented Generation to Complement LLMs