Getting started
eLLMental is a toolset for building AI-powered applications written in Kotlin, and it offers a variety of components that you can use right away. In this guide, we will guide you through an example of how to use the SemanticSearch component to build an intelligent note taking application for the terminal that learns from your notes and is able to find relevant notes based on a query.
Step 0: Create a new Kotlin application project
This can be done using your preferred way of Kotlin project initialization. If you're using IntelliJ IDEA, you can follow the steps below:
- Open IntelliJ IDEA and click on
Create New Project
. - Select
New Project
in the left panel and then selectKotlin
andGradle
in the right panel. ChooseKotlin
as the Build DSL. - Click
Create
and then enter the project name and location.
Step 1: Add the eLLMental dependencies using JitPack
Import the eLLMental dependencies in your build.gradle.kts
file.
You can use this one as a starting point:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.9.0"
application
}
group = "com.theagilemonkeys"
version = "1.0-SNAPSHOT"
allprojects { repositories { maven { url = uri("https://jitpack.io") } } }
repositories { mavenCentral() }
dependencies {
implementation("com.github.theam.ellmental:core:main-SNAPSHOT")
implementation("com.github.theam.ellmental:semanticsearch:main-SNAPSHOT")
implementation("com.github.theam.ellmental:vectorstore:main-SNAPSHOT")
implementation("com.github.theam.ellmental:embeddingsmodel:main-SNAPSHOT")
implementation("com.aallam.openai:openai-client:3.3.0")
testImplementation(kotlin("test"))
}
tasks.test { useJUnitPlatform() }
tasks.withType<KotlinCompile> { kotlinOptions.jvmTarget = "17" }
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions { freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers" }
}
tasks.named<JavaExec>("run") { standardInput = System.`in` }
application { mainClass.set("MainKt") }
Step 2: Creating the Note class
Let's create a Note
class. This class will have two
properties: id
type Int
for the note identifier and content
type String
for the note content.
data class Note(
val id: Int,
val content: String
)
Step 3: Initializing the SemanticSearch component
Before initializing the SemanticSearch
component, we need to set up the OpenAIEmbeddingsModel
and PineconeVectorStore
, which are two key components required by SemanticSearch
.
You can initialize these components in their own function, so you can do stuff like loading the tokens from your environment variables.
You can follow both the PineCone quickstart guide as well as the OpenAI API keys guide to get the required tokens.
import com.aallam.openai.client.OpenAI
import com.theagilemonkeys.ellmental.embeddingsmodel.openai.OpenAIEmbeddingsModel
import com.theagilemonkeys.ellmental.vectorstore.pinecone.PineconeVectorStore
fun embeddingsModel(): OpenAIEmbeddingsModel {
val openaiToken = System.getenv("OPEN_AI_API_KEY")
check(openaiToken != null) { "OPEN_AI_API_KEY environment variable is not set" }
with(OpenAI(token = openaiToken)) {
return OpenAIEmbeddingsModel()
}
}
fun vectorStore(): PineconeVectorStore {
val pineconeToken = System.getenv("PINECONE_API_KEY")
check(pineconeToken != null) { "PINECONE_API_KEY environment variable is not set" }
val pineconeUrl = System.getenv("PINECONE_URL")
check(pineconeUrl != null) { "PINECONE_URL environment variable is not set" }
// This is an optional parameter. It allows you to specify a namespace for your vector store.
val pineconeNamespace = System.getenv("PINECONE_NAMESPACE")
return PineconeVectorStore(apiKey = pineconeToken, url = pineconeUrl, namespace = pineconeNamespace)
}
Next, we will do the same for initializing the SemanticSearch
instance. Import the SemanticSearch
component
from eLLMental and create an instance using the functions you created above.
import com.theagilemonkeys.ellmental.embeddingsmodel.openai.OpenAIEmbeddingsModel
import com.theagilemonkeys.ellmental.semanticsearch.SemanticSearch
import com.theagilemonkeys.ellmental.vectorstore.pinecone.PineconeVectorStore
fun semanticSearch(): SemanticSearch {
val embeddingsModel = embeddingsModel()
val vectorStore = vectorStore()
with(embeddingsModel) {
with(vectorStore) {
return SemanticSearch()
}
}
}
Step 4: Implementing the learn
and search
features
Let's implement the learn
and search
features to add new notes into the SemanticSearch
index and find them
later.
import com.theagilemonkeys.ellmental.semanticsearch.SemanticSearch
import com.theagilemonkeys.ellmental.semanticsearch.SearchInput
suspend fun learn(semanticSearch: SemanticSearch, note: Note) {
semanticSearch.learn(LearnInput(listOf(note.content)))
}
suspend fun search(semanticSearch: SemanticSearch, query: String): List<String> {
// We will put a limit of 10 items for now
semanticSearch.search(query, itemsLimit = 10).entries.map {
// Here entries can be mapped to your corresponding data models based on the returned `SemanticEntry` object
// we're just gonna return the id
it.id.value
}
}
Step 5: Creating a main function
The only thing that's missing now is an application loop. Let's implement so in the main
function.
fun main() = runBlocking {
val semanticSearch = semanticSearch()
println("Available commands: learn, search, quit\n")
var shouldQuit = false
while (!shouldQuit) {
print("> ")
when (readln()) {
"help" -> {
println("Available commands: learn, search, quit")
}
"learn" -> {
println("Enter note content:")
val txt = readln()
val note = Note(
id = 1,
content = txt
)
learn(semanticSearch, note)
}
"search" -> {
println("Enter query:")
val query = readln()
val results = search(semanticSearch, query)
println(results)
}
"quit" -> {
println("Bye!")
shouldQuit = true
}
else -> {
println("Invalid command")
}
}
}
}
Step 6: Running the application
Now you can run your application either from the IDE run button or from the command line using ./gradlew run
.
Available commands: learn, search, quit
> learn
Enter note content:
This is a note about eLLMental, an open source library for building intelligent applications.
> search
Enter query:
eLLMental
[This is a note about eLLMental, an open source library for building intelligent applications.]
> quit
Bye!
This is how you can use the SemanticSearch
component from eLLMental to build an intelligent note taking application
backend that learns from your notes and is able to find relevant notes based on a query.
Here is a link to the repository that contains this entire example.
Wanna learn more? Read the Components page to discover the different components available in eLLMental, together with their thorough usage, and if you have any question, you are very welcome at the community Discord server!
Additional sample code
In addition to this guide, you can find a simpler sample application that exposes the SemanticSearch
component from
eLLMental as a REST API in
the eLLMental Examples repository.