-- 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 PRAGMA AUTONOMOUS_TRANSACTION; 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; COMMIT; RETURN v_example_id; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; 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.';