-
Notifications
You must be signed in to change notification settings - Fork 13
Enum/Classification support for models that do not support logitBias
#746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
raulraja
wants to merge
15
commits into
main
Choose a base branch
from
enum-without-logitBias
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 9 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
63de352
Enum/Classification support for models that do not support `logitBias`
raulraja 3f28a1e
Add testcontainers ollama and classification test for gemma 2b
raulraja d925081
attempt to fix container load on CI
raulraja 71c7c7c
attempt to fix container load on CI. 2
raulraja aba9d4f
do not bail if there is no token
raulraja 766feff
try with llama3 8b
raulraja 05a9189
try with llama3 8b (separate test cases)
raulraja 6cbf754
try saving docker image
raulraja 984e97d
Rewire tests container setup lifecycle
raulraja 5c0eea3
Update core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt
raulraja 543d491
Update core/src/jvmTest/kotlin/com/xebia/functional/xef/ollama/tests/…
raulraja b6fd9ff
Apply spotless formatting
raulraja 6ea9778
Merge branch 'main' into enum-without-logitBias
raulraja ffc6a9a
Merge branch 'main' into enum-without-logitBias
raulraja 81b7022
Merge branch 'main' into enum-without-logitBias
javipacheco File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
core/src/jvmTest/kotlin/com/xebia/functional/xef/ollama/tests/EnumClassificationTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.xebia.functional.xef.ollama.tests | ||
|
|
||
| import com.xebia.functional.xef.ollama.tests.models.OllamaModels | ||
| import com.xebia.functional.xef.ollama.tests.models.Sentiment | ||
| import kotlinx.coroutines.runBlocking | ||
| import org.junit.jupiter.api.Test | ||
|
|
||
| class EnumClassificationTest : OllamaTests() { | ||
|
|
||
| @Test | ||
| fun `positive sentiment`() { | ||
| runBlocking { | ||
| val sentiment = | ||
| ollama<Sentiment>( | ||
| model = OllamaModels.Gemma2B, | ||
| prompt = "The context of the situation is very positive.", | ||
| ) | ||
| assert(sentiment == Sentiment.POSITIVE) { "Expected POSITIVE but got $sentiment" } | ||
| } | ||
| } | ||
|
|
||
| @Test | ||
| fun `negative sentiment`() { | ||
| runBlocking { | ||
| val sentiment = | ||
| ollama<Sentiment>( | ||
| model = OllamaModels.LLama3_8B, | ||
| prompt = "The context of the situation is very negative.", | ||
| ) | ||
| assert(sentiment == Sentiment.NEGATIVE) { "Expected NEGATIVE but got $sentiment" } | ||
| } | ||
| } | ||
| } |
100 changes: 100 additions & 0 deletions
100
core/src/jvmTest/kotlin/com/xebia/functional/xef/ollama/tests/OllamaTests.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| package com.xebia.functional.xef.ollama.tests | ||
|
|
||
| import com.github.dockerjava.api.model.Image | ||
| import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel | ||
| import com.xebia.functional.xef.AI | ||
| import com.xebia.functional.xef.Config | ||
| import com.xebia.functional.xef.OpenAI | ||
| import io.github.oshai.kotlinlogging.KotlinLogging | ||
| import java.util.concurrent.ConcurrentHashMap | ||
| import org.junit.jupiter.api.AfterAll | ||
| import org.testcontainers.DockerClientFactory | ||
| import org.testcontainers.ollama.OllamaContainer | ||
| import org.testcontainers.utility.DockerImageName | ||
|
|
||
| abstract class OllamaTests { | ||
|
|
||
| val logger = KotlinLogging.logger {} | ||
|
|
||
| companion object { | ||
| private const val OLLAMA_IMAGE = "ollama/ollama:0.1.26" | ||
|
|
||
| private val registeredContainers: MutableMap<String, OllamaContainer> = ConcurrentHashMap() | ||
|
|
||
| @PublishedApi | ||
| internal fun useModel(model: String): OllamaContainer = | ||
| if (registeredContainers.containsKey(model)) { | ||
| registeredContainers[model]!! | ||
| } else { | ||
| ollamaContainer(model) | ||
| } | ||
|
|
||
| private fun ollamaContainer(model: String, imageName: String = model): OllamaContainer { | ||
| if (registeredContainers.containsKey(model)) { | ||
| return registeredContainers[model]!! | ||
| } | ||
| // create the new image if it is not already a docker image | ||
| val listImagesCmd: List<Image> = | ||
| DockerClientFactory.lazyClient().listImagesCmd().withImageNameFilter(imageName).exec() | ||
|
|
||
| val ollama = | ||
| if (listImagesCmd.isEmpty()) { | ||
| // ship container emoji: 🚢 | ||
| println("🐳 Creating a new Ollama container with $model image...") | ||
| val ollama = OllamaContainer(OLLAMA_IMAGE) | ||
| ollama.start() | ||
| println("🐳 Pulling $model image...") | ||
| ollama.execInContainer("ollama", "pull", model) | ||
| println("🐳 Committing $model image...") | ||
| ollama.commitToImage(imageName) | ||
| ollama.withReuse(true) | ||
| } else { | ||
| println("🐳 Using existing Ollama container with $model image...") | ||
| // Substitute the default Ollama image with our model variant | ||
| val ollama = | ||
| OllamaContainer( | ||
| DockerImageName.parse(imageName).asCompatibleSubstituteFor("ollama/ollama") | ||
| ) | ||
| .withReuse(true) | ||
| ollama.start() | ||
| ollama | ||
| } | ||
| println("🐳 Starting Ollama container with $model image...") | ||
| registeredContainers[model] = ollama | ||
| ollama.execInContainer("ollama", "run", model) | ||
| return ollama | ||
| } | ||
|
|
||
| @AfterAll | ||
| @JvmStatic | ||
| fun teardown() { | ||
| registeredContainers.forEach { (model, container) -> | ||
| println("🐳 Stopping Ollama container for model $model") | ||
| container.stop() | ||
| } | ||
| } | ||
| } | ||
|
|
||
| protected suspend inline fun <reified A> ollama( | ||
| model: String, | ||
| prompt: String, | ||
| ): A { | ||
| useModel(model) | ||
| val config = Config(supportsLogitBias = false, baseUrl = ollamaBaseUrl(model)) | ||
| val api = OpenAI(config = config, logRequests = true).chat | ||
| val result: A = | ||
| AI( | ||
| prompt = prompt, | ||
| config = config.copy(), | ||
|
raulraja marked this conversation as resolved.
Outdated
|
||
| api = api, | ||
| model = CreateChatCompletionRequestModel.Custom(model), | ||
| ) | ||
| logger.info { "🚀 Inference on model $model: $result" } | ||
| return result | ||
| } | ||
|
|
||
| fun ollamaBaseUrl(model: String): String { | ||
| val ollama = registeredContainers[model]!! | ||
| return "http://${ollama.host}:${ollama.getMappedPort(ollama.exposedPorts.first())}/v1/" | ||
| } | ||
| } | ||
8 changes: 8 additions & 0 deletions
8
core/src/jvmTest/kotlin/com/xebia/functional/xef/ollama/tests/models/OllamaModels.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package com.xebia.functional.xef.ollama.tests.models | ||
|
|
||
| object OllamaModels { | ||
| const val Gemma2B = "gemma:2b" | ||
| const val Phi3Latest = "phi3:latest" | ||
| const val LLama3_8B = "llama3:8b" | ||
| const val Qwen0_5B = "qwen:0.5b" | ||
| } |
9 changes: 9 additions & 0 deletions
9
core/src/jvmTest/kotlin/com/xebia/functional/xef/ollama/tests/models/Sentiment.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.xebia.functional.xef.ollama.tests.models | ||
|
|
||
| import kotlinx.serialization.Serializable | ||
|
|
||
| @Serializable | ||
| enum class Sentiment { | ||
| POSITIVE, | ||
| NEGATIVE, | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| <?xml version="1.0" encoding="UTF-8" ?> | ||
| <!DOCTYPE configuration> | ||
|
|
||
| <configuration> | ||
| <statusListener class="ch.qos.logback.core.status.NopStatusListener" /> | ||
|
|
||
| <appender name="NOOP" class="ch.qos.logback.core.helpers.NOPAppender" /> | ||
|
|
||
| <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||
| <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> | ||
| <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern> | ||
| </encoder> | ||
| </appender> | ||
|
|
||
| <root level="info"> | ||
| <appender-ref ref="STDOUT"/> | ||
| </root> | ||
|
|
||
| <logger name="com.xebia.functional.xef" level="debug"> | ||
| <appender-ref ref="STDOUT" /> | ||
| </logger> | ||
|
|
||
| <logger name="com.gargoylesoftware.htmlunit" level="off"> | ||
| <appender-ref ref="STDOUT" /> | ||
| </logger> | ||
| </configuration> |
18 changes: 18 additions & 0 deletions
18
examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/EnumOllama.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.xebia.functional.xef.dsl.chat | ||
|
|
||
| import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel | ||
| import com.xebia.functional.xef.AI | ||
| import com.xebia.functional.xef.Config | ||
| import com.xebia.functional.xef.OpenAI | ||
|
|
||
| suspend fun main() { | ||
| val config = Config(baseUrl = "http://localhost:11434/v1/", supportsLogitBias = false) | ||
| val sentiment = | ||
| AI<Sentiment>( | ||
| prompt = "I love Xef!", | ||
| model = CreateChatCompletionRequestModel.Custom("orca-mini:3b"), | ||
| config = config, | ||
| api = OpenAI(config, logRequests = true).chat, | ||
| ) | ||
| println(sentiment) // positive | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.