Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: true
matrix:
platform-version: [233, 241 ]
platform-version: [223, 233, 241 ]
env:
ORG_GRADLE_PROJECT_platformVersion: ${{ matrix.platform-version }}

Expand Down
30 changes: 15 additions & 15 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ configure(

testOutput(sourceSets.test.get().output.classesDirs)

if (platformVersion == 223) {
// https://mvnrepository.com/artifact/org.jetbrains/annotations
implementation("org.jetbrains:annotations:26.0.1")
}

intellijPlatform {
testFramework(TestFrameworkType.Bundled)
}
Expand Down Expand Up @@ -408,12 +413,13 @@ project(":core") {
testFramework(TestFrameworkType.Bundled)
}

implementation("com.theokanning.openai-gpt3-java:service:0.18.2")
implementation("com.squareup.okhttp3:okhttp:4.4.1")
implementation("com.squareup.okhttp3:okhttp-sse:4.4.1")
implementation("io.reactivex.rxjava3:rxjava:3.1.10")

implementation("com.squareup.retrofit2:converter-jackson:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:okhttp-sse:4.12.0")

implementation("com.squareup.retrofit2:converter-jackson:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.2")
implementation("com.fasterxml.jackson.core:jackson-databind:2.14.2")

Expand All @@ -424,31 +430,25 @@ project(":core") {

implementation("com.nfeld.jsonpathkt:jsonpathkt:2.0.1")

implementation("org.jetbrains:markdown:0.6.1")
implementation("org.jetbrains:markdown:0.7.3")

// chocolate factory
// follow: https://onnxruntime.ai/docs/get-started/with-java.html
// implementation("com.microsoft.onnxruntime:onnxruntime:1.18.0")
// implementation("ai.djl.huggingface:tokenizers:0.29.0")

implementation("cc.unitmesh:cocoa-core:1.0.0")
implementation("cc.unitmesh:document:1.0.0")
// implementation("cc.unitmesh:document:1.0.0")

// kanban
implementation("org.kohsuke:github-api:1.314")
implementation("org.gitlab4j:gitlab4j-api:5.3.0")
implementation("org.kohsuke:github-api:1.326")
implementation("org.gitlab4j:gitlab4j-api:5.8.0")

// template engine
implementation("org.apache.velocity:velocity-engine-core:2.3")

// http request/response
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.2")

// token count
implementation("com.knuddels:jtokkit:1.0.0")

implementation("org.apache.commons:commons-text:1.12.0")

implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
// junit
testImplementation("io.kotest:kotest-assertions-core:5.7.2")
Expand Down
12 changes: 1 addition & 11 deletions core/src/main/kotlin/cc/unitmesh/devti/llms/LlmFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ package cc.unitmesh.devti.llms

import cc.unitmesh.devti.llms.custom.CustomLLMProvider
import cc.unitmesh.devti.llms.custom.InlayCustomLLMProvider
import cc.unitmesh.devti.llms.openai.OpenAIProvider
import cc.unitmesh.devti.settings.AIEngines
import cc.unitmesh.devti.settings.AutoDevSettingsState
import cc.unitmesh.devti.settings.coder.AutoDevCoderSettingService
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
Expand All @@ -13,15 +10,8 @@ import com.intellij.openapi.project.Project

@Service
class LlmFactory {
private val aiEngine: AIEngines
get() = AIEngines.values()
.find { it.name.lowercase() == AutoDevSettingsState.getInstance().aiEngine.lowercase() } ?: AIEngines.OpenAI

fun create(project: Project): LLMProvider {
return when (aiEngine) {
AIEngines.OpenAI -> project.getService(OpenAIProvider::class.java)
AIEngines.Custom -> project.getService(CustomLLMProvider::class.java)
}
return project.getService(CustomLLMProvider::class.java)
}

fun createForInlayCodeComplete(project: Project): LLMProvider {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,15 @@ class CustomLLMProvider(val project: Project) : LLMProvider, CustomSSEProcessor(
private val url get() = autoDevSettingsState.customEngineServer
private val key get() = autoDevSettingsState.customEngineToken

override val requestFormat: String get() = autoDevSettingsState.customEngineRequestFormat
override val responseFormat get() = autoDevSettingsState.customEngineResponseFormat
private val modelName: String
get() = AutoDevSettingsState.getInstance().customModel

override val requestFormat: String get() = autoDevSettingsState.customEngineRequestFormat.ifEmpty {
"""{ "customFields": {"model": "$modelName", "temperature": 0.0, "stream": true} }"""
}
override val responseFormat get() = autoDevSettingsState.customEngineResponseFormat.ifEmpty {
"\$.choices[0].delta.content"
}

private var client = OkHttpClient()
private val timeout = Duration.ofSeconds(defaultTimeout)
Expand Down Expand Up @@ -69,11 +76,7 @@ class CustomLLMProvider(val project: Project) : LLMProvider, CustomSSEProcessor(
clearMessage()
}

return if (autoDevSettingsState.customEngineResponseType == ResponseType.SSE.name) {
streamSSE(call, promptText, keepHistory, messages)
} else {
streamJson(call, promptText, messages)
}
return streamSSE(call, promptText, keepHistory, messages)
}

fun prompt(instruction: String, input: String): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.nfeld.jsonpathkt.JsonPath
import com.nfeld.jsonpathkt.extension.read
import com.theokanning.openai.completion.chat.ChatCompletionResult
import com.theokanning.openai.service.SSE
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.FlowableEmitter
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.FlowableEmitter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
Expand Down
46 changes: 46 additions & 0 deletions core/src/main/kotlin/cc/unitmesh/devti/llms/custom/OpenAIDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cc.unitmesh.devti.llms.custom

import com.fasterxml.jackson.annotation.JsonAlias
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.JsonNode

data class ChatFunctionCall(
val name: String? = null,
val arguments: JsonNode? = null,
)

data class ChatMessage(
val role: String,
@JsonInclude
val content: String? = null,
val name: String? = null,
@JsonProperty("function_call")
val functionCall: ChatFunctionCall? = null,
)

data class ChatCompletionChoice(
val index: Int? = null,
@JsonAlias("delta")
val message: ChatMessage? = null,
@JsonProperty("finish_reason")
val finishReason: String? = null,
)

data class Usage(
@JsonProperty("prompt_tokens")
val promptTokens: Long = 0,
@JsonProperty("completion_tokens")
val completionTokens: Long = 0,
@JsonProperty("total_tokens")
val totalTokens: Long = 0,
)

data class ChatCompletionResult(
val id: String? = null,
val `object`: String? = null,
val created: Long = 0,
val model: String? = null,
val choices: List<ChatCompletionChoice>,
val usage: Usage? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
package cc.unitmesh.devti.llms.custom

import com.intellij.openapi.diagnostic.logger
import com.theokanning.openai.service.OpenAiService
import com.theokanning.openai.service.SSE
import com.theokanning.openai.service.SSEFormatException
import io.reactivex.FlowableEmitter
import io.reactivex.rxjava3.core.FlowableEmitter
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
Expand Down Expand Up @@ -85,7 +82,7 @@ class ResponseBodyCallback(private val emitter: FlowableEmitter<SSE>, private va
val eventName = line!!.substring(6).trim { it <= ' ' }
if (eventName == "ping") {
// skip ping event and data
emitter.onNext(sse)
emitter.onNext(sse!!)
emitter.onNext(sse)
}

Expand All @@ -111,7 +108,7 @@ class ResponseBodyCallback(private val emitter: FlowableEmitter<SSE>, private va
}

else -> {
throw SSEFormatException("Invalid sse format! '$line'")
throw AutoDevHttpException("Invalid sse format! '$line'", response.code)
}
}
}
Expand All @@ -137,8 +134,4 @@ class ResponseBodyCallback(private val emitter: FlowableEmitter<SSE>, private va
override fun onFailure(call: Call, e: IOException) {
emitter.onError(e)
}

companion object {
private val mapper = OpenAiService.defaultObjectMapper()
}
}
14 changes: 14 additions & 0 deletions core/src/main/kotlin/cc/unitmesh/devti/llms/custom/SSE.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cc.unitmesh.devti.llms.custom

class SSE(val data: String) {
fun toBytes(): ByteArray {
return String.format("data: %s\n\n", this.data).toByteArray()
}

val isDone: Boolean
get() = DONE_DATA.equals(this.data, ignoreCase = true)

companion object {
private const val DONE_DATA = "[DONE]"
}
}
Loading