refs #708: move Smilegate Select AI to OCI GPT 5.4 Mini

This commit is contained in:
devmrko
2026-07-23 13:45:55 +09:00
parent 32fccced20
commit 75d0a9a998
6 changed files with 128 additions and 6 deletions

View File

@@ -56,7 +56,7 @@ export BACKOFFICE_ORDS_DB_PASSWORD=""
export BACKOFFICE_SELECT_AI_DB_URL="${BACKOFFICE_DB_URL}"
export BACKOFFICE_SELECT_AI_DB_USERNAME="SGMP_POC"
export BACKOFFICE_SELECT_AI_DB_PASSWORD=""
export BACKOFFICE_SELECT_AI_PROFILE="SGMP_POC_HAIKU45"
export BACKOFFICE_SELECT_AI_PROFILE="SGMP_POC_OCI_GPT54MINI"
# --- (2c) OpenAI 호환 AI 호출 (MCP-style Reasoning 탭) ---
export BACKOFFICE_AI_ENABLED="false"

View File

@@ -0,0 +1,48 @@
# #708 Smilegate Select AI OCI GenAI 전환
## 프로젝트 개요
Smilegate DATA & AI PoC는 Autonomous Database의 게임 데이터에서 Select AI Text2SQL을 생성하고, MCP와 백오피스를 통해 결과를 조회한다. 현재 운영 프로파일은 외부 OpenRouter 경유 Claude를 사용한다.
## 목표
`SGMP_POC_HAIKU45`가 가진 게임 데이터 object list와 메타데이터 활용 범위는 유지하면서, LLM 호출 경로만 OCI Generative AI `openai.gpt-5.4-mini`로 전환한다. ADB Resource Principal이 아닌 이 머신의 `~/.oci/config` DEFAULT API signing credential을 ADB credential으로 등록한다.
## 전환 설계
| 구분 | 기존 | 전환 후 |
| --- | --- | --- |
| 프로파일 | `SGMP_POC_HAIKU45` | `SGMP_POC_OCI_GPT54MINI` |
| 제공자 | OpenAI 호환 외부 경로 | OCI Generative AI (`provider: oci`) |
| 모델 | Claude Haiku 4.5 | `openai.gpt-5.4-mini` |
| 인증 | 외부 API credential | DEFAULT API signing key 기반 `SGMP_POC_OCI_DEFAULT_CRED` |
| OCI 리전 | 외부 서비스 | `us-chicago-1` (GPT-5.4 Mini OCI inference route) |
| 게임 데이터 범위 | 기존 object list | 기존 profile attributes에서 복제 |
| MCP 설정 | 기존 프로파일명 | `BACKOFFICE_SELECT_AI_PROFILE=SGMP_POC_OCI_GPT54MINI` |
신규 프로파일은 기존 프로파일의 metadata 관련 attributes를 복사하고, 외부 endpoint·credential·model은 OCI 값으로 새로 설정한다. 따라서 object list, comment, annotation, constraint 기반 Text2SQL 문맥은 유지된다. 기존 외부 프로파일은 삭제하지 않으며, 전환 실패 시 환경변수만 원래 값으로 되돌린다.
## 사전 조건
1. `~/.oci/config` DEFAULT의 user, tenancy, fingerprint, key_file이 유효한 OCI API signing key여야 한다.
2. DEFAULT API signing user가 Chicago 리전 root compartment에서 OCI Generative AI `openai.gpt-5.4-mini` 호출 권한을 가져야 한다. DEFAULT config의 signing region과 GPT inference route는 독립적이므로 profile attribute `region``us-chicago-1`로 명시한다.
3. 스크립트는 `SGMP_POC` 프로파일 소유자로 실행한다.
## 구현 순서
1. `sql/adb/72_sgmp_select_ai_oci_genai_profile.sql`로 신규 OCI 프로파일을 만든다.
2. 새 프로파일로 한글 Text2SQL `SHOWSQL`과 생성 SQL의 읽기 전용 실행을 검증한다.
3. 운영 서버의 `BACKOFFICE_SELECT_AI_PROFILE`만 새 프로파일로 교체하고 백오피스를 재기동한다.
4. 운영 MCP의 `oracle.select_ai.smilegate_game_text2sql` 응답 profile과 집계 결과를 검증한다.
## 롤백
새 프로파일을 삭제하지 않는다. MCP에서 오류가 나거나 SQL 품질이 허용 기준을 충족하지 않으면 `/etc/smilegate/backoffice.env``BACKOFFICE_SELECT_AI_PROFILE``SGMP_POC_HAIKU45`로 되돌린 뒤 서비스를 재기동한다.
## 검증 기준
- 새 프로파일 provider=`oci`, model=`openai.gpt-5.4-mini`, credential=`SGMP_POC_OCI_DEFAULT_CRED`, region=`us-chicago-1`
- 한글 질의는 SQLcl UTF-8 base64 복원식으로 전달한다.
- `DBMS_CLOUD_AI.GENERATE(..., 'showsql')`이 읽기 전용 `SELECT` 또는 `WITH` SQL을 생성한다.
- 해당 SQL을 읽기 전용 트랜잭션에서 실행해 결과를 반환한다.
- 운영 MCP 응답의 `profile``SGMP_POC_OCI_GPT54MINI`이다.

View File

