feat: add dedicated Cohere Embed 4 QA vector retrieval
This commit is contained in:
193
database/adb/75_sgmp_qa_vector_retrieval.sql
Normal file
193
database/adb/75_sgmp_qa_vector_retrieval.sql
Normal file
@@ -0,0 +1,193 @@
|
||||
-- SGMP QA example vector store.
|
||||
--
|
||||
-- Run as SGMP_POC after scripts/setup-sgmp-qa-vector.sh has registered the
|
||||
-- DBMS_VECTOR credential and granted the HTTPS ACL. No API key material is
|
||||
-- stored in this file.
|
||||
--
|
||||
-- Cohere Embed 4 is intentionally fixed to 1536 dimensions. Stored examples
|
||||
-- use search_document; incoming questions use search_query.
|
||||
|
||||
DECLARE
|
||||
v_count PLS_INTEGER;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO v_count
|
||||
FROM user_tables
|
||||
WHERE table_name = 'SG_QA_VECTOR_CONFIG';
|
||||
|
||||
IF v_count = 0 THEN
|
||||
EXECUTE IMMEDIATE q'[
|
||||
CREATE TABLE sg_qa_vector_config (
|
||||
config_key VARCHAR2(64) PRIMARY KEY,
|
||||
config_value VARCHAR2(4000) NOT NULL,
|
||||
updated_at TIMESTAMP(6) DEFAULT SYSTIMESTAMP NOT NULL
|
||||
)]';
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
MERGE INTO sg_qa_vector_config c
|
||||
USING (
|
||||
SELECT 'CREDENTIAL_NAME' AS config_key, 'SGMP_POC_QA_VECTOR_CRED' AS config_value FROM dual
|
||||
UNION ALL SELECT 'ENDPOINT_URL', 'https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText' FROM dual
|
||||
UNION ALL SELECT 'MODEL_NAME', 'cohere.embed-v4.0' FROM dual
|
||||
UNION ALL SELECT 'DIMENSION', '1536' FROM dual
|
||||
) s
|
||||
ON (c.config_key = s.config_key)
|
||||
WHEN MATCHED THEN UPDATE SET c.config_value = s.config_value, c.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (config_key, config_value) VALUES (s.config_key, s.config_value);
|
||||
/
|
||||
|
||||
DECLARE
|
||||
v_count PLS_INTEGER;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO v_count
|
||||
FROM user_tables
|
||||
WHERE table_name = 'SG_QA_VECTOR_EXAMPLE';
|
||||
|
||||
IF v_count = 0 THEN
|
||||
EXECUTE IMMEDIATE q'[
|
||||
CREATE TABLE sg_qa_vector_example (
|
||||
example_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
question CLOB NOT NULL,
|
||||
answer_sql CLOB NOT NULL,
|
||||
answer_text CLOB,
|
||||
embedding_input CLOB NOT NULL,
|
||||
embedding VECTOR(1536, FLOAT32) NOT NULL,
|
||||
embedding_model VARCHAR2(128) DEFAULT 'cohere.embed-v4.0' NOT NULL,
|
||||
created_at TIMESTAMP(6) DEFAULT SYSTIMESTAMP NOT NULL,
|
||||
updated_at TIMESTAMP(6) DEFAULT SYSTIMESTAMP NOT NULL
|
||||
)]';
|
||||
END IF;
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE FUNCTION sg_qa_vector_params(p_input_type IN VARCHAR2)
|
||||
RETURN CLOB
|
||||
AUTHID DEFINER
|
||||
IS
|
||||
v_credential VARCHAR2(4000);
|
||||
v_endpoint VARCHAR2(4000);
|
||||
v_model VARCHAR2(4000);
|
||||
BEGIN
|
||||
SELECT MAX(CASE WHEN config_key = 'CREDENTIAL_NAME' THEN config_value END),
|
||||
MAX(CASE WHEN config_key = 'ENDPOINT_URL' THEN config_value END),
|
||||
MAX(CASE WHEN config_key = 'MODEL_NAME' THEN config_value END)
|
||||
INTO v_credential, v_endpoint, v_model
|
||||
FROM sg_qa_vector_config;
|
||||
|
||||
IF v_credential IS NULL OR v_endpoint IS NULL OR v_model IS NULL THEN
|
||||
RAISE_APPLICATION_ERROR(-20001, 'SG QA vector configuration is incomplete.');
|
||||
END IF;
|
||||
|
||||
RETURN TO_CLOB('{"provider":"ocigenai","credential_name":"')
|
||||
|| v_credential
|
||||
|| '","url":"' || v_endpoint
|
||||
|| '","model":"' || v_model
|
||||
|| '","truncate":"END"}';
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE FUNCTION sg_qa_vector_store(
|
||||
p_question IN CLOB,
|
||||
p_answer_sql IN CLOB,
|
||||
p_answer IN CLOB DEFAULT NULL
|
||||
) RETURN NUMBER
|
||||
AUTHID DEFINER
|
||||
IS
|
||||
v_input CLOB;
|
||||
v_embedding VECTOR;
|
||||
v_example_id NUMBER;
|
||||
BEGIN
|
||||
IF p_question IS NULL OR p_answer_sql IS NULL THEN
|
||||
RAISE_APPLICATION_ERROR(-20002, 'question and answer_sql are required.');
|
||||
END IF;
|
||||
|
||||
v_input := TO_CLOB('Question: ') || p_question
|
||||
|| TO_CLOB(CHR(10) || 'Answer SQL: ') || p_answer_sql
|
||||
|| CASE WHEN p_answer IS NULL THEN NULL ELSE TO_CLOB(CHR(10) || 'Answer: ') || p_answer END;
|
||||
v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING(
|
||||
v_input,
|
||||
JSON(sg_qa_vector_params('search_document'))
|
||||
);
|
||||
|
||||
INSERT INTO sg_qa_vector_example (
|
||||
question, answer_sql, answer_text, embedding_input, embedding, embedding_model
|
||||
) VALUES (
|
||||
p_question, p_answer_sql, p_answer, v_input, v_embedding, 'cohere.embed-v4.0'
|
||||
) RETURNING example_id INTO v_example_id;
|
||||
|
||||
RETURN v_example_id;
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE FUNCTION sg_qa_vector_search(
|
||||
p_question IN CLOB,
|
||||
p_top_k IN PLS_INTEGER DEFAULT 3
|
||||
) RETURN SYS_REFCURSOR
|
||||
AUTHID DEFINER
|
||||
IS
|
||||
v_query_vector VECTOR;
|
||||
v_results SYS_REFCURSOR;
|
||||
BEGIN
|
||||
IF p_question IS NULL THEN
|
||||
RAISE_APPLICATION_ERROR(-20003, 'question is required.');
|
||||
END IF;
|
||||
IF p_top_k IS NULL OR p_top_k < 1 OR p_top_k > 20 THEN
|
||||
RAISE_APPLICATION_ERROR(-20004, 'top_k must be between 1 and 20.');
|
||||
END IF;
|
||||
|
||||
v_query_vector := DBMS_VECTOR.UTL_TO_EMBEDDING(
|
||||
p_question,
|
||||
JSON(sg_qa_vector_params('search_query'))
|
||||
);
|
||||
|
||||
OPEN v_results FOR
|
||||
SELECT example_id,
|
||||
question,
|
||||
answer_sql,
|
||||
answer_text,
|
||||
embedding_model,
|
||||
vector_distance(embedding, v_query_vector, COSINE) AS cosine_distance
|
||||
FROM sg_qa_vector_example
|
||||
ORDER BY vector_distance(embedding, v_query_vector, COSINE), example_id
|
||||
FETCH FIRST p_top_k ROWS ONLY;
|
||||
RETURN v_results;
|
||||
END;
|
||||
/
|
||||
|
||||
CREATE OR REPLACE FUNCTION sg_qa_vector_context(
|
||||
p_question IN CLOB,
|
||||
p_top_k IN PLS_INTEGER DEFAULT 3
|
||||
) RETURN CLOB
|
||||
AUTHID DEFINER
|
||||
IS
|
||||
v_results SYS_REFCURSOR;
|
||||
v_id NUMBER;
|
||||
v_q CLOB;
|
||||
v_sql CLOB;
|
||||
v_answer CLOB;
|
||||
v_model VARCHAR2(128);
|
||||
v_dist NUMBER;
|
||||
v_context CLOB := EMPTY_CLOB();
|
||||
BEGIN
|
||||
v_results := sg_qa_vector_search(p_question, p_top_k);
|
||||
LOOP
|
||||
FETCH v_results INTO v_id, v_q, v_sql, v_answer, v_model, v_dist;
|
||||
EXIT WHEN v_results%NOTFOUND;
|
||||
v_context := v_context
|
||||
|| CASE WHEN DBMS_LOB.GETLENGTH(v_context) = 0 THEN NULL ELSE CHR(10) || CHR(10) END
|
||||
|| '[Example ' || v_id || ', cosine_distance=' || TO_CHAR(v_dist, 'FM0D000000') || ']' || CHR(10)
|
||||
|| 'Question: ' || v_q || CHR(10)
|
||||
|| 'Answer SQL: ' || v_sql
|
||||
|| CASE WHEN v_answer IS NULL THEN NULL ELSE CHR(10) || 'Answer: ' || v_answer END;
|
||||
END LOOP;
|
||||
CLOSE v_results;
|
||||
RETURN v_context;
|
||||
END;
|
||||
/
|
||||
|
||||
COMMENT ON TABLE sg_qa_vector_example IS
|
||||
'Question-to-SQL QA examples embedded with OCI GenAI Cohere Embed 4 for retrieval-augmented prompt context.';
|
||||
|
||||
COMMENT ON COLUMN sg_qa_vector_example.embedding IS
|
||||
'1536-dimensional Cohere Embed 4 document embedding; generated through the dedicated SGMP vector API credential.';
|
||||
Reference in New Issue
Block a user