diff --git a/.github/workflows/publish-development-version.yml b/.github/workflows/publish-development-version.yml
index d373c3827..36fa1407a 100644
--- a/.github/workflows/publish-development-version.yml
+++ b/.github/workflows/publish-development-version.yml
@@ -34,7 +34,7 @@ jobs:
- name: Assemble
uses: gradle/gradle-build-action@v2
with:
- arguments: assemble -x:xef-java-examples:assemble -x:xef-scala:assemble -x:xef-scala-examples:assemble
+ arguments: assemble
- name: Upload reports
if: failure()
@@ -46,36 +46,4 @@ jobs:
- name: Publish development version
uses: gradle/gradle-build-action@v2
with:
- arguments: publishToSonatype -x:xef-scala:publishToSonatype closeAndReleaseSonatypeStagingRepository
-
- publish-modules-with-loom:
- timeout-minutes: 30
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- ref: ${{ github.ref_name }}
-
- - name: Set up Java
- uses: actions/setup-java@v3
- with:
- distribution: 'zulu'
- java-version: 20
-
- - name: assemble
- uses: gradle/gradle-build-action@v2
- with:
- arguments: :xef-scala:assemble :xef-java-examples:assemble
-
- - name: Upload reports
- if: failure()
- uses: actions/upload-artifact@v3
- with:
- name: 'reports-${{ matrix.os }}'
- path: '**/build/reports/**'
-
- - name: Publish development version
- uses: gradle/gradle-build-action@v2
- with:
- arguments: :xef-scala:publishToSonatype closeAndReleaseSonatypeStagingRepository
+ arguments: publishToSonatype closeAndReleaseSonatypeStagingRepository
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index f6523d87c..10b5e15a4 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -32,7 +32,7 @@ jobs:
- name: Assemble
uses: gradle/gradle-build-action@v2
with:
- arguments: assemble -x:xef-java-examples:assemble -x:xef-scala:assemble -x:xef-scala-examples:assemble
+ arguments: assemble
- name: Upload reports
if: failure()
@@ -44,36 +44,4 @@ jobs:
- name: Publish final version
uses: gradle/gradle-build-action@v2
with:
- arguments: publishToSonatype -x:xef-scala:publishToSonatype closeSonatypeStagingRepository
-
- publish-modules-with-loom:
- timeout-minutes: 30
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0
- ref: ${{ github.ref_name }}
-
- - name: Set up Java
- uses: actions/setup-java@v3
- with:
- distribution: 'zulu'
- java-version: 20
-
- - name: assemble
- uses: gradle/gradle-build-action@v2
- with:
- arguments: :xef-scala:assemble :xef-java-examples:assemble
-
- - name: Upload reports
- if: failure()
- uses: actions/upload-artifact@v3
- with:
- name: 'reports-${{ matrix.os }}'
- path: '**/build/reports/**'
-
- - name: Publish final version
- uses: gradle/gradle-build-action@v2
- with:
- arguments: :xef-scala:publishToSonatype closeSonatypeStagingRepository
+ arguments: publishToSonatype closeSonatypeStagingRepository
diff --git a/README.md b/README.md
index dccf15acd..ca77c7c77 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Our goal is to make the move to this new world as simple as possible for the dev
xef.ai is packaged in two layers:
1. Core libraries bringing integration with the basic services in an AI application.
These libraries expose an _idiomatic_ interface, so there's one per programming language.
- At this moment we support Kotlin and Scala.
+ At this moment we support Kotlin.
2. Integrations with other libraries which complement the core mission of xef.ai.
xef.ai draws inspiration from libraries like [LangChain](https://docs.langchain.com/docs/)
@@ -47,11 +47,9 @@ strategies.
Libraries are published in Maven Central, under the `com.xebia` group.
-1. `xef-kotlin` for Kotlin support, `xef-scala` for Scala, `xef-java` for Java.
+1. `xef-kotlin` for Kotlin support.
2. The name of a library we provide integration for, like `xef-lucene`.
-
- Gradle (Kotlin DSL)
Libraries are published in Maven Central. You may need to add that repository explicitly
in your build, if you haven't done it before.
@@ -73,51 +71,10 @@ We publish all libraries at once under the same version, so
[version catalogs](https://docs.gradle.org/current/userguide/platforms.html#sec:sharing-catalogs)
could be useful.
-
-
-
- SBT
-
-```sbt
-libraryDependencies += "com.xebia" %% "xef-scala" % ""
-```
-
-> **Warning**
-> `xef-scala` is currently only available for Scala 3, and depends on project [Loom](https://openjdk.org/projects/loom/),
-> so you will need at least Java 20 to use the library.
-
-
-
-
- Maven
-
-Libraries are published in Maven Central. You may need to add that repository explicitly
-in your build, if you haven't done it before.
-
-```xml
-
- com.xebia
- xef-java
- x.x.x
- pom
- runtime
-
-```
-
-
-
## 📖 Quick Introduction
-In this small introduction we look at the main features of xef, including the `conversation` function.
-
-- [ Kotlin version](https://github.com/xebia-functional/xef/blob/main/docs/intro/kotlin.md)
-- [ Scala version](https://github.com/xebia-functional/xef/blob/main/docs/intro/scala.md)
-- [ Java version](https://github.com/xebia-functional/xef/blob/main/docs/intro/java.md)
+In [this](https://github.com/xebia-functional/xef/blob/main/docs/intro.md) small introduction we look at the main features of xef, including the `conversation` function.
## 🚀 Examples
-You can also have a look at the examples to have a feeling of how using the library looks like.
-
-- [ Examples in Kotlin](https://github.com/xebia-functional/xef/tree/main/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation)
-- [ Examples in Scala](https://github.com/xebia-functional/xef/tree/main/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala)
-- [ Examples in Java](https://github.com/xebia-functional/xef/tree/main/examples/java/src/main/java/com/xebia/functional/xef/java/auto)
+You can also have a look at the [examples](https://github.com/xebia-functional/xef/tree/main/examples/src/main/kotlin/com/xebia/functional/xef/conversation) to have a feeling of how using the library looks like.
diff --git a/buildSrc/src/main/kotlin/ScalaPublishingConventionsPlugin.kt b/buildSrc/src/main/kotlin/ScalaPublishingConventionsPlugin.kt
deleted file mode 100644
index 400817204..000000000
--- a/buildSrc/src/main/kotlin/ScalaPublishingConventionsPlugin.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.plugins.BasePlugin
-import org.gradle.api.plugins.BasePluginExtension
-import org.gradle.api.publish.PublishingExtension
-import org.gradle.api.publish.maven.MavenPublication
-import org.gradle.api.tasks.TaskProvider
-import org.gradle.api.tasks.bundling.Jar
-import org.gradle.kotlin.dsl.findByType
-import org.gradle.kotlin.dsl.get
-import org.gradle.kotlin.dsl.register
-import org.gradle.plugins.signing.SigningExtension
-
-class ScalaPublishingConventionsPlugin : Plugin {
-
- override fun apply(project: Project): Unit = project.run {
- val scaladocJarTask: TaskProvider = tasks.register("scaladocJar") {
- group = BasePlugin.BUILD_GROUP
- tasks.findByName("scaladoc")?.let { dependsOn(it) }
- ?: errorMessage("The scaladoc task was not found. The Javadoc jar file won't contain any documentation")
- archiveClassifier.set("javadoc")
- from("${layout.buildDirectory.get()}/docs/scaladoc")
- }
-
- val publishingExtension: PublishingExtension =
- extensions.findByType()
- ?: throw IllegalStateException("The Maven Publish plugin is required to publish the build artifacts")
-
- val signingExtension: SigningExtension =
- extensions.findByType()
- ?: throw IllegalStateException("The Signing plugin is required to digitally sign the built artifacts")
-
- val basePluginExtension: BasePluginExtension =
- extensions.findByType()
- ?: throw IllegalStateException("The Base plugin is required to configure the name of artifacts")
-
- publishingExtension.run {
- publications {
- register("maven") {
- val scala3Suffix = "_3"
- artifactId = basePluginExtension.archivesName.get() + scala3Suffix
- from(components["java"])
- artifact(scaladocJarTask)
- pomConfiguration(project)
- }
- }
- }
-
- signingExtension.run {
- val isLocal = gradle.startParameter.taskNames.any { it.contains("publishToMavenLocal", ignoreCase = true) }
- val signingKeyId: String? = configValue("signing.keyId", "SIGNING_KEY_ID")
- val signingKey: String? = configValue("signing.key", "SIGNING_KEY")
- val signingPassphrase: String? = configValue("signing.passphrase", "SIGNING_KEY_PASSPHRASE")
- isRequired = !isLocal
- useGpgCmd()
- useInMemoryPgpKeys(signingKeyId, signingKey, signingPassphrase)
- sign(publishingExtension.publications)
- }
- }
-}
diff --git a/buildSrc/src/main/kotlin/xef-scala-publishing-conventions.gradle.kts b/buildSrc/src/main/kotlin/xef-scala-publishing-conventions.gradle.kts
deleted file mode 100644
index 97fa1cfd8..000000000
--- a/buildSrc/src/main/kotlin/xef-scala-publishing-conventions.gradle.kts
+++ /dev/null
@@ -1 +0,0 @@
-apply()
diff --git a/core/TECHNICAL.MD b/core/TECHNICAL.MD
index 22b88ceb0..70969ee8e 100644
--- a/core/TECHNICAL.MD
+++ b/core/TECHNICAL.MD
@@ -14,11 +14,9 @@ The breakdown is only in terms of JVM, since that's where we _mostly_ care about
We include the following dependencies in our _core_ module to implement a _common_ layer to interact with LLMs.
The dependency on Kotlin Stdlib is unavoidable, since we use Kotlin as our main language.
-We also require KotlinX Coroutines such that we can leverage the `suspend` keyword in our API and expose `Future` to the
-Java/Scala API.
-Additionally, we also have a need for a HTTP client, and a serialization framework. Here we use Ktor and KotlinX
-Serialization respectively,
-and Xef relies on the CIO engine for Ktor, which avoids any additional dependencies.
+We also require KotlinX Coroutines such that we can leverage the `suspend` keyword in our API.
+Additionally, we also have a need for an HTTP client, and a serialization framework. Here we use Ktor and KotlinX
+Serialization respectively, and Xef relies on the CIO engine for Ktor, which avoids any additional dependencies.
- kotlin-stdlib (1810 Kb = 1598 Kb + 212 Kb)
- kotlinx-coroutines-core (1608 Kb = 1442 Kb + 166 Kb)
diff --git a/core/src/jvmMain/kotlin/com/xebia/functional/xef/conversation/futures/ExecutionContext.kt b/core/src/jvmMain/kotlin/com/xebia/functional/xef/conversation/futures/ExecutionContext.kt
deleted file mode 100644
index c9fad09f4..000000000
--- a/core/src/jvmMain/kotlin/com/xebia/functional/xef/conversation/futures/ExecutionContext.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.xebia.functional.xef.conversation.futures
-
-import java.util.concurrent.CompletableFuture
-import java.util.concurrent.ExecutorService
-import java.util.concurrent.Executors
-import java.util.concurrent.ThreadFactory
-import java.util.concurrent.atomic.AtomicInteger
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.CoroutineStart
-import kotlinx.coroutines.asCoroutineDispatcher
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.future.future
-
-interface ExecutionContext : AutoCloseable {
-
- val executorService: ExecutorService
- val coroutineScope: CoroutineScope
-
- fun future(block: suspend CoroutineScope.() -> A): CompletableFuture =
- coroutineScope.future(coroutineScope.coroutineContext, CoroutineStart.DEFAULT, block)
-
- override fun close() {
- coroutineScope.cancel()
- executorService.shutdown()
- }
-
- private class AIScopeThreadFactory : ThreadFactory {
- private val counter = AtomicInteger()
-
- override fun newThread(r: Runnable): Thread {
- val t = Thread(r)
- t.name = "xef-ai-scope-worker-${counter.getAndIncrement()}"
- t.isDaemon = true
- return t
- }
- }
-
- companion object {
- @JvmField val DEFAULT = from(Executors.newCachedThreadPool(AIScopeThreadFactory()))
-
- @JvmStatic
- fun from(executorService: ExecutorService): ExecutionContext =
- object : ExecutionContext {
- override val executorService: ExecutorService = executorService
- override val coroutineScope: CoroutineScope =
- CoroutineScope(executorService.asCoroutineDispatcher())
- }
- }
-}
diff --git a/docs/intro/kotlin.md b/docs/intro.md
similarity index 100%
rename from docs/intro/kotlin.md
rename to docs/intro.md
diff --git a/docs/intro/java.md b/docs/intro/java.md
deleted file mode 100644
index 2d16ccdc7..000000000
--- a/docs/intro/java.md
+++ /dev/null
@@ -1,193 +0,0 @@
-# Quick introduction to xef.ai (Java version)
-
-After adding the library to your project
-(see the [main README](https://github.com/xebia-functional/xef/blob/main/README.md) for instructions),
-you get access to the `AIScope` class, which is your port of entry to the modern AI world.
-Using it, you can _prompt_ for information, which means posing the question to an LLM
-(Large Language Model). The easiest way is to just get the information back as a string.
-
-```java
-package my.example;
-
-import com.xebia.functional.xef.java.auto.AIScope;
-
-import java.util.concurrent.ExecutionException;
-
-public class Example {
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (AIScope scope = new AIScope()) {
- String topic = "artificial intelligence";
- scope.promptMessage("Give me a selection of books about " + topic)
- .thenAccept(System.out::println)
- .get();
- }
- }
-}
-```
-
-> **Note**
-> By default the `AIScope` connects to [OpenAI](https://platform.openai.com/).
-> To use their services you should provide the corresponding API key in the `OPENAI_TOKEN`
-> environment variable, and have enough credits.
-
-In the example above we create an `AIScope` using the `try-with-resources` syntax,
-which ensures that the scope is closed at the end of the block.
-The `AIScope` gives us access to the `promptMessage` & co functions, which allow us to interact with the LLM.
-
-All the functions of `AIScope` are returned as a `Future` for maximum backward compatibility until JDK8,
-but you can inject `Executors.newVirtualThreadPerTaskExecutor()` to have the `Future`s work on virtual threads.
-
-Remember that exceptions in `Future`are wrapped in `ExecutionException`,
-so to inspect the actual exception you need to call `getCause()` on it.
-_Structured Concurrency_ is implemented under the hood by Kotlin's `CoroutineScope`,
-and all futures are cancelled when the `AIScope` is closed and `Future#get` will throw `CancellationException`.
-
-In the next examples we'll write functions that rely on `AIScope`'s DSL functionality
-
-## Structure
-
-
-The output from the `books` function above may be hard to parse back from the
-strings we obtain. Fortunately, you can also ask xef.ai to give you back the information
-using a _custom type_. The library takes care of instructing the LLM on building such
-a structure, and deserialize the result back for you.
-
-We can thus define a `Book` class that describes the desired response we want to receive from the LLM.
-Relying on [Jakarta validation](https://beanvalidation.org) we can also specify which fields are mandatory using `NotNull`,
-or include additional constraints in the [Json Schema](https://json-schema.org).
-
-xef.ai reuses [Jackson](https://github.com/FasterXML/jackson-databind),
-and [JsonSchema generator](https://github.com/victools/jsonschema-generator) to parse and generate the Json Schema V7 for you.
-
-```java
-package my.example;
-
-import jakarta.validation.constraints.NotNull;
-
-public class Book {
- @NotNull public String title;
- @NotNull public String author;
- @NotNull public int year;
- @NotNull public String genre;
-
- @Override
- public String toString() {
- return "Book{" +
- "title='" + title + '\'' +
- ", author='" + author + '\'' +
- ", year=" + year +
- ", genre='" + genre + '\'' +
- '}';
- }
-}
-```
-
-Using the definition of `Book`, we can rewrite our previous example as:
-
-```java
-package my.example;
-
-import com.xebia.functional.xef.java.auto.AIScope;
-import jakarta.validation.constraints.NotNull;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class Example {
-
- private final AIScope scope;
-
- public Example(AIScope scope) {
- this.scope = scope;
- }
-
- public CompletableFuture bookSelection(String topic) {
- return scope.prompt("Give me a selection of books about " + topic, Example.Book.class);
- }
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (AIScope scope = new AIScope()) {
- Example example = new Example(scope);
- example.bookSelection("artificial intelligence")
- .thenAccept(System.out::println)
- .get();
- }
- }
-}
-```
-
-Here we also show how you can easily capture the `AIScope` in a class,
-and build and compose additional functionality on top.
-If you're using any dependency injection framework, you can also construct `AIScope` and inject it as usual.
-Make sure that the dependency injection framework properly closes the `AIScope` when the application shuts down.
-
-## Context
-
-LLMs have knowledge about a broad variety of topics. But by construction they are not able
-to respond to questions about information not available in their training set. However, you
-often want to supplement the LLM with more data:
-- Transient information referring to the current moment, like the current weather, or
- the trends in the stock market in the past 10 days.
-- Non-public information, for example for summarizing a piece of text you're creating
- within you organization.
-
-These additional pieces of information are called the _contextScope_ in xef.ai, and are attached
-to every question to the LLM. Although you can add arbitrary strings to the context at any
-point, the most common mode of usage is using an _agent_ to consult an external service,
-and make its response part of the context. One such agent is `search`, which uses a web
-search service to enrich that context.
-
-```java
-package my.example;
-
-import java.util.concurrent.CompletableFuture;
-
-public class Weather {
- private final AIScope scope;
-
- public Weather(AIScope scope) {
- this.scope = scope;
- }
-
- public CompletableFuture recommendation() {
- return scope.contextScope(scope.search("Weather in $place"), () ->
- scope.promptMessage("Knowing this forecast, what clothes do you recommend I should wear?")
- );
- }
-}
-```
-
-> **Note**
-> The underlying mechanism of the context is a _vector store_, a data structure which
-> saves a set of strings, and is able to find those similar to another given one.
-> By default xef.ai uses an _in-memory_ vector store, since it provides maximum
-> compatibility across platforms. However, if you foresee your context growing above
-> the hundreds of elements, you may consider switching to another alternative, like
-> Lucene or PostgreSQL.
->
-> ```java
-> package my.example;
->
-> import com.xebia.functional.xef.store.LuceneKt;
->
-> import java.nio.file.Path;
-> import java.util.concurrent.CompletableFuture;
->
-> public class VectorStore {
->
-> private final AIScope scope;
->
-> public VectorStore(AIScope scope) {
-> this.scope = scope;
-> }
->
-> public void example() {
-> Path LUCENE_PATH = Path.of("lucene");
-> scope.contextScope(
-> LuceneKt.InMemoryLuceneBuilder(LUCENE_PATH),
-> () -> CompletableFuture.completedFuture("do stuff")
-> );
-> }
->
-> }
-> ```
diff --git a/docs/intro/scala.md b/docs/intro/scala.md
deleted file mode 100644
index a40fca0d5..000000000
--- a/docs/intro/scala.md
+++ /dev/null
@@ -1,146 +0,0 @@
-# Quick introduction to xef.ai (Scala version)
-
-After adding the library to your project (see the
-[main README](https://github.com/xebia-functional/xef/blob/main/README.md) for instructions),
-you get access to the `conversation` function, which is your port of entry to the modern AI world.
-Inside of it, you can _prompt_ for information, which means posing the question to an LLM
-(Large Language Model). The easiest way is to just get the information back as a string or list of strings.
-
-```scala 3
-import com.xebia.functional.xef.scala.conversation.*
-
-def books(topic: String): Unit = conversation:
- val topBook: String = promptMessage(s"Give me the top-selling book about $topic")
- println(topBook)
- val selectedBooks: List[String] = promptMessages(s"Give me a selection of books about $topic")
- println(selectedBooks.mkString("\n"))
-```
-
-## Additional setup
-
-If the code above fails, you may need to perform some additional setup.
-
-### OpenAI
-
-By default, the `conversation` block connects to [OpenAI](https://platform.openai.com/).
-To use their services you should provide the corresponding API key in the `OPENAI_TOKEN`
-environment variable, and have enough credits.
-
-
-SBT
-
-```shell
-env OPENAI_TOKEN= sbt
-```
-
-
-
-IntelliJ
-
-Set the environment variable `OPENAI_TOKEN=xxx`
-
-
-
-### Project Loom
-
-The Scala module depends on project [Loom](https://openjdk.org/projects/loom/),
-so you will need at least Java 20 to use the library. Furthermore, if using Java 20 specifically,
-you need to pass the `--enable-preview` flag.
-
-
-SBT
-
-```shell
-env OPENAI_TOKEN= sbt -J--enable-preview
-```
-
-
-
-IntelliJ
-
-- Set the Java version to at least 20
-- If using Java 20 specifically, set VM options to `--enable-preview`
-
-
-
-## Structure
-
-The output from the `books` function above may be hard to parse back from the
-strings we obtain. Fortunately, you can also ask xef.ai to give you back the information
-using a _custom type_. The library takes care of instructing the LLM on building such
-a structure, and deserialize the result back for you.
-
-This can be done by declaring a case class that `derives SerialDescriptor, Decoder`:
-
-```scala 3
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-case class Book(name: String, author: String, pages: Int) derives SerialDescriptor, Decoder
-```
-
-The `conversation` block can then be written in this way:
-
-```scala 3
-def bookExample(topic: String): Unit = conversation:
- val Book(title, author, pages) = prompt[Book](s"Give me the best-selling book about $topic")
- println(s"The book $title is by $author and has $pages pages.")
-```
-
-xef.ai for Scala uses xef.ai core, which is based on the Kotlin implementation. Hence, the core
-reuses [Kotlin's common serialization](https://kotlinlang.org/docs/serialization.html), and
-Scala uses [circe](https://github.com/circe/circe) to derive the required serializable instance.
-The LLM is usually able to detect which kind of information should go in each field based on its name
-(like `title` and `author` above).
-
-## Context
-
-LLMs have knowledge about a broad variety of topics. But by construction they are not able
-to respond to questions about information not available in their training set. However, you
-often want to supplement the LLM with more data:
-- Transient information referring to the current moment, like the current weather, or
- the trends in the stock market in the past 10 days.
-- Non-public information, for example for summarizing a piece of text you're creating
- within your organization.
-
-These additional pieces of information are called the _context_ in xef.ai, and are attached
-to every question to the LLM. Although you can add arbitrary strings to the context at any
-point, the most common mode of usage is using an _agent_ to consult an external service,
-and make its response part of the context. One such agent is `search`, which uses the
-[Google Search API (SerpApi)](https://serpapi.com/) to enrich that context.
-
-(Note that a SerpApi token may be required to run this example.)
-
-```scala 3
-import com.xebia.functional.xef.conversation.llm.openai.*
-import com.xebia.functional.xef.reasoning.serpapi.*
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-val openAI: OpenAI = OpenAI.fromEnvironment()
-
-def setContext(query: String)(using conversation: ScalaConversation): Unit =
- addContext(Search(openAI.DEFAULT_CHAT, conversation, 3).search(query).get)
-
-@main def runWeather(): Unit = conversation:
- setContext("Weather in Cádiz, Spain")
- val question = "Knowing this forecast, what clothes do you recommend I should wear if I live in Cádiz?"
- val answer = promptMessage(question)
- println(answer)
-```
-
-> **Note**
-> The underlying mechanism of the context is a _vector store_, a data structure which
-> saves a set of strings, and is able to find those similar to another given one.
-> By default xef.ai uses an _in-memory_ vector store, since this provides maximum
-> compatibility across platforms. However, if you foresee your context growing above
-> the hundreds of elements, you may consider switching to another alternative, like
-> Lucene or PostgreSQL.
-
-## Examples
-
-Check out the
-[examples folder](https://github.com/xebia-functional/xef/blob/main/examples/scala/src/main/scala/com/xebia/functional/xef/examples)
-for a complete list of different use cases.
diff --git a/examples/kotlin/build.gradle.kts b/examples/build.gradle.kts
similarity index 86%
rename from examples/kotlin/build.gradle.kts
rename to examples/build.gradle.kts
index b3e74135a..a3751ab09 100644
--- a/examples/kotlin/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -15,14 +15,13 @@ java {
}
dependencies {
- implementation(projects.xefKotlin)
+ implementation(projects.xefCore)
+ implementation(projects.xefOpenai)
implementation(projects.xefFilesystem)
implementation(projects.xefPdf)
implementation(projects.xefSql)
implementation(projects.xefTokenizer)
- implementation(projects.xefGpt4all)
implementation(projects.xefGcp)
- implementation(projects.xefOpenai)
implementation(projects.xefReasoning)
implementation(projects.xefOpentelemetry)
implementation(projects.xefMlflow)
@@ -43,12 +42,6 @@ spotless {
}
}
-tasks.getByName("processResources") {
- dependsOn(projects.xefGpt4all.dependencyProject.tasks.getByName("jvmProcessResources"))
- from("${projects.xefGpt4all.dependencyProject.layout.buildDirectory}/processedResources/jvm/main")
- into("${layout.buildDirectory}/resources/main")
-}
-
@Suppress("MaxLineLength")
tasks.create("docker-sql-example-up") {
diff --git a/examples/java/build.gradle.kts b/examples/java/build.gradle.kts
deleted file mode 100644
index aded6cd45..000000000
--- a/examples/java/build.gradle.kts
+++ /dev/null
@@ -1,16 +0,0 @@
-@file:Suppress("DSL_SCOPE_VIOLATION")
-
-plugins {
- java
- alias(libs.plugins.spotless)
-}
-
-dependencies {
- implementation(projects.xefJava)
- implementation(projects.xefReasoning)
- implementation(projects.xefGpt4all)
-}
-
-tasks.test {
- useJUnitPlatform()
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/BreakingNews.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/BreakingNews.java
deleted file mode 100644
index f4c56619e..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/BreakingNews.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.contexts;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-import com.xebia.functional.xef.reasoning.serpapi.Search;
-
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class BreakingNews {
-
- static DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/M/yyyy");
- static LocalDateTime now = LocalDateTime.now();
-
- public record BreakingNew(String summary) {
- }
-
- private static CompletableFuture writeParagraph(PlatformConversation scope) {
- var currentDate = dtf.format(now);
-
- return scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("write a paragraph of about 300 words about: " + currentDate + " Covid News"), BreakingNews.BreakingNew.class)
- .thenAccept(breakingNews -> System.out.println(currentDate + " Covid news summary:\n" + breakingNews));
- }
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- var currentDate = dtf.format(now);
- var search = new Search(OpenAI.fromEnvironment().DEFAULT_CHAT, scope, 3);
- scope.addContextFromArray(search.search(currentDate + " Covid News").get());
- writeParagraph(scope).get();
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/DivergentTasks.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/DivergentTasks.java
deleted file mode 100644
index 80790b2d5..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/DivergentTasks.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.contexts;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-import com.xebia.functional.xef.reasoning.serpapi.Search;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class DivergentTasks {
-
- public Long numberOfMedicalNeedlesInWorld;
-
- private static CompletableFuture numberOfMedical(PlatformConversation scope) {
- return scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("Provide the number of medical needles in the world"), DivergentTasks.class)
- .thenAccept(numberOfNeedles -> System.out.println("Needles in world:\n" + numberOfNeedles.numberOfMedicalNeedlesInWorld));
- }
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- Search search = new Search(OpenAI.fromEnvironment().DEFAULT_CHAT, scope, 3);
- scope.addContextFromArray(search.search("Estimate amount of medical needles in the world").get());
- numberOfMedical(scope).get();
- }
- }
-
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/Markets.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/Markets.java
deleted file mode 100644
index 9f09bd86d..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/Markets.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.contexts;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-import com.xebia.functional.xef.reasoning.serpapi.Search;
-
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class Markets {
-
- public record Market(String news, List raisingStockSymbols, List decreasingStockSymbols) {
- }
-
- private static CompletableFuture stockMarketSummary(PlatformConversation scope) {
- var news = new Prompt("Write a short summary of the stock market results given the provided context.");
-
- return scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, news, Market.class)
- .thenAccept(markets -> System.out.println(markets));
- }
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- var dtf = DateTimeFormatter.ofPattern("dd/M/yyyy");
- var now = LocalDateTime.now();
- var currentDate = dtf.format(now);
- var search = new Search(OpenAI.fromEnvironment().DEFAULT_CHAT, scope, 3);
- scope.addContextFromArray(search.search(currentDate + "Stock market results, raising stocks, decreasing stocks").get());
- stockMarketSummary(scope).get();
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/PDFDocument.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/PDFDocument.java
deleted file mode 100644
index 6640d3613..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/PDFDocument.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.contexts;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.java.auto.jdk21.util.ConsoleUtil;
-import com.xebia.functional.xef.prompt.Prompt;
-import com.xebia.functional.xef.reasoning.pdf.PDF;
-
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-
-public class PDFDocument {
-
- private static ConsoleUtil util = new ConsoleUtil();
-
- public record AIResponse(String answer, String source){}
-
- private static final String PDF_URL = "https://people.cs.ksu.edu/~schmidt/705a/Scala/Programming-in-Scala.pdf";
-
- private static CompletableFuture askQuestion(PlatformConversation scope) {
- System.out.println("Enter your question ( to exit): ");
-
-
- var line = util.readLine();
- if (line == null || line.isBlank()) {
- return CompletableFuture.completedFuture(null);
- } else {
- scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt(line), AIResponse.class)
- .thenAccept(aiRes -> System.out.println(aiRes.answer + "\n---\n" +
- aiRes.source + "\n---\n"));
-
- return askQuestion(scope);
- }
- }
-
- public static void main(String[] args) throws Exception {
- try (PlatformConversation scope = OpenAI.conversation()) {
- PDF pdf = new PDF(OpenAI.fromEnvironment().DEFAULT_CHAT,
- OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, scope);
- scope.addContext(List.of(pdf.readPDFFromUrl.readPDFFromUrl(PDF_URL).get()));
- askQuestion(scope).get();
- }
- finally {
- util.close();
- }
- }
-
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/Weather.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/Weather.java
deleted file mode 100644
index d596eb734..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/contexts/Weather.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.contexts;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-import com.xebia.functional.xef.reasoning.serpapi.Search;
-
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class Weather {
- public List answer;
-
- private static CompletableFuture clothesRecommend(PlatformConversation scope) {
- return scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("Knowing this forecast, what clothes do you recommend I should wear?"), Weather.class)
- .thenAccept(weather ->
- System.out.println(weather.answer)
- );
- }
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- Search search = new Search(OpenAI.fromEnvironment().DEFAULT_CHAT, scope, 3);
- scope.addContextFromArray(search.search("Weather in Cádiz, Spain").get());
- clothesRecommend(scope).get();
- }
- }
-
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/conversations/Animals.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/conversations/Animals.java
deleted file mode 100644
index 49d4b3c9d..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/conversations/Animals.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.conversations;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.JvmPromptBuilder;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class Animals {
-
- private final PlatformConversation scope;
-
- public Animals(PlatformConversation scope) {
- this.scope = scope;
- }
-
- public CompletableFuture uniqueAnimal() {
- return scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("A unique animal species."), Animal.class);
- }
-
- public CompletableFuture groundbreakingInvention() {
- return scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("A groundbreaking invention from the 20th century."), Invention.class);
- }
-
- public CompletableFuture story(Animal animal, Invention invention) {
- Prompt storyPrompt = new JvmPromptBuilder()
- .addSystemMessage("You are a writer for a science fiction magazine.")
- .addUserMessage("Write a short story of 200 words that involves the animal and the invention")
- .build();
- return scope.promptMessage(OpenAI.fromEnvironment().DEFAULT_CHAT, storyPrompt);
- }
-
- public record Animal(String name, String habitat, String diet){}
- public record Invention(String name, String inventor, int year, String purpose){}
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- Animals animals = new Animals(scope);
- animals.uniqueAnimal()
- .thenCompose(animal ->
- animals.groundbreakingInvention()
- .thenCompose(invention ->
- animals.story(animal, invention)
- .thenAccept(System.out::println)
- )).get();
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/gpt4all/Chat.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/gpt4all/Chat.java
deleted file mode 100644
index 6c16baded..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/gpt4all/Chat.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.gpt4all;
-
-import com.xebia.functional.gpt4all.GPT4All;
-import com.xebia.functional.gpt4all.Gpt4AllModel;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-import org.reactivestreams.Subscriber;
-import org.reactivestreams.Subscription;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.concurrent.ExecutionException;
-
-public class Chat {
- public static void main(String[] args) throws ExecutionException, InterruptedException, IOException {
- var userDir = System.getProperty("user.dir");
- var path = userDir + "/models/gpt4all/ggml-replit-code-v1-3b.bin";
-
- var supportedModels = Gpt4AllModel.Companion.getSupportedModels();
-
- supportedModels.forEach(it -> {
- var url = (Objects.nonNull(it.getUrl())) ? " - " + it.getUrl() : "";
- System.out.println("🤖 " + it.getName() + url);
- });
-
- var url = "https://huggingface.co/nomic-ai/ggml-replit-code-v1-3b/resolve/main/ggml-replit-code-v1-3b.bin";
- var modelPath = Path.of(path);
- var gpt4all = GPT4All.Companion.invoke(url, modelPath);
-
- System.out.println("🤖 GPT4All loaded: " + gpt4all);
- /**
- * Uses internally [HuggingFaceLocalEmbeddings] default of "sentence-transformers", "msmarco-distilbert-dot-v5"
- * to provide embeddings for docs in contextScope.
- */
-
- try (var scope = OpenAI.conversation();
- var br = new BufferedReader(new InputStreamReader(System.in))) {
-
- System.out.println("\n🤖 Enter your question: ");
-
- while(true){
- String line = br.readLine();
- if (line.equals("exit")) break;
-
- var answer = scope.promptStreamingToPublisher(gpt4all, new Prompt(line));
-
- answer.subscribe(new Subscriber() {
- StringBuilder answer = new StringBuilder();
-
- @Override
- public void onSubscribe(Subscription s) {
- System.out.print("\n🤖 --> " + s);
- s.request(Long.MAX_VALUE);
- }
-
- @Override
- public void onNext(String s) {
- answer.append(s);
- }
-
- @Override
- public void onError(Throwable t) {
- System.out.println(t);
- }
-
- @Override
- public void onComplete() {
- System.out.println("\n🤖 --> " + answer.toString());
- System.out.println("\n🤖 --> Done");
- System.out.println("\n🤖 Enter your question: ");
- }
- });
- }
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/ASCIIArt.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/ASCIIArt.java
deleted file mode 100644
index f30e8b1ef..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/ASCIIArt.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.serialization;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import java.util.concurrent.ExecutionException;
-
-public class ASCIIArt {
- public String art;
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("ASCII art of a cat dancing"), ASCIIArt.class)
- .thenAccept(art -> System.out.println(art.art))
- .get();
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Book.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Book.java
deleted file mode 100644
index 157606044..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Book.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.serialization;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import java.util.concurrent.ExecutionException;
-
-public class Book {
-
- public String title;
- public String author;
- public String summary;
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("To Kill a Mockingbird by Harper Lee summary."), Book.class)
- .thenAccept(book -> System.out.println("To Kill a Mockingbird summary:\n" + book.summary))
- .get();
- }
- }
-
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Books.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Books.java
deleted file mode 100644
index b3c492a69..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Books.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.serialization;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-import jakarta.validation.constraints.NotNull;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class Books {
-
- private final PlatformConversation scope;
-
- public Books(PlatformConversation scope) {
- this.scope = scope;
- }
-
- public record Book(@NotNull String title, @NotNull String author, @NotNull int year, @NotNull String genre){}
-
- public CompletableFuture bookSelection(String topic) {
- return scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("Give me a selection of books about " + topic), Books.Book.class);
- }
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- Books books = new Books(scope);
- books.bookSelection("artificial intelligence")
- .thenAccept(System.out::println)
- .get();
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/ChessAI.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/ChessAI.java
deleted file mode 100644
index 5112d56dd..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/ChessAI.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.serialization;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import java.util.ArrayList;
-import java.util.concurrent.ExecutionException;
-import java.util.stream.Collectors;
-
-public class ChessAI {
-
- public record ChessMove(String player, String move){}
- public record ChessBoard(String board){}
- public record GameState(Boolean ended, String winner){}
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- var moves = new ArrayList();
- var gameEnded = false;
- var winner = "";
-
- while (!gameEnded) {
- var currentPlayer = ((moves.size() % 2) == 0) ? "Player 1 (White)" : "Player 2 (Black)";
-
- var prompt = String.format("""
- |%s, it's your turn.
- |Previous moves: %s
- |Make your next move:""",
- currentPlayer,
- moves.stream().map(ChessMove::toString).collect(Collectors.joining(", ")));
-
- ChessMove move = scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt(prompt), ChessMove.class).get();
- moves.add(move);
-
- // Update boardState according to move.move
- // ...
-
- var boardPrompt = String.format("""
- Given the following chess moves: %s,
- generate a chess board on a table with appropriate emoji representations for each move and piece.
- Add a brief description of the move and it's implications""",
- moves.stream().map(it -> it.player + ":" + it.move).collect(Collectors.joining(", ")));
-
- ChessBoard chessBoard= scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt(boardPrompt), ChessBoard.class).get();
- System.out.println("Current board:\n" + chessBoard.board);
-
- var gameStatePrompt = String.format("""
- Given the following chess moves: %s,
- has the game ended (win, draw, or stalemate)?""",
- moves.stream().map(ChessMove::toString).collect(Collectors.joining(", ")));
-
- GameState gameState = scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt(gameStatePrompt), GameState.class).get();
-
- gameEnded = gameState.ended;
- winner = gameState.winner;
- }
-
- System.out.println("Game over. Final move: " + moves.get(moves.size() - 1) + ", Winner: " + winner);
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Movies.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Movies.java
deleted file mode 100644
index f399de71b..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Movies.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.serialization;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import java.util.concurrent.ExecutionException;
-
-public class Movies {
-
- public record Movie(String title, String genre, String director){}
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("Please provide a movie title, genre and director for the Inception movie"), Movie.class)
- .thenAccept(movie -> System.out.println(movie))
- .get();
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Recipes.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Recipes.java
deleted file mode 100644
index 879a293e0..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/serialization/Recipes.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.serialization;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-public class Recipes {
-
- public record Recipe(String name, List ingredients){}
-
- public static void main(String[] args) throws ExecutionException, InterruptedException {
- try (PlatformConversation scope = OpenAI.conversation()) {
- var recipe = scope.prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, new Prompt("Recipe for chocolate chip cookies."), Recipe.class).get();
- System.out.println("The recipe for " + recipe.name + " is " + recipe.ingredients );
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Checker.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Checker.java
deleted file mode 100644
index 59a53b3a8..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Checker.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.tot;
-
-public class Checker {
-
- public static Solutions.Solution checkSolution(Solutions.Solution response){
- System.out.println("✅ Validating solution: " + Rendering.truncateText(response.answer) + "...");
- return response.isValid ? response :
- Solutions.makeSolution(response.answer, false, "Invalid solution", null);
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/ControlSignals.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/ControlSignals.java
deleted file mode 100644
index ecc0309a6..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/ControlSignals.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.tot;
-
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import static com.xebia.functional.xef.java.auto.jdk21.tot.Rendering.renderHistory;
-import static com.xebia.functional.xef.java.auto.jdk21.tot.Rendering.truncateText;
-
-import java.util.concurrent.CompletableFuture;
-
-public class ControlSignals {
-
- static class ControlSignal {
- public String value = "";
- }
-
- public static CompletableFuture controlSignal(Problems.Memory memory){
- System.out.println("\uD83E\uDDE0 Generating control signal for problem:" + truncateText(memory.problem.description) + "...");
- var guidancePrompt = new Prompt(Rendering.trimMargin(
- " You are an expert advisor on information extraction.\n" +
- " You generate guidance for a problem.\n" +
- " " + renderHistory(memory) + "\n" +
- " You are given the following problem:\n" +
- " " + memory.problem.description + "\n" +
- " Instructions:\n" +
- " 1. Generate 1 guidance to get the best results for this problem.\n" +
- " 2. Ensure the guidance is relevant to the problem.\n" +
- " 3. Ensure the guidance is accurate, complete, and unambiguous.\n" +
- " 4. Ensure the guidance is actionable.\n" +
- " 5. Ensure the guidance accounts for previous answers in the `history`.\n" +
- " \n"));
-
- return Problems.Memory.getAiScope().prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, guidancePrompt, ControlSignal.class);
- }
-
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Critiques.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Critiques.java
deleted file mode 100644
index 49ad2f22d..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Critiques.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.tot;
-
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import static com.xebia.functional.xef.java.auto.jdk21.tot.Rendering.truncateText;
-
-import java.util.concurrent.CompletableFuture;
-
-public class Critiques {
-
- static class Critique {
- public String answer;
- public String reasoning;
- public boolean answerTrulyAccomplishesTheGoal;
- }
-
- public static CompletableFuture critique(Problems.Memory memory, Solutions.Solution currentSolution){
- System.out.println("🕵️ Critiquing solution: " + truncateText(currentSolution.answer) + "...");
-
- var prompt = new Prompt(Rendering.trimMargin(
- " You are an expert advisor critiquing a solution.\n" +
- " \n" +
- " Previous history:\n" +
- " " + Rendering.renderHistory(memory) + "\n" +
- " \n" +
- " You are given the following problem:\n" +
- " " + memory.problem.description + "\n" +
- " \n" +
- " You are given the following solution:\n" +
- " " + currentSolution.answer + "\n" +
- " \n" +
- " Instructions:\n" +
- " 1. Provide a critique and determine if the answer truly accomplishes the goal.\n" +
- " \n"));
-
- return Problems.Memory.getAiScope().prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, prompt, Critique.class);
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Main.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Main.java
deleted file mode 100644
index 67cae5025..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Main.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.tot;
-
-public class Main {
-
- private static final int MAX_ROUNDS = 5;
-
- public static void main(String[] args) {
- Problems.Problem problem = new Problems.Problem();
- problem.description = Rendering.trimMargin(
- " You are an expert functional programmer.\n" +
- " 1. You never throw exceptions.\n" +
- " 2. You never use null.\n" +
- " 3. You never use `for` `while` or loops in general, prefer tail recursion.\n" +
- " 4. You never use mutable state.\n" +
- " \n" +
- " This code is unsafe. Find the problems in this code and provide a Github suggestion code fence with the `diff` to fix it.\n" +
- " \n" +
- " ```kotlin\n" +
- " fun access(list: List, index: Int): Int {\n" +
- " return list[index]\n" +
- " }\n" +
- " ```\n" +
- " \n" +
- " Return a concise solution that fixes the problems in the code.");
-
-
- var solve = Problems.solve(problem, MAX_ROUNDS);
-
- System.out.println("✅ Final solution: " + solve.answer);
- System.out.println("✅ Solution validity: " + solve.isValid);
- System.out.println("✅ Solution reasoning: " + solve.reasoning);
- System.out.println("✅ Solution code: " + solve.value);
- }
-
- static class FinalSolution {
- public String solution;
- }
-
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Problems.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Problems.java
deleted file mode 100644
index 167225f00..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Problems.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.tot;
-
-import com.xebia.functional.xef.conversation.PlatformConversation;
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-
-import static com.xebia.functional.xef.java.auto.jdk21.tot.Rendering.truncateText;
-
-public class Problems {
-
- static class Problem{
- public String description;
- }
-
- public static Solutions.Solution solve(Problem problem, int maxRounds) {
- try(Memory initialMemory = new Memory<>(problem, new ArrayList<>())) {
- return solveRec(maxRounds, initialMemory);
- }
- }
-
- private static Solutions.Solution solveRec(int remainingRounds, Memory sMemory) {
- if(remainingRounds <= 0){
- System.out.println("❌ Maximum rounds reached. Unable to find a solution.");
- return Solutions.makeSolution("", false, "No Response", null);
- } else{
- System.out.println("🌱 Solving problem: " +
- truncateText(sMemory.problem.description, 100) +
- " (Remaining rounds: " + remainingRounds + "...");
-
- ControlSignals.ControlSignal controlSignal = getControlSignal(sMemory);
- Solutions.Solution response = Solutions.solution(sMemory, controlSignal);
- Solutions.Solution result = Checker.checkSolution(response);
- Memory updatedMemory = sMemory.addResult(result);
- if(result.isValid){
- System.out.println("✅ Solution found: " + truncateText(result.answer) + "!");
- Critiques.Critique critique = getCritique(result, updatedMemory);
- if(critique != null && critique.answerTrulyAccomplishesTheGoal){
- System.out.println("❌ Solution does not accomplish the goal: " + truncateText(result.answer) + "!");
- System.out.println("⏪ Backtracking...");
- return solveRec(remainingRounds - 1, updatedMemory);
- }
- else {
- return result;
- }
- }
- else{
- System.out.println("⏪ Backtracking...");
- return solveRec(remainingRounds - 1, updatedMemory);
- }
- }
- }
-
- private static ControlSignals.ControlSignal getControlSignal(Memory sMemory) {
- try {
- ControlSignals.ControlSignal controlSignal = ControlSignals.controlSignal(sMemory).get();
- System.out.println("\uD83E\uDDE0 Generated control signal: " + truncateText(controlSignal.value));
- return controlSignal;
- } catch (Exception e) {
- System.err.printf("ControlSignals.controlSignal prompt threw exception: %s - %s\n",
- e.getClass().getName(), e.getMessage());
- return new ControlSignals.ControlSignal();
- }
- }
-
- @Nullable
- private static Critiques.Critique getCritique(Solutions.Solution result, Memory updatedMemory) {
- try {
- return Critiques.critique(updatedMemory, result).get();
- } catch (Exception e) {
- System.err.printf("Critiques.critique prompt threw exception: %s - %s\n",
- e.getClass().getName(), e.getMessage());
- return null;
- }
- }
-
- static class Memory implements AutoCloseable {
-
- public Problem problem;
- public List> history;
-
- private static PlatformConversation aiScope = null;
-
- public Memory(Problem problem, List> history) {
- this.problem = problem;
- this.history = history;
- checkPlatformConversation();
- }
-
- public Memory addResult(Solutions.Solution result) {
- List> historyUpdate = Stream.concat(this.history.stream(), Stream.of(result)).toList();
- checkPlatformConversation();
- return new Memory<>(this.problem, historyUpdate);
- }
-
- private static void checkPlatformConversation() {
- if(aiScope == null){
- aiScope = OpenAI.conversation();
- }
- }
-
- public static PlatformConversation getAiScope() {
- return aiScope;
- }
-
- public void close(){
- if(aiScope != null) {
- aiScope.close();
- aiScope = null;
- }
- }
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Rendering.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Rendering.java
deleted file mode 100644
index b1fdda157..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Rendering.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.tot;
-
-import java.util.Arrays;
-import java.util.stream.Collectors;
-
-public class Rendering {
-
- public static String trimMargin(String input){
- return Arrays.stream(input.split("\n")).map(String::trim).collect(Collectors.joining("\n"));
- }
-
- public static String truncateText(String answer) {
- return truncateText(answer, 150);
- }
-
- public static String truncateText(String answer, int limit) {
- if(answer == null)
- return "";
- if(answer.length() > limit) {
- answer = answer.substring(0, limit - 3) + "...";
- }
- return answer.replace("\n", " ");
- }
-
- public static String renderHistory(Problems.Memory memory){
- return trimMargin(" ```history \n\n" +
- memory.history.stream()
- .map(Rendering::renderHistoryItem)
- .collect(Collectors.joining("\n")) +
- "```");
- }
-
- private static String renderHistoryItem(Solutions.Solution solution){
- return trimMargin(solution.answer + "\n" +
- solution.reasoning + "\n" +
- (solution.isValid ? "✅" : "❌") + "\n");
- }
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Solutions.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Solutions.java
deleted file mode 100644
index 5fbf8062c..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/tot/Solutions.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.tot;
-
-import com.xebia.functional.xef.conversation.llm.openai.OpenAI;
-import com.xebia.functional.xef.prompt.Prompt;
-
-import static com.xebia.functional.xef.java.auto.jdk21.tot.Rendering.renderHistory;
-import static com.xebia.functional.xef.java.auto.jdk21.tot.Rendering.truncateText;
-
-public class Solutions{
-
- static class Solution{
- public String answer;
- public boolean isValid;
- public String reasoning;
-
- public A value;
- }
-
- public static Solution makeSolution(String answer, boolean isValid, String reasoning, B value) {
- Solution solution = new Solution<>();
- solution.isValid = isValid;
- solution.answer = answer;
- solution.reasoning = reasoning;
- solution.value = value;
- return solution;
- }
-
- public static Solution solution(Problems.Memory memory,
- ControlSignals.ControlSignal controlSignal){
- //ai emoji
- System.out.println("\uD83E\uDD16 Generating solution for problem: " + truncateText(memory.problem.description) + "...");
-
- Prompt enhancedPrompt = new Prompt(
- " Given previous history:\n" +
- " " + renderHistory(memory) + "\n" +
- " Given the goal: \n" +
- " ```goal\n" +
- " " + memory.problem.description + " \n" +
- " ```\n" +
- " and considering the guidance: \n" +
- " ```guidance\n" +
- " " + controlSignal.value + "\n" +
- " ```\n" +
- " \n" +
- " Instructions:\n" +
- " \n" +
- " 1. Please provide a comprehensive solution. \n" +
- " 2. Consider all possible scenarios and edge cases. \n" +
- " 3. Ensure your solution is accurate, complete, and unambiguous. \n" +
- " 4. If you are unable to provide a solution, please provide a reason why and set `isValid` to false.\n" +
- " 5. Include citations, references and links at the end to support your solution based on your sources.\n" +
- " 6. Do not provide recommendations, only provide a solution.\n" +
- " 7. when `isValid` is true Include in the `value` field the value of the solution according to the `value` json schema.\n" +
- " 8. If no solution is found set the `value` field to `null`.\n" +
- " 9. If the solution is not valid set the `isValid` field to `false` and the `value` field to `null`.\n" +
- " 10. If the solution is valid set the `isValid` field to `true` and the `value` field to the value of the solution.\n" +
- " \n");
-
- try {
- return Problems.Memory.getAiScope().prompt(OpenAI.fromEnvironment().DEFAULT_SERIALIZATION, enhancedPrompt, Solution.class).get();
- } catch (Exception e) {
- System.err.printf("Solutions.solution enhancedPrompt threw exception: %s - %s\n",
- e.getClass().getName(), e.getMessage());
- return null;
- }
- }
-
-}
diff --git a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/util/ConsoleUtil.java b/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/util/ConsoleUtil.java
deleted file mode 100644
index a06678b28..000000000
--- a/examples/java/src/main/java/com/xebia/functional/xef/java/auto/jdk21/util/ConsoleUtil.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.xebia.functional.xef.java.auto.jdk21.util;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-public class ConsoleUtil implements AutoCloseable{
-
- private final BufferedReader sysin;
-
- public ConsoleUtil(){
- sysin = new BufferedReader(new InputStreamReader(System.in));
- }
-
- /**
- * Read line from the console (IDE friendly)
- * @return line from console input
- */
- public String readLine() {
- try {
- return sysin.readLine();
- } catch (IOException e) {
- return null;
- }
- }
-
- @Override
- public void close() throws Exception {
- sysin.close();
- }
-}
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpc/Pipelines.kt b/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpc/Pipelines.kt
deleted file mode 100644
index e494e0b22..000000000
--- a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpc/Pipelines.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.xebia.functional.xef.conversation.gpc
-
-import com.xebia.functional.gpt4all.conversation
-import com.xebia.functional.xef.env.getenv
-import com.xebia.functional.xef.gcp.GcpConfig
-import com.xebia.functional.xef.gcp.VertexAIRegion
-import com.xebia.functional.xef.gcp.pipelines.GcpPipelinesClient
-
-suspend fun main() {
- conversation {
- val token = getenv("GCP_TOKEN") ?: error("missing gcp token")
- val pipelineClient =
- autoClose(GcpPipelinesClient(GcpConfig(token, "xefdemo", VertexAIRegion.US_CENTRAL1)))
- val answer = pipelineClient.list()
- println("\n🤖 $answer")
- }
-}
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpt4all/Chat.kt b/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpt4all/Chat.kt
deleted file mode 100644
index c316b5fd3..000000000
--- a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpt4all/Chat.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.xebia.functional.xef.conversation.gpt4all
-
-import com.xebia.functional.gpt4all.GPT4All
-import com.xebia.functional.gpt4all.Gpt4AllModel
-import com.xebia.functional.xef.prompt.Prompt
-import java.nio.file.Path
-import kotlinx.coroutines.flow.onCompletion
-
-suspend fun main() {
- val userDir = System.getProperty("user.dir")
- val path = "$userDir/models/gpt4all/ggml-replit-code-v1-3b.bin"
-
- Gpt4AllModel.supportedModels.forEach { println("🤖 ${it.name} ${it.url?.let { "- $it" }}") }
-
- val url =
- "https://huggingface.co/nomic-ai/ggml-replit-code-v1-3b/resolve/main/ggml-replit-code-v1-3b.bin"
- val modelPath: Path = Path.of(path)
- val model = GPT4All(url, modelPath)
-
- println("🤖 GPT4All loaded: $GPT4All")
- /**
- * Uses internally [HuggingFaceLocalEmbeddings] default of "sentence-transformers",
- * "msmarco-distilbert-dot-v5" to provide embeddings for docs in contextScope.
- */
- GPT4All.conversation {
- println("🤖 Context loaded: $store")
- // hack until https://github.com/nomic-ai/gpt4all/pull/1126 is accepted or merged
- val out = System.out
- model.use { gpT4All: GPT4All ->
- while (true) {
- print("\n🤖 Enter your question: ")
- val userInput = readlnOrNull() ?: break
- gpT4All
- .promptStreaming(Prompt(userInput), this)
- .onCompletion { println("\n🤖 Done") }
- .collect { out.print(it) }
- }
- }
- }
-}
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/manual/NoAI.kt b/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/manual/NoAI.kt
deleted file mode 100644
index 5d2403806..000000000
--- a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/manual/NoAI.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.xebia.functional.xef.conversation.manual
-
-import com.xebia.functional.gpt4all.GPT4All
-import com.xebia.functional.gpt4all.HuggingFaceLocalEmbeddings
-import com.xebia.functional.gpt4all.huggingFaceUrl
-import com.xebia.functional.xef.conversation.Conversation
-import com.xebia.functional.xef.metrics.LogsMetric
-import com.xebia.functional.xef.pdf.pdf
-import com.xebia.functional.xef.prompt.Prompt
-import com.xebia.functional.xef.store.LocalVectorStore
-import java.nio.file.Path
-
-suspend fun main() {
- // Choose your base folder for downloaded models
- val userDir = System.getProperty("user.dir")
-
- // Specify the local model path
- val modelPath: Path = Path.of("$userDir/models/gpt4all/ggml-gpt4all-j-v1.3-groovy.bin")
-
- // Specify the Hugging Face URL for the model
- val url = huggingFaceUrl("orel12", "ggml-gpt4all-j-v1.3-groovy", "bin")
-
- // Create an instance of GPT4All with the local model
- val gpt4All = GPT4All(url, modelPath)
-
- // Create an instance of the embeddings
- val embeddings = HuggingFaceLocalEmbeddings.DEFAULT
- val scope = Conversation(LocalVectorStore(embeddings), LogsMetric())
-
- // Fetch and add texts from a PDF document to the vector store
- val results = pdf("https://arxiv.org/pdf/2305.10601.pdf")
- scope.store.addTexts(results)
-
- // Prompt the GPT4All model with a question and provide the vector store for context
- val result: String =
- gpt4All.use {
- it.promptMessage(
- prompt = Prompt("What is the Tree of Thoughts framework about?"),
- scope = scope
- )
- }
-
- // Print the response
- println(result)
-}
diff --git a/examples/kotlin/src/main/resources/logback.xml b/examples/kotlin/src/main/resources/logback.xml
deleted file mode 100644
index dfb690eb2..000000000
--- a/examples/kotlin/src/main/resources/logback.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/examples/scala/.scalafmt.conf b/examples/scala/.scalafmt.conf
deleted file mode 100644
index 038d0ede0..000000000
--- a/examples/scala/.scalafmt.conf
+++ /dev/null
@@ -1,36 +0,0 @@
-# tune this file as appropriate to your style! see: https://olafurpg.github.io/scalafmt/#Configuration
-
-version = "3.7.15"
-
-runner.dialect = "scala3"
-
-maxColumn = 150
-
-continuationIndent.callSite = 2
-
-newlines {
- sometimesBeforeColonInMethodReturnType = false
-}
-
-align {
- arrowEnumeratorGenerator = false
- ifWhileOpenParen = false
- openParenCallSite = false
- openParenDefnSite = false
- tokens = ["%", "%%"]
-}
-
-docstrings.style = Asterisk
-
-rewrite {
- rules = [SortImports, RedundantBraces]
- redundantBraces.maxLines = 1
-}
-
-optIn {
- breaksInsideChains = true
-}
-
-project.excludeFilters = [
- "metals.sbt"
-]
diff --git a/examples/scala/build.gradle.kts b/examples/scala/build.gradle.kts
deleted file mode 100644
index 615adf2a5..000000000
--- a/examples/scala/build.gradle.kts
+++ /dev/null
@@ -1,30 +0,0 @@
-@file:Suppress("DSL_SCOPE_VIOLATION")
-
-plugins {
- scala
- alias(libs.plugins.spotless)
-}
-
-java {
- sourceCompatibility = JavaVersion.VERSION_21
- targetCompatibility = JavaVersion.VERSION_21
- toolchain { languageVersion = JavaLanguageVersion.of(21) }
-}
-
-dependencies {
- implementation(projects.xefCore)
- implementation(projects.xefScala)
- implementation(projects.xefReasoning)
- implementation(projects.xefOpenai)
- implementation(libs.circe.parser)
- implementation(libs.scala.lang)
- implementation(libs.logback)
-}
-
-tasks.withType().configureEach { useJUnit() }
-
-tasks.withType {
- scalaCompileOptions.additionalParameters = listOf("-Wunused:all", "-Wvalue-discard")
-}
-
-spotless { scala { scalafmt("3.7.15").configFile(".scalafmt.conf") } }
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/Simple.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/Simple.scala
deleted file mode 100644
index c9f4b17d1..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/Simple.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.xebia.functional.xef.examples.scala
-
-import com.xebia.functional.xef.scala.conversation.*
-
-@main def runBooks(): Unit = conversation:
- val topic = "functional programming"
- val topBook: String = promptMessage(s"Give me the top-selling book about $topic")
- println(topBook)
- val selectedBooks: List[String] = promptMessages(s"Give me a selection of books about $topic")
- println(selectedBooks.mkString("\n"))
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/context/serpapi/Simple.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/context/serpapi/Simple.scala
deleted file mode 100644
index 68ee8a49a..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/context/serpapi/Simple.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.xebia.functional.xef.examples.scala.context.serpapi
-
-import com.xebia.functional.xef.conversation.llm.openai.*
-import com.xebia.functional.xef.reasoning.serpapi.*
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-import java.text.SimpleDateFormat
-import java.util.Date
-
-val openAI: OpenAI = OpenAI.fromEnvironment()
-
-val sdf = SimpleDateFormat("dd/M/yyyy")
-def currentDate: String = sdf.format(new Date)
-
-def setContext(query: String)(using conversation: ScalaConversation): Unit =
- addContext(Search(openAI.DEFAULT_CHAT, conversation, 3).search(query).get)
-
-case class BreakingNews(summary: String) derives SerialDescriptor, Decoder
-
-case class MarketNews(news: String, risingStockSymbols: List[String], fallingStockSymbols: List[String]) derives SerialDescriptor, Decoder
-
-case class Estimate(number: Long) derives SerialDescriptor, Decoder
-
-@main def runWeather(): Unit = conversation:
- setContext("Weather in Cádiz, Spain")
- val question = "Knowing this forecast, what clothes do you recommend I should wear if I live in Cádiz?"
- val answer = promptMessage(question)
- println(answer)
-
-@main def runBreakingNews(): Unit = conversation:
- setContext(s"$currentDate COVID News")
- val BreakingNews(summary) = prompt[BreakingNews](s"Write a summary of about 300 words given the provided context.")
- println(summary)
-
-@main def runMarketNews(): Unit = conversation:
- setContext(s"$currentDate Stock market results, rising stocks, falling stocks")
- val news = prompt[MarketNews]("Write a short summary of the stock market results given the provided context.")
- println(news)
-
-@main def runFermiEstimate(): Unit = conversation:
- setContext("Estimate the number of medical needles in the world")
- val Estimate(needlesInWorld) = prompt[Estimate]("Answer the question with an integer number given the provided context.")
- println(s"Needles in world: $needlesInWorld")
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/context/serpapi/UserQueries.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/context/serpapi/UserQueries.scala
deleted file mode 100644
index 711db19da..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/context/serpapi/UserQueries.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.xebia.functional.xef.examples.scala.context.serpapi
-
-import com.xebia.functional.xef.reasoning.pdf.PDF
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-import scala.io.StdIn.readLine
-
-case class AIResponse(answer: String) derives SerialDescriptor, Decoder
-
-val PdfUrl = "https://people.cs.ksu.edu/~schmidt/705a/Scala/Programming-in-Scala.pdf"
-
-@main def runUserQueries(): Unit = conversation:
- val pdf = PDF(openAI.DEFAULT_CHAT, openAI.DEFAULT_SERIALIZATION, summon[ScalaConversation])
- addContext(Array(pdf.readPDFFromUrl.readPDFFromUrl(PdfUrl).get))
- while (true)
- println("Enter your question: ")
- val AIResponse(answer) = prompt[AIResponse](readLine())
- println(s"$answer\n---\n")
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/images/HybridCity.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/images/HybridCity.scala
deleted file mode 100644
index 1c9a3b4a9..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/images/HybridCity.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.xebia.functional.xef.examples.scala.images
-
-import com.xebia.functional.xef.prompt.Prompt
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-@main def runHybridCity(): Unit = conversation:
- val imageUrls = images(Prompt("A hybrid city of Cádiz, Spain and Seattle, US."))
- println(imageUrls)
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/iteration/AnimalStory.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/iteration/AnimalStory.scala
deleted file mode 100644
index 19e6d433e..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/iteration/AnimalStory.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.xebia.functional.xef.examples.scala.iteration
-
-import com.xebia.functional.xef.prompt.JvmPromptBuilder
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-case class Animal(name: String, habitat: String, diet: String) derives SerialDescriptor, Decoder
-case class Invention(name: String, inventor: String, year: Int, purpose: String) derives SerialDescriptor, Decoder
-
-@main def runAnimalStory(): Unit = conversation:
- val animal = prompt[Animal]("A unique animal species")
- val invention = prompt[Invention]("A groundbreaking invention from the 20th century.")
- println(s"Animal: $animal")
- println(s"Invention: $invention")
- val builder = new JvmPromptBuilder()
- .addSystemMessage("You are a writer for a science fiction magazine.")
- .addUserMessage("Write a short story of 200 words that involves the animal and the invention.")
- val story = promptMessage(builder.build)
- println(story)
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/iteration/ChessGame.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/iteration/ChessGame.scala
deleted file mode 100644
index 42472e1a0..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/iteration/ChessGame.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.xebia.functional.xef.examples.scala.iteration
-
-import com.xebia.functional.xef.prompt.Prompt
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-import scala.annotation.tailrec
-
-case class ChessMove(player: String, move: String) derives SerialDescriptor, Decoder
-case class ChessBoard(board: String) derives SerialDescriptor, Decoder
-case class GameState(ended: Boolean = false, winner: Option[String] = None) derives SerialDescriptor, Decoder
-
-@tailrec
-private def chessGame(moves: List[ChessMove] = Nil, gameState: GameState = new GameState)(using ScalaConversation): (String, ChessMove) =
- if !gameState.ended then
- val currentPlayer = if moves.size % 2 == 0 then "Player 1 (White)" else "Player 2 (Black)"
- val previousMoves = moves.map(m => m.player + ":" + m.move).mkString(", ")
- val movePrompt = moves match {
- case Nil => s"""
- |$currentPlayer, you are playing chess and it's your turn.
- |Make your first move:
- """.stripMargin
- case l => s"""
- |$currentPlayer, you are playing chess and it's your turn.
- |Here are the previous moves: $previousMoves
- |Make your next move:
- """.stripMargin
- }
- println(movePrompt)
- val move = prompt[ChessMove](movePrompt)
- println(s"Move is: $move")
- val boardPrompt =
- s"""
- |Given the following chess moves: $previousMoves,
- |generate a chess board on a table with appropriate emoji representations for each move and piece.
- |Add a brief description of the move and its implications.
- """.stripMargin
- val chessBoard = prompt[ChessBoard](boardPrompt)
- println(s"Current board:\n${chessBoard.board}")
- val gameStatePrompt =
- s"""
- |Given the following chess moves: ${moves.mkString(", ")},
- |has the game ended (win, draw, or stalemate)?
- """.stripMargin
- val gameState = prompt[GameState](gameStatePrompt)
- chessGame(moves :+ move, gameState)
- else (gameState.winner.getOrElse("Something went wrong"), moves.last)
-
-@main def runChessGame(): Unit = conversation:
- val (winner, fMove) = chessGame()
- println(s"Game over. Final move: $fMove, Winner: $winner")
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/serialization/Annotated.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/serialization/Annotated.scala
deleted file mode 100644
index 168599987..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/serialization/Annotated.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.xebia.functional.xef.examples.scala.serialization
-
-import com.xebia.functional.xef.prompt.Prompt
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-@Description("A book")
-case class AnnotatedBook(
- @Description("The name of the book") name: String,
- @Description("The author of the book") author: String,
- @Description("A 50 word paragraph with a summary of this book") summary: String
-) derives SerialDescriptor,
- Decoder
-
-@main def runAnnotatedBook(): Unit = conversation:
- val book = prompt[AnnotatedBook]("To Kill a Mockingbird")
- println(book)
diff --git a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/serialization/Simple.scala b/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/serialization/Simple.scala
deleted file mode 100644
index 2652fd8a3..000000000
--- a/examples/scala/src/main/scala/com/xebia/functional/xef/examples/scala/serialization/Simple.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.xebia.functional.xef.examples.scala.serialization
-
-import com.xebia.functional.xef.scala.conversation.*
-import com.xebia.functional.xef.scala.serialization.*
-import io.circe.Decoder
-
-case class AsciiArt(art: String) derives SerialDescriptor, Decoder
-
-case class Book(title: String, author: String, pages: Int) derives SerialDescriptor, Decoder
-
-case class City(population: Int, description: String) derives SerialDescriptor, Decoder
-
-case class Movie(title: String, genre: String, director: String) derives SerialDescriptor, Decoder
-
-case class Recipe(name: String, ingredients: List[String]) derives SerialDescriptor, Decoder
-
-@main def runAsciiArt(): Unit = conversation:
- val AsciiArt(art) = prompt[AsciiArt]("ASCII art of a cat dancing")
- println(art)
-
-@main def runBook(): Unit = conversation:
- val topic = "functional programming"
- val Book(title, author, pages) = prompt[Book](s"Give me the best-selling book about $topic")
- println(s"The book $title is by $author and has $pages pages.")
-
-@main def runMovie(): Unit = conversation:
- val Movie(title, genre, director) = prompt[Movie]("Inception movie genre and director.")
- println(s"The movie $title is a $genre film directed by $director.")
-
-@main def runCities(): Unit = conversation:
- val cadiz = prompt[City]("Cádiz, Spain")
- val seattle = prompt[City]("Seattle, WA")
- println(s"The population of Cádiz is ${cadiz.population} and the population of Seattle is ${seattle.population}.")
-
-@main def runRecipe(): Unit = conversation:
- val Recipe(name, ingredients) = prompt[Recipe]("Recipe for chocolate chip cookies.")
- println(s"The recipe for $name is $ingredients.")
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/BreakingNews.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/BreakingNews.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/BreakingNews.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/BreakingNews.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/DivergentTasks.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/DivergentTasks.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/DivergentTasks.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/DivergentTasks.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/PDFDocument.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/PDFDocument.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/PDFDocument.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/PDFDocument.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/Weather.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/Weather.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/Weather.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/contexts/Weather.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Simple.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Simple.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Simple.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Simple.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/DigitalDetoxPlanner.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/DigitalDetoxPlanner.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/DigitalDetoxPlanner.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/DigitalDetoxPlanner.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/PromptCrafter.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/PromptCrafter.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/PromptCrafter.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/PromptCrafter.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/RecipeGenerator.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/RecipeGenerator.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/RecipeGenerator.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/RecipeGenerator.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/TravelItinerary.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/TravelItinerary.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/TravelItinerary.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/TravelItinerary.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/WorkoutPlanProgram.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/WorkoutPlanProgram.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/WorkoutPlanProgram.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/expressions/WorkoutPlanProgram.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/fields/Book.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/fields/Book.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/fields/Book.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/fields/Book.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/fields/NewsSummary.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/fields/NewsSummary.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/fields/NewsSummary.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/fields/NewsSummary.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/finetuning/FineTunedModelChat.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/finetuning/FineTunedModelChat.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/finetuning/FineTunedModelChat.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/finetuning/FineTunedModelChat.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpc/Chat.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/gpc/Chat.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/gpc/Chat.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/gpc/Chat.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/memory/ChatWithMemory.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/memory/ChatWithMemory.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/memory/ChatWithMemory.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/memory/ChatWithMemory.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/mlflow/Example.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/mlflow/Example.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/mlflow/Example.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/mlflow/Example.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/ExpertSystemExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/ExpertSystemExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/ExpertSystemExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/ExpertSystemExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/PromptEvaluationExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/PromptEvaluationExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/PromptEvaluationExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/PromptEvaluationExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/StructuredInput.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/StructuredInput.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/StructuredInput.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/prompts/StructuredInput.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CodeExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CodeExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CodeExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CodeExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CreatePRDescription.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CreatePRDescription.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CreatePRDescription.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/CreatePRDescription.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActWikipediaExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActWikipediaExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActWikipediaExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ReActWikipediaExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/SerpApiExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/SerpApiExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/SerpApiExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/SerpApiExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/TextExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/TextExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/TextExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/TextExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ToolSelectionExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ToolSelectionExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ToolSelectionExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/ToolSelectionExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchByParamsExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchByParamsExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchByParamsExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchByParamsExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/reasoning/WikipediaSearchExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/ChessAI.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/ChessAI.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/ChessAI.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/ChessAI.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Movie.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Movie.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Movie.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Movie.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Recipe.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Recipe.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Recipe.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/serialization/Recipe.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/sql/MysqlExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/sql/MysqlExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/sql/MysqlExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/sql/MysqlExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/sql/README.md b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/sql/README.md
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/sql/README.md
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/sql/README.md
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/OpenAIStreamingExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/OpenAIStreamingExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/OpenAIStreamingExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/OpenAIStreamingExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/SpaceCraft.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/SpaceCraft.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/SpaceCraft.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/SpaceCraft.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/StreamingFunctionsExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/StreamingFunctionsExample.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/StreamingFunctionsExample.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/streaming/StreamingFunctionsExample.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Checker.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Checker.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Checker.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Checker.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/ControlSignal.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/ControlSignal.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/ControlSignal.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/ControlSignal.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Critique.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Critique.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Critique.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Critique.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Main.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Main.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Main.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Main.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Problem.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Problem.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Problem.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Problem.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Rendering.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Rendering.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Rendering.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Rendering.kt
diff --git a/examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Solution.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Solution.kt
similarity index 100%
rename from examples/kotlin/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Solution.kt
rename to examples/src/main/kotlin/com/xebia/functional/xef/conversation/tot/Solution.kt
diff --git a/examples/kotlin/src/main/resources/documents/weather.csv b/examples/src/main/resources/documents/weather.csv
similarity index 100%
rename from examples/kotlin/src/main/resources/documents/weather.csv
rename to examples/src/main/resources/documents/weather.csv
diff --git a/examples/scala/src/main/resources/logback.xml b/examples/src/main/resources/logback.xml
similarity index 100%
rename from examples/scala/src/main/resources/logback.xml
rename to examples/src/main/resources/logback.xml
diff --git a/examples/kotlin/src/main/resources/sql/data/mysql_diagram.png b/examples/src/main/resources/sql/data/mysql_diagram.png
similarity index 100%
rename from examples/kotlin/src/main/resources/sql/data/mysql_diagram.png
rename to examples/src/main/resources/sql/data/mysql_diagram.png
diff --git a/examples/kotlin/src/main/resources/sql/data/mysql_dump.sql b/examples/src/main/resources/sql/data/mysql_dump.sql
similarity index 100%
rename from examples/kotlin/src/main/resources/sql/data/mysql_dump.sql
rename to examples/src/main/resources/sql/data/mysql_dump.sql
diff --git a/examples/kotlin/src/main/resources/sql/stack.yml b/examples/src/main/resources/sql/stack.yml
similarity index 100%
rename from examples/kotlin/src/main/resources/sql/stack.yml
rename to examples/src/main/resources/sql/stack.yml
diff --git a/gpt4all-kotlin/README.MD b/gpt4all-kotlin/README.MD
deleted file mode 100644
index 8f937af29..000000000
--- a/gpt4all-kotlin/README.MD
+++ /dev/null
@@ -1,24 +0,0 @@
-# gpt4all-kotlin
-
-Kotlin multiplatform bindings for GP4All.
-
-Right now, only `Kotlin/JVM` platform is supported via JNA.
-
-# Configuration
-
-By default, the library is using last model backend built from: [c5de9634c90bba5b528a6fceebc9a48a7f2e2597](https://github.com/nomic-ai/gpt4all/tree/c5de9634c90bba5b528a6fceebc9a48a7f2e2597/gpt4all-backend), which is included inside `src/commonMain/resources` folder.
-
-Right now, only `darwin-aarch64`, `darwin-x86-64` and `linux-x86-64` platforms are included.
-
-It is also possible to use a GPT4All local installation by setting the `jna.library.path` system property to the path where the model backend is located: `/lib`
-
-# How to use
-
-In order to use the library, apart from the previous configuration, you must have downloaded some GPT4All model in your local, and pass both the model path and the model type:
-
-```kotlin
-GPT4All(Path.of("models/gpt4all/ggml-gpt4all-j-v1.3-groovy.bin"), GPT4AllModel.Type.GPTJ).use { gpt4All ->
- val promptMessage = Message(Message.Role.USER, "Some prompt goes here")
- gpt4All.chatCompletion(listOf(promptMessage))
-}
-```
diff --git a/gpt4all-kotlin/build.gradle.kts b/gpt4all-kotlin/build.gradle.kts
deleted file mode 100644
index f81c495e6..000000000
--- a/gpt4all-kotlin/build.gradle.kts
+++ /dev/null
@@ -1,89 +0,0 @@
-plugins {
- alias(libs.plugins.kotlin.multiplatform)
- alias(libs.plugins.kotest.multiplatform)
- alias(libs.plugins.spotless)
- alias(libs.plugins.arrow.gradle.publish)
- alias(libs.plugins.semver.gradle)
- alias(libs.plugins.kotlinx.serialization)
- alias(libs.plugins.detekt)
-}
-
-dependencies { detektPlugins(project(":detekt-rules")) }
-
-repositories { mavenCentral() }
-
-java {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
- toolchain { languageVersion = JavaLanguageVersion.of(11) }
-}
-
-detekt {
- toolVersion = "1.23.1"
- source.setFrom(files("src/commonMain/kotlin", "src/jvmMain/kotlin"))
- config.setFrom("../config/detekt/detekt.yml")
- autoCorrect = true
-}
-
-kotlin {
- jvm {
- compilations {
- val integrationTest by compilations.creating {
- // Create a test task to run the tests produced by this compilation:
- tasks.register("integrationTest") {
- description = "Run the integration tests"
- group = "verification"
- classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs
- testClassesDirs = output.classesDirs
- testLogging { events("passed") }
- }
- }
- val test by compilations.getting
- integrationTest.associateWith(test)
- }
- }
- js(IR) { browser() }
- sourceSets {
- val commonMain by getting { dependencies { implementation(projects.xefCore) } }
- commonTest {
- dependencies {
- implementation(kotlin("test"))
- implementation(libs.kotest.property)
- implementation(libs.kotest.framework)
- implementation(libs.kotest.assertions)
- }
- }
- val jvmMain by getting {
- dependencies {
- implementation(libs.gpt4all.java.bindings)
- implementation(libs.ai.djl.huggingface.tokenizers)
- }
- }
- val jsMain by getting {}
- val jvmTest by getting { dependencies { implementation(libs.kotest.junit5) } }
- }
-}
-
-tasks {
- withType().configureEach {
- dependsOn(":detekt-rules:assemble")
- autoCorrect = true
- }
- named("detektJvmMain") {
- dependsOn(":detekt-rules:assemble")
- getByName("build").dependsOn(this)
- }
- named("detekt") {
- dependsOn(":detekt-rules:assemble")
- getByName("build").dependsOn(this)
- }
- withType().configureEach {
- maxParallelForks = Runtime.getRuntime().availableProcessors()
- useJUnitPlatform()
- testLogging {
- setExceptionFormat("full")
- setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError"))
- }
- }
- withType { dependsOn(withType()) }
-}
diff --git a/gpt4all-kotlin/src/commonMain/kotlin/com/xebia/functional/gpt4all/models.kt b/gpt4all-kotlin/src/commonMain/kotlin/com/xebia/functional/gpt4all/models.kt
deleted file mode 100644
index 33be8d3f8..000000000
--- a/gpt4all-kotlin/src/commonMain/kotlin/com/xebia/functional/gpt4all/models.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.xebia.functional.gpt4all
-
-data class GenerationConfig(
- val logitsSize: Int = 0,
- val tokensSize: Int = 0,
- val nPast: Int = 0,
- val nCtx: Int = 4096,
- val nPredict: Int = 128,
- val topK: Int = 40,
- val topP: Double = 0.95,
- val temp: Double = 0.28,
- val nBatch: Int = 8,
- val repeatPenalty: Double = 1.1,
- val repeatLastN: Int = 64,
- val contextErase: Double = 0.5
-)
diff --git a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/Conversation.kt b/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/Conversation.kt
deleted file mode 100644
index fc9b74165..000000000
--- a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/Conversation.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.xebia.functional.gpt4all
-
-import com.xebia.functional.xef.conversation.Conversation
-import com.xebia.functional.xef.metrics.LogsMetric
-import com.xebia.functional.xef.metrics.Metric
-import com.xebia.functional.xef.store.LocalVectorStore
-import com.xebia.functional.xef.store.VectorStore
-
-suspend inline fun conversation(
- store: VectorStore = LocalVectorStore(HuggingFaceLocalEmbeddings.DEFAULT),
- metric: Metric = Metric.EMPTY,
- noinline block: suspend Conversation.() -> A
-): A = block(Conversation(store, metric))
diff --git a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/GPT4All.kt b/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/GPT4All.kt
deleted file mode 100644
index 84e97316f..000000000
--- a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/GPT4All.kt
+++ /dev/null
@@ -1,197 +0,0 @@
-package com.xebia.functional.gpt4all
-
-import ai.djl.training.util.DownloadUtils
-import ai.djl.training.util.ProgressBar
-import com.hexadevlabs.gpt4all.LLModel
-import com.xebia.functional.tokenizer.EncodingType
-import com.xebia.functional.tokenizer.ModelType
-import com.xebia.functional.xef.conversation.Conversation
-import com.xebia.functional.xef.conversation.PlatformConversation
-import com.xebia.functional.xef.llm.Chat
-import com.xebia.functional.xef.llm.Completion
-import com.xebia.functional.xef.llm.models.chat.*
-import com.xebia.functional.xef.llm.models.text.CompletionChoice
-import com.xebia.functional.xef.llm.models.text.CompletionRequest
-import com.xebia.functional.xef.llm.models.text.CompletionResult
-import com.xebia.functional.xef.llm.models.usage.Usage
-import com.xebia.functional.xef.metrics.LogsMetric
-import com.xebia.functional.xef.metrics.Metric
-import com.xebia.functional.xef.store.LocalVectorStore
-import com.xebia.functional.xef.store.VectorStore
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
-import kotlinx.coroutines.flow.*
-import java.io.OutputStream
-import java.io.PrintStream
-import java.nio.charset.StandardCharsets
-import java.nio.file.Files
-import java.nio.file.Path
-import java.util.*
-import kotlin.io.path.name
-
-
-interface GPT4All : AutoCloseable, Chat, Completion {
-
- override fun close() {
- }
-
- companion object {
-
- @JvmSynthetic
- suspend inline fun conversation(
- store: VectorStore = LocalVectorStore(HuggingFaceLocalEmbeddings.DEFAULT),
- metric: Metric = Metric.EMPTY,
- noinline block: suspend Conversation.() -> A
- ): A = block(conversation(store))
-
- @JvmSynthetic
- suspend fun conversation(
- block: suspend Conversation.() -> A
- ): A = block(conversation())
-
- @JvmStatic
- @JvmOverloads
- fun conversation(
- store: VectorStore = LocalVectorStore(HuggingFaceLocalEmbeddings.DEFAULT),
- metric: Metric = Metric.EMPTY
- ): PlatformConversation = Conversation(store, metric)
-
- operator fun invoke(
- url: String,
- path: Path
- ): GPT4All = object : GPT4All {
-
- init {
- if (!Files.exists(path)) {
- DownloadUtils.download(url, path.toFile().absolutePath, ProgressBar())
- }
- }
-
- val llModel = LLModel(path)
-
- override fun copy(modelType: ModelType) =
- GPT4All(url, path)
-
- override suspend fun createCompletion(request: CompletionRequest): CompletionResult =
- with(request) {
- val config = LLModel.config()
- .withTopP(request.topP?.toFloat() ?: 0.4f)
- .withTemp(request.temperature?.toFloat() ?: 0f)
- .withRepeatPenalty(request.frequencyPenalty.toFloat())
- .build()
- val response: String = generateCompletion(prompt, config, request.streamToStandardOut)
- return CompletionResult(
- UUID.randomUUID().toString(),
- path.name,
- System.currentTimeMillis(),
- path.name,
- listOf(CompletionChoice(response, 0, null, null)),
- Usage.ZERO
- )
- }
-
- override suspend fun createChatCompletion(request: ChatCompletionRequest): ChatCompletionResponse =
- with(request) {
- val prompt: String = messages.buildPrompt()
- val config = LLModel.config()
- .withTopP(request.topP.toFloat())
- .withTemp(request.temperature.toFloat())
- .withRepeatPenalty(request.frequencyPenalty.toFloat())
- .build()
- val response: String = generateCompletion(prompt, config, request.streamToStandardOut)
- return ChatCompletionResponse(
- UUID.randomUUID().toString(),
- path.name,
- System.currentTimeMillis().toInt(),
- path.name,
- Usage.ZERO,
- listOf(Choice(Message(Role.ASSISTANT, response, Role.ASSISTANT.name), null, 0)),
- )
- }
-
- /**
- * Creates chat completions based on the given ChatCompletionRequest.
- *
- * hacks the System.out until https://github.com/nomic-ai/gpt4all/pull/1126 is accepted or merged
- *
- * @param request The ChatCompletionRequest containing the necessary information for creating completions.
- * @return A Flow of ChatCompletionChunk objects representing the generated chat completions.
- */
- override suspend fun createChatCompletions(request: ChatCompletionRequest): Flow {
- val prompt: String = request.messages.buildPrompt()
- val config = with(request) {
- LLModel.config()
- .withTopP(topP.toFloat())
- .withTemp(temperature.toFloat())
- .withRepeatPenalty(frequencyPenalty.toFloat())
- .build()
- }
-
- val channel = Channel(capacity = UNLIMITED)
- val outputStream = object : OutputStream() {
- override fun write(b: Int) {
- val c = b.toChar()
- channel.trySend(c.toString())
- }
- }
-
- val originalOut = System.out // Save the original standard output
-
- fun toChunk(text: String?): ChatCompletionChunk = ChatCompletionChunk(
- UUID.randomUUID().toString(),
- System.currentTimeMillis().toInt(),
- path.name,
- listOf(ChatChunk(delta = ChatDelta(Role.ASSISTANT, text))),
- Usage.ZERO,
- )
-
- return merge(
- emptyFlow()
- .onStart {
- val printStream = PrintStream(outputStream, true, StandardCharsets.UTF_8)
- System.setOut(printStream) // Set the standard output to the print stream
- generateCompletion(prompt, config, request.streamToStandardOut)
- channel.close()
- System.setOut(originalOut) // Restore the original standard output
- }
- .flowOn(Dispatchers.IO),
- channel
- .consumeAsFlow()
- .map(::toChunk)
- )
- }
-
- override fun tokensFromMessages(messages: List): Int {
- return 0
- }
-
- override val name: String = path.name
-
- override fun close(): Unit = llModel.close()
-
- override val modelType: ModelType = ModelType.LocalModel(name, EncodingType.CL100K_BASE, 4096)
-
- private fun List.buildPrompt(): String {
- val messages: String = joinToString("") { message ->
- when (message.role) {
- Role.SYSTEM -> message.content
- Role.USER -> "\n### Human: ${message.content}"
- Role.ASSISTANT -> "\n### Response: ${message.content}"
- }
- }
- return "$messages\n### Response:"
- }
-
- private fun generateCompletion(
- prompt: String,
- config: LLModel.GenerationConfig,
- stream: Boolean,
- ): String {
- return llModel.generate(prompt, config, stream)
- }
- }
-
- }
-
-}
diff --git a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/HuggingFaceLocalEmbeddings.kt b/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/HuggingFaceLocalEmbeddings.kt
deleted file mode 100644
index 679294158..000000000
--- a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/HuggingFaceLocalEmbeddings.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.xebia.functional.gpt4all
-
-import ai.djl.huggingface.tokenizers.HuggingFaceTokenizer
-import com.xebia.functional.tokenizer.ModelType
-import com.xebia.functional.xef.llm.Embeddings
-import com.xebia.functional.xef.llm.models.embeddings.Embedding
-import com.xebia.functional.xef.llm.models.embeddings.EmbeddingRequest
-import com.xebia.functional.xef.llm.models.embeddings.EmbeddingResult
-import com.xebia.functional.xef.llm.models.embeddings.RequestConfig
-import com.xebia.functional.xef.llm.models.usage.Usage
-
-class HuggingFaceLocalEmbeddings(
- override val modelType: ModelType,
- private val artifact: String,
-) : Embeddings {
-
- private val tokenizer = HuggingFaceTokenizer.newInstance("${modelType.name}/$artifact")
-
- override val name: String = HuggingFaceLocalEmbeddings::class.java.canonicalName
-
- override fun copy(modelType: ModelType) =
- HuggingFaceLocalEmbeddings(modelType, artifact)
-
- override suspend fun createEmbeddings(request: EmbeddingRequest): EmbeddingResult {
- val embedings = tokenizer.batchEncode(request.input)
- return EmbeddingResult(
- data = embedings.map { Embedding(it.ids.map { it.toFloat() }) },
- usage = Usage.ZERO
- )
- }
-
- override suspend fun embedDocuments(
- texts: List,
- requestConfig: RequestConfig,
- chunkSize: Int?
- ): List =
- tokenizer.batchEncode(texts).map { em -> Embedding(em.ids.map { it.toFloat() }) } // TODO we need to remove the index
-
- companion object {
- @JvmField
- val DEFAULT = HuggingFaceLocalEmbeddings(ModelType.TODO("sentence-transformers"), artifact = "msmarco-distilbert-dot-v5")
- }
-}
diff --git a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/HuggingFaceUtils.kt b/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/HuggingFaceUtils.kt
deleted file mode 100644
index ac2f1f4fb..000000000
--- a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/HuggingFaceUtils.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.xebia.functional.gpt4all
-
-fun huggingFaceUrl(name: String, artifact:String, extension: String): String =
- "https://huggingface.co/$name/$artifact/resolve/main/$artifact.$extension"
diff --git a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/Models.kt b/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/Models.kt
deleted file mode 100644
index 392a29bf8..000000000
--- a/gpt4all-kotlin/src/jvmMain/kotlin/com/xebia/functional/gpt4all/Models.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.xebia.functional.gpt4all
-
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.Json
-import java.net.URL
-
-@Serializable
-data class Gpt4AllModel(
- val order: String,
- val md5sum: String,
- val name: String,
- val filename: String,
- val filesize: String,
- val requires: String? = null,
- val ramrequired: String,
- val parameters: String,
- val quant: String,
- val type: String,
- val description: String,
- val disableGUI: String? = null,
- val url: String? = null,
- val promptTemplate: String? = null,
- val systemPrompt: String? = null,
-) {
- companion object {
- private val url = "https://raw.githubusercontent.com/nomic-ai/gpt4all/main/gpt4all-chat/metadata/models.json"
- val supportedModels : List by lazy {
- // fetch the content as string from https://raw.githubusercontent.com/nomic-ai/gpt4all/main/gpt4all-chat/metadata/models.json
- val json = URL(url).readText()
- // parse the json string into a list of Model objects
- Json.decodeFromString>(json)
- }
- }
-}
diff --git a/gpt4all-kotlin/src/jvmTest/kotlin/com/xebia/functional/xef/tests/GPT4ALLModelSpec.kt b/gpt4all-kotlin/src/jvmTest/kotlin/com/xebia/functional/xef/tests/GPT4ALLModelSpec.kt
deleted file mode 100644
index 50d8c3ede..000000000
--- a/gpt4all-kotlin/src/jvmTest/kotlin/com/xebia/functional/xef/tests/GPT4ALLModelSpec.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.xebia.functional.xef.tests
-
-import com.xebia.functional.gpt4all.Gpt4AllModel
-import io.kotest.core.spec.style.StringSpec
-import io.kotest.matchers.ints.shouldBeGreaterThan
-
-class GPT4ALLModelSpec :
- StringSpec({
- "should return a list of supported models by GPT4ALL" {
- Gpt4AllModel.supportedModels.size shouldBeGreaterThan 0
- }
- })
diff --git a/gradle.properties b/gradle.properties
index a0979c287..e42fb3212 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,7 +4,7 @@ kotlin.native.cacheKind=none
project.group=com.xebia
pom.name=xef
-pom.description=Building applications with LLMs through composability, in Kotlin and Scala
+pom.description=Building applications with LLMs through composability in Kotlin
pom.url=https://github.com/xebia-functional/xef
pom.license.name=The Apache Software License, Version 2.0
pom.license.url=https://www.apache.org/licenses/LICENSE-2.0.txt
@@ -21,5 +21,3 @@ systemProp.org.gradle.unsafe.kotlin.assignment=true
# Workaround to disable Dokka setup from Arrow Gradle Config
dokkaEnabled=false
-
-scalaVersion=3.3.1
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 8c36b5552..b9b0801e8 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -20,23 +20,14 @@ dokka = "1.9.10"
logback = "1.4.11"
node-gradle = "7.0.1"
kotlinx-coroutines = "1.7.3"
-scalaMultiversion = "2.0.6"
-circe = "0.14.6"
-catsEffect = "3.6-0142603"
-munit = "0.7.29"
-munitCatsEffect = "1.0.7"
scrapeit = "1.1.5"
rssreader = "3.5.0"
lucene = "9.8.0"
-assertj = "3.24.2"
junit = "5.10.0"
pdfbox = "3.0.0"
mysql = "8.0.33"
semverGradle = "0.5.0-rc.5"
-scala = "3.3.1"
openai-client-version = "3.5.1"
-gpt4all-java = "1.1.5"
-ai-djl = "0.24.0"
jackson = "2.15.3"
jsonschema = "4.32.0"
jakarta = "3.0.2"
@@ -65,7 +56,6 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa
kotlinx-serialization-hocon = { module = "org.jetbrains.kotlinx:kotlinx-serialization-hocon", version.ref = "kotlinx-json" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref="kotlinx-coroutines" }
kotlinx-coroutines-reactive = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-reactive", version.ref="kotlinx-coroutines" }
-kotlinx-coroutines-jdk8 = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8", version.ref="kotlinx-coroutines" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
ktor-utils = { module = "io.ktor:ktor-utils", version.ref = "ktor" }
ktor-http = { module = "io.ktor:ktor-http", version.ref = "ktor" }
@@ -104,24 +94,15 @@ hikari = { module = "com.zaxxer:HikariCP", version.ref = "hikari" }
postgresql = { module = "org.postgresql:postgresql", version.ref = "postgresql" }
testcontainers-postgresql = { module = "org.testcontainers:postgresql", version.ref = "testcontainers" }
logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
-circe = { module = "io.circe:circe-generic_3", version.ref = "circe" }
-circe-parser = { module = "io.circe:circe-parser_3", version.ref = "circe" }
-cats-effect = { module = "org.typelevel:cats-effect_3", version.ref = "catsEffect" }
-munit-core = { module = "org.scalameta:munit_3", version.ref = "munit" }
-munit-cats-effect = { module = "org.typelevel:munit-cats-effect-3_3", version.ref = "munitCatsEffect" }
skrape = { module = "it.skrape:skrapeit", version.ref = "scrapeit" }
skrape-browser-fetcher = { module = "it.skrape:skrapeit-browser-fetcher", version.ref = "scrapeit" }
skrape-async-fetcher = { module = "it.skrape:skrapeit-asyn-fetcher", version.ref = "scrapeit" }
rss-reader = { module = "com.apptasticsoftware:rssreader", version.ref = "rssreader" }
lucene-core = { module = "org.apache.lucene:lucene-core", version.ref = "lucene" }
lucene-queries = { module = "org.apache.lucene:lucene-queries", version.ref = "lucene" }
-assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" }
apache-pdf-box = { module = "org.apache.pdfbox:pdfbox", version.ref = "pdfbox" }
jdbc-mysql-connector = { module = "mysql:mysql-connector-java", version.ref = "mysql" }
-scala-lang = { module = "org.scala-lang:scala3-library_3", version.ref = "scala" }
openai-client = { module = "com.aallam.openai:openai-client", version.ref = "openai-client-version" }
-gpt4all-java-bindings = { module = "com.hexadevlabs:gpt4all-java-binding", version.ref = "gpt4all-java" }
-ai-djl-huggingface-tokenizers = { module = "ai.djl.huggingface:tokenizers", version.ref = "ai-djl" }
jackson = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
jackson-schema = { module = "com.github.victools:jsonschema-generator", version.ref = "jsonschema" }
jackson-schema-jakarta = { module = "com.github.victools:jsonschema-module-jakarta-validation", version.ref = "jsonschema" }
@@ -155,10 +136,8 @@ spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
arrow-gradle-nexus = { id = "io.arrow-kt.arrow-gradle-config-nexus", version.ref = "arrowGradle" }
arrow-gradle-publish = { id = "io.arrow-kt.arrow-gradle-config-publish", version.ref = "arrowGradle" }
-scala-multiversion = { id = "com.adtran.scala-multiversion-plugin", version.ref = "scalaMultiversion" }
kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotest" }
semver-gradle = { id="com.javiersc.semver", version.ref="semverGradle" }
-suspend-transform-plugin = { id="love.forte.plugin.suspend-transform", version.ref="suspend-transform" }
resources = { id="com.goncalossilva.resources", version.ref="resources-kmp" }
detekt = { id="io.gitlab.arturbosch.detekt", version.ref="detekt"}
node-gradle = { id = "com.github.node-gradle.node", version.ref = "node-gradle" }
diff --git a/java/README.md b/java/README.md
deleted file mode 100644
index 380f6937b..000000000
--- a/java/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# xef.ai for Java
-
-Build the project locally, from the project root:
-
-```shell
-./gradlew build
-```
-
-## Java Spotless
-
-The Java module uses the [spotless](https://github.com/diffplug/spotless/tree/main/plugin-gradle#java) plugin.
-Therefore, the previous command (`./gradlew build`) will fail in case there is any formatting issue. To apply format, you can run the following command:
-
-```shell
-./gradlew spotlessApply
-```
-
-## Examples
-
-Check out some use case at the [Java examples](../examples/java) folder.
-
-### Running the Examples
-
-How to run the examples (from IntelliJ IDEA):
-
-* Set Env variable: `OPENAI_TOKEN=xxx`
diff --git a/java/build.gradle.kts b/java/build.gradle.kts
deleted file mode 100644
index 99ba21ab2..000000000
--- a/java/build.gradle.kts
+++ /dev/null
@@ -1,32 +0,0 @@
-@file:Suppress("DSL_SCOPE_VIOLATION")
-
-plugins {
- `java-library`
- `maven-publish`
- signing
- `xef-java-publishing-conventions`
- alias(libs.plugins.semver.gradle)
- alias(libs.plugins.spotless)
-}
-
-dependencies {
- api(projects.xefCore)
- api(projects.xefOpenai)
- api(projects.xefPdf)
- api(projects.xefSql)
- api(libs.jdbc.mysql.connector)
- api(libs.jackson)
- api(libs.jackson.schema)
- api(libs.jackson.schema.jakarta)
- api(libs.jakarta.validation)
- api(libs.kotlinx.coroutines.reactive)
-}
-
-java {
- withJavadocJar()
- withSourcesJar()
-}
-
-tasks.withType().configureEach { useJUnit() }
-
-tasks.withType { dependsOn(tasks.withType()) }
diff --git a/java/src/main/java/com/xebia/functional/xef/java/auto/Empty.java b/java/src/main/java/com/xebia/functional/xef/java/auto/Empty.java
deleted file mode 100644
index 82c339a6b..000000000
--- a/java/src/main/java/com/xebia/functional/xef/java/auto/Empty.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.xebia.functional.xef.java.auto;
-
-/**
- * Module placeholder
- */
-public class Empty {
-}
diff --git a/kotlin/build.gradle.kts b/kotlin/build.gradle.kts
deleted file mode 100644
index 42afef530..000000000
--- a/kotlin/build.gradle.kts
+++ /dev/null
@@ -1,102 +0,0 @@
-import org.jetbrains.dokka.gradle.DokkaTask
-
-repositories { mavenCentral() }
-
-plugins {
- base
- alias(libs.plugins.kotlin.multiplatform)
- alias(libs.plugins.kotest.multiplatform)
- alias(libs.plugins.kotlinx.serialization)
- alias(libs.plugins.spotless)
- alias(libs.plugins.dokka)
- alias(libs.plugins.arrow.gradle.publish)
- alias(libs.plugins.semver.gradle)
- alias(libs.plugins.detekt)
-}
-
-dependencies { detektPlugins(project(":detekt-rules")) }
-
-detekt {
- toolVersion = "1.23.1"
- source.setFrom(files("src/commonMain/kotlin", "src/jvmMain/kotlin"))
- config.setFrom("../config/detekt/detekt.yml")
- autoCorrect = true
-}
-
-java {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
- toolchain { languageVersion = JavaLanguageVersion.of(11) }
-}
-
-kotlin {
- jvm()
- js(IR) {
- browser()
- nodejs()
- }
- linuxX64()
- macosX64()
- macosArm64()
- mingwX64()
- sourceSets {
- val commonMain by getting {
- dependencies {
- api(projects.xefCore)
- api(projects.xefOpenai)
- }
- }
- }
-}
-
-spotless {
- kotlin {
- target("**/*.kt")
- ktfmt().googleStyle()
- }
-}
-
-tasks {
- withType().configureEach {
- dependsOn(":detekt-rules:assemble")
- autoCorrect = true
- }
- named("detektJvmMain") {
- dependsOn(":detekt-rules:assemble")
- getByName("build").dependsOn(this)
- }
- named("detekt") {
- dependsOn(":detekt-rules:assemble")
- getByName("build").dependsOn(this)
- }
- withType().configureEach {
- maxParallelForks = Runtime.getRuntime().availableProcessors()
- useJUnitPlatform()
- testLogging {
- setExceptionFormat("full")
- setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError"))
- }
- }
- withType().configureEach {
- kotlin.sourceSets.forEach { kotlinSourceSet ->
- dokkaSourceSets.named(kotlinSourceSet.name) {
- perPackageOption {
- matchingRegex.set(".*\\.internal.*")
- suppress.set(true)
- }
- skipDeprecated.set(true)
- reportUndocumented.set(false)
- val baseUrl = checkNotNull(project.properties["pom.smc.url"]?.toString())
- kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir ->
- sourceLink {
- localDirectory.set(srcDir)
- remoteUrl.set(uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}").toURL())
- remoteLineSuffix.set("#L")
- }
- }
- }
- }
- }
-}
-
-tasks.withType { dependsOn(tasks.withType()) }
diff --git a/kotlin/src/commonMain/kotlin/com/xebia/functional/xef/conversation/DSLExtensions.kt b/kotlin/src/commonMain/kotlin/com/xebia/functional/xef/conversation/DSLExtensions.kt
deleted file mode 100644
index d0a8ebcc0..000000000
--- a/kotlin/src/commonMain/kotlin/com/xebia/functional/xef/conversation/DSLExtensions.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.xebia.functional.xef.conversation
-
-import com.xebia.functional.xef.llm.Embeddings
-import com.xebia.functional.xef.metrics.Metric
-import com.xebia.functional.xef.store.LocalVectorStore
-import com.xebia.functional.xef.store.VectorStore
-
-/**
- * Executes a conversation with the given embeddings and vector store.
- *
- * @param embeddings The embeddings used for the conversation.
- * @param store The vector store used for the conversation. Defaults to a local vector store.
- * @param block The block of code representing the conversation logic.
- * @return The result of the conversation execution.
- */
-suspend inline fun conversation(
- embeddings: Embeddings,
- store: VectorStore = LocalVectorStore(embeddings),
- metric: Metric = Metric.EMPTY,
- noinline block: suspend Conversation.() -> A
-): A = block(Conversation(store, metric))
diff --git a/models/gpt4all/get-models.sh b/models/gpt4all/get-models.sh
deleted file mode 100755
index 32afa866d..000000000
--- a/models/gpt4all/get-models.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env bash
-
-curl --url https://gpt4all.io/models/ggml-gpt4all-j-v1.3-groovy.bin --output ./ggml-gpt4all-j-v1.3-groovy.bin
diff --git a/scala/.scalafmt.conf b/scala/.scalafmt.conf
deleted file mode 100644
index 038d0ede0..000000000
--- a/scala/.scalafmt.conf
+++ /dev/null
@@ -1,36 +0,0 @@
-# tune this file as appropriate to your style! see: https://olafurpg.github.io/scalafmt/#Configuration
-
-version = "3.7.15"
-
-runner.dialect = "scala3"
-
-maxColumn = 150
-
-continuationIndent.callSite = 2
-
-newlines {
- sometimesBeforeColonInMethodReturnType = false
-}
-
-align {
- arrowEnumeratorGenerator = false
- ifWhileOpenParen = false
- openParenCallSite = false
- openParenDefnSite = false
- tokens = ["%", "%%"]
-}
-
-docstrings.style = Asterisk
-
-rewrite {
- rules = [SortImports, RedundantBraces]
- redundantBraces.maxLines = 1
-}
-
-optIn {
- breaksInsideChains = true
-}
-
-project.excludeFilters = [
- "metals.sbt"
-]
diff --git a/scala/README.md b/scala/README.md
deleted file mode 100644
index e74c18873..000000000
--- a/scala/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# xef.ai for Scala
-
-Build the project locally, from the project root:
-
-```shell
-./gradlew build
-```
-
-## Scalafmt
-
-The Scala module uses the [spotless](https://github.com/diffplug/spotless/tree/main/plugin-gradle#scala) plugin.
-Therefore, the previous command (`./gradlew build`) will fail if there are any formatting issues.
-To apply formatting, you can run the following command:
-
-```shell
-./gradlew spotlessApply
-```
-
-## Examples
-
-Check out some use case at the [Scala examples](../examples/scala) folder.
-
-### Running the Examples
-
-How to run the examples (from IntelliJ IDEA):
-
-* Set Java version 20 or above
-* Set VM options: `--enable-preview` (if using Java 20 specifically)
-* Set Env variable: `OPENAI_TOKEN=xxx`
diff --git a/scala/build.gradle.kts b/scala/build.gradle.kts
deleted file mode 100644
index e17e0c4c4..000000000
--- a/scala/build.gradle.kts
+++ /dev/null
@@ -1,38 +0,0 @@
-@file:Suppress("DSL_SCOPE_VIOLATION")
-
-plugins {
- scala
- `maven-publish`
- signing
- alias(libs.plugins.semver.gradle)
- alias(libs.plugins.spotless)
- `xef-scala-publishing-conventions`
-}
-
-dependencies {
- implementation(projects.xefCore)
- implementation(projects.xefOpenai)
- implementation(libs.kotlinx.coroutines.reactive)
- // TODO split to separate Scala library
- implementation(projects.xefPdf)
- implementation(libs.circe.parser)
- implementation(libs.circe)
- implementation(libs.scala.lang)
- implementation(libs.logback)
- testImplementation(libs.munit.core)
-}
-
-java {
- sourceCompatibility = JavaVersion.VERSION_21
- targetCompatibility = JavaVersion.VERSION_21
- toolchain { languageVersion = JavaLanguageVersion.of(21) }
- withSourcesJar()
-}
-
-tasks.withType().configureEach { useJUnit() }
-
-tasks.withType {
- scalaCompileOptions.additionalParameters = listOf("-Wunused:all", "-Wvalue-discard")
-}
-
-spotless { scala { scalafmt("3.7.15").configFile(".scalafmt.conf") } }
diff --git a/scala/src/main/resources/logback.xml b/scala/src/main/resources/logback.xml
deleted file mode 100644
index 8b62c8b02..000000000
--- a/scala/src/main/resources/logback.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/scala/src/main/scala/com/xebia/functional/xef/scala/conversation/package.scala b/scala/src/main/scala/com/xebia/functional/xef/scala/conversation/package.scala
deleted file mode 100644
index c30cc9396..000000000
--- a/scala/src/main/scala/com/xebia/functional/xef/scala/conversation/package.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.xebia.functional.xef.scala.conversation
-
-import com.xebia.functional.xef.conversation.*
-import com.xebia.functional.xef.conversation.llm.openai.*
-import com.xebia.functional.xef.llm.*
-import com.xebia.functional.xef.llm.models.images.*
-import com.xebia.functional.xef.metrics.*
-import com.xebia.functional.xef.prompt.Prompt
-import com.xebia.functional.xef.scala.serialization.*
-import com.xebia.functional.xef.store.*
-import io.circe.Decoder
-import io.circe.parser.parse
-import org.reactivestreams.*
-
-import java.util.UUID.*
-import java.util.concurrent.LinkedBlockingQueue
-import scala.jdk.CollectionConverters.*
-
-class ScalaConversation(store: VectorStore, metric: Metric, conversationId: ConversationId) extends JVMConversation(store, metric, conversationId)
-
-def addContext(context: Array[String])(using conversation: ScalaConversation): Unit =
- conversation.addContextFromArray(context).join()
-
-def prompt[A: Decoder: SerialDescriptor](prompt: Prompt, chat: ChatWithFunctions = OpenAI.fromEnvironment().DEFAULT_SERIALIZATION)(using
- conversation: ScalaConversation
-): A =
- conversation.prompt(chat, prompt, chat.chatFunction(SerialDescriptor[A].serialDescriptor), fromJson).join()
-
-def promptMessage(prompt: Prompt, chat: Chat = OpenAI.fromEnvironment().DEFAULT_CHAT)(using conversation: ScalaConversation): String =
- conversation.promptMessage(chat, prompt).join()
-
-def promptMessages(prompt: Prompt, chat: Chat = OpenAI.fromEnvironment().DEFAULT_CHAT)(using conversation: ScalaConversation): List[String] =
- conversation.promptMessages(chat, prompt).join().asScala.toList
-
-def promptStreaming(prompt: Prompt, chat: Chat = OpenAI.fromEnvironment().DEFAULT_CHAT)(using conversation: ScalaConversation): LazyList[String] =
- val publisher = conversation.promptStreamingToPublisher(chat, prompt)
- val queue = new LinkedBlockingQueue[String]()
- publisher.subscribe(new Subscriber[String]: // TODO change to fs2 or similar
- def onSubscribe(s: Subscription): Unit = s.request(Long.MaxValue)
- def onNext(t: String): Unit = queue.add(t); ()
- def onError(t: Throwable): Unit = throw t
- def onComplete(): Unit = ()
- )
- LazyList.continually(queue.take)
-
-def prompt[A: Decoder: SerialDescriptor](message: String)(using ScalaConversation): A =
- prompt(Prompt(message))
-
-def promptMessage(message: String)(using ScalaConversation): String =
- promptMessage(Prompt(message))
-
-def promptMessages(message: String)(using ScalaConversation): List[String] =
- promptMessages(Prompt(message))
-
-def promptStreaming(message: String)(using ScalaConversation): LazyList[String] =
- promptStreaming(Prompt(message))
-
-def images(prompt: Prompt, images: Images = OpenAI.fromEnvironment().DEFAULT_IMAGES, numberImages: Int = 1, size: String = "1024x1024")(using
- conversation: ScalaConversation
-): ImagesGenerationResponse =
- conversation.images(images, prompt, numberImages, size).join()
-
-def conversation[A](block: ScalaConversation ?=> A, id: ConversationId = ConversationId(randomUUID.toString)): A =
- block(using ScalaConversation(LocalVectorStore(OpenAI.fromEnvironment().DEFAULT_EMBEDDING), LogsMetric(), id))
-
-private def fromJson[A: Decoder]: FromJson[A] = json => parse(json).flatMap(Decoder[A].decodeJson(_)).fold(throw _, identity)
diff --git a/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/KotlinXSerializers.scala b/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/KotlinXSerializers.scala
deleted file mode 100644
index 30aa05e4a..000000000
--- a/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/KotlinXSerializers.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.xebia.functional.xef.scala.serialization
-
-import kotlin.jvm.internal.*
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.builtins.BuiltinSerializersKt
-import kotlinx.serialization.builtins.BuiltinSerializersKt.serializer
-
-object KotlinXSerializers:
- val int: KSerializer[java.lang.Integer] = serializer(IntCompanionObject.INSTANCE)
- val string: KSerializer[String] = serializer(StringCompanionObject.INSTANCE)
- val boolean: KSerializer[java.lang.Boolean] = serializer(BooleanCompanionObject.INSTANCE)
- val double: KSerializer[java.lang.Double] = serializer(DoubleCompanionObject.INSTANCE)
- val float: KSerializer[java.lang.Float] = serializer(FloatCompanionObject.INSTANCE)
- val long: KSerializer[java.lang.Long] = serializer(LongCompanionObject.INSTANCE)
- val short: KSerializer[java.lang.Short] = serializer(ShortCompanionObject.INSTANCE)
- val byte: KSerializer[java.lang.Byte] = serializer(ByteCompanionObject.INSTANCE)
- val char: KSerializer[Character] = serializer(CharCompanionObject.INSTANCE)
- val unit: KSerializer[kotlin.Unit] = serializer(kotlin.Unit.INSTANCE)
diff --git a/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptor.scala b/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptor.scala
deleted file mode 100644
index 9b574065a..000000000
--- a/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptor.scala
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.xebia.functional.xef.scala.serialization
-
-import com.xebia.functional.xef.conversation.jvm.Description as JvmDescription
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.descriptors.{SerialDescriptor as KtSerialDescriptor, SerialKind, StructureKind}
-import kotlinx.serialization.encoding.{Decoder as KtDecoder, Encoder as KtEncoder}
-
-import java.lang.annotation.Annotation
-import java.util
-import scala.annotation.meta.*
-import scala.compiletime.*
-import scala.deriving.*
-import scala.jdk.CollectionConverters.*
-import scala.quoted.*
-import scala.reflect.ClassTag
-
-trait SerialDescriptor[A]:
- def serialDescriptor: KtSerialDescriptor
- def kserializer: KSerializer[A] = new KSerializer[A]:
- override def getDescriptor: KtSerialDescriptor = serialDescriptor
- override def serialize(encoder: KtEncoder, t: A): Unit = ??? // TODO should we implement this?
- override def deserialize(decoder: KtDecoder): A = ??? // TODO should we implement this?
-
-object SerialDescriptor extends SerialDescriptorInstances:
- def apply[A](using ev: SerialDescriptor[A]): SerialDescriptor[A] = ev
-
- private inline def getElemsLabel[T <: Tuple]: List[String] = inline erasedValue[T] match
- case _: EmptyTuple => Nil
- case _: (h *: t) => erasedValue[h].toString :: getElemsLabel[t]
-
- private inline def getSerialDescriptor[T <: Tuple]: List[KtSerialDescriptor] = inline erasedValue[T] match
- case _: EmptyTuple => Nil
- case _: (String *: t) => KotlinXSerializers.string.getDescriptor :: getSerialDescriptor[t]
- case _: (Boolean *: t) => KotlinXSerializers.boolean.getDescriptor :: getSerialDescriptor[t]
- case _: (Byte *: t) => KotlinXSerializers.byte.getDescriptor :: getSerialDescriptor[t]
- case _: (Char *: t) => KotlinXSerializers.char.getDescriptor :: getSerialDescriptor[t]
- case _: (Double *: t) => KotlinXSerializers.double.getDescriptor :: getSerialDescriptor[t]
- case _: (Float *: t) => KotlinXSerializers.float.getDescriptor :: getSerialDescriptor[t]
- case _: (Int *: t) => KotlinXSerializers.int.getDescriptor :: getSerialDescriptor[t]
- case _: (Long *: t) => KotlinXSerializers.long.getDescriptor :: getSerialDescriptor[t]
- case _: (Short *: t) => KotlinXSerializers.short.getDescriptor :: getSerialDescriptor[t]
- case _: (Unit *: t) => KotlinXSerializers.unit.getDescriptor :: getSerialDescriptor[t]
- case _: (h *: t) => summonInline[SerialDescriptor[h]].serialDescriptor :: getSerialDescriptor[t]
-
- inline final def derived[A](using m: Mirror.Of[A]): SerialDescriptor[A] =
- val fieldAnnotationMap = getFieldAnnotationsMap[A]
- new SerialDescriptor[A]:
- val serialDescriptorImpl: KtSerialDescriptor = new KtSerialDescriptor:
- val labels = getElemsLabel[m.MirroredElemLabels]
- val serialDescriptors = getSerialDescriptor[m.MirroredElemTypes]
-
- override def getElementIndex(name: String): Int = labels.indexOf(name)
-
- // We're going to ignore annotations for now, it's not relevant for JsonSchema
- override def getElementAnnotations(index: Int): util.List[Annotation] =
- val fieldName = labels(index)
- val annotations = fieldAnnotationMap(fieldName)
- annotations.filter(_.isInstanceOf[Description]).asJava.asInstanceOf[util.List[Annotation]]
-
- override def getElementDescriptor(index: Int): KtSerialDescriptor = serialDescriptors(index)
-
- // We're going to ignore annotations for now, it's not relevant for JsonSchema
- override def getAnnotations: util.List[Annotation] =
- val annotations = getStaticAnnotations[A]
- annotations.filter(_.isInstanceOf[Description]).asJava.asInstanceOf[util.List[Annotation]]
-
- override def getElementsCount: Int = labels.size
-
- override def isInline: Boolean = false
-
- // Is the element wrapped in `Option`, or is a union with `Null`?
- override def isNullable: Boolean = false
-
- override def getKind: SerialKind = StructureKind.CLASS.INSTANCE
-
- override def getSerialName: String = constValue[m.MirroredLabel]
-
- override def getElementName(i: Int): String = labels(i)
-
- // Does the element at the given index have a default value, or is it wrapped in `Option`, or is a union with `Null`?
- override def isElementOptional(index: Int): Boolean = false
-
- def serialDescriptor: KtSerialDescriptor = serialDescriptorImpl
-
-inline def getStaticAnnotations[A]: List[Any] = ${ getAnnotationsImpl[A] }
-
-def getAnnotationsImpl[A: Type](using Quotes): Expr[List[Any]] =
- import quotes.reflect.*
- val annotations = TypeRepr.of[A].typeSymbol.annotations.map(_.asExpr)
- Expr.ofList(annotations)
-
-inline def getFieldAnnotationsMap[A]: Map[String, List[Any]] =
- ${ getFieldAnnotationsMapImpl[A] }
-
-def getFieldAnnotationsMapImpl[A: Type](using Quotes): Expr[Map[String, List[Any]]] =
- import quotes.reflect.*
- // Extract the fields from the type
- val fields = TypeRepr.of[A].typeSymbol.primaryConstructor.paramSymss.flatten
- // For each field, extract its name and annotations
- val fieldAnnotationsMap: List[Expr[(String, List[Any])]] = fields.map: field =>
- val fieldName = Expr(field.name)
- val annotations = Expr.ofList(field.annotations.map(_.asExpr))
- '{ ($fieldName, $annotations) }
- // Convert list of (String, List[Any]) tuples to a map
- fieldAnnotationsMap match
- case Nil => '{ Map.empty[String, List[Any]] }
- case _ =>
- val mapExpr = Expr.ofList(fieldAnnotationsMap)
- '{ $mapExpr.toMap }
-
-/**
- * A scala annotation that maps to the jvm description annotation
- */
-class Description(description: String) extends JvmDescription with scala.annotation.StaticAnnotation:
- override def value(): String = description
- override def annotationType(): Class[_ <: Annotation] = classOf[JvmDescription]
diff --git a/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptorInstances.scala b/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptorInstances.scala
deleted file mode 100644
index ee761f27c..000000000
--- a/scala/src/main/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptorInstances.scala
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.xebia.functional.xef.scala.serialization
-
-import kotlin.jvm.internal.Reflection
-import kotlin.reflect.KClass
-import kotlinx.serialization.builtins.BuiltinSerializersKt
-
-import scala.compiletime.summonInline
-import scala.reflect.ClassTag
-
-class SerialDescriptorInstances:
-
- given [T: SerialDescriptor]: SerialDescriptor[Option[T]] = new SerialDescriptor[Option[T]]:
- def serialDescriptor = BuiltinSerializersKt.getNullable(SerialDescriptor[T].kserializer).getDescriptor
-
- given [T: ClassTag: SerialDescriptor]: SerialDescriptor[Array[T]] = new SerialDescriptor[Array[T]]:
- def serialDescriptor =
- val kClass = Reflection.createKotlinClass(summonInline[ClassTag[T]].runtimeClass).asInstanceOf[KClass[T]]
- BuiltinSerializersKt.ArraySerializer(kClass, SerialDescriptor[T].kserializer).getDescriptor
-
- given [T: SerialDescriptor]: SerialDescriptor[List[T]] = new SerialDescriptor[List[T]]:
- def serialDescriptor = BuiltinSerializersKt.ListSerializer(SerialDescriptor[T].kserializer).getDescriptor
-
- given [T: SerialDescriptor]: SerialDescriptor[Seq[T]] = new SerialDescriptor[Seq[T]]:
- def serialDescriptor = BuiltinSerializersKt.ListSerializer(SerialDescriptor[T].kserializer).getDescriptor
-
- given [T: SerialDescriptor]: SerialDescriptor[Vector[T]] = new SerialDescriptor[Vector[T]]:
- def serialDescriptor = BuiltinSerializersKt.ListSerializer(SerialDescriptor[T].kserializer).getDescriptor
-
- given [T: SerialDescriptor]: SerialDescriptor[Set[T]] = new SerialDescriptor[Set[T]]:
- def serialDescriptor = BuiltinSerializersKt.SetSerializer(SerialDescriptor[T].kserializer).getDescriptor
-
- given [K: SerialDescriptor, V: SerialDescriptor]: SerialDescriptor[Map[K, V]] = new SerialDescriptor[Map[K, V]]:
- def serialDescriptor =
- BuiltinSerializersKt.MapSerializer(SerialDescriptor[K].kserializer, SerialDescriptor[V].kserializer).getDescriptor
-
- given SerialDescriptor[Boolean] = new SerialDescriptor[Boolean]:
- def serialDescriptor = KotlinXSerializers.boolean.getDescriptor
-
- given SerialDescriptor[Byte] = new SerialDescriptor[Byte]:
- def serialDescriptor = KotlinXSerializers.byte.getDescriptor
-
- given SerialDescriptor[Char] = new SerialDescriptor[Char]:
- def serialDescriptor = KotlinXSerializers.char.getDescriptor
-
- given SerialDescriptor[Double] = new SerialDescriptor[Double]:
- def serialDescriptor = KotlinXSerializers.double.getDescriptor
-
- given SerialDescriptor[Float] = new SerialDescriptor[Float]:
- def serialDescriptor = KotlinXSerializers.float.getDescriptor
-
- given SerialDescriptor[Int] = new SerialDescriptor[Int]:
- def serialDescriptor = KotlinXSerializers.int.getDescriptor
-
- given SerialDescriptor[Long] = new SerialDescriptor[Long]:
- def serialDescriptor = KotlinXSerializers.long.getDescriptor
-
- given SerialDescriptor[Short] = new SerialDescriptor[Short]:
- def serialDescriptor = KotlinXSerializers.short.getDescriptor
-
- given SerialDescriptor[String] = new SerialDescriptor[String]:
- def serialDescriptor = KotlinXSerializers.string.getDescriptor
-
- given SerialDescriptor[Unit] = new SerialDescriptor[Unit]:
- def serialDescriptor = KotlinXSerializers.unit.getDescriptor
diff --git a/scala/src/test/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptorSpec.scala b/scala/src/test/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptorSpec.scala
deleted file mode 100644
index 4c103b6e1..000000000
--- a/scala/src/test/scala/com/xebia/functional/xef/scala/serialization/SerialDescriptorSpec.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.xebia.functional.xef.scala.serialization
-
-import cats.syntax.either.*
-import kotlinx.serialization.builtins.BuiltinSerializersKt
-import munit.FunSuite
-
-import scala.collection.immutable.HashSet
-import scala.compiletime.summonInline
-import scala.reflect.ClassTag
-
-class SerialDescriptorSpec extends FunSuite:
-
- test("Should create a SerialDescriptor for a simple case class") {
- final case class Person(age: Int, name: String) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a simple case class with optional fields") {
- final case class Person(age: Int, name: String, id: Option[Long]) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a simple case class with set and list fields") {
- final case class Person(age: Int, name: String, siblingNames: Set[String], nationality: List[String]) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a simple case class with a list case class") {
- final case class Pet(age: Int, name: String) derives SerialDescriptor
- final case class Person(age: Int, name: String, pets: List[Pet]) derives SerialDescriptor
-
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a simple case class with seq and vector fields") {
- final case class Person(age: Int, name: String, other1: Seq[Byte], other2: Vector[Short]) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a simple case class with an array field") {
- final case class Person(other: Array[Double]) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a simple case class with map fields") {
- final case class Person(age: Int, name: String, alias: Map[String, String]) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a simple case class with HashSet field, providing a custom given") {
- given [T: SerialDescriptor]: SerialDescriptor[HashSet[T]] = new SerialDescriptor[HashSet[T]]:
- def serialDescriptor = BuiltinSerializersKt.SetSerializer(SerialDescriptor[T].kserializer).getDescriptor
- final case class Person(age: Int, name: String, alias: HashSet[String]) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a composite case class") {
- final case class Person(age: Int, name: PersonName) derives SerialDescriptor
- final case class PersonName(firstName: String, lastName: String) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
-
- test("Should create a SerialDescriptor for a composite (level 2) case class") {
- final case class Person(age: Int, placeOfBirth: PlaceOfBirth) derives SerialDescriptor
- final case class PlaceOfBirth(city: String, country: Country) derives SerialDescriptor
- final case class Country(country: String) derives SerialDescriptor
- assert(Either.catchNonFatal(SerialDescriptor[Person].serialDescriptor).isRight)
- }
diff --git a/server/build.gradle.kts b/server/build.gradle.kts
index d7d360436..57c8f6c87 100644
--- a/server/build.gradle.kts
+++ b/server/build.gradle.kts
@@ -48,7 +48,7 @@ dependencies {
implementation(libs.suspendApp.core)
implementation(libs.suspendApp.ktor)
implementation(libs.uuid)
- implementation(projects.xefKotlin)
+ implementation(projects.xefOpenai)
implementation(projects.xefCore)
implementation(projects.xefLucene)
implementation(projects.xefPostgresql)
@@ -69,12 +69,6 @@ spotless {
}
}
-tasks.getByName("processResources") {
- dependsOn(projects.xefGpt4all.dependencyProject.tasks.getByName("jvmProcessResources"))
- from("${projects.xefGpt4all.dependencyProject.buildDir}/processedResources/jvm/main")
- into("$buildDir/resources/main")
-}
-
task("web-app") {
dependsOn("npm_run_build")
group = "Execution"
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 8f598cd6f..713130d35 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -35,9 +35,7 @@ project(":xef-tokenizer").projectDir = file("tokenizer")
include("xef-openai")
project(":xef-openai").projectDir = file("openai")
-
-include("xef-gpt4all")
-project(":xef-gpt4all").projectDir = file("gpt4all-kotlin")
+//
//
include("xef-lucene")
@@ -61,40 +59,13 @@ project(":xef-opentelemetry").projectDir = file("integrations/opentelemetry")
include("xef-mlflow")
project(":xef-mlflow").projectDir = file("integrations/mlflow")
//
-//
-
-//
-include("xef-kotlin")
-project(":xef-kotlin").projectDir = file("kotlin")
-
-include("xef-kotlin-examples")
-project(":xef-kotlin-examples").projectDir = file("examples/kotlin")
-//
-//
-include("xef-scala-examples")
-project(":xef-scala-examples").projectDir = file("examples/scala")
+include("xef-examples")
+project(":xef-examples").projectDir = file("examples")
-include("xef-scala")
-project(":xef-scala").projectDir = file("scala")
-//
-
-//
-include("xef-java")
-project(":xef-java").projectDir = file("java")
-
-include("xef-java-examples")
-project(":xef-java-examples").projectDir = file("examples/java")
-//
-
-//
include("xef-reasoning")
project(":xef-reasoning").projectDir = file("reasoning")
-include("xef-java-examples")
-project(":xef-java-examples").projectDir = file("examples/java")
-//
-
//
include("xef-server")
project(":xef-server").projectDir = file("server")