feat: Add support for internal LiteLLM models (Qwen3, Gemma-4)
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 0s
Some checks failed
Deploy to OCIWP / deploy (push) Failing after 0s
- Add dynamic routing in ChatController for Qwen3-Coder and Gemma-4-31B - Update scaffold.html and chat.html model selection dropdowns - Maintain existing OpenRouter fallback via application.yml
This commit is contained in:
@@ -81,27 +81,59 @@ public class ChatController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String selectedModel = request.getOrDefault("model", "cohere/north-mini-code:free").trim();
|
String selectedModel = request.getOrDefault("model", "Qwen3-Coder").trim();
|
||||||
if (selectedModel.isEmpty()) {
|
if (selectedModel.isEmpty()) {
|
||||||
selectedModel = "cohere/north-mini-code:free";
|
selectedModel = "Qwen3-Coder";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. gemini-flash-latest 선택 시 OpenRouter의 Google Gemma 4 모델로 라우팅
|
// LiteLLM 내부망 모델 매핑
|
||||||
if (selectedModel.equals("gemini-flash-latest")) {
|
if (selectedModel.equals("gemini-flash-latest")) {
|
||||||
selectedModel = "google/gemma-4-31b-it:free";
|
selectedModel = "Gemma-4-31B";
|
||||||
log.info("[Real AI Chat] Gemini 직접 API → OpenRouter Google Gemma 4 31B 로 라우팅 전환");
|
log.info("[Real AI Chat] 화면의 Gemini 플래시 선택을 사내 Gemma-4-31B 모델로 라우팅 전환");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. OpenRouter 무료 모델 처리 (Spring AI 빌드된 ChatClient 및 MCP 툴 호출 완벽 지원!)
|
ChatClient activeChatClient;
|
||||||
ChatClient activeChatClient = chatClientBuilder
|
org.springframework.ai.chat.prompt.ChatOptions chatOptions;
|
||||||
.defaultSystem("You are AX HUB Assistant, a highly capable enterprise AI agent. You must use the provided tools to answer user questions when necessary. Always answer politely in Korean.")
|
|
||||||
.build();
|
// 2. 모델 분기 처리: 사내 모델(Qwen3/Gemma-4) vs 기존 외부 모델(OpenRouter 등)
|
||||||
|
if ("Qwen3-Coder".equalsIgnoreCase(selectedModel) || "Gemma-4-31B".equalsIgnoreCase(selectedModel)) {
|
||||||
|
// 사내 LiteLLM 환경 동적 ChatModel 생성
|
||||||
|
String liteLlmBaseUrl = "https://dev-iam-litellm.shinhanlife.co.kr:18020";
|
||||||
|
String apiKey = "Gemma-4-31B".equalsIgnoreCase(selectedModel) ? "sk-EH107wYBZuU6RUTqthR17A" : "sk-UJ2IRenvaMPbY3ozQdj6zw";
|
||||||
|
|
||||||
|
org.springframework.ai.openai.api.OpenAiApi openAiApi = org.springframework.ai.openai.api.OpenAiApi.builder()
|
||||||
|
.baseUrl(liteLlmBaseUrl)
|
||||||
|
.apiKey(new org.springframework.ai.model.SimpleApiKey(apiKey))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
org.springframework.ai.openai.OpenAiChatModel dynamicChatModel = org.springframework.ai.openai.OpenAiChatModel.builder()
|
||||||
|
.openAiApi(openAiApi)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
activeChatClient = ChatClient.builder(dynamicChatModel)
|
||||||
|
.defaultSystem("You are AX HUB Assistant, a highly capable enterprise AI agent. You must use the provided tools to answer user questions when necessary. Always answer politely in Korean.")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
chatOptions = org.springframework.ai.openai.OpenAiChatOptions.builder()
|
||||||
|
.model(selectedModel)
|
||||||
|
.temperature(0.2)
|
||||||
|
.maxTokens(16384)
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
// 기존 방식: application.yml 에 설정된 기본 Bean (OpenRouter 등) 사용
|
||||||
|
activeChatClient = chatClientBuilder
|
||||||
|
.defaultSystem("You are AX HUB Assistant, a highly capable enterprise AI agent. You must use the provided tools to answer user questions when necessary. Always answer politely in Korean.")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
chatOptions = org.springframework.ai.openai.OpenAiChatOptions.builder()
|
||||||
|
.model(selectedModel)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
Flux<String> responseStream = activeChatClient.prompt()
|
Flux<String> responseStream = activeChatClient.prompt()
|
||||||
.user(message)
|
.user(message)
|
||||||
.toolCallbacks(callbacks.toArray(new ToolCallback[0]))
|
.toolCallbacks(callbacks.toArray(new ToolCallback[0]))
|
||||||
.options(org.springframework.ai.openai.OpenAiChatOptions.builder()
|
.options(chatOptions)
|
||||||
.model(selectedModel).build())
|
|
||||||
.stream()
|
.stream()
|
||||||
.content();
|
.content();
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ spring:
|
|||||||
lifecycle:
|
lifecycle:
|
||||||
timeout-per-shutdown-phase: 20s
|
timeout-per-shutdown-phase: 20s
|
||||||
ai:
|
ai:
|
||||||
|
# 기본(외부) 모델로 사용할 OpenRouter 설정입니다.
|
||||||
openai:
|
openai:
|
||||||
api-key: ${OPENROUTER_API_KEY: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}
|
api-key: ${OPENROUTER_API_KEY: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}
|
||||||
base-url: https://openrouter.ai/api/v1
|
base-url: https://openrouter.ai/api/v1
|
||||||
@@ -18,6 +19,13 @@ spring:
|
|||||||
model: cohere/north-mini-code:free
|
model: cohere/north-mini-code:free
|
||||||
temperature: 0.3
|
temperature: 0.3
|
||||||
|
|
||||||
|
# 신한라이프 다중 모델 동적 라우팅을 위한 커스텀 설정
|
||||||
|
shinhan:
|
||||||
|
ai:
|
||||||
|
base-url: https://dev-iam-litellm.shinhanlife.co.kr:18020
|
||||||
|
qwen-key: sk-UJ2IRenvaMPbY3ozQdj6zw
|
||||||
|
gemma-key: sk-EH107wYBZuU6RUTqthR17A
|
||||||
|
|
||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8081
|
||||||
http2:
|
http2:
|
||||||
|
|||||||
@@ -953,11 +953,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<select id="aiModelSelect" class="form-select" aria-label="AI 모델 선택">
|
<select id="aiModelSelect" class="form-select" aria-label="AI 모델 선택">
|
||||||
<option value="cohere/north-mini-code:free" selected>Cohere North Mini Code</option>
|
<optgroup label="[신한라이프 내부망]">
|
||||||
<option value="inclusionai/ling-3.0-flash:free">InclusionAI Ling 3 Flash</option>
|
<option value="Qwen3-Coder" selected>Qwen3-Coder</option>
|
||||||
<option value="openai/gpt-oss-20b:free">OpenAI GPT-OSS 20B</option>
|
<option value="Gemma-4-31B">Gemma-4-31B</option>
|
||||||
<option value="google/gemma-4-31b-it:free">Google Gemma 4 31B</option>
|
</optgroup>
|
||||||
<option value="nvidia/nemotron-3-nano-30b-a3b:free">NVIDIA Nemotron 3 Nano</option>
|
<optgroup label="[외부 OpenRouter 무료]">
|
||||||
|
<option value="cohere/north-mini-code:free">Cohere North Mini Code</option>
|
||||||
|
<option value="inclusionai/ling-3.0-flash:free">InclusionAI Ling 3 Flash</option>
|
||||||
|
<option value="openai/gpt-oss-20b:free">OpenAI GPT-OSS 20B</option>
|
||||||
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 d-grid">
|
<div class="col-md-3 d-grid">
|
||||||
|
|||||||
@@ -88,14 +88,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<select id="model-select" class="bg-[#1e2128] text-slate-300 text-xs px-3 py-1.5 rounded-lg border border-white/10 focus:outline-none focus:border-emerald-500/50 cursor-pointer">
|
<select id="model-select" class="bg-[#1e2128] text-slate-300 text-xs px-3 py-1.5 rounded-lg border border-white/10 focus:outline-none focus:border-emerald-500/50 cursor-pointer">
|
||||||
<option value="Gemma-4-31B" selected>Gemma-4-31B (사내 로컬 제공)</option>
|
<optgroup label="[신한라이프 내부망]">
|
||||||
<option value="Qwen3-Coder">Qwen3-Coder (사내 로컬 제공)</option>
|
<option value="Qwen3-Coder" selected>Qwen3-Coder</option>
|
||||||
<option value="inclusionai/ling-3.0-flash:free">Ling 3.0 Flash (무료 - 외부)</option>
|
<option value="Gemma-4-31B">Gemma-4-31B</option>
|
||||||
<option value="openai/gpt-oss-20b:free">GPT-OSS 20B (무료 - 외부)</option>
|
</optgroup>
|
||||||
<option value="google/gemma-4-31b-it:free">Gemma 4 31B (무료 - 외부)</option>
|
<optgroup label="[외부 OpenRouter 무료]">
|
||||||
<option value="nvidia/nemotron-3-nano-30b-a3b:free">NVIDIA Nemotron Nano 30B (무료 - 외부)</option>
|
<option value="cohere/north-mini-code:free">Cohere North Mini Code</option>
|
||||||
<option value="cohere/north-mini-code:free">Cohere North Mini (기본 · 무료 - 외부)</option>
|
<option value="inclusionai/ling-3.0-flash:free">Ling 3.0 Flash</option>
|
||||||
<option value="gemini-flash-latest">Gemini 1.5 Flash (직접 API - Google)</option>
|
<option value="openai/gpt-oss-20b:free">GPT-OSS 20B</option>
|
||||||
|
</optgroup>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user