-- Generate one reusable, question-specific Few-shot pattern per customer QA -- benchmark without promoting the benchmark answer itself. Game identity is -- deliberately not inferred here: sg_game_query_plan owns that through OCI -- GenAI chat + the current game catalog. CREATE OR REPLACE FUNCTION sg_qa_genai_generalize_pattern( p_question IN CLOB, p_answer_sql IN CLOB, p_target_type IN VARCHAR2 ) RETURN CLOB AUTHID DEFINER IS v_prompt CLOB; v_result CLOB; BEGIN v_prompt := 'Create one reusable, question-specific Few-shot SQL pattern from the source example. ' || 'This is training guidance, never an answer key. Return exactly these tagged sections and nothing else: ' || '[[PATTERN_QUESTION]], [[STRUCTURAL_SQL_PATTERN]], [[OBJECT_ROLE]], [[TARGET_TYPE]], ' || '[[APPLICABILITY]], [[END]]. ' || 'Preserve only the query intent and structural operations such as aggregation, joins, ' || 'grouping, ordering, date semantics, and filters. Replace every game name, alias, game ID, ' || 'schema name, physical object name, column name, literal date, literal number, user ID, ' || 'currency amount, and expected output with semantic placeholders such as , ' || ', , , , , and . ' || 'In STRUCTURAL_SQL_PATTERN, every non-SQL identifier must be an angle-bracket placeholder: ' || 'do not retain any source column, alias, table, schema, literal, code, or business value. ' || 'Do not include executable SQL. Do not include a game name or a customer answer. ' || 'The current game scope is supplied separately at runtime by a database OCI GenAI chat ' || 'resolver, therefore never choose or imply a game. The TARGET_TYPE section must be one of NONE, ' || 'SINGLE, MULTI, ALL, ANY and must describe applicability, not a game identity. ' || 'Source target type from the current resolver: ' || NVL(p_target_type, 'ANY') || CHR(10) || 'Source question:' || CHR(10) || DBMS_LOB.SUBSTR(p_question, 4000, 1) || CHR(10) || 'Source SQL (structure only; do not copy identifiers or values):' || CHR(10) || DBMS_LOB.SUBSTR(p_answer_sql, 12000, 1); v_result := DBMS_CLOUD_AI.GENERATE( prompt => v_prompt, profile_name => 'SGMP_POC_OCI_GPT54MINI', action => 'chat' ); RETURN v_result; END; / CREATE OR REPLACE FUNCTION sg_qa_genai_validate_pattern( p_pattern_json IN CLOB ) RETURN CLOB AUTHID DEFINER IS v_prompt CLOB; v_result CLOB; BEGIN v_prompt := 'Inspect only concrete-answer leakage in this reusable Few-shot pattern. Return exactly ' || '[[CONCRETE_LEAKAGE]] YES or NO, then [[REASON]] and a short reason, then [[END]]. ' || 'Return YES only when a customer answer, concrete game identity, physical schema/table/column ' || 'identifier, literal date, literal business result, or executable SQL against a real object remains. ' || 'Return NO when all such references are semantic angle-bracket placeholders. A pseudo-SQL pattern ' || 'using SELECT/FROM/JOIN/GROUP BY, generic game-scope checks, EXISTS, UNION, or equality with ' || 'angle-bracket placeholders is not concrete leakage and must return NO. Do not judge usefulness or ' || 'completeness; classify leakage only. ' || 'Candidate:' || CHR(10) || DBMS_LOB.SUBSTR(p_pattern_json, 16000, 1); v_result := DBMS_CLOUD_AI.GENERATE( prompt => v_prompt, profile_name => 'SGMP_POC_OCI_GPT54MINI', action => 'chat' ); RETURN v_result; END; / CREATE OR REPLACE FUNCTION sg_qa_generate_generalized_patterns RETURN NUMBER AUTHID DEFINER IS PRAGMA AUTONOMOUS_TRANSACTION; v_plan_raw CLOB; v_plan JSON_OBJECT_T; v_target_type VARCHAR2(16); v_pattern_raw CLOB; v_validation_raw CLOB; v_status VARCHAR2(16); v_validation_note CLOB; v_question CLOB; v_sql_pattern CLOB; v_answer_text CLOB; v_object_role VARCHAR2(64); v_embedding_input CLOB; v_embedding VECTOR; v_count NUMBER := 0; FUNCTION parse_json_result(p_value CLOB) RETURN JSON_OBJECT_T IS v_text CLOB := TRIM(p_value); BEGIN IF DBMS_LOB.SUBSTR(v_text, 7, 1) = '```json' THEN v_text := REGEXP_REPLACE(v_text, '^```json[[:space:]]*', ''); v_text := REGEXP_REPLACE(v_text, '[[:space:]]*```[[:space:]]*$', ''); ELSIF DBMS_LOB.SUBSTR(v_text, 3, 1) = '```' THEN v_text := REGEXP_REPLACE(v_text, '^```[[:space:]]*', ''); v_text := REGEXP_REPLACE(v_text, '[[:space:]]*```[[:space:]]*$', ''); END IF; RETURN JSON_OBJECT_T.parse(v_text); END; FUNCTION section_value( p_raw IN CLOB, p_start_tag IN VARCHAR2, p_end_tag IN VARCHAR2 ) RETURN CLOB IS v_start PLS_INTEGER; v_end PLS_INTEGER; BEGIN v_start := DBMS_LOB.INSTR(p_raw, p_start_tag, 1, 1); IF v_start = 0 THEN RAISE_APPLICATION_ERROR(-20071, 'OCI GenAI response is missing ' || p_start_tag); END IF; v_start := v_start + LENGTH(p_start_tag); v_end := DBMS_LOB.INSTR(p_raw, p_end_tag, v_start, 1); IF v_end = 0 OR v_end <= v_start THEN RAISE_APPLICATION_ERROR(-20072, 'OCI GenAI response is missing ' || p_end_tag); END IF; RETURN TRIM(DBMS_LOB.SUBSTR(p_raw, LEAST(v_end - v_start, 32767), v_start)); END; PROCEDURE upsert_pattern( p_case_id IN VARCHAR2, p_status IN VARCHAR2, p_note IN CLOB ) IS BEGIN UPDATE sg_qa_vector_example SET question = v_question, answer_sql = v_sql_pattern, answer_text = v_answer_text, embedding_input = v_embedding_input, embedding = v_embedding, embedding_model = 'cohere.embed-v4.0', reference_status = p_status, reference_kind = 'SQL_PATTERN', target_type = v_target_type, object_role = v_object_role, inspection_status = CASE WHEN p_status = 'APPROVED' THEN 'GENAI_VERIFIED' ELSE 'GENAI_REJECTED' END, inspection_note = p_note, verified_at = SYSTIMESTAMP, verified_by = 'SGMP_POC_OCI_GENAI_PATTERN' WHERE source_type = 'GENERALIZED_QUESTION_PATTERN' AND source_case_id = 'PAT-' || p_case_id; IF SQL%ROWCOUNT = 0 THEN INSERT INTO sg_qa_vector_example ( question, answer_sql, answer_text, embedding_input, embedding, embedding_model, reference_status, reference_kind, target_type, object_role, inspection_status, inspection_note, verified_at, verified_by, source_case_id, source_type ) VALUES ( v_question, v_sql_pattern, v_answer_text, v_embedding_input, v_embedding, 'cohere.embed-v4.0', p_status, 'SQL_PATTERN', v_target_type, v_object_role, CASE WHEN p_status = 'APPROVED' THEN 'GENAI_VERIFIED' ELSE 'GENAI_REJECTED' END, p_note, SYSTIMESTAMP, 'SGMP_POC_OCI_GENAI_PATTERN', 'PAT-' || p_case_id, 'GENERALIZED_QUESTION_PATTERN' ); END IF; END; BEGIN FOR source_row IN ( SELECT source.source_case_id, source.question, source.answer_sql FROM sg_qa_vector_example source WHERE source.source_type = 'CUSTOMER_QA_BENCHMARK' AND NOT EXISTS ( SELECT 1 FROM sg_qa_vector_example pattern WHERE pattern.source_type = 'GENERALIZED_QUESTION_PATTERN' AND pattern.source_case_id = 'PAT-' || source.source_case_id AND pattern.reference_status = 'APPROVED' ) ORDER BY source_case_id ) LOOP BEGIN -- The target category comes from the existing OCI GenAI game resolver; -- no alias, prefix, table, or name is transformed in this migration. v_plan_raw := sg_game_query_plan(source_row.question, 5); v_plan := parse_json_result(v_plan_raw); v_target_type := UPPER(NVL(v_plan.get_string('targetType'), 'ANY')); IF v_target_type NOT IN ('NONE', 'SINGLE', 'MULTI', 'ALL') THEN v_target_type := 'ANY'; END IF; v_pattern_raw := sg_qa_genai_generalize_pattern( source_row.question, source_row.answer_sql, v_target_type ); v_question := section_value(v_pattern_raw, '[[PATTERN_QUESTION]]', '[[STRUCTURAL_SQL_PATTERN]]'); v_sql_pattern := section_value(v_pattern_raw, '[[STRUCTURAL_SQL_PATTERN]]', '[[OBJECT_ROLE]]'); v_object_role := SUBSTR(section_value(v_pattern_raw, '[[OBJECT_ROLE]]', '[[TARGET_TYPE]]'), 1, 64); IF section_value(v_pattern_raw, '[[TARGET_TYPE]]', '[[APPLICABILITY]]') IN ('NONE', 'SINGLE', 'MULTI', 'ALL', 'ANY') THEN v_target_type := section_value(v_pattern_raw, '[[TARGET_TYPE]]', '[[APPLICABILITY]]'); END IF; v_answer_text := TO_CLOB('Generalized, question-specific structural pattern. ' || 'Current game scope must be supplied only by sg_game_query_plan. Applicability: ') || section_value(v_pattern_raw, '[[APPLICABILITY]]', '[[END]]'); v_embedding_input := TO_CLOB('Question-specific generalized Few-shot pattern:' || CHR(10)) || v_question || CHR(10) || 'Logical role: ' || v_object_role || CHR(10) || 'Structural SQL pattern:' || CHR(10) || v_sql_pattern; v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING( v_embedding_input, JSON(sg_qa_vector_params('search_document')) ); v_validation_raw := sg_qa_genai_validate_pattern(v_pattern_raw); v_status := CASE WHEN REGEXP_SUBSTR( UPPER(section_value(v_validation_raw, '[[CONCRETE_LEAKAGE]]', '[[REASON]]')), '[A-Z]+' ) = 'NO' THEN 'APPROVE' ELSE 'REJECT' END; v_validation_note := section_value(v_validation_raw, '[[REASON]]', '[[END]]'); IF v_status = 'APPROVE' THEN upsert_pattern(source_row.source_case_id, 'APPROVED', 'ADB OCI GenAI generated and independently validated a generalized pattern. ' || 'The original customer QA remains evaluation-only. ' || v_validation_note); v_count := v_count + 1; ELSE upsert_pattern(source_row.source_case_id, 'DRAFT', 'ADB OCI GenAI rejected the generalized pattern: ' || v_validation_note); END IF; EXCEPTION WHEN OTHERS THEN -- Persist an auditable non-runtime draft and continue with the other -- customer questions; one malformed LLM response must not block all 47. v_question := source_row.question; v_sql_pattern := TO_CLOB(''); v_answer_text := TO_CLOB('No runtime Few-shot pattern: OCI GenAI generalization failed.'); v_object_role := 'UNSPECIFIED'; v_target_type := 'ANY'; v_embedding_input := TO_CLOB('Failed generalized pattern: ') || source_row.question; v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING( v_embedding_input, JSON(sg_qa_vector_params('search_document')) ); upsert_pattern(source_row.source_case_id, 'DRAFT', 'OCI GenAI pattern generation error: ' || SQLERRM); END; END LOOP; COMMIT; RETURN v_count; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END; / -- Re-run only the independent OCI Chat safety review after its policy changes. -- It never reads a customer benchmark and never changes the generated pattern. CREATE OR REPLACE FUNCTION sg_qa_revalidate_generalized_patterns RETURN NUMBER AUTHID DEFINER IS PRAGMA AUTONOMOUS_TRANSACTION; v_raw CLOB; v_status VARCHAR2(16); v_reason CLOB; v_start PLS_INTEGER; v_end PLS_INTEGER; v_count NUMBER := 0; FUNCTION section_value( p_raw IN CLOB, p_start_tag IN VARCHAR2, p_end_tag IN VARCHAR2 ) RETURN CLOB IS v_from PLS_INTEGER; v_to PLS_INTEGER; BEGIN v_from := DBMS_LOB.INSTR(p_raw, p_start_tag, 1, 1); IF v_from = 0 THEN RAISE_APPLICATION_ERROR(-20073, 'Missing ' || p_start_tag); END IF; v_from := v_from + LENGTH(p_start_tag); v_to := DBMS_LOB.INSTR(p_raw, p_end_tag, v_from, 1); IF v_to = 0 OR v_to <= v_from THEN RAISE_APPLICATION_ERROR(-20074, 'Missing ' || p_end_tag); END IF; RETURN TRIM(DBMS_LOB.SUBSTR(p_raw, LEAST(v_to - v_from, 32767), v_from)); END; BEGIN FOR item IN ( SELECT example_id, question, answer_sql, answer_text FROM sg_qa_vector_example WHERE source_type = 'GENERALIZED_QUESTION_PATTERN' ORDER BY source_case_id ) LOOP BEGIN v_raw := sg_qa_genai_validate_pattern( TO_CLOB('[[PATTERN_QUESTION]]') || item.question || TO_CLOB(CHR(10) || '[[STRUCTURAL_SQL_PATTERN]]') || item.answer_sql || TO_CLOB(CHR(10) || '[[APPLICABILITY]]') || item.answer_text || CHR(10) || '[[END]]' ); v_status := CASE WHEN REGEXP_SUBSTR( UPPER(section_value(v_raw, '[[CONCRETE_LEAKAGE]]', '[[REASON]]')), '[A-Z]+' ) = 'NO' THEN 'APPROVE' ELSE 'REJECT' END; v_reason := section_value(v_raw, '[[REASON]]', '[[END]]'); UPDATE sg_qa_vector_example SET reference_status = CASE WHEN v_status = 'APPROVE' THEN 'APPROVED' ELSE 'DRAFT' END, inspection_status = CASE WHEN v_status = 'APPROVE' THEN 'GENAI_VERIFIED' ELSE 'GENAI_REJECTED' END, inspection_note = 'ADB OCI GenAI independent revalidation: ' || v_reason, verified_at = SYSTIMESTAMP, verified_by = 'SGMP_POC_OCI_GENAI_PATTERN' WHERE example_id = item.example_id; IF v_status = 'APPROVE' THEN v_count := v_count + 1; END IF; EXCEPTION WHEN OTHERS THEN v_reason := TO_CLOB('OCI GenAI revalidation error: ' || SQLERRM); UPDATE sg_qa_vector_example SET reference_status = 'DRAFT', inspection_status = 'GENAI_REJECTED', inspection_note = v_reason, verified_at = SYSTIMESTAMP, verified_by = 'SGMP_POC_OCI_GENAI_PATTERN' WHERE example_id = item.example_id; END; END LOOP; COMMIT; RETURN v_count; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END; / -- Production retrieval accepts only independently generalized patterns or -- policy templates. Customer QA benchmarks remain evaluation-only forever. CREATE OR REPLACE FUNCTION sg_qa_vector_search( p_question IN CLOB, p_top_k IN PLS_INTEGER DEFAULT 3, p_target_type IN VARCHAR2 DEFAULT 'ANY' ) RETURN SYS_REFCURSOR AUTHID DEFINER IS v_query_vector VECTOR; v_results SYS_REFCURSOR; v_target_type VARCHAR2(16) := UPPER(TRIM(NVL(p_target_type, 'ANY'))); 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; IF v_target_type NOT IN ('NONE', 'SINGLE', 'MULTI', 'ALL', 'ANY') THEN RAISE_APPLICATION_ERROR(-20005, 'invalid target type.'); 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, reference_kind, target_type, object_role, source_case_id, source_type, vector_distance(embedding, v_query_vector, COSINE) AS cosine_distance FROM sg_qa_vector_example WHERE reference_status = 'APPROVED' AND source_type IN ('GENERALIZED_QUESTION_PATTERN', 'POLICY_TEMPLATE') AND (target_type = 'ANY' OR v_target_type = 'ANY' OR target_type = v_target_type) ORDER BY vector_distance(embedding, v_query_vector, COSINE), example_id FETCH FIRST p_top_k ROWS ONLY; RETURN v_results; END; /