refs #739: document DB-owned task and few-shot policy
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
-- STD-25 is a period AU metric, not the daily AU_FLAG metric.
|
||||
-- Keep the evaluation evidence explicit so the LLM judge accepts the valid
|
||||
-- weekly result shape produced by the NL2SQL tool.
|
||||
|
||||
UPDATE sg_ai_qa_question
|
||||
SET expected_focus = 'Weekly AU: use one as-of snapshot (BASE_DT=2026-07-15), '
|
||||
|| 'count DISTINCT GUID whose LAST_CONN_DT is in the inclusive seven-day window '
|
||||
|| '(2026-07-09 through 2026-07-15), with STD_USER_YN=''Y'' and EXPT_USER_YN=''N''. '
|
||||
|| 'This is one aggregate result, not daily rows. Do not substitute daily AU_FLAG=1 for the period definition.',
|
||||
baseline_sql = TO_CLOB('SELECT COUNT(DISTINCT u."GUID") AS "RECENT_7DAY_AU"' || CHR(10)
|
||||
|| 'FROM "SGMP_POC"."CZN_COMN_USER_MST" u' || CHR(10)
|
||||
|| 'WHERE u."BASE_DT" = DATE ''2026-07-15''' || CHR(10)
|
||||
|| ' AND u."LAST_CONN_DT" BETWEEN DATE ''2026-07-09'' AND DATE ''2026-07-15''' || CHR(10)
|
||||
|| ' AND u."STD_USER_YN" = ''Y''' || CHR(10)
|
||||
|| ' AND u."EXPT_USER_YN" = ''N'''),
|
||||
baseline_answer = 'RECENT_7DAY_AU=0',
|
||||
evaluation_rule_json = '{"required_sql_terms":["CZN_COMN_USER_MST","LAST_CONN_DT","STD_USER_YN","EXPT_USER_YN","COUNT"],"recommended_sql_terms":["BASE_DT"],"forbidden_sql_terms":["AU_FLAG"],"required_result_shape":"SINGLE_AGGREGATE"}',
|
||||
updated_at = SYSTIMESTAMP
|
||||
WHERE question_code = 'STD-25';
|
||||
|
||||
/
|
||||
|
||||
COMMIT;
|
||||
|
||||
/
|
||||
|
||||
SELECT question_code, expected_focus, baseline_sql, baseline_answer, evaluation_rule_json
|
||||
FROM sg_ai_qa_question
|
||||
WHERE question_code = 'STD-25';
|
||||
@@ -0,0 +1,40 @@
|
||||
-- CZN-02 customer sample marks STD_USER_YN='Y' as optional for daily
|
||||
-- standard-AU reporting. It must not turn an otherwise correct AU query into
|
||||
-- a failure merely because the condition is present.
|
||||
|
||||
UPDATE sg_ai_qa_question
|
||||
SET expected_focus = 'Daily standard AU: COUNT(DISTINCT GUID) from CZN_COMN_USER_MST '
|
||||
|| 'for BASE_DT=2026-07-15 with AU_FLAG=1 and EXPT_USER_YN=''N''. '
|
||||
|| 'STD_USER_YN=''Y'' is an allowed optional cohort filter in the customer sample; '
|
||||
|| 'its presence or absence is not a contradiction to this baseline.',
|
||||
evaluation_rule_json = '{"required_sql_terms":["CZN_COMN_USER_MST","AU_FLAG","EXPT_USER_YN","COUNT"],"recommended_sql_terms":["BASE_DT","STD_USER_YN"],"optional_sql_terms":["STD_USER_YN"]}',
|
||||
updated_at = SYSTIMESTAMP
|
||||
WHERE question_code = 'CZN-02';
|
||||
|
||||
/
|
||||
|
||||
UPDATE sg_qa_vector_example
|
||||
SET answer_text = 'Expected focus: daily standard AU uses CZN_COMN_USER_MST, BASE_DT=2026-07-15, '
|
||||
|| 'AU_FLAG=1 and EXPT_USER_YN=''N''. The customer sample permits STD_USER_YN=''Y'' '
|
||||
|| 'as an optional standard-user cohort filter; do not treat its presence as a conflicting condition. '
|
||||
|| 'Historical answer: STD_AU_COUNT=0',
|
||||
inspection_note = 'Customer sample permits optional STD_USER_YN filtering for daily standard AU; AU_FLAG and excluded-user filtering remain mandatory.',
|
||||
verified_at = SYSTIMESTAMP,
|
||||
verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND source_case_id = 'CZN-02'
|
||||
AND reference_status = 'APPROVED';
|
||||
|
||||
/
|
||||
|
||||
COMMIT;
|
||||
|
||||
/
|
||||
|
||||
SELECT q.question_code, q.expected_focus, q.evaluation_rule_json,
|
||||
e.example_id, e.answer_text
|
||||
FROM sg_ai_qa_question q
|
||||
LEFT JOIN sg_qa_vector_example e
|
||||
ON e.source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND e.source_case_id = q.question_code
|
||||
WHERE q.question_code = 'CZN-02';
|
||||
90
database/adb/131_sgmp_independent_au_comparison_pattern.sql
Normal file
90
database/adb/131_sgmp_independent_au_comparison_pattern.sql
Normal file
@@ -0,0 +1,90 @@
|
||||
-- Reusable SINGLE-scope pattern: two AU populations must be aggregated
|
||||
-- independently before comparison. A user-master LEFT JOIN may erase valid
|
||||
-- business-user rows and must not define the business population.
|
||||
|
||||
UPDATE sg_ai_qa_question
|
||||
SET expected_focus = 'Compare standard AU and business AU as two independent single-row aggregates for the same as-of date. '
|
||||
|| 'Standard AU uses the resolved game user master with AU_FLAG=1 and EXPT_USER_YN=''N''. '
|
||||
|| 'Business AU uses the resolved game business-user fact with BIZ_AU_FLAG=1 and EXPT_USER_YN=''N''. '
|
||||
|| 'Do not make the business count depend on a LEFT JOIN from the user-master population. '
|
||||
|| 'STD_USER_YN=''Y'' is an allowed optional cohort filter, not a reason to reject the result.',
|
||||
evaluation_rule_json = '{"required_sql_terms":["CZN_COMN_USER_MST","CZN_CUSTOM_BIZ_USER_TXN","AU_FLAG","BIZ_AU_FLAG","EXPT_USER_YN","COUNT"],"recommended_sql_terms":["BASE_DT","STD_USER_YN"],"optional_sql_terms":["STD_USER_YN"],"required_result_shape":"SINGLE_COMPARISON"}',
|
||||
updated_at = SYSTIMESTAMP
|
||||
WHERE question_code = 'CZN-03';
|
||||
|
||||
/
|
||||
|
||||
DECLARE
|
||||
v_input CLOB;
|
||||
v_embedding VECTOR;
|
||||
v_exists NUMBER;
|
||||
BEGIN
|
||||
v_input := TO_CLOB('Question pattern: compare daily standard active users and business active users for one resolved game and one business date.')
|
||||
|| CHR(10) || 'Question pattern Korean: 한 게임의 기준일 일간 표준 AU와 사업 AU를 비교해줘.'
|
||||
|| CHR(10) || 'Logical object role: USER_BUSINESS_AU_COMPARISON'
|
||||
|| CHR(10) || 'Required result shape: one row with two independent aggregate metrics.'
|
||||
|| CHR(10) || 'Business population must be aggregated independently; a LEFT JOIN from the user-master population may not define it.';
|
||||
v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING(
|
||||
v_input, JSON(sg_qa_vector_params('search_document'))
|
||||
);
|
||||
|
||||
SELECT COUNT(*) INTO v_exists
|
||||
FROM sg_qa_vector_example
|
||||
WHERE source_type = 'POLICY_TEMPLATE'
|
||||
AND source_case_id = 'STD_BIZ_AU_COMPARE';
|
||||
|
||||
IF v_exists = 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 (
|
||||
'한 게임의 기준일 일간 표준 AU와 사업 AU를 비교해줘.',
|
||||
TO_CLOB('SELECT' || CHR(10)
|
||||
|| ' (SELECT COUNT(DISTINCT u."GUID")' || CHR(10)
|
||||
|| ' FROM <RESOLVED_GAME_USER_MASTER> u' || CHR(10)
|
||||
|| ' WHERE u."BASE_DT" = <BUSINESS_DATE>' || CHR(10)
|
||||
|| ' AND u."AU_FLAG" = 1' || CHR(10)
|
||||
|| ' AND u."EXPT_USER_YN" = ''N'') AS "STANDARD_AU_COUNT",' || CHR(10)
|
||||
|| ' (SELECT COUNT(DISTINCT b."GUID")' || CHR(10)
|
||||
|| ' FROM <RESOLVED_GAME_BUSINESS_USER> b' || CHR(10)
|
||||
|| ' WHERE b."BASE_DT" = <BUSINESS_DATE>' || CHR(10)
|
||||
|| ' AND b."BIZ_AU_FLAG" = 1' || CHR(10)
|
||||
|| ' AND b."EXPT_USER_YN" = ''N'') AS "BUSINESS_AU_COUNT"' || CHR(10)
|
||||
|| 'FROM DUAL'),
|
||||
'Applicable metric reference: for this daily AU comparison, the standard metric must use AU_FLAG=1 and EXPT_USER_YN=''N''; do not replace it with LAST_CONN_DT period logic or STD_USER_YN alone. The business metric must use BIZ_AU_FLAG=1 and EXPT_USER_YN=''N''. Produce one row from two independent aggregate subqueries, and do not count business users through a LEFT JOIN from the standard-user population. STD_USER_YN may be added only as an optional cohort filter.',
|
||||
v_input, v_embedding, 'cohere.embed-v4.0',
|
||||
'APPROVED', 'SQL_TEMPLATE', 'SINGLE', 'USER_BUSINESS_AU_COMPARISON',
|
||||
'VERIFIED',
|
||||
'Reusable comparison pattern with logical placeholders only; no customer game, date, result, or physical object is embedded.',
|
||||
SYSTIMESTAMP, 'SGMP_POC_METADATA_REVIEW',
|
||||
'STD_BIZ_AU_COMPARE', 'POLICY_TEMPLATE'
|
||||
);
|
||||
ELSE
|
||||
UPDATE sg_qa_vector_example
|
||||
SET question = '한 게임의 기준일 일간 표준 AU와 사업 AU를 비교해줘.',
|
||||
answer_sql = TO_CLOB('SELECT' || CHR(10)
|
||||
|| ' (SELECT COUNT(DISTINCT u."GUID")' || CHR(10)
|
||||
|| ' FROM <RESOLVED_GAME_USER_MASTER> u' || CHR(10)
|
||||
|| ' WHERE u."BASE_DT" = <BUSINESS_DATE>' || CHR(10)
|
||||
|| ' AND u."AU_FLAG" = 1' || CHR(10)
|
||||
|| ' AND u."EXPT_USER_YN" = ''N'') AS "STANDARD_AU_COUNT",' || CHR(10)
|
||||
|| ' (SELECT COUNT(DISTINCT b."GUID")' || CHR(10)
|
||||
|| ' FROM <RESOLVED_GAME_BUSINESS_USER> b' || CHR(10)
|
||||
|| ' WHERE b."BASE_DT" = <BUSINESS_DATE>' || CHR(10)
|
||||
|| ' AND b."BIZ_AU_FLAG" = 1' || CHR(10)
|
||||
|| ' AND b."EXPT_USER_YN" = ''N'') AS "BUSINESS_AU_COUNT"' || CHR(10)
|
||||
|| 'FROM DUAL'),
|
||||
answer_text = 'Applicable metric reference: for this daily AU comparison, the standard metric must use AU_FLAG=1 and EXPT_USER_YN=''N''; do not replace it with LAST_CONN_DT period logic or STD_USER_YN alone. The business metric must use BIZ_AU_FLAG=1 and EXPT_USER_YN=''N''. Produce one row from two independent aggregate subqueries, and do not count business users through a LEFT JOIN from the standard-user population. STD_USER_YN may be added only as an optional cohort filter.',
|
||||
embedding_input = v_input,
|
||||
embedding = v_embedding,
|
||||
reference_status = 'APPROVED', inspection_status = 'VERIFIED',
|
||||
verified_at = SYSTIMESTAMP, verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'POLICY_TEMPLATE'
|
||||
AND source_case_id = 'STD_BIZ_AU_COMPARE';
|
||||
END IF;
|
||||
COMMIT;
|
||||
END;
|
||||
|
||||
/
|
||||
58
database/adb/132_sgmp_country_daily_au_pattern.sql
Normal file
58
database/adb/132_sgmp_country_daily_au_pattern.sql
Normal file
@@ -0,0 +1,58 @@
|
||||
-- Reusable SINGLE-scope pattern for country-grouped daily AU.
|
||||
|
||||
UPDATE sg_ai_qa_question
|
||||
SET expected_focus = 'Country-grouped daily standard AU uses the resolved game user master with BASE_DT, AU_FLAG=1 and EXPT_USER_YN=''N''. '
|
||||
|| 'Group by LAST_CONN_COUNTRY_CD and use the approved country dimension only for display/classification. '
|
||||
|| 'STD_USER_YN is optional and cannot replace AU_FLAG for the daily metric.',
|
||||
evaluation_rule_json = '{"required_sql_terms":["CZN_COMN_USER_MST","AU_FLAG","EXPT_USER_YN","LAST_CONN_COUNTRY_CD","COUNT"],"recommended_sql_terms":["BASE_DT","COMN_COUNTRY_BAS","STD_USER_YN"],"optional_sql_terms":["STD_USER_YN"],"required_result_shape":"COUNTRY_GROUPED"}',
|
||||
updated_at = SYSTIMESTAMP
|
||||
WHERE question_code = 'CZN-06';
|
||||
|
||||
/
|
||||
|
||||
DECLARE
|
||||
v_input CLOB;
|
||||
v_embedding VECTOR;
|
||||
v_exists NUMBER;
|
||||
BEGIN
|
||||
v_input := TO_CLOB('Question pattern: show daily active-user counts by country for one resolved game and one business date.')
|
||||
|| CHR(10) || 'Question pattern Korean: 한 게임의 기준일 주요 국가별 표준 AU 수를 알려줘.'
|
||||
|| CHR(10) || 'Logical object role: COUNTRY_GROUPED_DAILY_AU'
|
||||
|| CHR(10) || 'Required metric: AU_FLAG=1 and excluded-user filtering; group by the last connection country.';
|
||||
v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING(v_input, JSON(sg_qa_vector_params('search_document')));
|
||||
SELECT COUNT(*) INTO v_exists FROM sg_qa_vector_example
|
||||
WHERE source_type = 'POLICY_TEMPLATE' AND source_case_id = 'COUNTRY_DAILY_AU';
|
||||
IF v_exists = 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 (
|
||||
'한 게임의 기준일 주요 국가별 표준 AU 수를 알려줘.',
|
||||
TO_CLOB('SELECT u."LAST_CONN_COUNTRY_CD" AS "COUNTRY_CD",' || CHR(10)
|
||||
|| ' c."COUNTRY_KR_NM" AS "COUNTRY_NAME",' || CHR(10)
|
||||
|| ' COUNT(DISTINCT u."GUID") AS "STANDARD_AU_COUNT"' || CHR(10)
|
||||
|| 'FROM <RESOLVED_GAME_USER_MASTER> u' || CHR(10)
|
||||
|| 'LEFT JOIN <APPROVED_COUNTRY_DIMENSION> c' || CHR(10)
|
||||
|| ' ON c."COUNTRY_2CHAR_CD" = u."LAST_CONN_COUNTRY_CD"' || CHR(10)
|
||||
|| 'WHERE u."BASE_DT" = <BUSINESS_DATE>' || CHR(10)
|
||||
|| ' AND u."AU_FLAG" = 1' || CHR(10)
|
||||
|| ' AND u."EXPT_USER_YN" = ''N''' || CHR(10)
|
||||
|| 'GROUP BY u."LAST_CONN_COUNTRY_CD", c."COUNTRY_KR_NM"'),
|
||||
'Applicable metric reference: country-grouped daily AU must use AU_FLAG=1 and EXPT_USER_YN=''N''; do not replace AU_FLAG with STD_USER_YN alone. Group by LAST_CONN_COUNTRY_CD. Use an approved country dimension for country display or a current approved major-country classification when the request requires it.',
|
||||
v_input, v_embedding, 'cohere.embed-v4.0',
|
||||
'APPROVED', 'SQL_TEMPLATE', 'SINGLE', 'COUNTRY_GROUPED_DAILY_AU',
|
||||
'VERIFIED', 'Reusable country-grouped daily-AU pattern; no customer game, date, result, or physical object is embedded.',
|
||||
SYSTIMESTAMP, 'SGMP_POC_METADATA_REVIEW', 'COUNTRY_DAILY_AU', 'POLICY_TEMPLATE'
|
||||
);
|
||||
ELSE
|
||||
UPDATE sg_qa_vector_example
|
||||
SET embedding_input = v_input, embedding = v_embedding,
|
||||
reference_status = 'APPROVED', inspection_status = 'VERIFIED',
|
||||
verified_at = SYSTIMESTAMP, verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'POLICY_TEMPLATE' AND source_case_id = 'COUNTRY_DAILY_AU';
|
||||
END IF;
|
||||
COMMIT;
|
||||
END;
|
||||
|
||||
/
|
||||
17
database/adb/133_sgmp_restore_czn06_exact_fewshot.sql
Normal file
17
database/adb/133_sgmp_restore_czn06_exact_fewshot.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- CZN-06 is a verified, exact customer question/SQL pair. It must be a
|
||||
-- runtime Few-shot when approved; RETIRED is the DB switch that excludes it.
|
||||
-- This is a single-game reference, so keep the retrieval scope explicit.
|
||||
UPDATE sg_qa_vector_example
|
||||
SET reference_status = 'APPROVED',
|
||||
reference_kind = 'SQL_TEMPLATE',
|
||||
target_type = 'SINGLE',
|
||||
object_role = 'COUNTRY_GROUPED_DAILY_AU',
|
||||
inspection_status = 'VERIFIED',
|
||||
inspection_note = 'Verified exact CZN-06 Few-shot restored for runtime retrieval. Daily country AU requires AU_FLAG=1 and EXPT_USER_YN=''N''; STD_USER_YN alone is insufficient.',
|
||||
verified_at = SYSTIMESTAMP,
|
||||
verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND source_case_id = 'CZN-06'
|
||||
/
|
||||
|
||||
COMMIT
|
||||
69
database/adb/135_sgmp_semantic_fewshot_retrieval.sql
Normal file
69
database/adb/135_sgmp_semantic_fewshot_retrieval.sql
Normal file
@@ -0,0 +1,69 @@
|
||||
-- Runtime Few-shots remain semantic vector retrieval. Customer examples are
|
||||
-- governed by their DB approval state, not restricted to exact text matches.
|
||||
|
||||
UPDATE sg_qa_vector_example
|
||||
SET reference_status = 'APPROVED',
|
||||
reference_kind = 'SQL_TEMPLATE',
|
||||
target_type = 'SINGLE',
|
||||
object_role = 'GAME_GOODS_HOLDINGS',
|
||||
inspection_status = 'VERIFIED',
|
||||
inspection_note = 'Verified CZN-07 semantic Few-shot. Use goods holdings, crystal dimension, RU_FLAG=1, excluded-user filter, nonzero holdings, and daily grouping.',
|
||||
verified_at = SYSTIMESTAMP,
|
||||
verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND source_case_id = 'CZN-07'
|
||||
/
|
||||
|
||||
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')));
|
||||
v_max_cosine_distance NUMBER;
|
||||
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;
|
||||
|
||||
SELECT number_value INTO v_max_cosine_distance
|
||||
FROM sg_game_scope_policy
|
||||
WHERE policy_key = 'QA_VECTOR_MAX_COSINE_DISTANCE'
|
||||
AND active_yn = 'Y'
|
||||
AND number_value IS NOT NULL;
|
||||
|
||||
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,
|
||||
cosine_distance
|
||||
FROM (
|
||||
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 inspection_status = 'VERIFIED'
|
||||
AND answer_sql IS NOT NULL
|
||||
AND (source_type = 'POLICY_TEMPLATE'
|
||||
OR NOT REGEXP_LIKE(answer_sql, '<[A-Z][A-Z0-9_]*>', 'i'))
|
||||
AND (target_type = 'ANY' OR v_target_type = 'ANY' OR target_type = v_target_type)
|
||||
)
|
||||
WHERE cosine_distance <= v_max_cosine_distance
|
||||
ORDER BY cosine_distance, example_id
|
||||
FETCH FIRST p_top_k ROWS ONLY;
|
||||
RETURN v_results;
|
||||
END;
|
||||
/
|
||||
|
||||
COMMIT
|
||||
87
database/adb/136_sgmp_fewshot_neighbor_margin.sql
Normal file
87
database/adb/136_sgmp_fewshot_neighbor_margin.sql
Normal file
@@ -0,0 +1,87 @@
|
||||
-- Keep semantic vector retrieval, but do not inject weak trailing neighbours
|
||||
-- when a materially stronger example has already been found.
|
||||
MERGE INTO sg_game_scope_policy t
|
||||
USING (
|
||||
SELECT 'QA_VECTOR_NEIGHBOR_DISTANCE_MARGIN' AS policy_key,
|
||||
0.120000 AS number_value,
|
||||
'Maximum additional cosine distance from the best runtime Few-shot candidate.' AS description
|
||||
FROM dual
|
||||
) s
|
||||
ON (t.policy_key = s.policy_key)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
t.number_value = s.number_value,
|
||||
t.description = s.description,
|
||||
t.active_yn = 'Y',
|
||||
t.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
policy_key, number_value, text_value, description, active_yn
|
||||
) VALUES (
|
||||
s.policy_key, s.number_value, NULL, s.description, 'Y'
|
||||
)
|
||||
/
|
||||
|
||||
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')));
|
||||
v_max_cosine_distance NUMBER;
|
||||
v_neighbor_margin NUMBER;
|
||||
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;
|
||||
|
||||
SELECT number_value INTO v_max_cosine_distance
|
||||
FROM sg_game_scope_policy
|
||||
WHERE policy_key = 'QA_VECTOR_MAX_COSINE_DISTANCE'
|
||||
AND active_yn = 'Y'
|
||||
AND number_value IS NOT NULL;
|
||||
|
||||
SELECT number_value INTO v_neighbor_margin
|
||||
FROM sg_game_scope_policy
|
||||
WHERE policy_key = 'QA_VECTOR_NEIGHBOR_DISTANCE_MARGIN'
|
||||
AND active_yn = 'Y'
|
||||
AND number_value IS NOT NULL;
|
||||
|
||||
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,
|
||||
cosine_distance
|
||||
FROM (
|
||||
SELECT c.*,
|
||||
MIN(c.cosine_distance) OVER () AS best_cosine_distance
|
||||
FROM (
|
||||
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 inspection_status = 'VERIFIED'
|
||||
AND answer_sql IS NOT NULL
|
||||
AND (source_type = 'POLICY_TEMPLATE'
|
||||
OR NOT REGEXP_LIKE(answer_sql, '<[A-Z][A-Z0-9_]*>', 'i'))
|
||||
AND (target_type = 'ANY' OR v_target_type = 'ANY' OR target_type = v_target_type)
|
||||
) c
|
||||
WHERE c.cosine_distance <= v_max_cosine_distance
|
||||
)
|
||||
WHERE cosine_distance <= best_cosine_distance + v_neighbor_margin
|
||||
ORDER BY cosine_distance, example_id
|
||||
FETCH FIRST p_top_k ROWS ONLY;
|
||||
RETURN v_results;
|
||||
END;
|
||||
/
|
||||
|
||||
COMMIT
|
||||
@@ -0,0 +1,16 @@
|
||||
-- CZN-08 is the reviewed semantic reference for daily standard-AU crystal
|
||||
-- total and per-user average holdings.
|
||||
UPDATE sg_qa_vector_example
|
||||
SET reference_status = 'APPROVED',
|
||||
reference_kind = 'SQL_TEMPLATE',
|
||||
target_type = 'SINGLE',
|
||||
object_role = 'GAME_GOODS_HOLDINGS',
|
||||
inspection_status = 'VERIFIED',
|
||||
inspection_note = 'Verified CZN-08 Few-shot. Standard-AU crystal holdings require AU_FLAG=1, excluded-user filtering, and per-user average as SUM(HAVE_CNT) / COUNT(DISTINCT GUID), not AVG(HAVE_CNT).',
|
||||
verified_at = SYSTIMESTAMP,
|
||||
verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND source_case_id = 'CZN-08'
|
||||
/
|
||||
|
||||
COMMIT
|
||||
11
database/adb/138_sgmp_tighten_fewshot_neighbor_margin.sql
Normal file
11
database/adb/138_sgmp_tighten_fewshot_neighbor_margin.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
-- Calibrate the semantic-neighbour window using reviewed CZN patterns:
|
||||
-- retain close paraphrases, exclude adjacent metric shapes.
|
||||
UPDATE sg_game_scope_policy
|
||||
SET number_value = 0.100000,
|
||||
description = 'Maximum additional cosine distance from the best runtime Few-shot candidate.',
|
||||
active_yn = 'Y',
|
||||
updated_at = SYSTIMESTAMP
|
||||
WHERE policy_key = 'QA_VECTOR_NEIGHBOR_DISTANCE_MARGIN'
|
||||
/
|
||||
|
||||
COMMIT
|
||||
@@ -0,0 +1,15 @@
|
||||
-- CZN-05 is the reviewed reference for country-grouped business AU.
|
||||
UPDATE sg_qa_vector_example
|
||||
SET reference_status = 'APPROVED',
|
||||
reference_kind = 'SQL_TEMPLATE',
|
||||
target_type = 'SINGLE',
|
||||
object_role = 'COUNTRY_GROUPED_BUSINESS_AU',
|
||||
inspection_status = 'VERIFIED',
|
||||
inspection_note = 'Verified CZN-05 Few-shot. Join business-user data to user master on GUID and BASE_DT before grouping by user country; filter BIZ_AU_FLAG=1 and EXPT_USER_YN=''N''.',
|
||||
verified_at = SYSTIMESTAMP,
|
||||
verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND source_case_id = 'CZN-05'
|
||||
/
|
||||
|
||||
COMMIT
|
||||
95
database/adb/140_sgmp_hybrid_fewshot_reranking.sql
Normal file
95
database/adb/140_sgmp_hybrid_fewshot_reranking.sql
Normal file
@@ -0,0 +1,95 @@
|
||||
-- Hybrid retrieval remains database-driven: dense vector similarity handles
|
||||
-- paraphrases, while lexical similarity distinguishes decisive request terms.
|
||||
MERGE INTO sg_game_scope_policy t
|
||||
USING (
|
||||
SELECT 'QA_VECTOR_LEXICAL_WEIGHT' AS policy_key, 0.350000 AS number_value,
|
||||
'Weight of normalized lexical question similarity in runtime Few-shot reranking.' AS description
|
||||
FROM dual
|
||||
UNION ALL
|
||||
SELECT 'QA_VECTOR_HYBRID_SCORE_MARGIN', 0.050000,
|
||||
'Maximum hybrid-score difference from the best runtime Few-shot candidate.'
|
||||
FROM dual
|
||||
) s
|
||||
ON (t.policy_key = s.policy_key)
|
||||
WHEN MATCHED THEN UPDATE SET
|
||||
t.number_value = s.number_value,
|
||||
t.description = s.description,
|
||||
t.active_yn = 'Y',
|
||||
t.updated_at = SYSTIMESTAMP
|
||||
WHEN NOT MATCHED THEN INSERT (
|
||||
policy_key, number_value, text_value, description, active_yn
|
||||
) VALUES (
|
||||
s.policy_key, s.number_value, NULL, s.description, 'Y'
|
||||
)
|
||||
/
|
||||
|
||||
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')));
|
||||
v_max_cosine_distance NUMBER;
|
||||
v_lexical_weight NUMBER;
|
||||
v_hybrid_margin NUMBER;
|
||||
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;
|
||||
|
||||
SELECT number_value INTO v_max_cosine_distance FROM sg_game_scope_policy
|
||||
WHERE policy_key = 'QA_VECTOR_MAX_COSINE_DISTANCE' AND active_yn = 'Y';
|
||||
SELECT number_value INTO v_lexical_weight FROM sg_game_scope_policy
|
||||
WHERE policy_key = 'QA_VECTOR_LEXICAL_WEIGHT' AND active_yn = 'Y';
|
||||
SELECT number_value INTO v_hybrid_margin FROM sg_game_scope_policy
|
||||
WHERE policy_key = 'QA_VECTOR_HYBRID_SCORE_MARGIN' AND active_yn = 'Y';
|
||||
|
||||
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,
|
||||
cosine_distance
|
||||
FROM (
|
||||
SELECT s.*,
|
||||
MAX(s.hybrid_score) OVER () AS best_hybrid_score
|
||||
FROM (
|
||||
SELECT c.*,
|
||||
((1 - v_lexical_weight) * (1 - c.cosine_distance)
|
||||
+ v_lexical_weight * c.lexical_similarity) AS hybrid_score
|
||||
FROM (
|
||||
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,
|
||||
UTL_MATCH.JARO_WINKLER_SIMILARITY(
|
||||
DBMS_LOB.SUBSTR(question, 4000, 1),
|
||||
DBMS_LOB.SUBSTR(p_question, 4000, 1)
|
||||
) / 100 AS lexical_similarity
|
||||
FROM sg_qa_vector_example
|
||||
WHERE reference_status = 'APPROVED'
|
||||
AND inspection_status = 'VERIFIED'
|
||||
AND answer_sql IS NOT NULL
|
||||
AND (source_type = 'POLICY_TEMPLATE'
|
||||
OR NOT REGEXP_LIKE(answer_sql, '<[A-Z][A-Z0-9_]*>', 'i'))
|
||||
AND (target_type = 'ANY' OR v_target_type = 'ANY' OR target_type = v_target_type)
|
||||
) c
|
||||
WHERE c.cosine_distance <= v_max_cosine_distance
|
||||
) s
|
||||
)
|
||||
WHERE hybrid_score >= best_hybrid_score - v_hybrid_margin
|
||||
ORDER BY hybrid_score DESC, cosine_distance, example_id
|
||||
FETCH FIRST p_top_k ROWS ONLY;
|
||||
RETURN v_results;
|
||||
END;
|
||||
/
|
||||
|
||||
COMMIT
|
||||
15
database/adb/141_sgmp_restore_czn13_ether_usage_fewshot.sql
Normal file
15
database/adb/141_sgmp_restore_czn13_ether_usage_fewshot.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- CZN-13 is the reviewed reference for Ether usage and distinct users.
|
||||
UPDATE sg_qa_vector_example
|
||||
SET reference_status = 'APPROVED',
|
||||
reference_kind = 'SQL_TEMPLATE',
|
||||
target_type = 'SINGLE',
|
||||
object_role = 'GAME_GOODS_CHANGE',
|
||||
inspection_status = 'VERIFIED',
|
||||
inspection_note = 'Verified CZN-13 Few-shot. Ether usage requires goods-change data joined to the goods dimension and user master by GUID and BASE_DT, CHANGE_TYPE_CD=''USE'', active Ether dimension, excluded-user filter, and GOODS_CHANGE_CNT aggregation.',
|
||||
verified_at = SYSTIMESTAMP,
|
||||
verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND source_case_id = 'CZN-13'
|
||||
/
|
||||
|
||||
COMMIT
|
||||
@@ -0,0 +1,15 @@
|
||||
-- CZN-16 is the reviewed reference for purchasers of a named package.
|
||||
UPDATE sg_qa_vector_example
|
||||
SET reference_status = 'APPROVED',
|
||||
reference_kind = 'SQL_TEMPLATE',
|
||||
target_type = 'SINGLE',
|
||||
object_role = 'SALES_PRODUCT_PURCHASER',
|
||||
inspection_status = 'VERIFIED',
|
||||
inspection_note = 'Verified CZN-16 Few-shot. Join sales transactions to product display by GAME_ID and PRODUCT_ID, filter the resolved package name and excluded users, and use the payment business date when counting distinct purchasers.',
|
||||
verified_at = SYSTIMESTAMP,
|
||||
verified_by = 'SGMP_POC_METADATA_REVIEW'
|
||||
WHERE source_type = 'CUSTOMER_QA_BENCHMARK'
|
||||
AND source_case_id = 'CZN-16'
|
||||
/
|
||||
|
||||
COMMIT
|
||||
@@ -1,11 +1,13 @@
|
||||
# SGMP Few-shot NL2SQL MCP (#735)
|
||||
# Redmine #735 · SGMP Few-shot NL2SQL MCP
|
||||
|
||||
> 상태: Approved
|
||||
> 구현: `McpSseService`, `SelectAiService`, `McpProperties`
|
||||
|
||||
## 목적
|
||||
|
||||
기존 Select AI Text2SQL 경로와 분리된 검증용 MCP tool을 제공한다. 질문과 유사한 검토 완료 예제를 벡터 검색하고, 그 SQL 패턴을 prompt에 참고자료로 넣은 뒤 `SHOWSQL`로 생성한 SQL을 읽기 전용으로 실행한다.
|
||||
기존 Select AI Text2SQL 경로와 분리된 MCP tool을 제공한다. 질문과 의미가 유사한 검토
|
||||
완료 예제를 DB에서 검색하고, 승인 SQL 구조를 참고자료로 넣은 뒤 `SHOWSQL`로 생성한 SQL을
|
||||
읽기 전용으로 실행한다.
|
||||
|
||||
## MCP 계약
|
||||
|
||||
@@ -13,11 +15,26 @@
|
||||
- **입력**: `prompt` (최대 4,000자)
|
||||
- **출력**: 벡터 Few-shot 예제(질문, SQL, 모델, cosine distance), 생성 SQL, 실행 상태, 행 수, 최대 100건 결과
|
||||
|
||||
Few-shot SQL은 실행하지 않는다. 현재 메타데이터·alias 정책을 우선하고, Select AI가 새로 생성한 SQL만 read-only 검증 후 실행한다.
|
||||
Few-shot SQL은 실행하지 않는다. 현재 메타데이터·alias 정책을 우선하고, Select AI가 새로
|
||||
생성한 SQL만 read-only 검증 후 실행한다.
|
||||
|
||||
## DB 검색·승인 기준
|
||||
|
||||
- `sg_qa_vector_example`의 `reference_status='APPROVED'`,
|
||||
`inspection_status='VERIFIED'`, SQL 존재 예제만 후보가 된다.
|
||||
- `RETIRED`는 동일 질문이라도 후보에서 제외된다. 리타이어 여부는 DB 컬럼으로 저장하며
|
||||
Java가 별도 목록으로 판단하지 않는다.
|
||||
- 벡터 cosine distance가 `QA_VECTOR_MAX_COSINE_DISTANCE` 이하여야 한다.
|
||||
- 후보 순위는 벡터 유사도와 질문 문자열 유사도를 DB에서 결합한다. 정책값
|
||||
`QA_VECTOR_LEXICAL_WEIGHT=0.35`, `QA_VECTOR_HYBRID_SCORE_MARGIN=0.05`는
|
||||
유사한 후속 질문에는 참고 범위를 남기되, 핵심 요청어가 다른 예제가 최상위가 되는 문제를
|
||||
줄인다.
|
||||
- 고객 기준 예제는 개별 승인 상태로 관리한다. 같은 문장만 허용하는 방식으로 제한하지 않으며,
|
||||
승인된 SQL 구조가 새 질문의 참고 근거가 될 수 있다.
|
||||
|
||||
## 안전 규칙
|
||||
|
||||
1. 벡터 검색 실패는 `UNAVAILABLE` 상태로 남기고 기존 정책 prompt로 폴백한다.
|
||||
1. 검색 후보가 없으면 `NO_MATCH`로 기록하고 일반 Select AI 생성은 계속한다.
|
||||
2. 생성 결과는 단일 `SELECT` 또는 `WITH`만 허용한다.
|
||||
3. DDL, DML, PL/SQL, 시스템 객체, 잠금 구문, 다중 문장은 차단한다.
|
||||
4. JDBC read-only 트랜잭션과 30초 query timeout, 최대 100행 제한을 적용한다.
|
||||
|
||||
41
docs/design/741-db-owned-execution-task-contract/README.md
Normal file
41
docs/design/741-db-owned-execution-task-contract/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Redmine #739 · DB 소유 게임별 실행 작업 계약
|
||||
|
||||
## 목표
|
||||
|
||||
복수 게임 질문에서 Portal과 `smilegate_fewshot_nl2sql`은 게임명을 재해석하거나 원 질문을
|
||||
수정하지 않는다. ADB의 `sg_game_query_plan`이 DB 카탈로그·OCI Chat 결과를 바탕으로 실행
|
||||
가능한 작업을 만들고, 호출자는 그 작업을 그대로 실행한다.
|
||||
|
||||
## 계약
|
||||
|
||||
`executionTasks`의 `QUERY` 작업은 다음 값을 모두 가진다.
|
||||
|
||||
- `action`: `QUERY`
|
||||
- `workerTool`: 호출할 worker 도구명
|
||||
- `workerArguments.prompt`: 원 질문의 지표·날짜·필터·결과 모양을 보존한 해당 target 전용 질의
|
||||
- `workerArguments.scopeGameKey`: DB가 확정한 game key
|
||||
- `workerArguments.queryPlan`: 해당 target 하나만 담긴 `SINGLE` plan
|
||||
- `fewShotArguments.question`: 보조 진단 도구가 필요할 때만 사용할 같은 target 전용 질의
|
||||
|
||||
`REPORT_UNAVAILABLE` 작업은 worker 인자를 갖지 않으며 최종 응답 항목으로만 사용한다.
|
||||
|
||||
## 책임 분리
|
||||
|
||||
| 구성요소 | 책임 |
|
||||
| --- | --- |
|
||||
| `sg_game_query_plan` | 게임 식별, 데이터 가능 여부, target별 자연어 작업 생성, 단일 target plan 생성 |
|
||||
| Portal 오케스트레이터 | 작업 순회, worker 호출, 결과 합성, task 완료 판정 |
|
||||
| `fewshot_preflight` | reasoning에서 필요할 때만 후보 적합성을 확인하는 보조 진단 도구 |
|
||||
| `smilegate_fewshot_nl2sql` | 전달된 단일 작업으로 DB Few-shot 검색·승인 판정 후 SQL 생성 및 읽기 전용 실행 |
|
||||
|
||||
## 안전 규칙
|
||||
|
||||
- planner가 생성한 target 전용 작업 질의에는 다른 계획 target의 실제 mention이 포함되면 실패 처리한다. 호출자가 문자열을 제거하거나 보정하지 않는다.
|
||||
- worker는 `queryPlan`이 단일 target인지 검증만 하며, 전체 plan에서 target을 추출하거나 원 질문을 재작성하지 않는다.
|
||||
- worker의 Few-shot 검색은 DB가 발급한 `workerArguments.prompt`로 수행한다. preflight 결과는 선택적으로만 전달할 수 있으며 worker 실행의 조건이 아니다.
|
||||
- Java는 지표별 SQL 조건, 결과 모양, Few-shot 활성화/리타이어, 후보 유사도에 관여하지 않는다.
|
||||
이 정책은 DB 메타데이터와 `sg_qa_vector_search`에서 관리한다.
|
||||
|
||||
## 검증
|
||||
|
||||
STD-11에서 Bubblyz는 `REPORT_UNAVAILABLE`, 카제나는 `QUERY` 한 건이 되어야 한다. 카제나 worker에 전달되는 prompt·plan·생성 SQL 어디에도 Bubblyz가 없어야 하며, 결과는 2026-07-15 매출 227681이어야 한다.
|
||||
118
docs/smilegate-mcp-current-operation-guide.md
Normal file
118
docs/smilegate-mcp-current-operation-guide.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Smilegate Data & AI PoC — 현재 MCP 도구 운영 안내
|
||||
|
||||
## 1. 현재 기본 실행 경로
|
||||
|
||||
모든 게임 데이터 질문은 먼저 `oracle.select_ai.game_query_plan`을 호출한다.
|
||||
|
||||
```text
|
||||
일반 데이터 분석 질문
|
||||
game_query_plan → smilegate_fewshot_nl2sql
|
||||
|
||||
게임별·일반 분석 질문
|
||||
game_query_plan → executionTasks → smilegate_fewshot_nl2sql
|
||||
```
|
||||
|
||||
`game_query_plan`은 게임 카탈로그, 별칭, 벡터 검색 결과를 사용하여 질의 범위를 `NONE`,
|
||||
`SINGLE`, `MULTI`, `ALL` 중 하나로 판정하고 `executionTasks`를 발급한다. 다음 worker에는
|
||||
원 질문을 보존한 DB 작업 인자와 `GAME QUERY REFERENCE`를 전달한다. Portal은 이를 보정하지
|
||||
않고 task 종료 상태를 합산한다.
|
||||
|
||||
## 2. 기본 실행 MCP 도구
|
||||
|
||||
### `oracle.select_ai.game_query_plan`
|
||||
|
||||
- 모든 게임 데이터 질의의 필수 첫 단계다.
|
||||
- OCI GenAI Chat으로 질문에서 게임명 후보를 식별하고 게임 카탈로그 벡터 검색 결과를 검증한다.
|
||||
- `targetType`, `supportedGames`, `dataEligibleTargets`, 미매칭 대상을 반환한다.
|
||||
- 게임명·prefix·물리 테이블을 Java나 포털 코드에서 하드코딩하지 않는다.
|
||||
|
||||
### `oracle.select_ai.smilegate_fewshot_nl2sql`
|
||||
|
||||
- AU 외 일반 분석 질의의 주 실행 도구다.
|
||||
- 현재 질문으로 QA 벡터 저장소에서 승인·검증된 유사 Few-shot 예제를 찾는다.
|
||||
- 선택된 Few-shot 예제의 질문·승인 SQL·논리 객체 역할을 현재 질문 및 `queryPlan`과 함께 Select AI 프롬프트에 추가한다.
|
||||
- ADB `DBMS_CLOUD_AI.GENERATE(..., 'showsql')`로 SQL을 생성한다.
|
||||
- 생성 SQL을 읽기 전용으로 검증한 후 실행한다.
|
||||
- Few-shot 근거, 생성 SQL, 실행 결과, 행 수를 반환한다.
|
||||
- 예제 승인·리타이어·유사도 기준은 DB가 관리한다. Java/Portal은 지표 조건이나
|
||||
검색 결과를 보정하지 않는다.
|
||||
|
||||
### `oracle.select_ai.game_daily_au_lookup`
|
||||
|
||||
- 고정 정의 AU를 별도로 점검할 때 쓰는 전용 도구다. 고객 질의의 기본 실행 경로는
|
||||
`executionTasks`가 지정한 worker이며, 일반적으로 `smilegate_fewshot_nl2sql`이다.
|
||||
- 입력은 `queryPlan`과 선택적인 `baseDate(YYYY-MM-DD)`다.
|
||||
- `queryPlan`의 게임 키를 `SG_GAME_CATALOG`에서 다시 검증하고 `USER_MASTER_OBJECT_NAME`을 동적으로 선택한다.
|
||||
- 선택된 사용자 마스터 객체에 대해 아래 정의로 AU를 집계한다.
|
||||
|
||||
```sql
|
||||
SELECT COUNT(DISTINCT GUID) AS AU_COUNT
|
||||
FROM <catalog_user_master_object>
|
||||
WHERE BASE_DT = :baseDate
|
||||
AND AU_FLAG = 1
|
||||
AND EXPT_USER_YN = 'N'
|
||||
```
|
||||
|
||||
- 게임명·별칭·prefix·물리 테이블명을 입력값이나 코드에서 직접 사용하지 않는다.
|
||||
- `SINGLE`, `MULTI`, `ALL` 계획의 각 대상에 대해 결과를 반환한다.
|
||||
|
||||
## 3. 등록돼 있으나 기본 경로에서 직접 실행하지 않는 도구
|
||||
|
||||
### `oracle.select_ai.qa_vector_search`
|
||||
|
||||
- 유사 질문과 승인 SQL 예제를 직접 확인하는 관리자·점검용 도구다.
|
||||
- 일반 질의에서는 `smilegate_fewshot_nl2sql`이 내부적으로 Few-shot 검색을 수행하므로 별도 호출하지 않는다.
|
||||
|
||||
### `oracle.select_ai.qa_vector_store`
|
||||
|
||||
- 검토 완료한 질문·읽기 전용 SQL·검토 메모를 Few-shot 벡터 지식으로 저장하는 관리자 도구다.
|
||||
- 사용자 질의 실행 중에는 호출하지 않는다.
|
||||
|
||||
### `oracle.select_ai.game_catalog_resolve`
|
||||
|
||||
- 게임명 후보의 벡터 검색 결과를 독립적으로 점검하는 진단 도구다.
|
||||
- 정상 흐름에서는 `game_query_plan` 내부의 게임 식별 과정이 이 역할을 수행한다.
|
||||
|
||||
### `oracle.select_ai.game_scope_resolve`
|
||||
|
||||
- 과거 게임 범위와 별칭 매칭을 점검하기 위한 보조 도구다.
|
||||
- 현재 기본 판정 기준은 `game_query_plan`이므로 정상 경로에는 넣지 않는다.
|
||||
|
||||
### `oracle.select_ai.smilegate_game_text2sql`
|
||||
|
||||
- Few-shot을 붙이지 않은 기본 Select AI 결과를 비교·점검하는 보조 Text2SQL 도구다.
|
||||
- 고객용 기본 분석 경로는 `smilegate_fewshot_nl2sql`이다.
|
||||
|
||||
### `oracle.select_ai.smilegate_game_showprompt`
|
||||
|
||||
- SQL 생성에 전달된 최종 Select AI 프롬프트를 확인하는 진단 도구다.
|
||||
- 테이블 comment, 컬럼 annotation, 제약조건, 게임 범위 계획, Few-shot 근거가 프롬프트에 반영됐는지 점검한다.
|
||||
- SQL을 실행하지 않는다.
|
||||
|
||||
### `oracle.select_ai.fewshot_preflight`
|
||||
|
||||
- Few-shot 후보의 적합성을 별도로 확인할 때 사용하는 점검 도구다.
|
||||
- 현재 `smilegate.cloud-handson.com` 포털의 기본 질문 allowlist와 기본 실행 경로에는 직접 넣지 않는다.
|
||||
|
||||
## 4. 실제 검증 결과
|
||||
|
||||
| 항목 | 확인 결과 |
|
||||
|---|---|
|
||||
| 질문 | 카제나의 2026-07-15 AU |
|
||||
| 게임 범위 | `SINGLE / SUPPORTED` |
|
||||
| 게임 키 | `STOVE_CHAOSZERO` |
|
||||
| 카탈로그 선택 객체 | `CZN_COMN_USER_MST` |
|
||||
| AU 실행 상태 | `GAME_AU_LOOKUP / READY` |
|
||||
| 기준일 | `2026-07-15` |
|
||||
| 반환 AU | `0` |
|
||||
|
||||
이 검증에서 테이블명은 코드에 고정하지 않았으며, 게임 계획 결과와 `SG_GAME_CATALOG` 메타데이터를 통해 선택됐다.
|
||||
|
||||
## 5. 운영 원칙
|
||||
|
||||
1. 게임 범위 판단과 실행 작업 생성은 항상 `game_query_plan`이 담당한다.
|
||||
2. Portal은 DB task를 실행·합성하며, 질문·SQL·결과를 보정하지 않는다.
|
||||
3. 분석성 질의는 승인·검증된 Few-shot 기반 Select AI로 처리한다.
|
||||
4. `RETIRED` 예제는 검색하지 않으며, 승인/리타이어는 DB에 저장한다.
|
||||
5. 정답지 SQL을 런타임에 실행하지 않는다. Select AI가 새로 만든 읽기 전용 SQL만 실행한다.
|
||||
6. 문제 발생 시 SHOWPROMPT, 생성 SQL, 실행 결과, 판정 이력을 근거로 metadata·Few-shot을 보완한다.
|
||||
Reference in New Issue
Block a user