diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt index 7b720c1..8392541 100644 --- a/src/main/kotlin/Main.kt +++ b/src/main/kotlin/Main.kt @@ -80,7 +80,7 @@ fun main() = application { // 앱 실행 시 필요한 바이너리 경로 (실행 파일 위치) val binPath = getLlamaBinPath() val windowState = rememberWindowState( - placement = WindowPlacement.Fullscreen + placement = WindowPlacement.Floating ) Window(onCloseRequest = ::exitApplication, title = "KIS AI 자동매매", state = windowState) { var currentScreen by remember { mutableStateOf(AppScreen.Settings) } diff --git a/src/main/kotlin/database/DatabaseFactory.kt b/src/main/kotlin/database/DatabaseFactory.kt index 8e88d24..20d8b1b 100644 --- a/src/main/kotlin/database/DatabaseFactory.kt +++ b/src/main/kotlin/database/DatabaseFactory.kt @@ -1,6 +1,7 @@ import androidx.compose.runtime.mutableStateListOf import kotlinx.serialization.Serializable import model.AppConfig +import network.TradingDecision import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq import org.jetbrains.exposed.sql.javatime.datetime @@ -413,7 +414,7 @@ object TradingLogStore { } } - fun addLog(tradingDecision: TradingDecision , decision: String, log: String) { + fun addLog(tradingDecision: TradingDecision, decision: String, log: String) { synchronized(this) { if (decisionLogs.size > 1000) decisionLogs.removeAt(0) decisionLogs.add( diff --git a/src/main/kotlin/network/RagService.kt b/src/main/kotlin/network/RagService.kt index 24e23cd..01c50b5 100644 --- a/src/main/kotlin/network/RagService.kt +++ b/src/main/kotlin/network/RagService.kt @@ -1,23 +1,36 @@ -// src/main/kotlin/network/RagService.kt +package network// src/main/kotlin/network/RagService.kt import dev.langchain4j.community.rag.content.retriever.lucene.LuceneEmbeddingStore import dev.langchain4j.data.document.Metadata -import dev.langchain4j.data.message.UserMessage import dev.langchain4j.data.segment.TextSegment +import dev.langchain4j.exception.InternalServerException import dev.langchain4j.model.openai.OpenAiChatModel import dev.langchain4j.model.openai.OpenAiEmbeddingModel +import dev.langchain4j.service.AiServices +import dev.langchain4j.service.SystemMessage import dev.langchain4j.store.embedding.EmbeddingSearchRequest import dev.langchain4j.store.embedding.filter.MetadataFilterBuilder +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import model.CandleData -import network.DartCodeManager -import network.FinancialMapper -import network.FinancialStatement -import network.NewsService +import kotlinx.serialization.json.add +import kotlinx.serialization.json.addJsonObject +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import kotlinx.serialization.json.put +import kotlinx.serialization.json.putJsonArray +import kotlinx.serialization.json.putJsonObject +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody import org.apache.lucene.store.MMapDirectory +import org.slf4j.MDC.put import service.FinancialAnalyzer import service.InvestmentScores import service.TechnicalAnalyzer @@ -25,9 +38,10 @@ import service.TradingDecisionCallback import service.UrlCacheManager import java.nio.file.Paths import java.time.Duration +import java.util.concurrent.TimeUnit interface TradingAnalyst { - @dev.langchain4j.service.SystemMessage(""" + @SystemMessage(""" You are a Senior Stock Analyst. Analyze the data and provide a decision in JSON format. You must respond ONLY with a valid JSON object. @@ -48,13 +62,13 @@ object RagService { .apiKey("unused") .temperature(0.0) // [중요] 0.0으로 설정하여 결정론적 응답 유도 .timeout(Duration.ofSeconds(60)) - .frequencyPenalty(1.1) - .maxTokens(500) // 👈 루프 방지를 위해 반드시 짧게 제한! +// .frequencyPenalty(1.1) + .maxTokens(400) // 👈 루프 방지를 위해 반드시 짧게 제한! // 1.x 버전에서는 responseFormat이 아래처럼 바뀔 수 있으니 체크하세요 .responseFormat("json_object") .build() - private val analyst = dev.langchain4j.service.AiServices.builder(TradingAnalyst::class.java) + private val analyst = AiServices.builder(TradingAnalyst::class.java) .chatModel(chatModel) .build() @@ -139,8 +153,18 @@ object RagService { object JsonSanitizer { fun formatJson(raw: String): String { + // 실제 응답 로그 출력 (디버깅용) + println("📥 [AI Raw Response]:\n$raw") + val regex = Regex("""\{.*\}""", RegexOption.DOT_MATCHES_ALL) - return raw.trim() + val match = regex.find(raw)?.value + + if (match == null) { + println("⚠️ [JsonSanitizer] JSON 형식을 찾을 수 없습니다.") + return "{}" // 빈 객체라도 반환하여 EOF 방지 + } + + return match.trim() .removePrefix("```json") .removePrefix("```") .removeSuffix("```") @@ -264,13 +288,80 @@ object RagService { //// println(response) // return response.aiMessage().text() // } + private const val LLM_API_URL = "http://127.0.0.1:8080/v1/chat/completions" + private suspend fun callLlamaWithSchema(prompt: String): String { + val jsonMediaType = "application/json; charset=utf-8".toMediaType() + + // 문자열 치환 대신 안전한 JSON 객체 빌더 사용 + val requestBodyJson = buildJsonObject { + put("model", "local-model") + put("temperature", 0.1) // 0.1 유지 (결정론적 응답) + put("top_p", 0.9) + put("max_tokens", 500) + + putJsonArray("messages") { + addJsonObject { + put("role", "system") + put("content", "You are a helpful AI financial analyst. You must output responses ONLY in valid JSON format.") + } + addJsonObject { + put("role", "user") + put("content", prompt) + } + } + + // 💡 복잡한 json_schema를 지우고, 단순히 JSON 형식으로만 내보내라고 지시합니다. + putJsonObject("response_format") { + put("type", "json_object") + } + }.toString() + println("requestBodyJson =>> $requestBodyJson") + val request = Request.Builder() + .url(LLM_API_URL) + .post(requestBodyJson.toRequestBody(jsonMediaType)) + .build() + + return kotlinx.coroutines.Dispatchers.IO.let { + kotlinx.coroutines.withContext(it) { + httpClient.newCall(request).execute().use { response -> + if (!response.isSuccessful) throw Exception("LLM API Error: ${response.code} ${response.message}") + + val responseBody = response.body?.string() ?: "{}" + val json = Json.parseToJsonElement(responseBody).jsonObject + json["choices"]?.jsonArray?.get(0)?.jsonObject?.get("message")?.jsonObject?.get("content")?.jsonPrimitive?.content ?: "{}" + } + } + } + } + + private val httpClient = OkHttpClient.Builder() + .connectTimeout(60, TimeUnit.SECONDS) + .readTimeout(120, TimeUnit.SECONDS) + .build() suspend fun decideTrading( stockName: String, scores: InvestmentScores, // 직접 계산한 점수 객체 financialStmt: FinancialStatement, // 매핑된 재무 수치 객체 tempDecision: TradingDecision ): TradingDecision? { + // 💡 1. 뉴스 데이터가 유효한지(100자 이상인지) 확인 + val validNews = tempDecision.newsContext?.takeIf { it.trim().length >= 100 } + + // 💡 2. 동적 데이터 섹션 구성 + val newsDataSection = if (validNews != null) { + "3. News Context: $validNews" + } else { + "3. News Context: None available. Base your decision ONLY on System Scores and Financials." + } + + // 💡 3. 동적 제약 조건 구성 + val newsConstraint = if (validNews != null) { + "- Match Financials with News: If profit is negative but news is hyped, stay CAUTIOUS (HOLD)." + } else { + "- No news data is available. Rely strictly on Financials and System Scores for your 'decision' and 'reason'." + } + val prompt = """ # Task: Senior AI Investment Analyst Analyze the stock '$stockName' and determine the final trading decision based on the data below. @@ -278,51 +369,52 @@ Analyze the stock '$stockName' and determine the final trading decision based on # Data 1. System Scores: Scalping(${scores.ultraShort}), Short(${scores.shortTerm}), Mid(${scores.midTerm}), Long(${scores.longTerm}) 2. Financials: Operating Profit ${if(financialStmt.isOperatingProfitPositive) "PROFIT" else "LOSS"} (Growth: ${"%.2f".format(financialStmt.operatingProfitGrowth)}%), ROE: ${"%.2f".format(financialStmt.roe)}%, Debt: ${"%.2f".format(financialStmt.debtRatio)}% -3. News Context: ${tempDecision.newsContext?.take(400)} // 👈 뉴스 길이를 물리적으로 제한 +$newsDataSection # Constraints -1. 모든 점수와 confidence는 0에서 100 사이의 **정수(Integer)**로만 작성하십시오. +- Copy the exact 'System Scores' from the Data section into the output JSON. - Match Financials with News: If profit is negative but news is hyped, stay CAUTIOUS (HOLD). -- Synchronization: High scalping score + positive news momentum = Higher BUY confidence. -- Output: Response ONLY in valid JSON format. No extra text. +- The "reason" field MUST be written in KOREAN and MUST NOT exceed 50 characters. Keep it concise. +- Output ONLY a valid JSON object matching the exact structure below. DO NOT output placeholder text like '(integer)'. -# Output JSON Format (Reason must be in Korean) +# Example Output JSON Format { - "ultraShortScore": ${scores.ultraShort}, - "shortTermScore": ${scores.shortTerm}, - "midTermScore": ${scores.midTerm}, - "longTermScore": ${scores.longTerm}, - "decision": "BUY/SELL/HOLD", - "reason": "재무와 뉴스를 대조한 분석 결과 (한국어)", - "confidence": 0~100 + "ultraShortScore": 0, + "shortTermScore": 0, + "midTermScore": 0, + "longTermScore": 0, + "decision": "HOLD", + "reason": "적자 지속 및 네수파립 임상 대기 중으로 관망 필요", + "confidence": 50 } """.trimIndent() - val response = chatModel.chat(UserMessage.from(prompt)) - val rawResponse = response.aiMessage().text() - val jsonResponse = JsonSanitizer.formatJson(rawResponse) -// println("📥 [AI Raw JSON]:\n$jsonResponse") - // 2. 유연한 파서 설정 (소수점 및 예외 상황 대응) - val lenientJson = Json { - ignoreUnknownKeys = true - isLenient = true - coerceInputValues = true - } - - - // JSON 파싱 (Kotlinx Serialization 활용) return try { -// println(jsonResponse) - val decision = lenientJson.decodeFromString(jsonResponse) - decision.financialData = tempDecision.financialData - decision.newsContext = tempDecision.newsContext - decision.techSummary = tempDecision.techSummary - decision.stockCode = tempDecision.stockCode - decision.corpName = tempDecision.corpName - decision.stockName = tempDecision.stockName + val rawResponse = callLlamaWithSchema(prompt) + println("📥 [AI Strict JSON]:\n$rawResponse") + + // 엄격한 스키마가 적용되었으므로 JsonSanitizer 없이 바로 파싱 가능 + val lenientJson = Json { + ignoreUnknownKeys = true + isLenient = true + coerceInputValues = true + } + + val decision = lenientJson.decodeFromString(rawResponse) + + // 데이터 매핑 + decision.apply { + financialData = tempDecision.financialData + newsContext = tempDecision.newsContext + techSummary = tempDecision.techSummary + stockCode = tempDecision.stockCode + corpName = tempDecision.corpName + this.stockName = tempDecision.stockName + } + decision - } catch (e: dev.langchain4j.exception.InternalServerException) { + } catch (e: InternalServerException) { // 서버 에러 (컨텍스트 초과 등) 발생 시 로그 남기고 null 반환 혹은 커스텀 에러 처리 println("🚨 [AI Server Error] ${e.message}") if (e.message?.contains("Context size") == true) { diff --git a/src/main/kotlin/service/AutoTradingManager.kt b/src/main/kotlin/service/AutoTradingManager.kt index 47b0ff9..3163582 100644 --- a/src/main/kotlin/service/AutoTradingManager.kt +++ b/src/main/kotlin/service/AutoTradingManager.kt @@ -1,9 +1,8 @@ package service import AutoTradeItem -import TradingDecision +import network.TradingDecision import TradingLogStore -import androidx.compose.runtime.remember import getLlamaBinPath import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -27,11 +26,11 @@ import model.RankingStock import model.RankingType import model.UnifiedBalance import network.DartCodeManager -import network.FinancialMapper import network.FinancialStatement import network.KisAuthService import network.KisTradeService import network.KisWebSocketManager +import network.RagService import network.StockUniverseLoader import util.MarketUtil import java.time.LocalDateTime diff --git a/src/main/kotlin/service/DynamicNewsScraper.kt b/src/main/kotlin/service/DynamicNewsScraper.kt index fc2f228..9d08e50 100644 --- a/src/main/kotlin/service/DynamicNewsScraper.kt +++ b/src/main/kotlin/service/DynamicNewsScraper.kt @@ -2,13 +2,9 @@ package service import com.microsoft.playwright.Browser import com.microsoft.playwright.Playwright -import com.microsoft.playwright.BrowserType import com.microsoft.playwright.Page import com.microsoft.playwright.options.LoadState import com.microsoft.playwright.options.WaitUntilState -import kotlinx.coroutines.TimeoutCancellationException -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.sync.Mutex @@ -18,6 +14,7 @@ import kotlinx.coroutines.sync.withPermit import kotlinx.coroutines.withTimeout import model.NewsItem import network.CorpInfo +import network.RagService import java.net.URL import kotlin.random.Random diff --git a/src/main/kotlin/service/LlamaServerManager.kt b/src/main/kotlin/service/LlamaServerManager.kt index de2cbeb..03c665b 100644 --- a/src/main/kotlin/service/LlamaServerManager.kt +++ b/src/main/kotlin/service/LlamaServerManager.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch +import network.RagService import java.io.BufferedReader import java.io.File import java.io.InputStreamReader @@ -31,7 +32,7 @@ object LlamaServerManager { else -> 0 to 4 // 인텔 맥 2017 등 } - val command = listOf( + val command = mutableListOf( binPath, "-m", modelPath, "--port", port.toString(), @@ -40,7 +41,13 @@ object LlamaServerManager { "-t", threads.toString(), "--embedding" ) - + if (port != 8081) { // 텍스트 생성용 모델에만 적용 + command.addAll(listOf( + "-b", "512", // Batch size (토큰 병렬 처리량 제한으로 연산 안정화) + "--threads-batch", threads.toString(), + "-fa","on" // Flash Attention 활성화 (메모리 절약 및 긴 컨텍스트 연산 안정성 증가) + )) + } scope.launch { try { val pb = ProcessBuilder(command) diff --git a/src/main/kotlin/service/SystemSleepPreventer.kt b/src/main/kotlin/service/SystemSleepPreventer.kt index 8fe960f..1d6da90 100644 --- a/src/main/kotlin/service/SystemSleepPreventer.kt +++ b/src/main/kotlin/service/SystemSleepPreventer.kt @@ -59,18 +59,25 @@ object SystemSleepPreventer { * 맥의 절전 모드 및 디스플레이 취침을 방지하는 명령 실행 */ fun start() { + val os = System.getProperty("os.name").lowercase() + val arch = System.getProperty("os.arch").lowercase() + val isWin = os.contains("win") val root = LoggerFactory.getLogger("Exposed") as Logger root.level = Level.ERROR - checkAndRequestAccessibility() - if (process?.isAlive == true) return + if (!isWin) { + checkAndRequestAccessibility() + } - try { - // -i: 시스템 절전 방지, -d: 디스플레이 취침 방지, -m: 디스크 유휴 상태 방지 - val command = listOf("caffeinate", "-i", "-d", "-m") - process = ProcessBuilder(command).start() - println("☕ [System] caffeinate 실행됨: 앱이 켜져 있는 동안 절전 모드가 방지됩니다.") - } catch (e: Exception) { - println("⚠️ [System] caffeinate 실행 실패: ${e.message}") + if (process?.isAlive == true) return + if (!isWin) { + try { + // -i: 시스템 절전 방지, -d: 디스플레이 취침 방지, -m: 디스크 유휴 상태 방지 + val command = listOf("caffeinate", "-i", "-d", "-m") + process = ProcessBuilder(command).start() + println("☕ [System] caffeinate 실행됨: 앱이 켜져 있는 동안 절전 모드가 방지됩니다.") + } catch (e: Exception) { + println("⚠️ [System] caffeinate 실행 실패: ${e.message}") + } } } diff --git a/src/main/kotlin/ui/DashboardScreen.kt b/src/main/kotlin/ui/DashboardScreen.kt index 7c63aa6..d98d537 100644 --- a/src/main/kotlin/ui/DashboardScreen.kt +++ b/src/main/kotlin/ui/DashboardScreen.kt @@ -2,7 +2,7 @@ package ui import AutoTradeItem -import TradingDecision +import network.TradingDecision import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.grid.GridCells @@ -19,10 +19,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.delay import kotlinx.coroutines.launch import model.CandleData import model.ConfigIndex diff --git a/src/main/kotlin/ui/IntegratedOrderSection.kt b/src/main/kotlin/ui/IntegratedOrderSection.kt index c4c1aad..0980b72 100644 --- a/src/main/kotlin/ui/IntegratedOrderSection.kt +++ b/src/main/kotlin/ui/IntegratedOrderSection.kt @@ -2,7 +2,7 @@ package ui import AutoTradeItem -import TradingDecision +import network.TradingDecision import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape @@ -18,7 +18,6 @@ import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.min import androidx.compose.ui.unit.sp import kotlinx.coroutines.launch import model.ConfigIndex diff --git a/src/main/kotlin/ui/SettingsScreen.kt b/src/main/kotlin/ui/SettingsScreen.kt index 60beeb2..356dc83 100644 --- a/src/main/kotlin/ui/SettingsScreen.kt +++ b/src/main/kotlin/ui/SettingsScreen.kt @@ -128,32 +128,60 @@ fun SettingsScreen(onAuthSuccess: () -> Unit) { Row( modifier = Modifier.fillMaxWidth(), // 필요에 따라 너비 설정 verticalAlignment = Alignment.CenterVertically // 상하 중앙 정렬 추가 - ){ + ) { Box( modifier = Modifier.weight(0.5f).height(60.dp).border(1.dp, Color.Gray, RoundedCornerShape(8.dp)) .onExternalDrag(onDrop = { state -> val data = state.dragData if (data is DragData.FilesList) { - val path = data.readFiles().firstOrNull()?.removePrefix("file:") - if (path?.endsWith(".gguf") == true) config = config.copy(modelPath = path,) + val rawUri = data.readFiles().firstOrNull() + if (rawUri != null) { + // 1. file:// 또는 file: 접두사 제거 + var path = rawUri.removePrefix("file://").removePrefix("file:") + + // 2. 윈도우 환경의 드라이브 문자(예: /C:/) 앞의 슬래시 제거 + if (path.startsWith("/") && path.getOrNull(2) == ':') { + path = path.drop(1) + } + + if (path.endsWith(".gguf")) config = config.copy(modelPath = path) + } } }), contentAlignment = Alignment.Center ) { - Text(if(config.modelPath.isEmpty()) "GGUF 모델 파일을 여기로 드래그하세요" else config.modelPath, fontSize = 12.sp) + Text( + if (config.modelPath.isEmpty()) "GGUF 모델 파일을 여기로 드래그하세요" else config.modelPath, + fontSize = 12.sp + ) } + Box( modifier = Modifier.weight(0.5f).height(60.dp).border(1.dp, Color.Gray, RoundedCornerShape(8.dp)) .onExternalDrag(onDrop = { state -> val data = state.dragData if (data is DragData.FilesList) { - val embedModelPath = data.readFiles().firstOrNull()?.removePrefix("file:") - if (embedModelPath?.endsWith(".gguf") == true) config = config.copy(embedModelPath = embedModelPath,) + val rawUri = data.readFiles().firstOrNull() + if (rawUri != null) { + // 1. file:// 또는 file: 접두사 제거 + var embedModelPath = rawUri.removePrefix("file://").removePrefix("file:") + + // 2. 윈도우 환경의 드라이브 문자(예: /C:/) 앞의 슬래시 제거 + if (embedModelPath.startsWith("/") && embedModelPath.getOrNull(2) == ':') { + embedModelPath = embedModelPath.drop(1) + } + + if (embedModelPath.endsWith(".gguf")) config = + config.copy(embedModelPath = embedModelPath) + } } }), contentAlignment = Alignment.Center ) { - Text(if(config.embedModelPath.isEmpty()) "임베드용 GGUF 모델 파일을 여기로 드래그하세요" else config.embedModelPath, fontSize = 12.sp) + Text( + if (config.embedModelPath.isEmpty()) "임베드용 GGUF 모델 파일을 여기로 드래그하세요" else config.embedModelPath, + fontSize = 12.sp + ) } } Spacer(Modifier.height(10.dp)) diff --git a/src/main/kotlin/ui/StockDetailArea.kt b/src/main/kotlin/ui/StockDetailArea.kt index a6725f2..5042952 100644 --- a/src/main/kotlin/ui/StockDetailArea.kt +++ b/src/main/kotlin/ui/StockDetailArea.kt @@ -2,7 +2,7 @@ package ui -import TradingDecision +import network.TradingDecision import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* diff --git a/src/main/resources/bin/win-x64/ggml-base.dll b/src/main/resources/bin/win-x64/ggml-base.dll index 85c4a14..bc25816 100644 Binary files a/src/main/resources/bin/win-x64/ggml-base.dll and b/src/main/resources/bin/win-x64/ggml-base.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-alderlake.dll b/src/main/resources/bin/win-x64/ggml-cpu-alderlake.dll index 37d892e..36443cf 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-alderlake.dll and b/src/main/resources/bin/win-x64/ggml-cpu-alderlake.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-cannonlake.dll b/src/main/resources/bin/win-x64/ggml-cpu-cannonlake.dll index 069a7fb..3af2d7e 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-cannonlake.dll and b/src/main/resources/bin/win-x64/ggml-cpu-cannonlake.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-cascadelake.dll b/src/main/resources/bin/win-x64/ggml-cpu-cascadelake.dll index 93d9a12..c47795e 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-cascadelake.dll and b/src/main/resources/bin/win-x64/ggml-cpu-cascadelake.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-cooperlake.dll b/src/main/resources/bin/win-x64/ggml-cpu-cooperlake.dll index fd1769c..6ed39c2 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-cooperlake.dll and b/src/main/resources/bin/win-x64/ggml-cpu-cooperlake.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-haswell.dll b/src/main/resources/bin/win-x64/ggml-cpu-haswell.dll index b7b24f9..a372f41 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-haswell.dll and b/src/main/resources/bin/win-x64/ggml-cpu-haswell.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-icelake.dll b/src/main/resources/bin/win-x64/ggml-cpu-icelake.dll index ca43f77..87038c9 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-icelake.dll and b/src/main/resources/bin/win-x64/ggml-cpu-icelake.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-ivybridge.dll b/src/main/resources/bin/win-x64/ggml-cpu-ivybridge.dll index 58cb4dd..6c59eea 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-ivybridge.dll and b/src/main/resources/bin/win-x64/ggml-cpu-ivybridge.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-piledriver.dll b/src/main/resources/bin/win-x64/ggml-cpu-piledriver.dll index 4ee6252..bd5d029 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-piledriver.dll and b/src/main/resources/bin/win-x64/ggml-cpu-piledriver.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-sandybridge.dll b/src/main/resources/bin/win-x64/ggml-cpu-sandybridge.dll index ec00070..24747df 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-sandybridge.dll and b/src/main/resources/bin/win-x64/ggml-cpu-sandybridge.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-sapphirerapids.dll b/src/main/resources/bin/win-x64/ggml-cpu-sapphirerapids.dll index 4df14d6..b739c35 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-sapphirerapids.dll and b/src/main/resources/bin/win-x64/ggml-cpu-sapphirerapids.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-skylakex.dll b/src/main/resources/bin/win-x64/ggml-cpu-skylakex.dll index fb91cf9..f00823a 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-skylakex.dll and b/src/main/resources/bin/win-x64/ggml-cpu-skylakex.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-sse42.dll b/src/main/resources/bin/win-x64/ggml-cpu-sse42.dll index 5560b3d..70cf311 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-sse42.dll and b/src/main/resources/bin/win-x64/ggml-cpu-sse42.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-x64.dll b/src/main/resources/bin/win-x64/ggml-cpu-x64.dll index 6eca703..d726e88 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-x64.dll and b/src/main/resources/bin/win-x64/ggml-cpu-x64.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-cpu-zen4.dll b/src/main/resources/bin/win-x64/ggml-cpu-zen4.dll index a83f6e9..3db75c2 100644 Binary files a/src/main/resources/bin/win-x64/ggml-cpu-zen4.dll and b/src/main/resources/bin/win-x64/ggml-cpu-zen4.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-rpc.dll b/src/main/resources/bin/win-x64/ggml-rpc.dll index 616ed6e..e603011 100644 Binary files a/src/main/resources/bin/win-x64/ggml-rpc.dll and b/src/main/resources/bin/win-x64/ggml-rpc.dll differ diff --git a/src/main/resources/bin/win-x64/ggml-vulkan.dll b/src/main/resources/bin/win-x64/ggml-vulkan.dll index 961b50b..4206a2b 100644 Binary files a/src/main/resources/bin/win-x64/ggml-vulkan.dll and b/src/main/resources/bin/win-x64/ggml-vulkan.dll differ diff --git a/src/main/resources/bin/win-x64/ggml.dll b/src/main/resources/bin/win-x64/ggml.dll index cd07475..7643cc2 100644 Binary files a/src/main/resources/bin/win-x64/ggml.dll and b/src/main/resources/bin/win-x64/ggml.dll differ diff --git a/src/main/resources/bin/win-x64/llama-batched-bench.exe b/src/main/resources/bin/win-x64/llama-batched-bench.exe index 14466a9..54ffce4 100644 Binary files a/src/main/resources/bin/win-x64/llama-batched-bench.exe and b/src/main/resources/bin/win-x64/llama-batched-bench.exe differ diff --git a/src/main/resources/bin/win-x64/llama-bench.exe b/src/main/resources/bin/win-x64/llama-bench.exe index 68c2824..fd2d611 100644 Binary files a/src/main/resources/bin/win-x64/llama-bench.exe and b/src/main/resources/bin/win-x64/llama-bench.exe differ diff --git a/src/main/resources/bin/win-x64/llama-cli.exe b/src/main/resources/bin/win-x64/llama-cli.exe index 6f4f4b2..fa893a3 100644 Binary files a/src/main/resources/bin/win-x64/llama-cli.exe and b/src/main/resources/bin/win-x64/llama-cli.exe differ diff --git a/src/main/resources/bin/win-x64/llama-completion.exe b/src/main/resources/bin/win-x64/llama-completion.exe index d00ac9e..37f756b 100644 Binary files a/src/main/resources/bin/win-x64/llama-completion.exe and b/src/main/resources/bin/win-x64/llama-completion.exe differ diff --git a/src/main/resources/bin/win-x64/llama-fit-params.exe b/src/main/resources/bin/win-x64/llama-fit-params.exe index d290071..71b12e6 100644 Binary files a/src/main/resources/bin/win-x64/llama-fit-params.exe and b/src/main/resources/bin/win-x64/llama-fit-params.exe differ diff --git a/src/main/resources/bin/win-x64/llama-gemma3-cli.exe b/src/main/resources/bin/win-x64/llama-gemma3-cli.exe index 32c4530..8da971c 100644 Binary files a/src/main/resources/bin/win-x64/llama-gemma3-cli.exe and b/src/main/resources/bin/win-x64/llama-gemma3-cli.exe differ diff --git a/src/main/resources/bin/win-x64/llama-gguf-split.exe b/src/main/resources/bin/win-x64/llama-gguf-split.exe index 1638c28..8af12a9 100644 Binary files a/src/main/resources/bin/win-x64/llama-gguf-split.exe and b/src/main/resources/bin/win-x64/llama-gguf-split.exe differ diff --git a/src/main/resources/bin/win-x64/llama-imatrix.exe b/src/main/resources/bin/win-x64/llama-imatrix.exe index 3e9c7ad..6f33123 100644 Binary files a/src/main/resources/bin/win-x64/llama-imatrix.exe and b/src/main/resources/bin/win-x64/llama-imatrix.exe differ diff --git a/src/main/resources/bin/win-x64/llama-llava-cli.exe b/src/main/resources/bin/win-x64/llama-llava-cli.exe index 32c4530..8da971c 100644 Binary files a/src/main/resources/bin/win-x64/llama-llava-cli.exe and b/src/main/resources/bin/win-x64/llama-llava-cli.exe differ diff --git a/src/main/resources/bin/win-x64/llama-minicpmv-cli.exe b/src/main/resources/bin/win-x64/llama-minicpmv-cli.exe index 32c4530..9ca57c9 100644 Binary files a/src/main/resources/bin/win-x64/llama-minicpmv-cli.exe and b/src/main/resources/bin/win-x64/llama-minicpmv-cli.exe differ diff --git a/src/main/resources/bin/win-x64/llama-mtmd-cli.exe b/src/main/resources/bin/win-x64/llama-mtmd-cli.exe index 3080dba..39e0286 100644 Binary files a/src/main/resources/bin/win-x64/llama-mtmd-cli.exe and b/src/main/resources/bin/win-x64/llama-mtmd-cli.exe differ diff --git a/src/main/resources/bin/win-x64/llama-perplexity.exe b/src/main/resources/bin/win-x64/llama-perplexity.exe index 7f49162..67bef46 100644 Binary files a/src/main/resources/bin/win-x64/llama-perplexity.exe and b/src/main/resources/bin/win-x64/llama-perplexity.exe differ diff --git a/src/main/resources/bin/win-x64/llama-quantize.exe b/src/main/resources/bin/win-x64/llama-quantize.exe index 39c2227..c5d5e6f 100644 Binary files a/src/main/resources/bin/win-x64/llama-quantize.exe and b/src/main/resources/bin/win-x64/llama-quantize.exe differ diff --git a/src/main/resources/bin/win-x64/llama-qwen2vl-cli.exe b/src/main/resources/bin/win-x64/llama-qwen2vl-cli.exe index 32c4530..9ca57c9 100644 Binary files a/src/main/resources/bin/win-x64/llama-qwen2vl-cli.exe and b/src/main/resources/bin/win-x64/llama-qwen2vl-cli.exe differ diff --git a/src/main/resources/bin/win-x64/llama-server.exe b/src/main/resources/bin/win-x64/llama-server.exe index 7d09a1e..3f9ddfb 100644 Binary files a/src/main/resources/bin/win-x64/llama-server.exe and b/src/main/resources/bin/win-x64/llama-server.exe differ diff --git a/src/main/resources/bin/win-x64/llama-tokenize.exe b/src/main/resources/bin/win-x64/llama-tokenize.exe index 22a862e..7507139 100644 Binary files a/src/main/resources/bin/win-x64/llama-tokenize.exe and b/src/main/resources/bin/win-x64/llama-tokenize.exe differ diff --git a/src/main/resources/bin/win-x64/llama-tts.exe b/src/main/resources/bin/win-x64/llama-tts.exe index 1533630..e8fccc1 100644 Binary files a/src/main/resources/bin/win-x64/llama-tts.exe and b/src/main/resources/bin/win-x64/llama-tts.exe differ diff --git a/src/main/resources/bin/win-x64/llama.dll b/src/main/resources/bin/win-x64/llama.dll index 7b7b4eb..af73479 100644 Binary files a/src/main/resources/bin/win-x64/llama.dll and b/src/main/resources/bin/win-x64/llama.dll differ diff --git a/src/main/resources/bin/win-x64/mtmd.dll b/src/main/resources/bin/win-x64/mtmd.dll index 7ee674c..9a06292 100644 Binary files a/src/main/resources/bin/win-x64/mtmd.dll and b/src/main/resources/bin/win-x64/mtmd.dll differ diff --git a/src/main/resources/bin/win-x64/rpc-server.exe b/src/main/resources/bin/win-x64/rpc-server.exe index 30d55d5..ec491e1 100644 Binary files a/src/main/resources/bin/win-x64/rpc-server.exe and b/src/main/resources/bin/win-x64/rpc-server.exe differ