Skip to content

Commit

Permalink
Merge pull request #13 from mloncode/renewed-client-api
Browse files Browse the repository at this point in the history
New api version for plugin
  • Loading branch information
bzz authored Sep 15, 2023
2 parents ff0c1ca + 48134d1 commit 466ded3
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 35 deletions.
21 changes: 11 additions & 10 deletions src/main/kotlin/OSSLLMCompletionProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,29 @@ import com.github.bzz.intellij.requests.Requester
import com.intellij.codeInsight.inline.completion.InlineCompletionElement
import com.intellij.codeInsight.inline.completion.InlineCompletionProvider
import com.intellij.codeInsight.inline.completion.InlineCompletionRequest
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.event.DocumentEvent
import org.jetbrains.annotations.ApiStatus

@ApiStatus.Experimental
class OSSLLMCompletionProvider : InlineCompletionProvider {

override suspend fun getProposals(request: InlineCompletionRequest): List<InlineCompletionElement> {
private val logger = Logger.getInstance("(when autocompleting)")

override suspend fun getProposals(request: InlineCompletionRequest): List<InlineCompletionElement> =
try {
val caretPosition = request.startOffset
val proposal = Requester.getModelSuggestions(
val proposals = Requester.getModelSuggestions(
request.document.text.substring(0, caretPosition)
).text ?: return emptyList()
return listOf(InlineCompletionElement(proposal))
)
proposals.results.map { InlineCompletionElement(it.text) }
} catch (knownException: Requester.RequesterException) {
thisLogger().warn(knownException.message)
return emptyList()
logger.warn(knownException.message)
emptyList()
} catch (exception: Exception) {
thisLogger().warn("Unknown exception. Message: ${exception.message}")
return emptyList()
logger.warn("Unknown exception. Message: ${exception.message}")
emptyList()
}
}

override fun isEnabled(event: DocumentEvent): Boolean {
return true
Expand Down
7 changes: 5 additions & 2 deletions src/main/kotlin/com/github/bzz/intellij/actions/TestAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class TestAction: AnAction() {

val editor = event.getRequiredData(CommonDataKeys.EDITOR)
val caretPosition = editor.caretModel.primaryCaret.selectionStart
logger.warn(Requester.getModelSuggestions(editor.document.text).text?.substring(0, caretPosition))
logger.warn(
Requester.getModelSuggestions(editor.document.text.substring(0, caretPosition)).
results.firstOrNull()?.text ?: "---"
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
package com.github.bzz.intellij.com.github.bzz.intellij.models

import com.github.bzz.intellij.requests.Requester
import com.intellij.openapi.diagnostic.Logger
import java.util.concurrent.atomic.AtomicInteger


object AvailableModels {

val currentModelIndex = AtomicInteger(0)

val modelsList: List<String> = listOf("proxy-model", "other proxy-model")
private val logger = Logger.getInstance("(getting available models)")

private fun getAvailableModels(): List<String> =
try {
Requester.getAvailableModels().models.map { it.modelName }
} catch (knownException: Requester.RequesterException) {
logger.warn(knownException.message)
emptyList()
} catch (otherException: Requester.RequesterException) {
logger.warn("Unknown exception. Message: ${otherException.message}")
emptyList()
}

val modelsList: List<String> = getAvailableModels()

fun currentModel() : String? {
return modelsList.getOrNull(currentModelIndex.get())
}
}
34 changes: 34 additions & 0 deletions src/main/kotlin/com/github/bzz/intellij/requests/JsonData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.bzz.intellij.com.github.bzz.intellij.requests

import com.google.gson.annotations.SerializedName
import kotlinx.serialization.Serializable


@Serializable
data class ServerProposal (
val text: String
)

@Serializable
data class ProposalsResponse (
val results: List<ServerProposal>
)

@Serializable
data class LLMModel (
@SerializedName("model_name")
val modelName: String
)

@Serializable
data class ModelsResponse(
val models: List<LLMModel>
)

@Serializable
data class ProposalsQuery(
val model: String,
val prompt: String,
@SerializedName("max_new_tokens")
val maxNewTokens: Int
)
55 changes: 41 additions & 14 deletions src/main/kotlin/com/github/bzz/intellij/requests/Requester.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.github.bzz.intellij.requests

import com.github.bzz.intellij.com.github.bzz.intellij.requests.ServerResponse
import com.github.bzz.intellij.com.github.bzz.intellij.models.AvailableModels
import com.github.bzz.intellij.com.github.bzz.intellij.requests.ModelsResponse
import com.github.bzz.intellij.com.github.bzz.intellij.requests.ProposalsQuery
import com.github.bzz.intellij.com.github.bzz.intellij.requests.ProposalsResponse
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import java.io.IOException
import java.net.URI
import java.net.http.HttpClient
Expand All @@ -11,30 +15,56 @@ import java.net.http.HttpTimeoutException


object Requester {

const val MAX_TOKEN_LENGTH = 10
open class RequesterException(message: String): RuntimeException("RequesterException: $message")

private class NoListenerRequesterException(ip: String, port: Int):
RequesterException("Probable cause: server $ip is not running or listening at port $port.")

private class TimeoutRequesterException():
RequesterException("Probable cause: new model is being downloaded currently.")
private class TimeoutRequesterException:
RequesterException("Probable cause: poor connection.")

private class GeneralRequesterException(ip: String, port: Int, httpStatus: Int):
RequesterException("HTTP Request to $ip:$port failed. Failure status code: $httpStatus")

private class LocationMissingException(ip: String):
RequesterException("Redirect response from $ip is missing Location header")
private class JsonRequesterException(ip: String, port: Int, answer: String?):
RequesterException("Response from $ip:$port has incompatible json: $answer")

private class NoLoadedLLMException:
RequesterException("No LLM is chosen due to the absence of any.")


private val client = HttpClient.newBuilder().build()

fun getModelSuggestions(context: String, ip: String = "localhost", port: Int = 8000): ServerResponse {
fun getAvailableModels(ip: String = "localhost", port: Int = 8000): ModelsResponse {
val request = HttpRequest.newBuilder()
.uri(URI.create("http://$ip:$port"))
.GET()
.timeout(java.time.Duration.ofSeconds(10))
.build()

return serverQuery(ip, port, request, ModelsResponse::class.java)
}

fun getModelSuggestions(context: String, ip: String = "localhost", port: Int = 8000): ProposalsResponse {
val queryParams = ProposalsQuery(
model = AvailableModels.currentModel() ?: throw NoLoadedLLMException(),
prompt = context,
maxNewTokens = MAX_TOKEN_LENGTH
)
val json = Gson().toJson(queryParams)
val request = HttpRequest.newBuilder()
.uri(URI.create("http://$ip:$port"))
.POST(HttpRequest.BodyPublishers.ofString(context))
.POST(HttpRequest.BodyPublishers.ofString(json))
.header("Content-type", "application/json")
.timeout(java.time.Duration.ofSeconds(10))
.build()

return serverQuery(ip, port, request, ProposalsResponse::class.java)
}

private fun <T> serverQuery(ip: String, port: Int, request: HttpRequest, serializableClass: Class<T>): T {
val response = try {
client.send(request, HttpResponse.BodyHandlers.ofString())
} catch(toe: HttpTimeoutException) {
Expand All @@ -44,13 +74,10 @@ object Requester {
}

return when (response.statusCode()) {
200 -> Gson().fromJson(response.body(), ServerResponse::class.java)
301, 302, 303, 307 -> {
val newLocation = response.headers().firstValue("Location")
.orElseThrow {
LocationMissingException(ip)
}
getModelSuggestions(context, newLocation)
200 -> try {
Gson().fromJson(response.body(), serializableClass)
} catch(jsonException: JsonSyntaxException) {
throw JsonRequesterException(ip, port, response.body())
}
else -> throw GeneralRequesterException(ip, port, response.statusCode())
}
Expand Down

This file was deleted.

0 comments on commit 466ded3

Please sign in to comment.