@@ -0,0 +1,74 @@
-- 72_sgmp_select_ai_oci_genai_profile.sql
-- Run as SGMP_POC after creating SGMP_POC_OCI_DEFAULT_CRED from the local
-- ~/.oci/config DEFAULT API signing key. No private-key material belongs in
-- this script or the repository.
--
-- The source external profile is retained. Metadata attributes are copied
-- individually so object_list, comments, annotations and instructions remain
-- intact while external endpoint, credential and model settings are replaced.
DECLARE
v_exists PLS_INTEGER;
BEGIN
SELECT COUNT(*)
INTO v_exists
FROM user_cloud_ai_profiles
WHERE profile_name = 'SGMP_POC_OCI_GPT54MINI';
IF v_exists > 0 THEN
DBMS_CLOUD_AI.DROP_PROFILE(
profile_name => 'SGMP_POC_OCI_GPT54MINI',
force => TRUE
);
END IF;
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name => 'SGMP_POC_OCI_GPT54MINI',
attributes => '{
"provider": "oci",
"credential_name": "SGMP_POC_OCI_DEFAULT_CRED",
"model": "openai.gpt-5.4-mini",
"region": "us-chicago-1",
"oci_compartment_id": "<DEFAULT tenancy OCID>"
}',
description => 'Smilegate Text2SQL on OCI GenAI GPT-5.4 Mini'
);
FOR source_attribute IN (
SELECT attribute_name,
attribute_value
FROM user_cloud_ai_profile_attributes
WHERE profile_name = 'SGMP_POC_HAIKU45'
AND attribute_name NOT IN (
'credential_name',
'model',
'provider',
'provider_endpoint',
'region',
'oci_compartment_id',
'oci_endpoint_id',
'oci_apiformat',
'oci_runtimetype'
)
) LOOP
DBMS_CLOUD_AI.SET_ATTRIBUTE(
profile_name => 'SGMP_POC_OCI_GPT54MINI',
attribute_name => source_attribute.attribute_name,
attribute_value => source_attribute.attribute_value
);
END LOOP;
END;
/
SELECT attribute_name,
attribute_value
FROM user_cloud_ai_profile_attributes
WHERE profile_name = 'SGMP_POC_OCI_GPT54MINI'
AND attribute_name IN (
'provider',
'model',
'credential_name',
'region',
'oci_compartment_id'
)
ORDER BY attribute_name;

View File

@@ -74,4 +74,4 @@ backoffice:
db-url: ${BACKOFFICE_SELECT_AI_DB_URL:}
db-username: ${BACKOFFICE_SELECT_AI_DB_USERNAME:}
db-password: ${BACKOFFICE_SELECT_AI_DB_PASSWORD:}
profile: ${BACKOFFICE_SELECT_AI_PROFILE:SGMP_POC_HAIKU45}
profile: ${BACKOFFICE_SELECT_AI_PROFILE:SGMP_POC_OCI_GPT54MINI}

View File

@@ -8,7 +8,7 @@
<h1>MCP 연동</h1>
<details class="explanation-details">
<summary>도움말</summary>
<p>사용자 Bearer Token을 검증한 뒤 <code>SGMP_POC_HAIKU45</code> Select AI 프로파일로 게임 데이터 Text2SQL을 생성하는 단일 MCP tool을 제공합니다. Select AI는 comment, annotation, constraint 메타데이터를 함께 사용하며, 생성 SQL은 자동 실행하지 않습니다.</p>
<p>사용자 Bearer Token을 검증한 뒤 <code>SGMP_POC_OCI_GPT54MINI</code> Select AI 프로파일로 게임 데이터 Text2SQL을 생성하는 단일 MCP tool을 제공합니다. Select AI는 comment, annotation, constraint 메타데이터를 함께 사용하며, 생성 SQL은 자동 실행하지 않습니다.</p>
</details>
</section>
@@ -118,7 +118,7 @@
<pre class="code-block">{
"prompt": "카제나의 최신 BASE_DT 기준 AU(활성 사용자 수)를 조회하는 SQL을 만들어줘."
}</pre>
<p class="form-hint">등록 tool은 <code>oracle.select_ai.smilegate_game_text2sql</code> 하나입니다. 활성 사용자 Bearer Token을 확인한 뒤 <code>SGMP_POC_HAIKU45</code>가 comment, annotation, constraint를 참고해 읽기 전용 게임 데이터 SQL을 생성합니다. 실행은 자동으로 수행하지 않습니다.</p>
<p class="form-hint">등록 tool은 <code>oracle.select_ai.smilegate_game_text2sql</code> 하나입니다. 활성 사용자 Bearer Token을 확인한 뒤 <code>SGMP_POC_OCI_GPT54MINI</code>가 comment, annotation, constraint를 참고해 읽기 전용 게임 데이터 SQL을 생성합니다. 실행은 자동으로 수행하지 않습니다.</p>
</details>
</section>

View File

@@ -49,7 +49,7 @@ class McpSseServiceTest {
assertThat(response.path("result").path("isError").asBoolean()).isFalse();
String payload = response.path("result").path("content").get(0).path("text").asText();
assertThat(payload)
.contains("SGMP_POC_HAIKU45")
.contains("SGMP_POC_OCI_GPT54MINI")
.contains("SELECT 1 FROM DUAL")
.contains("SHOWSQL_AND_EXECUTED")
.contains("READ_ONLY_EXECUTED")
@@ -94,7 +94,7 @@ class McpSseServiceTest {
this.bearerToken = bearerToken;
this.prompt = prompt;
ObjectNode response = new ObjectMapper().createObjectNode()
.put("profile", "SGMP_POC_HAIKU45")
.put("profile", "SGMP_POC_OCI_GPT54MINI")
.put("generatedSql", "SELECT 1 FROM DUAL")
.put("status", "SHOWSQL_AND_EXECUTED")
.put("execution", "READ_ONLY_EXECUTED")