From bb51c2d75446ecb9551065d8c618b08d7a26ae78 Mon Sep 17 00:00:00 2001 From: Andrew Charneski Date: Tue, 21 Nov 2023 02:09:31 -0500 Subject: [PATCH] 1.0.36 --- .../skyenet/actors/ActorSystem.kt | 2 +- .../simiacryptus/skyenet/actors/BaseActor.kt | 7 ++-- .../skyenet/actors/CodingActor.kt | 17 +++++---- .../skyenet/actors/ParsedActor.kt | 7 ++-- .../skyenet/actors/SimpleActor.kt | 5 ++- .../actors/record/CodingActorInterceptor.kt | 15 ++++---- .../actors/record/ParsedActorInterceptor.kt | 9 +++-- .../actors/record/SimpleActorInterceptor.kt | 7 ++-- .../skyenet/platform/DataStorage.kt | 2 +- .../simiacryptus/skyenet/platform/Session.kt | 4 +- .../skyenet/platform/UsageManager.kt | 4 +- .../com/simiacryptus/skyenet/platform/User.kt | 26 ++++++++++--- .../skyenet/util/FunctionWrapper.kt | 4 +- .../simiacryptus/skyenet/ApplicationBase.kt | 11 +++--- .../simiacryptus/skyenet/chat/ChatSocket.kt | 6 ++- .../skyenet/servlet/FileServlet.kt | 6 +-- .../skyenet/servlet/NewSessionServlet.kt | 2 +- .../skyenet/servlet/SessionListServlet.kt | 2 +- .../skyenet/servlet/SessionSettingsServlet.kt | 4 +- .../skyenet/servlet/WelcomeServlet.kt | 8 +++- .../skyenet/servlet/ZipServlet.kt | 5 +-- .../skyenet/session/ApplicationInterface.kt | 16 ++++++++ .../session/ApplicationSocketManager.kt | 18 ++------- .../skyenet/test/CodingActorTestApp.kt | 9 ++--- .../skyenet/test/ParsedActorTestApp.kt | 10 ++--- .../skyenet/test/SimpleActorTestApp.kt | 9 ++--- .../skyenet/util/EmbeddingVisualizer.kt | 9 +++-- webui/src/main/resources/codeChat/chat.css | 21 +++++++++- webui/src/main/resources/codeChat/index.html | 4 ++ .../src/main/resources/simpleSession/chat.css | 20 +++++++++- .../main/resources/simpleSession/index.html | 6 ++- webui/src/main/resources/welcome/chat.css | 38 +++++++++++++++++++ 32 files changed, 217 insertions(+), 96 deletions(-) create mode 100644 webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationInterface.kt diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ActorSystem.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ActorSystem.kt index d497f320..a579f63c 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ActorSystem.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ActorSystem.kt @@ -28,6 +28,6 @@ open class ActorSystem>( private val wrapperMap = mutableMapOf() private fun getWrapper(name: String) = wrapperMap.computeIfAbsent(name) { - FunctionWrapper(JsonFunctionRecorder(File(sessionDir, "actors/$name"))) + FunctionWrapper(JsonFunctionRecorder(File(sessionDir, ".sys/actors/$name"))) } } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt index 27af1824..6eb601cd 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/BaseActor.kt @@ -1,5 +1,6 @@ package com.simiacryptus.skyenet.actors +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.models.OpenAIModel import com.simiacryptus.openai.models.ChatModels import com.simiacryptus.openai.OpenAIClient @@ -12,7 +13,8 @@ abstract class BaseActor( val model: OpenAITextModel = ChatModels.GPT35Turbo, val temperature: Double = 0.3, ) { - open fun response(vararg messages: OpenAIClient.ChatMessage, model: OpenAIModel = this.model, api: OpenAIClient) = api.chat( + abstract fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): T + open fun response(vararg messages: OpenAIClient.ChatMessage, model: OpenAIModel = this.model, api: OpenAIAPI) = (api as OpenAIClient).chat( OpenAIClient.ChatRequest( messages = ArrayList(messages.toList()), temperature = temperature, @@ -20,8 +22,7 @@ abstract class BaseActor( ), model = this.model ) - abstract fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): T - open fun answer(vararg questions: String, api: OpenAIClient): T = answer(*chatMessages(*questions), api = api) + open fun answer(vararg questions: String, api: OpenAIAPI): T = answer(*chatMessages(*questions), api = api) open fun chatMessages(vararg questions: String) = arrayOf( OpenAIClient.ChatMessage( diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt index d73c69c0..f8b8e1bf 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt @@ -1,6 +1,7 @@ package com.simiacryptus.skyenet.actors import com.fasterxml.jackson.annotation.JsonIgnore +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.OpenAIClient import com.simiacryptus.openai.OpenAIClientBase.Companion.toContentList import com.simiacryptus.openai.models.ChatModels @@ -66,33 +67,33 @@ open class CodingActor( open val interpreter by lazy { interpreterClass.java.getConstructor(Map::class.java).newInstance(symbols) } - override fun answer(vararg questions: String, api: OpenAIClient): CodeResult = + override fun answer(vararg questions: String, api: OpenAIAPI): CodeResult = if (!autoEvaluate) answer(*chatMessages(*questions), api = api) else answerWithAutoEval(*chatMessages(*questions), api = api).first - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): CodeResult = - if (!autoEvaluate) CodeResultImpl(*messages, api = api) + override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): CodeResult = + if (!autoEvaluate) CodeResultImpl(*messages, api = (api as OpenAIClient)) else answerWithAutoEval(*messages, api = api).first open fun answerWithPrefix( codePrefix: String, vararg messages: OpenAIClient.ChatMessage, - api: OpenAIClient + api: OpenAIAPI ): CodeResult = - if (!autoEvaluate) CodeResultImpl(*injectCodePrefix(messages, codePrefix), api = api) + if (!autoEvaluate) CodeResultImpl(*injectCodePrefix(messages, codePrefix), api = (api as OpenAIClient)) else answerWithAutoEval(*injectCodePrefix(messages, codePrefix), api = api).first open fun answerWithAutoEval( vararg messages: String, - api: OpenAIClient, + api: OpenAIAPI, codePrefix: String = "" ) = answerWithAutoEval(*injectCodePrefix(chatMessages(*messages), codePrefix), api = api) open fun answerWithAutoEval( vararg messages: OpenAIClient.ChatMessage, - api: OpenAIClient + api: OpenAIAPI ): Pair { - var result = CodeResultImpl(*messages, api = api) + var result = CodeResultImpl(*messages, api = (api as OpenAIClient)) var lastError: Throwable? = null for (i in 0..fixIterations) try { return result to result.run() diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedActor.kt index 153646dc..1ac6097b 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedActor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/ParsedActor.kt @@ -1,5 +1,6 @@ package com.simiacryptus.skyenet.actors +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.OpenAIClient import com.simiacryptus.openai.models.ChatModels import com.simiacryptus.openai.models.OpenAITextModel @@ -20,10 +21,10 @@ open class ParsedActor( ) { val resultClass: Class by lazy { parserClass.getMethod("apply", String::class.java).returnType as Class } - private inner class ParsedResponseImpl(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient) : ParsedResponse(resultClass) { + private inner class ParsedResponseImpl(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI) : ParsedResponse(resultClass) { private val parser: Function = ChatProxy( clazz = parserClass, - api = api, + api = (api as OpenAIClient), model = ChatModels.GPT35Turbo, temperature = temperature, ).create() @@ -33,7 +34,7 @@ open class ParsedActor( override fun getObj(clazz: Class): T = _obj } - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): ParsedResponse { + override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): ParsedResponse { return ParsedResponseImpl(*messages, api = api) } } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt index e469e98c..825143a4 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/SimpleActor.kt @@ -1,5 +1,6 @@ package com.simiacryptus.skyenet.actors +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.OpenAIClient import com.simiacryptus.openai.models.ChatModels import com.simiacryptus.openai.models.OpenAITextModel @@ -16,7 +17,7 @@ open class SimpleActor( temperature = temperature, ) { - override fun answer(vararg questions: String, api: OpenAIClient): String = answer(*chatMessages(*questions), api = api) + override fun answer(vararg questions: String, api: OpenAIAPI): String = answer(*chatMessages(*questions), api = api) - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): String = response(*messages, api = api).choices.first().message?.content ?: throw RuntimeException("No response") + override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): String = response(*messages, api = api).choices.first().message?.content ?: throw RuntimeException("No response") } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/CodingActorInterceptor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/CodingActorInterceptor.kt index c0b4da68..ea52e26d 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/CodingActorInterceptor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/CodingActorInterceptor.kt @@ -1,5 +1,6 @@ package com.simiacryptus.skyenet.actors.record +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.OpenAIClient import com.simiacryptus.openai.models.OpenAIModel import com.simiacryptus.skyenet.actors.CodeResult @@ -20,10 +21,10 @@ class CodingActorInterceptor( temperature = inner.temperature, autoEvaluate = inner.autoEvaluate, ) { - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): CodeResult { + override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): CodeResult { return functionInterceptor.wrap(messages.toList().toTypedArray()) { messages: Array -> - CodingResultInterceptor(*messages, api = api, inner = inner.answer(*messages, api = api)) + CodingResultInterceptor(*messages, api = (api as OpenAIClient), inner = inner.answer(*messages, api = api)) } } @@ -41,7 +42,7 @@ class CodingActorInterceptor( override fun response( vararg messages: OpenAIClient.ChatMessage, model: OpenAIModel, - api: OpenAIClient + api: OpenAIAPI ) = functionInterceptor.wrap(messages.toList().toTypedArray(), model) { messages: Array, model: OpenAIModel -> @@ -52,14 +53,14 @@ class CodingActorInterceptor( inner.chatMessages(*it) } - override fun answer(vararg questions: String, api: OpenAIClient) = functionInterceptor.wrap(questions) { + override fun answer(vararg questions: String, api: OpenAIAPI) = functionInterceptor.wrap(questions) { inner.answer(*it, api = api) } override fun answerWithPrefix( codePrefix: String, vararg messages: OpenAIClient.ChatMessage, - api: OpenAIClient + api: OpenAIAPI ) = functionInterceptor.wrap(messages.toList().toTypedArray(), codePrefix) { messages: Array, codePrefix: String -> @@ -68,7 +69,7 @@ class CodingActorInterceptor( override fun answerWithAutoEval( vararg messages: String, - api: OpenAIClient, + api: OpenAIAPI, codePrefix: String ) = functionInterceptor.wrap(messages.toList().toTypedArray(), codePrefix) { messages: Array, @@ -78,7 +79,7 @@ class CodingActorInterceptor( override fun answerWithAutoEval( vararg messages: OpenAIClient.ChatMessage, - api: OpenAIClient + api: OpenAIAPI ) = functionInterceptor.wrap(messages.toList().toTypedArray()) { inner.answerWithAutoEval(*messages, api = api) } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/ParsedActorInterceptor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/ParsedActorInterceptor.kt index 693b8ebc..d3619907 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/ParsedActorInterceptor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/ParsedActorInterceptor.kt @@ -1,5 +1,6 @@ package com.simiacryptus.skyenet.actors.record +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.OpenAIClient import com.simiacryptus.openai.models.OpenAIModel import com.simiacryptus.skyenet.actors.ParsedActor @@ -16,13 +17,13 @@ class ParsedActorInterceptor( model = inner.model, temperature = inner.temperature, ) { - private inner class ParsedResponseInterceptor(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient, private val inner: ParsedResponse) : + private inner class ParsedResponseInterceptor(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI, private val inner: ParsedResponse) : ParsedResponse(this@ParsedActorInterceptor.inner.resultClass) { override fun getText() = functionInterceptor.wrap { inner.getText() } override fun getObj(clazz: Class) = functionInterceptor.intercept(clazz) { inner.getObj(clazz) } // <-- Cannot use 'T' as reified type parameter. Use a class instead. } - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): ParsedResponse { + override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI): ParsedResponse { return functionInterceptor.wrap(messages.toList().toTypedArray()) { messages: Array -> ParsedResponseInterceptor(*messages, api = api, inner = inner.answer(*messages, api = api)) @@ -32,14 +33,14 @@ class ParsedActorInterceptor( override fun response( vararg messages: OpenAIClient.ChatMessage, model: OpenAIModel, - api: OpenAIClient + api: OpenAIAPI ) = functionInterceptor.wrap(messages.toList().toTypedArray(), model) { messages: Array, model: OpenAIModel -> inner.response(*messages, model = model, api = api) } - override fun answer(vararg questions: String, api: OpenAIClient) = functionInterceptor.wrap(questions) { + override fun answer(vararg questions: String, api: OpenAIAPI) = functionInterceptor.wrap(questions) { inner.answer(*it, api = api) } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/SimpleActorInterceptor.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/SimpleActorInterceptor.kt index 02ffdaf3..4e90f18e 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/SimpleActorInterceptor.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/actors/record/SimpleActorInterceptor.kt @@ -1,5 +1,6 @@ package com.simiacryptus.skyenet.actors.record +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.OpenAIClient import com.simiacryptus.openai.models.OpenAIModel import com.simiacryptus.skyenet.actors.SimpleActor @@ -15,7 +16,7 @@ class SimpleActorInterceptor( temperature = inner.temperature, ) { - override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient) = + override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIAPI) = functionInterceptor.wrap(messages.toList().toTypedArray()) { messages: Array -> inner.answer(*messages, api = api) @@ -24,7 +25,7 @@ class SimpleActorInterceptor( override fun response( vararg messages: OpenAIClient.ChatMessage, model: OpenAIModel, - api: OpenAIClient + api: OpenAIAPI ) = functionInterceptor.wrap(messages.toList().toTypedArray(), model) { messages: Array, model: OpenAIModel -> @@ -35,7 +36,7 @@ class SimpleActorInterceptor( inner.chatMessages(*it) } - override fun answer(vararg questions: String, api: OpenAIClient) = functionInterceptor.wrap(questions) { + override fun answer(vararg questions: String, api: OpenAIAPI) = functionInterceptor.wrap(questions) { inner.answer(*it, api = api) } } \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/DataStorage.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/DataStorage.kt index 8e2a8045..e966adf5 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/DataStorage.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/DataStorage.kt @@ -182,7 +182,7 @@ open class DataStorage( return Session("U-$yyyyMMdd-$uuid") } - private const val MESSAGE_DIR = "messages" + private val MESSAGE_DIR = ".sys" + File.separator + "messages" } } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/Session.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/Session.kt index bbff5b49..871f7645 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/Session.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/Session.kt @@ -3,9 +3,11 @@ package com.simiacryptus.skyenet.platform import com.simiacryptus.skyenet.platform.DataStorage.Companion.validateSessionId data class Session( - val sessionId: String + internal val sessionId: String ) { init { validateSessionId(this) } + + override fun toString() = sessionId } \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UsageManager.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UsageManager.kt index 3073eb0c..99c663c5 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UsageManager.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/UsageManager.kt @@ -120,8 +120,8 @@ open class UsageManager { val txLogFileWriter = txLogFileWriter if (null != txLogFileWriter) { synchronized(txLogFile) { - txLogFileWriter.write("$session,$user,${model.modelName},${tokens.prompt_tokens},input\n") - txLogFileWriter.write("$session,$user,${model.modelName},${tokens.completion_tokens},output\n") + txLogFileWriter.write("$session,${user?.email},${model.modelName},${tokens.prompt_tokens},input\n") + txLogFileWriter.write("$session,${user?.email},${model.modelName},${tokens.completion_tokens},output\n") txLogFileWriter.flush() } } diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt index 9b05f1db..1b2d4d8a 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/platform/User.kt @@ -1,8 +1,24 @@ package com.simiacryptus.skyenet.platform data class User( - val email: String, - val id: String? = null, // TODO: Remove default value - val name: String? = null, // TODO: Remove default value - val picture: String? = null, // TODO: Remove default value -) \ No newline at end of file + internal val email: String, + internal val name: String? = null, + internal val id: String? = null, + internal val picture: String? = null, +) { + override fun toString() = email + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as User + + return email == other.email + } + + override fun hashCode(): Int { + return email.hashCode() + } + +} \ No newline at end of file diff --git a/core/src/main/kotlin/com/simiacryptus/skyenet/util/FunctionWrapper.kt b/core/src/main/kotlin/com/simiacryptus/skyenet/util/FunctionWrapper.kt index 4092199a..1bbfe387 100644 --- a/core/src/main/kotlin/com/simiacryptus/skyenet/util/FunctionWrapper.kt +++ b/core/src/main/kotlin/com/simiacryptus/skyenet/util/FunctionWrapper.kt @@ -80,7 +80,9 @@ class JsonFunctionRecorder(baseDir: File) : FunctionInterceptor, Closeable { ) // Get the caller method name from the stack trace (first caller not in internalClassList) val caller = Thread.currentThread().stackTrace - .firstOrNull { !internalClassList.contains(Class.forName(it.className)) } + .filter { !internalClassList.contains(Class.forName(it.className)) } + .filter { it.methodName != "intercept" } + .firstOrNull() val methodName = caller?.methodName ?: "unknown" val file = File(baseDirectory, "$id-$yyyyMMddHHmmss-$methodName") if(file.exists()) { diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationBase.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationBase.kt index b4a9d721..81077f9f 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationBase.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/ApplicationBase.kt @@ -1,8 +1,8 @@ package com.simiacryptus.skyenet +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.skyenet.servlet.AppInfoServlet import com.simiacryptus.skyenet.chat.ChatServer -import com.simiacryptus.skyenet.chat.ChatSocket import com.simiacryptus.skyenet.platform.ApplicationServices.authenticationManager import com.simiacryptus.skyenet.platform.ApplicationServices.authorizationManager import com.simiacryptus.skyenet.platform.ApplicationServices.dataStorageFactory @@ -14,6 +14,7 @@ import com.simiacryptus.skyenet.platform.AuthorizationManager import com.simiacryptus.skyenet.platform.DataStorage import com.simiacryptus.skyenet.platform.Session import com.simiacryptus.skyenet.platform.User +import com.simiacryptus.skyenet.session.ApplicationInterface import com.simiacryptus.skyenet.session.ApplicationSocketManager import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse @@ -50,14 +51,14 @@ abstract class ApplicationBase( userMessage: String, socketManager: ApplicationSocketManager, sessionMessage: SessionMessage, - socket: ChatSocket + api: OpenAIAPI ) = this@ApplicationBase.newSession( session = session, user = user, userMessage = userMessage, socketManager = socketManager.applicationInterface, sessionMessage = sessionMessage, - socket = socket + api = api ) } } @@ -66,9 +67,9 @@ abstract class ApplicationBase( session: Session, user: User?, userMessage: String, - socketManager: ApplicationSocketManager.ApplicationInterface, + socketManager: ApplicationInterface, sessionMessage: SessionMessage, - socket: ChatSocket + api: OpenAIAPI ) open val settingsClass: Class<*> get() = Map::class.java diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatSocket.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatSocket.kt index 5f90f1cc..6b788f45 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatSocket.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/chat/ChatSocket.kt @@ -17,6 +17,8 @@ class ChatSocket( private val user: User?, ) : WebSocketAdapter() { + private val logfile = ".sys/openai.log" + val api: OpenAIClient get() { val user = user @@ -27,7 +29,7 @@ class ChatSocket( return object : OpenAIClient( logLevel = Level.DEBUG, logStreams = mutableListOf( - dataStorage?.getSessionDir(user, session)?.resolve("openai.log")?.outputStream()?.buffered() + dataStorage?.getSessionDir(user, session)?.resolve(logfile)?.outputStream()?.buffered() ).filterNotNull().toMutableList() ) { override fun incrementTokens(model: OpenAIModel?, tokens: Usage) { @@ -46,7 +48,7 @@ class ChatSocket( key = userSettings.apiKey, logLevel = Level.DEBUG, logStreams = mutableListOf( - dataStorage?.getSessionDir(user, session)?.resolve("openai.log")?.outputStream()?.buffered() + dataStorage?.getSessionDir(user, session)?.resolve(logfile)?.outputStream()?.buffered() ).filterNotNull().toMutableList(), ) { override fun incrementTokens(model: OpenAIModel?, tokens: Usage) { diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/FileServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/FileServlet.kt index 6e3a4377..1a763c62 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/FileServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/FileServlet.kt @@ -30,10 +30,10 @@ class FileServlet(val dataStorage: DataStorage) : HttpServlet() { } else { resp.contentType = "text/html" resp.status = HttpServletResponse.SC_OK - val files = file.listFiles()?.filter { it.isFile }?.sortedBy { it.name }?.joinToString("
\n") { + val files = file.listFiles()?.filter { it.isFile && !it.name.startsWith(".") }?.sortedBy { it.name }?.joinToString("
\n") { """${it.name}""" } ?: "" - val folders = file.listFiles()?.filter { !it.isFile }?.sortedBy { it.name }?.joinToString("
\n") { + val folders = file.listFiles()?.filter { !it.isFile && !it.name.startsWith(".") }?.sortedBy { it.name }?.joinToString("
\n") { """${it.name}""" } ?: "" resp.writer.write( @@ -99,7 +99,7 @@ class FileServlet(val dataStorage: DataStorage) : HttpServlet() { | | |

Archive

- |ZIP + |ZIP |

Folders

|
|$folders diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/NewSessionServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/NewSessionServlet.kt index fca7d574..19d86a56 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/NewSessionServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/NewSessionServlet.kt @@ -10,6 +10,6 @@ class NewSessionServlet : HttpServlet() { val sessionId = DataStorage.newGlobalID() resp.contentType = "text/plain" resp.status = HttpServletResponse.SC_OK - resp.writer.write(sessionId.sessionId) + resp.writer.write(sessionId.toString()) } } \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt index ea194a3f..da47032d 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionListServlet.kt @@ -39,7 +39,7 @@ class SessionListServlet( ${sessions.joinToString("") { session -> """ - ${sessionName(req, session)} + ${sessionName(req, session)} """.trimIndent() }} diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionSettingsServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionSettingsServlet.kt index 16f7af32..daf1a631 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionSettingsServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/SessionSettingsServlet.kt @@ -31,7 +31,7 @@ class SessionSettingsServlet( | | |
- | + | | | | @@ -59,7 +59,7 @@ class SessionSettingsServlet( ApplicationServices.authenticationManager.getUser(req.getCookie()), session, "settings.json", settings ) - resp.sendRedirect("${req.contextPath}/#${session.sessionId}") + resp.sendRedirect("${req.contextPath}/#$session") } } } \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/WelcomeServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/WelcomeServlet.kt index 22a4a723..01a1b5a4 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/WelcomeServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/WelcomeServlet.kt @@ -86,9 +86,9 @@ open class WelcomeServlet(private val parent : ApplicationDirectory) : HttpServl ) if (!canRead) return@joinToString "" val newGlobalSessionLink = - if (canRun) """New Shared Session""" else "" + if (canRun) """New Shared Session""" else "" val newUserSessionLink = - if (canRun) """New Private Session""" else "" + if (canRun) """New Private Session""" else "" """ @@ -111,6 +111,10 @@ open class WelcomeServlet(private val parent : ApplicationDirectory) : HttpServl } + + """ diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ZipServlet.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ZipServlet.kt index bbc74440..91dcff6b 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ZipServlet.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/servlet/ZipServlet.kt @@ -42,9 +42,8 @@ class ZipServlet(val dataStorage: DataStorage) : HttpServlet() { zip.write(file.readBytes()) zip.closeEntry() } else { - file.listFiles()?.forEach { - write(basePath, it, zip) - } + file.listFiles()?.filter { !it.name.startsWith(".") } + ?.forEach { write(basePath, it, zip) } } } } \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationInterface.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationInterface.kt new file mode 100644 index 00000000..8c2e49e2 --- /dev/null +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationInterface.kt @@ -0,0 +1,16 @@ +package com.simiacryptus.skyenet.session + +import java.util.function.Consumer + +class ApplicationInterface(private val inner: ApplicationSocketManager) { + fun send(html: String) = inner.send(html) + fun hrefLink(linkText: String, classname: String = """href-link""", handler: Consumer) = + inner.hrefLink(linkText, classname, handler) + + fun textInput(handler: Consumer): String = + inner.textInput(handler) + + fun newMessage(operationID: String, spinner: String, cancelable: Boolean = false): SessionMessage = + inner.newMessage(operationID, spinner, cancelable) + +} \ No newline at end of file diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationSocketManager.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationSocketManager.kt index 8132a893..4dc20b49 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationSocketManager.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/session/ApplicationSocketManager.kt @@ -1,5 +1,6 @@ package com.simiacryptus.skyenet.session +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.skyenet.ApplicationBase import com.simiacryptus.skyenet.chat.ChatSocket import com.simiacryptus.skyenet.platform.DataStorage @@ -26,21 +27,10 @@ abstract class ApplicationSocketManager( val operationID = randomID() val sessionDiv = newMessage(operationID, spinner, true) threads[operationID] = Thread.currentThread() - newSession(session, user = userId, userMessage, this, sessionDiv, socket) + newSession(session, user = userId, userMessage, this, sessionDiv, socket.api) } - inner class ApplicationInterface { - fun send(html: String) = this@ApplicationSocketManager.send(html) - fun hrefLink(linkText: String, classname: String = """href-link""", handler: Consumer) = - this@ApplicationSocketManager.hrefLink(linkText, classname, handler) - fun textInput(handler: Consumer): String = - this@ApplicationSocketManager.textInput(handler) - - fun newMessage(operationID: String, spinner: String, cancelable: Boolean = false): SessionMessage = - this@ApplicationSocketManager.newMessage(operationID, spinner, cancelable) - - } - val applicationInterface by lazy { ApplicationInterface() } + val applicationInterface by lazy { ApplicationInterface(this) } override fun onCmd(id: String, code: String, socket: ChatSocket) { if (code == "cancel") { @@ -76,7 +66,7 @@ abstract class ApplicationSocketManager( userMessage: String, socketManager: ApplicationSocketManager, sessionMessage: SessionMessage, - socket: ChatSocket + api: OpenAIAPI ) companion object { diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/CodingActorTestApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/test/CodingActorTestApp.kt index 6694802a..ef8e9e49 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/CodingActorTestApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/test/CodingActorTestApp.kt @@ -1,9 +1,8 @@ package com.simiacryptus.skyenet.test +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.session.ApplicationSocketManager import com.simiacryptus.skyenet.actors.CodingActor -import com.simiacryptus.skyenet.chat.ChatSocket import com.simiacryptus.skyenet.platform.* import com.simiacryptus.skyenet.session.* import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown @@ -22,12 +21,12 @@ open class CodingActorTestApp( session: Session, user: User?, userMessage: String, - socketManager: ApplicationSocketManager.ApplicationInterface, + socketManager: ApplicationInterface, sessionMessage: SessionMessage, - socket: ChatSocket + api: OpenAIAPI ) { sessionMessage.append("""
${renderMarkdown(userMessage)}
""", true) - val response = actor.answer(userMessage, api = socket.api) + val response = actor.answer(userMessage, api = api) val canPlay = ApplicationServices.authorizationManager.isAuthorized( this::class.java, user, diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/ParsedActorTestApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/test/ParsedActorTestApp.kt index c6f8d018..a21fddd2 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/ParsedActorTestApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/test/ParsedActorTestApp.kt @@ -1,11 +1,11 @@ package com.simiacryptus.skyenet.test +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.session.ApplicationSocketManager import com.simiacryptus.skyenet.actors.ParsedActor -import com.simiacryptus.skyenet.chat.ChatSocket import com.simiacryptus.skyenet.platform.Session import com.simiacryptus.skyenet.platform.User +import com.simiacryptus.skyenet.session.ApplicationInterface import com.simiacryptus.skyenet.session.SessionMessage import com.simiacryptus.skyenet.util.MarkdownUtil.renderMarkdown import com.simiacryptus.util.JsonUtil @@ -23,12 +23,12 @@ open class ParsedActorTestApp( session: Session, user: User?, userMessage: String, - socketManager: ApplicationSocketManager.ApplicationInterface, + socketManager: ApplicationInterface, sessionMessage: SessionMessage, - socket: ChatSocket + api: OpenAIAPI ) { sessionMessage.append("""
${renderMarkdown(userMessage)}
""", true) - val response = actor.answer(userMessage, api = socket.api) + val response = actor.answer(userMessage, api = api) sessionMessage.append( """
${ renderMarkdown( diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/SimpleActorTestApp.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/test/SimpleActorTestApp.kt index 2a16e942..f551ec67 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/test/SimpleActorTestApp.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/test/SimpleActorTestApp.kt @@ -1,9 +1,8 @@ package com.simiacryptus.skyenet.test +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.skyenet.ApplicationBase -import com.simiacryptus.skyenet.session.ApplicationSocketManager import com.simiacryptus.skyenet.actors.SimpleActor -import com.simiacryptus.skyenet.chat.ChatSocket import com.simiacryptus.skyenet.platform.Session import com.simiacryptus.skyenet.platform.User import com.simiacryptus.skyenet.session.* @@ -29,13 +28,13 @@ open class SimpleActorTestApp( session: Session, user: User?, userMessage: String, - socketManager: ApplicationSocketManager.ApplicationInterface, + socketManager: ApplicationInterface, sessionMessage: SessionMessage, - socket: ChatSocket + api: OpenAIAPI ) { val actor = getSettings(session, user)?.actor ?: actor sessionMessage.append("""
${MarkdownUtil.renderMarkdown(userMessage)}
""", true) - val moderatorResponse = actor.answer(userMessage, api = socket.api) + val moderatorResponse = actor.answer(userMessage, api = api) sessionMessage.append("""
${MarkdownUtil.renderMarkdown(moderatorResponse)}
""", false) } diff --git a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/EmbeddingVisualizer.kt b/webui/src/main/kotlin/com/simiacryptus/skyenet/util/EmbeddingVisualizer.kt index c4aa889a..84bf5cc4 100644 --- a/webui/src/main/kotlin/com/simiacryptus/skyenet/util/EmbeddingVisualizer.kt +++ b/webui/src/main/kotlin/com/simiacryptus/skyenet/util/EmbeddingVisualizer.kt @@ -1,26 +1,27 @@ package com.simiacryptus.skyenet.util +import com.simiacryptus.openai.OpenAIAPI import com.simiacryptus.openai.OpenAIClient import com.simiacryptus.openai.models.EmbeddingModels -import com.simiacryptus.skyenet.session.ApplicationSocketManager import com.simiacryptus.skyenet.platform.DataStorage import com.simiacryptus.skyenet.platform.Session import com.simiacryptus.skyenet.platform.User +import com.simiacryptus.skyenet.session.ApplicationInterface import com.simiacryptus.util.JsonUtil class EmbeddingVisualizer( - val api: OpenAIClient, + val api: OpenAIAPI, val dataStorage: DataStorage, val sessionID: Session, val appPath: String, val host: String, - val session: ApplicationSocketManager.ApplicationInterface, + val session: ApplicationInterface, val userId: User?, ) { private fun toVectorMap(vararg words: String): Map { val vectors = words.map {word -> - word to api.createEmbedding( + word to (api as OpenAIClient).createEmbedding( OpenAIClient.EmbeddingRequest( model = EmbeddingModels.AdaEmbedding.modelName, input = word, diff --git a/webui/src/main/resources/codeChat/chat.css b/webui/src/main/resources/codeChat/chat.css index 380271af..1b0486b6 100644 --- a/webui/src/main/resources/codeChat/chat.css +++ b/webui/src/main/resources/codeChat/chat.css @@ -15,8 +15,8 @@ body { color: var(--primary-text-color); background-color: var(--primary-bg-color); margin: 0; - padding: 0; overflow: clip; + padding: 0 0 50px; } #messages { @@ -289,3 +289,22 @@ pre { font-weight: bold; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } + + +#footer { + position: fixed; + bottom: 0; + width: 100%; + text-align: right; + z-index: 1000; +} + +#footer a { + color: darkgray; + text-decoration: none; + font-weight: bold; +} + +#footer a:hover { + text-decoration: underline; +} diff --git a/webui/src/main/resources/codeChat/index.html b/webui/src/main/resources/codeChat/index.html index 7a626dcb..54abcedb 100644 --- a/webui/src/main/resources/codeChat/index.html +++ b/webui/src/main/resources/codeChat/index.html @@ -37,6 +37,10 @@
+ + diff --git a/webui/src/main/resources/simpleSession/chat.css b/webui/src/main/resources/simpleSession/chat.css index 98f9881e..9cfd5154 100644 --- a/webui/src/main/resources/simpleSession/chat.css +++ b/webui/src/main/resources/simpleSession/chat.css @@ -15,7 +15,7 @@ body { color: var(--primary-text-color); background-color: var(--primary-bg-color); margin: 0; - padding: 0; + padding: 0 0 50px; } #messages { @@ -300,3 +300,21 @@ pre.verbose, pre.response-message { margin-top: 20px; margin-bottom: 10px; } + +#footer { + position: fixed; + bottom: 0; + width: 100%; + text-align: right; + z-index: 1000; +} + +#footer a { + color: darkgray; + text-decoration: none; + font-weight: bold; +} + +#footer a:hover { + text-decoration: underline; +} diff --git a/webui/src/main/resources/simpleSession/index.html b/webui/src/main/resources/simpleSession/index.html index f8381a9d..99e4b719 100644 --- a/webui/src/main/resources/simpleSession/index.html +++ b/webui/src/main/resources/simpleSession/index.html @@ -28,7 +28,7 @@ Session Settings Files Usage - Hide Verbose + Show Verbose
@@ -50,6 +50,10 @@
+ + diff --git a/webui/src/main/resources/welcome/chat.css b/webui/src/main/resources/welcome/chat.css index 59411d60..e922a7ec 100644 --- a/webui/src/main/resources/welcome/chat.css +++ b/webui/src/main/resources/welcome/chat.css @@ -1,3 +1,23 @@ +:root { + --primary-bg-color: #f7f7f7; + --secondary-bg-color: #ffffff; + --primary-text-color: #333; + --secondary-text-color: #555; + --link-color: #0066cc; + --link-hover-color: #0044aa; + --border-radius: 4px; + --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + --transition-speed: 0.3s; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + color: var(--primary-text-color); + background-color: var(--primary-bg-color); + margin: 0; + padding: 0 0 50px; +} + #form { position: absolute; left: 0; @@ -132,3 +152,21 @@ pre { text-decoration: none; cursor: pointer; } + +#footer { + position: fixed; + bottom: 0; + width: 100%; + text-align: right; + z-index: 1000; +} + +#footer a { + color: darkgray; + text-decoration: none; + font-weight: bold; +} + +#footer a:hover { + text-decoration: underline; +}