Skip to content

Commit

Permalink
1.0.34 (#38)
Browse files Browse the repository at this point in the history
* recording
* fixed prism, moved platform
* added code chat
* Input ui enhancements
* Fixes for CodingActor
  • Loading branch information
acharneski authored Nov 19, 2023
1 parent 0558081 commit aa1078b
Show file tree
Hide file tree
Showing 62 changed files with 1,219 additions and 619 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,18 @@ Maven:
<dependency>
<groupId>com.simiacryptus</groupId>
<artifactId>skyenet-webui</artifactId>
<version>1.0.33</version>
<version>1.0.34</version>
</dependency>
```

Gradle:

```groovy
implementation group: 'com.simiacryptus', name: 'skyenet', version: '1.0.33'
implementation group: 'com.simiacryptus', name: 'skyenet', version: '1.0.34'
```

```kotlin
implementation("com.simiacryptus:skyenet:1.0.33")
implementation("com.simiacryptus:skyenet:1.0.34")
```

### 🌟 To Use
Expand Down
2 changes: 1 addition & 1 deletion core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ val logback_version = "1.4.11"

dependencies {

implementation(group = "com.simiacryptus", name = "joe-penai", version = "1.0.31")
implementation(group = "com.simiacryptus", name = "joe-penai", version = "1.0.32")

implementation(group = "org.slf4j", name = "slf4j-api", version = "2.0.9")
implementation(group = "commons-io", name = "commons-io", version = "2.15.0")
Expand Down
5 changes: 2 additions & 3 deletions core/src/main/kotlin/com/simiacryptus/skyenet/Brain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

package com.simiacryptus.skyenet

import com.simiacryptus.openai.models.OpenAIModel
import com.simiacryptus.openai.models.ChatModels
import com.simiacryptus.openai.OpenAIClient
import com.simiacryptus.openai.OpenAIClient.*
Expand Down Expand Up @@ -118,8 +117,8 @@ open class Brain(
}

companion object {
val log = org.slf4j.LoggerFactory.getLogger(Brain::class.java)
fun String.indent() = this.replace("\n", "\n ")
private val log = org.slf4j.LoggerFactory.getLogger(Brain::class.java)
fun String.indent(indent: String = " ") = this.replace("\n", "\n$indent")
fun joinYamlList(typeDescriptions: List<String>) = typeDescriptions.joinToString("\n") {
"- " + it.indent()
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/kotlin/com/simiacryptus/skyenet/Ears.kt
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ open class Ears(
private fun timeout(count: Long, timeUnit: TimeUnit): () -> Boolean = timeout(timeUnit.toMillis(count))

companion object {
val log = LoggerFactory.getLogger(Ears::class.java)
private val log = LoggerFactory.getLogger(Ears::class.java)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.simiacryptus.skyenet.actors

import com.simiacryptus.skyenet.actors.record.*
import com.simiacryptus.skyenet.platform.DataStorage
import com.simiacryptus.skyenet.util.FunctionWrapper
import com.simiacryptus.skyenet.util.JsonFunctionRecorder
import java.io.File

open class ActorSystem<T:Enum<*>>(
private val actors: Map<T, BaseActor<*>>,
private val dataStorage: DataStorage,
val userId: String?,
val sessionId: String
) {
val sessionDir = dataStorage.getSessionDir(userId, sessionId)
fun getActor(actor: T): BaseActor<*> {
val wrapper = FunctionWrapper(JsonFunctionRecorder(File(sessionDir, "${actor.name}.json")))
return when (val baseActor = actors[actor]) {
null -> throw RuntimeException("No actor for $actor")
is SimpleActor -> RecordingSimpleActor(baseActor, wrapper)
is ParsedActor<*> -> RecordingParsedActor(baseActor, wrapper)
is CodingActor -> RecordingCodingActor(baseActor, wrapper)
else -> throw RuntimeException("Unknown actor type: ${baseActor.javaClass}")
}
}
}
165 changes: 85 additions & 80 deletions core/src/main/kotlin/com/simiacryptus/skyenet/actors/CodingActor.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
package com.simiacryptus.skyenet.actors

import com.simiacryptus.openai.models.OpenAIModel
import com.simiacryptus.openai.models.ChatModels
import com.simiacryptus.openai.OpenAIClient
import com.simiacryptus.openai.OpenAIClientBase.Companion.toContentList
import com.simiacryptus.openai.models.ChatModels
import com.simiacryptus.openai.models.OpenAITextModel
import com.simiacryptus.skyenet.Brain
import com.simiacryptus.skyenet.Brain.Companion.indent
import com.simiacryptus.skyenet.Brain.Companion.superMethod
import com.simiacryptus.skyenet.Heart
import com.simiacryptus.skyenet.OutputInterceptor
import com.simiacryptus.util.describe.AbbrevWhitelistYamlDescriber
import java.lang.reflect.Modifier
import com.simiacryptus.util.describe.TypeDescriber
import kotlin.reflect.KClass

@Suppress("unused", "MemberVisibilityCanBePrivate")
open class CodingActor(
private val interpreterClass: KClass<out Heart>,
private val symbols: Map<String, Any> = mapOf(),
private val describer: AbbrevWhitelistYamlDescriber = AbbrevWhitelistYamlDescriber(
val interpreterClass: KClass<out Heart>,
val symbols: Map<String, Any> = mapOf(),
val describer: TypeDescriber = AbbrevWhitelistYamlDescriber(
"com.simiacryptus",
"com.github.simiacryptus"
),
Expand All @@ -26,6 +25,7 @@ open class CodingActor(
model: OpenAITextModel = ChatModels.GPT35Turbo,
val fallbackModel: OpenAITextModel = ChatModels.GPT4Turbo,
temperature: Double = 0.1,
val autoEvaluate: Boolean = false,
) : BaseActor<CodeResult>(
prompt = "",
name = name,
Expand All @@ -36,101 +36,106 @@ open class CodingActor(
val fixRetries = 2

override val prompt: String
get() {
val types = ArrayList<Class<*>>()
val apiobjs = symbols.map { (name, utilityObj) ->
val clazz = Class.forName(utilityObj.javaClass.typeName)
val methods = clazz.methods
.filter { Modifier.isPublic(it.modifiers) }
.filter { it.declaringClass == clazz }
.filter { !it.isSynthetic }
.map { it.superMethod() ?: it }
.filter { it.declaringClass != Object::class.java }
types.addAll(methods.flatMap { (listOf(it.returnType) + it.parameters.map { it.type }).filter { it != clazz } })
types.addAll(clazz.declaredClasses.filter { Modifier.isPublic(it.modifiers) })
"""
|$name:
| operations:
| ${Brain.joinYamlList(methods.map { describer.describe(it) }).indent().indent()}
|""".trimMargin().trim()
}.toTypedArray<String>()
val typeDescriptions = types
.filter { !it.isPrimitive }
.filter { !it.isSynthetic }
.filter { !it.name.startsWith("java.") }
.filter { !setOf("void").contains(it.name) }
.distinct().map {
"""
|${it.simpleName}:
| ${describer.describe(it).indent()}
""".trimMargin().trim()
}.toTypedArray<String>()
val apiDescription = """
|api_objects:
| ${apiobjs.joinToString("\n").indent()}
|components:
| schemas:
| ${typeDescriptions.joinToString("\n").indent().indent()}
""".trimMargin()
return """
|You will translate natural language instructions into
|an implementation using ${interpreter.getLanguage()} and the script context.
|Use ``` code blocks labeled with ${interpreter.getLanguage()} where appropriate.
|Defined symbols include ${symbols.keys.joinToString(", ")}.
|The runtime context is described below:
|
|$apiDescription
|
|${details ?: ""}
|""".trimMargin().trim()
get() = if (symbols.isNotEmpty()) """
|You will translate natural language instructions into
|an implementation using ${interpreter.getLanguage()} and the script context.
|Use ``` code blocks labeled with ${interpreter.getLanguage()} where appropriate.
|Defined symbols include ${symbols.keys.joinToString(", ")}.
|The runtime context is described below:
|
|${this.apiDescription}
|
|${details ?: ""}
|""".trimMargin().trim()
else """
|You will translate natural language instructions into
|an implementation using ${interpreter.getLanguage()} and the script context.
|Use ``` code blocks labeled with ${interpreter.getLanguage()} where appropriate.
|
|${details ?: ""}
|""".trimMargin().trim()

}
open val apiDescription: String
get() = this.symbols.map { (name, utilityObj) ->
"""
|$name:
| ${this.describer.describe(utilityObj.javaClass).indent(" ")}
|""".trimMargin().trim()
}.joinToString("\n")

open val interpreter by lazy { interpreterClass.java.getConstructor(Map::class.java).newInstance(symbols) }

override fun answer(vararg questions: String, api: OpenAIClient): CodeResult =
answer(*chatMessages(*questions), api = api)

override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): CodeResult {
return CodeResultImpl(*messages, api = api)
}
if (!autoEvaluate) answer(*chatMessages(*questions), api = api)
else answerWithAutoEval(*chatMessages(*questions), api = api).first

fun answerWithPrefix(codePrefix: String, vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): CodeResult {
val prevList = messages.toList()
val newList = prevList.dropLast(1) + listOf(
OpenAIClient.ChatMessage(OpenAIClient.Role.assistant, codePrefix.toContentList())
) + prevList.last()
return CodeResultImpl(*newList.toTypedArray(), api = api)
}
override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): CodeResult =
if (!autoEvaluate) CodeResultImpl(*messages, api = api)
else answerWithAutoEval(*messages, api = api).first

fun answerWithAutoEval(
open fun answerWithPrefix(
codePrefix: String,
vararg messages: OpenAIClient.ChatMessage,
api: OpenAIClient
): CodeResult =
if (!autoEvaluate) CodeResultImpl(*injectCodePrefix(messages, codePrefix), api = api)
else answerWithAutoEval(*injectCodePrefix(messages, codePrefix), api = api).first

open fun answerWithAutoEval(
vararg messages: String,
api: OpenAIClient,
codePrefix: String = ""
) = answerWithAutoEval(*injectCodePrefix(chatMessages(*messages), codePrefix), api = api)

open fun answerWithAutoEval(
vararg messages: OpenAIClient.ChatMessage,
api: OpenAIClient
): Pair<CodeResult, ExecutionResult> {
val prevList = messages.toList()
val messagesWithPrefix = prevList.dropLast(1) + if(codePrefix.isBlank()) listOf() else listOf(
OpenAIClient.ChatMessage(OpenAIClient.Role.assistant, codePrefix.toContentList())
) + prevList.last()
var result = CodeResultImpl(*messagesWithPrefix.toTypedArray(), api = api)
var result = CodeResultImpl(*messages, api = api)
var lastError: Throwable? = null
for (i in 0..fixIterations) try {
return result to result.run()
} catch (ex: Throwable) {
result = fix(api, messagesWithPrefix, result, ex)
lastError = ex
result = fix(api, messages, result, ex)
}
throw RuntimeException("Failed to fix ${messages.map { it.content }.joinToString("\n")}")
throw RuntimeException(
"""
|Failed to fix code. Last attempt:
|```${interpreter.getLanguage().lowercase()}
|${result.getCode()}
|```
|
|Last Error:
|```
|${lastError?.message}
|```
|""".trimMargin().trim()
)
}

private fun fix(api: OpenAIClient, messages: List<OpenAIClient.ChatMessage>, result: CodingActor.CodeResultImpl, ex: Throwable): CodingActor.CodeResultImpl {
val respondWithCode = brain(api, model).fixCommand(result.getCode(), ex, "", *messages.toTypedArray())
private fun injectCodePrefix(
messages: Array<out OpenAIClient.ChatMessage>,
codePrefix: String
) = (messages.dropLast(1) + if (codePrefix.isBlank()) listOf() else listOf(
OpenAIClient.ChatMessage(OpenAIClient.Role.assistant, codePrefix.toContentList())
) + messages.last()).toTypedArray()

private fun fix(
api: OpenAIClient,
messages: Array<out OpenAIClient.ChatMessage>,
result: CodingActor.CodeResultImpl,
ex: Throwable
): CodingActor.CodeResultImpl {
val respondWithCode = brain(api, model).fixCommand(result.getCode(), ex, "", *messages)
val renderedResponse = getRenderedResponse(respondWithCode.second)
val codedInstruction = getCode(interpreter.getLanguage(), respondWithCode.second)
log.info("Response: \n\t${renderedResponse.replace("\n", "\n\t", false)}".trimMargin())
log.info("Code: \n\t${codedInstruction.replace("\n", "\n\t", false)}".trimMargin())
return CodeResultImpl(*messages.toTypedArray(), codePrefix = codedInstruction, api = api)
return CodeResultImpl(*messages, codePrefix = codedInstruction, api = api)
}

fun brain(api: OpenAIClient, model: OpenAITextModel) = Brain(
private fun brain(api: OpenAIClient, model: OpenAITextModel) = Brain(
api = api,
symbols = symbols.mapValues { it as Object }.asJava,
language = interpreter.getLanguage(),
Expand Down Expand Up @@ -232,7 +237,7 @@ open class CodingActor(
}

companion object {
val log = org.slf4j.LoggerFactory.getLogger(CodingActor::class.java)
private val log = org.slf4j.LoggerFactory.getLogger(CodingActor::class.java)
fun errorMessage(
code: String,
line: Int,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package com.simiacryptus.skyenet.actors

import com.simiacryptus.openai.models.OpenAIModel
import com.simiacryptus.openai.models.ChatModels
import com.simiacryptus.openai.OpenAIClient
import com.simiacryptus.openai.models.ChatModels
import com.simiacryptus.openai.models.OpenAITextModel
import com.simiacryptus.openai.proxy.ChatProxy
import java.util.function.Function

open class ParsedActor<T>(
open class ParsedActor<T:Any>(
val parserClass: Class<out Function<String, T>>,
prompt: String,
val action: String? = null,
Expand All @@ -19,7 +18,9 @@ open class ParsedActor<T>(
model = model,
temperature = temperature,
) {
private inner class ParsedResponseImpl(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient) : ParsedResponse<T> {
val resultClass: Class<T> by lazy { parserClass.getMethod("apply", String::class.java).returnType as Class<T> }

private inner class ParsedResponseImpl(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient) : ParsedResponse<T>(resultClass) {
val parser: Function<String, T> = ChatProxy(
clazz = parserClass,
api = api,
Expand All @@ -29,11 +30,10 @@ open class ParsedActor<T>(
private val _text: String by lazy { response(*messages, api = api).choices.first().message?.content ?: throw RuntimeException("No response") }
private val _obj: T by lazy { parser.apply(getText()) }
override fun getText(): String = _text
override fun getObj(): T = _obj
override fun getObj(clazz: Class<T>): T = _obj
}

override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): ParsedResponse<T> {
return ParsedResponseImpl(*messages, api = api)
}
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.simiacryptus.skyenet.actors

interface ParsedResponse<T> {
fun getText(): String
fun getObj(): T
abstract class ParsedResponse<T>(val clazz: Class<T>) {
abstract fun getText(): String
abstract fun getObj(clazz: Class<T>): T
fun getObj(): T = getObj(clazz)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ open class SimpleActor(

override fun answer(vararg messages: OpenAIClient.ChatMessage, api: OpenAIClient): String = response(*messages, api = api).choices.first().message?.content ?: throw RuntimeException("No response")
}

Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ open class ActorOptimization(
).create()

companion object {
val log = LoggerFactory.getLogger(ActorOptimization::class.java)
private val log = LoggerFactory.getLogger(ActorOptimization::class.java)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory

abstract class Expectation {
companion object {
val log = LoggerFactory.getLogger(Expectation::class.java)
private val log = LoggerFactory.getLogger(Expectation::class.java)
}

open class VectorMatch(val example: String, private val metric: DistanceType = DistanceType.Cosine) : Expectation() {
Expand Down
Loading

0 comments on commit aa1078b

Please sign in to comment.