-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DRAFT: CU-865c5pdxy AI as a language primitive via an auto-agent (#15)
* AI as a language primitive via an auto-agent * Small clean-up, and fix ktor-client-js issue * Move around HttpClient dependencies * Add Simon's PR suggestion to fix bug listing tasks + additional example * Remove while and storages (#16) * Flatten structures * Improve Task and TaskResult model * Improve logging, and setup example module (#17) * Improve logging, and setup example module * Fix package, split logback into TOML, and remove old reference to storage * Simplify Auto agent by depending on just `ai` function + basic agents draft (#18) * autonomous agent in terms of `ai` function with self reasoning and agent support. Extended `ai` function to accept agents * wikipedia agent, currently failing JS node on import child_process.ExecOptions, io multiplatform solution based on https://github.com/jmfayard/kotlin-cli-starter * wikipedia agent, currently failing JS node on import child_process.ExecOptions, io multiplatform solution based on https://github.com/jmfayard/kotlin-cli-starter * Fix build --------- Co-authored-by: Simon Vergauwen <nomisRev@users.noreply.github.com> --------- Co-authored-by: Simon Vergauwen <nomisRev@users.noreply.github.com>
- 0.0.5-alpha.119
- 0.0.5-alpha.118
- 0.0.5-alpha.117
- 0.0.5-alpha.116
- 0.0.5-alpha.115
- 0.0.5-alpha.114
- 0.0.5-alpha.113
- 0.0.5-alpha.112
- 0.0.5-alpha.111
- 0.0.5-alpha.110
- 0.0.5-alpha.109
- 0.0.5-alpha.108
- 0.0.5-alpha.107
- 0.0.5-alpha.106
- 0.0.5-alpha.105
- 0.0.5-alpha.104
- 0.0.5-alpha.103
- 0.0.5-alpha.102
- 0.0.5-alpha.101
- 0.0.5-alpha.100
- 0.0.5-alpha.99
- 0.0.5-alpha.98
- 0.0.5-alpha.97
- 0.0.5-alpha.96
- 0.0.5-alpha.95
- 0.0.5-alpha.94
- 0.0.5-alpha.93
- 0.0.5-alpha.92
- 0.0.5-alpha.91
- 0.0.5-alpha.90
- 0.0.5-alpha.89
- 0.0.5-alpha.88
- 0.0.5-alpha.87
- 0.0.5-alpha.86
- 0.0.5-alpha.85
- 0.0.5-alpha.84
- 0.0.5-alpha.83
- 0.0.5-alpha.82
- 0.0.5-alpha.81
- 0.0.5-alpha.80
- 0.0.5-alpha.79
- 0.0.5-alpha.78
- 0.0.5-alpha.77
- 0.0.5-alpha.76
- 0.0.5-alpha.75
- 0.0.5-alpha.74
- 0.0.5-alpha.73
- 0.0.5-alpha.72
- 0.0.5-alpha.71
- 0.0.5-alpha.70
- 0.0.5-alpha.69
- 0.0.5-alpha.68
- 0.0.5-alpha.67
- 0.0.5-alpha.66
- 0.0.5-alpha.65
- 0.0.5-alpha.64
- 0.0.5-alpha.63
- 0.0.5-alpha.62
- 0.0.5-alpha.61
- 0.0.5-alpha.60
- 0.0.5-alpha.59
- 0.0.5-alpha.58
- 0.0.5-alpha.57
- 0.0.5-alpha.56
- 0.0.5-alpha.55
- 0.0.5-alpha.54
- 0.0.5-alpha.53
- 0.0.5-alpha.52
- 0.0.5-alpha.51
- 0.0.5-alpha.50
- 0.0.5-alpha.49
- 0.0.5-alpha.48
- 0.0.5-alpha.47
- 0.0.5-alpha.46
- 0.0.5-alpha.45
- 0.0.5-alpha.44
- 0.0.5-alpha.43
- 0.0.5-alpha.42
- 0.0.5-alpha.41
- 0.0.5-alpha.40
- 0.0.5-alpha.39
- 0.0.5-alpha.38
- 0.0.5-alpha.37
- 0.0.5-alpha.36
- 0.0.5-alpha.35
- 0.0.5-alpha.34
- 0.0.5-alpha.33
- 0.0.5-alpha.32
- 0.0.5-alpha.31
- 0.0.5-alpha.30
- 0.0.5-alpha.29
- 0.0.5-alpha.28
- 0.0.5-alpha.27
- 0.0.5-alpha.26
- 0.0.5-alpha.25
- 0.0.5-alpha.24
- 0.0.5-alpha.23
- 0.0.5-alpha.22
- 0.0.5-alpha.21
- 0.0.5-alpha.20
- 0.0.5-alpha.19
- 0.0.5-alpha.18
- 0.0.5-alpha.17
- 0.0.5-alpha.16
- 0.0.5-alpha.15
- 0.0.5-alpha.14
- 0.0.5-alpha.13
- 0.0.5-alpha.12
- 0.0.5-alpha.11
- 0.0.5-alpha.10
- 0.0.5-alpha.9
- 0.0.5-alpha.8
- 0.0.5-alpha.7
- 0.0.5-alpha.6
- 0.0.5-alpha.5
- 0.0.5-alpha.4
- 0.0.5-alpha.3
- 0.0.5-alpha.2
- 0.0.5-alpha.1
- 0.0.4
- 0.0.4-alpha.104
- 0.0.4-alpha.103
- 0.0.4-alpha.102
- 0.0.4-alpha.101
- 0.0.4-alpha.100
- 0.0.4-alpha.99
- 0.0.4-alpha.98
- 0.0.4-alpha.97
- 0.0.4-alpha.96
- 0.0.4-alpha.95
- 0.0.4-alpha.94
- 0.0.4-alpha.93
- 0.0.4-alpha.92
- 0.0.4-alpha.91
- 0.0.4-alpha.90
- 0.0.4-alpha.89
- 0.0.4-alpha.88
- 0.0.4-alpha.87
- 0.0.4-alpha.86
- 0.0.4-alpha.85
- 0.0.4-alpha.84
- 0.0.4-alpha.83
- 0.0.4-alpha.82
- 0.0.4-alpha.81
- 0.0.4-alpha.80
- 0.0.4-alpha.79
- 0.0.4-alpha.78
- 0.0.4-alpha.77
- 0.0.4-alpha.76
- 0.0.4-alpha.75
- 0.0.4-alpha.74
- 0.0.4-alpha.73
- 0.0.4-alpha.72
- 0.0.4-alpha.71
- 0.0.4-alpha.70
- 0.0.4-alpha.69
- 0.0.4-alpha.68
- 0.0.4-alpha.67
- 0.0.4-alpha.66
- 0.0.4-alpha.65
- 0.0.4-alpha.64
- 0.0.4-alpha.63
- 0.0.4-alpha.62
- 0.0.4-alpha.61
- 0.0.4-alpha.60
- 0.0.4-alpha.59
- 0.0.4-alpha.58
- 0.0.4-alpha.57
- 0.0.4-alpha.56
- 0.0.4-alpha.55
- 0.0.4-alpha.54
- 0.0.4-alpha.53
- 0.0.4-alpha.52
- 0.0.4-alpha.51
- 0.0.4-alpha.50
- 0.0.4-alpha.49
- 0.0.4-alpha.48
- 0.0.4-alpha.47
- 0.0.4-alpha.46
- 0.0.4-alpha.45
- 0.0.4-alpha.44
- 0.0.4-alpha.43
- 0.0.4-alpha.42
- 0.0.4-alpha.41
- 0.0.4-alpha.40
- 0.0.4-alpha.39
- 0.0.4-alpha.38
- 0.0.4-alpha.37
- 0.0.4-alpha.36
- 0.0.4-alpha.35
- 0.0.4-alpha.34
- 0.0.4-alpha.33
- 0.0.4-alpha.32
- 0.0.4-alpha.31
- 0.0.4-alpha.30
- 0.0.4-alpha.29
- 0.0.4-alpha.28
- 0.0.4-alpha.27
- 0.0.4-alpha.26
- 0.0.4-alpha.25
- 0.0.4-alpha.24
- 0.0.4-alpha.23
- 0.0.4-alpha.22
- 0.0.4-alpha.21
- 0.0.4-alpha.20
- 0.0.4-alpha.19
- 0.0.4-alpha.18
- 0.0.4-alpha.17
- 0.0.4-alpha.16
- 0.0.4-alpha.15
- 0.0.4-alpha.14
- 0.0.4-alpha.13
- 0.0.4-alpha.12
- 0.0.4-alpha.11
- 0.0.4-alpha.10
- 0.0.4-alpha.9
- 0.0.4-alpha.8
- 0.0.4-alpha.7
- 0.0.4-alpha.6
- 0.0.4-alpha.5
- 0.0.4-alpha.4
- 0.0.4-alpha.3
- 0.0.4-alpha.2
- 0.0.4-alpha.1
- 0.0.3
- 0.0.3-alpha.51
- 0.0.3-alpha.50
- 0.0.3-alpha.49
- 0.0.3-alpha.48
- 0.0.3-alpha.47
- 0.0.3-alpha.46
- 0.0.3-alpha.45
- 0.0.3-alpha.44
- 0.0.3-alpha.43
- 0.0.3-alpha.42
- 0.0.3-alpha.41
- 0.0.3-alpha.40
- 0.0.3-alpha.39
- 0.0.3-alpha.38
- 0.0.3-alpha.37
- 0.0.3-alpha.36
- 0.0.3-alpha.35
- 0.0.3-alpha.34
- 0.0.3-alpha.33
- 0.0.3-alpha.32
- 0.0.3-alpha.31
- 0.0.3-alpha.30
- 0.0.3-alpha.29
- 0.0.3-alpha.28
- 0.0.3-alpha.27
- 0.0.3-alpha.26
- 0.0.3-alpha.25
- 0.0.3-alpha.24
- 0.0.3-alpha.23
- 0.0.3-alpha.22
- 0.0.3-alpha.21
- 0.0.3-alpha.20
- 0.0.3-alpha.19
- 0.0.3-alpha.18
- 0.0.3-alpha.17
- 0.0.3-alpha.16
- 0.0.3-alpha.15
- 0.0.3-alpha.14
- 0.0.3-alpha.13
- 0.0.3-alpha.12
- 0.0.3-alpha.11
- 0.0.3-alpha.10
- 0.0.3-alpha.9
- 0.0.3-alpha.8
- 0.0.3-alpha.7
- 0.0.3-alpha.6
- 0.0.3-alpha.5
- 0.0.3-alpha.4
- 0.0.3-alpha.3
- 0.0.3-alpha.2
- 0.0.3-alpha.1
- 0.0.2
- 0.0.2-alpha.68
- 0.0.2-alpha.67
- 0.0.2-alpha.66
- 0.0.2-alpha.65
- 0.0.2-alpha.64
- 0.0.2-alpha.63
- 0.0.2-alpha.62
- 0.0.2-alpha.61
- 0.0.2-alpha.60
- 0.0.2-alpha.59
- 0.0.2-alpha.58
- 0.0.2-alpha.57
- 0.0.2-alpha.56
- 0.0.2-alpha.55
- 0.0.2-alpha.54
- 0.0.2-alpha.53
- 0.0.2-alpha.52
- 0.0.2-alpha.51
- 0.0.2-alpha.50
- 0.0.2-alpha.49
- 0.0.2-alpha.48
- 0.0.2-alpha.47
- 0.0.2-alpha.46
- 0.0.2-alpha.45
- 0.0.2-alpha.44
- 0.0.2-alpha.43
- 0.0.2-alpha.42
- 0.0.2-alpha.41
- 0.0.2-alpha.40
- 0.0.2-alpha.39
- 0.0.2-alpha.38
- 0.0.2-alpha.37
- 0.0.2-alpha.36
- 0.0.2-alpha.35
- 0.0.2-alpha.34
- 0.0.2-alpha.33
- 0.0.2-alpha.32
- 0.0.2-alpha.31
- 0.0.2-alpha.30
- 0.0.2-alpha.29
- 0.0.2-alpha.28
- 0.0.2-alpha.27
- 0.0.2-alpha.26
- 0.0.2-alpha.25
- 0.0.2-alpha.24
- 0.0.2-alpha.23
- 0.0.2-alpha.22
- 0.0.2-alpha.21
- 0.0.2-alpha.20
- 0.0.2-alpha.19
- 0.0.2-alpha.18
- 0.0.2-alpha.17
- 0.0.2-alpha.16
- 0.0.2-alpha.15
- 0.0.2-alpha.14
- 0.0.2-alpha.13
- 0.0.2-alpha.12
- 0.0.2-alpha.11
- 0.0.2-alpha.10
- 0.0.2-alpha.9
- 0.0.2-alpha.8
- 0.0.2-alpha.7
- 0.0.2-alpha.6
- 0.0.2-alpha.5
- 0.0.2-alpha.4
- 0.0.2-alpha.3
- 0.0.2-alpha.2
- 0.0.2-alpha.1
- 0.0.1
- 0.0.1-alpha.57
- 0.0.1-alpha.56
- 0.0.1-alpha.55
- 0.0.1-alpha.54
- 0.0.1-alpha.53
- 0.0.1-alpha.52
- 0.0.1-alpha.51
- 0.0.1-alpha.50
- 0.0.1-alpha.49
- 0.0.1-alpha.48
- 0.0.1-alpha.47
- 0.0.1-alpha.46
- 0.0.1-alpha.45
- 0.0.1-alpha.44
- 0.0.1-alpha.43
- 0.0.1-alpha.42
- 0.0.1-alpha.41
- 0.0.1-alpha.40
- 0.0.1-alpha.39
- 0.0.1-alpha.38
- 0.0.1-alpha.37
- 0.0.1-alpha.36
- 0.0.1-alpha.35
- 0.0.1-alpha.34
- 0.0.1-alpha.33
- 0.0.1-alpha.32
- 0.0.1-alpha.31
- 0.0.1-alpha.30
- 0.0.1-alpha.29
- 0.0.1-alpha.28
- 0.0.1-alpha.27
- 0.0.1-alpha.26
- 0.0.1-alpha.25
- 0.0.1-alpha.24
- 0.0.1-alpha.23
- 0.0.1-alpha.22
- 0.0.1-alpha.21
- 0.0.1-alpha.20
- 0.0.1-alpha.19
- 0.0.1-alpha.18
- 0.0.1-alpha.17
- 0.0.1-alpha.16
- 0.0.1-alpha.15
- 0.0.1-alpha.14
- 0.0.1-alpha.13
- 0.0.1-alpha.12
- 0.0.1-alpha.11
- 0.0.1-alpha.10
- 0.0.1-alpha.9
- 0.0.1-alpha.8
- 0.0.1-alpha.7
- 0.0.1-alpha.6
- 0.0.1-alpha.5
- 0.0.1-alpha.4
- 0.0.1-alpha.3
- 0.0.1-alpha.2
- 0.0.1-alpha.1
Showing
55 changed files
with
1,855 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
plugins { | ||
id(libs.plugins.kotlin.jvm.get().pluginId) | ||
id(libs.plugins.kotlinx.serialization.get().pluginId) | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
java { | ||
sourceCompatibility = JavaVersion.VERSION_11 | ||
targetCompatibility = JavaVersion.VERSION_11 | ||
toolchain { | ||
languageVersion = JavaLanguageVersion.of(11) | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation(rootProject) | ||
implementation(libs.kotlinx.serialization.json) | ||
implementation(libs.logback) | ||
} |
12 changes: 12 additions & 0 deletions
12
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/ASCIIArt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ASCIIArt(val art: String) | ||
|
||
suspend fun main() { | ||
val art: ASCIIArt = ai("ASCII art of a cat dancing") | ||
println(art.art) | ||
} |
29 changes: 29 additions & 0 deletions
29
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Animal.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Animal(val name: String, val habitat: String, val diet: String) | ||
|
||
@Serializable | ||
data class Invention(val name: String, val inventor: String, val year: Int, val purpose: String) | ||
|
||
@Serializable | ||
data class Story(val animal: Animal, val invention: Invention, val story: String) | ||
|
||
suspend fun main() { | ||
val animal: Animal = ai("A unique animal species.") | ||
val invention: Invention = ai("A groundbreaking invention from the 20th century.") | ||
|
||
val storyPrompt = """ | ||
Write a short story that involves the following elements: | ||
1. A unique animal species called ${animal.name} that lives in ${animal.habitat} and has a diet of ${animal.diet}. | ||
2. A groundbreaking invention from the 20th century called ${invention.name}, invented by ${invention.inventor} in ${invention.year}, which serves the purpose of ${invention.purpose}. | ||
""".trimIndent() | ||
|
||
val story: Story = ai(storyPrompt) | ||
|
||
println("Story about ${animal.name} and ${invention.name}: ${story.story}") | ||
} |
12 changes: 12 additions & 0 deletions
12
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Book.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Book(val title: String, val author: String, val summary: String) | ||
|
||
suspend fun main() { | ||
val toKillAMockingbird: Book = ai("To Kill a Mockingbird by Harper Lee summary.") | ||
println("To Kill a Mockingbird summary:\n ${toKillAMockingbird.summary}") | ||
} |
54 changes: 54 additions & 0 deletions
54
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/ChessAI.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class ChessMove(val player : String, val move: String) | ||
@Serializable | ||
data class ChessBoard(val board: String) | ||
@Serializable | ||
data class GameState(val ended: Boolean, val winner: String) | ||
|
||
suspend fun main() { | ||
val moves = mutableListOf<ChessMove>() | ||
var gameEnded = false | ||
var winner = "" | ||
|
||
while (!gameEnded) { | ||
val currentPlayer = if (moves.size % 2 == 0) "Player 1 (White)" else "Player 2 (Black)" | ||
val prompt = """ | ||
|$currentPlayer, it's your turn. | ||
|Previous moves: ${moves.joinToString(", ")} | ||
|Make your next move: | ||
""".trimIndent() | ||
|
||
val move: ChessMove = ai(prompt) | ||
moves.add(move) | ||
|
||
// Update boardState according to move.move | ||
// ... | ||
|
||
val boardPrompt = """ | ||
Given the following chess moves: ${moves.joinToString(", ") { it.player + ":"+ it.move }}}, | ||
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 | ||
""".trimIndent() | ||
|
||
val chessBoard: ChessBoard = ai(boardPrompt) | ||
println("Current board:\n${chessBoard.board}") | ||
|
||
val gameStatePrompt = """ | ||
Given the following chess moves: ${moves.joinToString(", ")}, | ||
has the game ended (win, draw, or stalemate)? | ||
""".trimIndent() | ||
|
||
val gameState: GameState = ai(gameStatePrompt) | ||
|
||
gameEnded = gameState.ended | ||
winner = gameState.winner | ||
} | ||
|
||
println("Game over. Final move: ${moves.last()}, Winner: $winner") | ||
} | ||
|
12 changes: 12 additions & 0 deletions
12
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Colors.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Colors(val colors: List<String>) | ||
|
||
suspend fun main() { | ||
val colors: Colors = ai("a selection of 10 beautiful colors that go well together") | ||
println(colors) | ||
} |
19 changes: 19 additions & 0 deletions
19
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/DivergentTasks.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import com.xebia.functional.auto.agents.Agent | ||
import com.xebia.functional.auto.agents.wikipedia | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class NumberOfMedicalNeedlesInWorld(val numberOfNeedles: Long) | ||
|
||
suspend fun main() { | ||
val needlesInWorld: NumberOfMedicalNeedlesInWorld = ai( | ||
"""|Provide the number of medical needles in the world. | ||
""".trimMargin(), | ||
agents = listOf(Agent.wikipedia()) | ||
) | ||
println("Needles in world: ${needlesInWorld.numberOfNeedles}") | ||
} | ||
|
26 changes: 26 additions & 0 deletions
26
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Employee.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Employee(val firstName: String, val lastName: String, val age: Int, val position: String, val company: Company) | ||
|
||
@Serializable | ||
data class Address(val street: String, val city: String, val country: String) | ||
|
||
@Serializable | ||
data class Company(val name: String, val address: Address) | ||
|
||
suspend fun main() { | ||
val complexPrompt = "Provide information for an Employee that includes their first name, last name, age, position, and their company's name and address (street, city, and country)." | ||
|
||
val employeeData: Employee = ai(complexPrompt) | ||
|
||
println("Employee Information:\n\n" + | ||
"Name: ${employeeData.firstName} ${employeeData.lastName}\n" + | ||
"Age: ${employeeData.age}\n" + | ||
"Position: ${employeeData.position}\n" + | ||
"Company: ${employeeData.company.name}\n" + | ||
"Address: ${employeeData.company.address.street}, ${employeeData.company.address.city}, ${employeeData.company.address.country}") | ||
} |
24 changes: 24 additions & 0 deletions
24
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Fact.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Fact(val topic: String, val content: String) | ||
|
||
suspend fun main() { | ||
val fact1: Fact = ai("A fascinating fact about you") | ||
val fact2: Fact = ai("An interesting fact about me") | ||
|
||
val riddlePrompt = """ | ||
Create a riddle that combines the following facts: | ||
Fact 1: ${fact1.content} | ||
Fact 2: ${fact2.content} | ||
""".trimIndent() | ||
|
||
val riddle: String = ai(riddlePrompt) | ||
|
||
println("Riddle:\n\n${riddle}") | ||
} | ||
|
8 changes: 8 additions & 0 deletions
8
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Love.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
|
||
suspend fun main() { | ||
val love: List<String> = ai("tell me you like me with just emojis") | ||
println(love) | ||
} |
26 changes: 26 additions & 0 deletions
26
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/MealPlan.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import com.xebia.functional.auto.agents.Agent | ||
import com.xebia.functional.auto.agents.wikipedia | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class MealPlan(val name: String, val recipes: List<Recipe>) { | ||
fun prettyPrint(): String { | ||
return recipes.joinToString("\n") { "${it.name}:\n${it.ingredients.joinToString("\n")}" } | ||
} | ||
} | ||
|
||
suspend fun main() { | ||
val mealPlan: MealPlan = | ||
ai( | ||
"Meal plan for the week for a person with gall bladder stones that includes 5 recipes.", | ||
auto = true, | ||
agents = listOf(Agent.wikipedia()) | ||
) | ||
println( | ||
"""The meal plan for the week is: | ||
|${mealPlan.prettyPrint()}""".trimMargin() | ||
) | ||
} |
12 changes: 12 additions & 0 deletions
12
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/MeaningOfLife.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class MeaningOfLife(val mainTheories: List<String>) | ||
|
||
suspend fun main() { | ||
val meaningOfLife: MeaningOfLife = ai("What are the main theories about the meaning of life") | ||
println("There are several theories about the meaning of life:\n ${meaningOfLife.mainTheories}") | ||
} |
12 changes: 12 additions & 0 deletions
12
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Movie.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Movie(val title: String, val genre: String, val director: String) | ||
|
||
suspend fun main() { | ||
val movie: Movie = ai("Inception movie genre and director.") | ||
println("The movie ${movie.title} is a ${movie.genre} film directed by ${movie.director}.") | ||
} |
12 changes: 12 additions & 0 deletions
12
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Person.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Person(val name: String, val age: Int) | ||
|
||
suspend fun main() { | ||
val bogus: List<Person> = ai("come up with some random data that matches the type") | ||
println(bogus) | ||
} |
26 changes: 26 additions & 0 deletions
26
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Planet.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import com.xebia.functional.auto.agents.Agent | ||
import com.xebia.functional.auto.agents.wikipedia | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Planet(val name: String, val distanceFromSun: Double, val moons: List<Moon>) | ||
|
||
@Serializable | ||
data class Moon(val name: String, val distanceFromPlanet: Double) | ||
|
||
suspend fun main() { | ||
val earth: Planet = ai("Information about Earth and its moon.", auto = true, agents = listOf(Agent.wikipedia())) | ||
val mars: Planet = ai("Information about Mars and its moons.", auto = true, agents = listOf(Agent.wikipedia())) | ||
|
||
fun planetInfo(planet: Planet): String { | ||
return """${planet.name} is ${planet.distanceFromSun} million km away from the Sun. | ||
|It has the following moons: | ||
|${planet.moons.joinToString("\n") { " - ${it.name}: ${it.distanceFromPlanet} km away from ${planet.name}" }} | ||
""".trimMargin() | ||
} | ||
|
||
println("Celestial bodies information:\n\n${planetInfo(earth)}\n\n${planetInfo(mars)}") | ||
} |
25 changes: 25 additions & 0 deletions
25
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Poem.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Poem(val title: String, val content: String) | ||
|
||
suspend fun main() { | ||
val poem1: Poem = ai("A poem about the beauty of nature.") | ||
val poem2: Poem = ai("A poem about the power of technology.") | ||
val poem3: Poem = ai("A poem about the wisdom of artificial intelligence.") | ||
|
||
val combinedPoemContent = "${poem1.content}\n\n${poem2.content}\n\n${poem3.content}" | ||
|
||
val newPoemPrompt = """ | ||
Write a new poem that combines ideas from the following themes: the beauty of nature, the power of technology, and the wisdom of artificial intelligence. Here are some examples of poems on these themes: | ||
$combinedPoemContent | ||
""".trimIndent() | ||
|
||
val newPoem: Poem = ai(newPoemPrompt) | ||
|
||
println("New Poem:\n\n${newPoem.content}") | ||
} |
13 changes: 13 additions & 0 deletions
13
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Population.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Population(val size: Int, val description: String) | ||
|
||
suspend fun main() { | ||
val cadiz: Population = ai("Population of Cádiz, Spain.") | ||
val seattle: Population = ai("Population of Seattle, WA.") | ||
println("The population of Cádiz is ${cadiz.size} and the population of Seattle is ${seattle.size}") | ||
} |
12 changes: 12 additions & 0 deletions
12
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/Recipe.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Recipe(val name: String, val ingredients: List<String>) | ||
|
||
suspend fun main() { | ||
val recipe: Recipe = ai("Recipe for chocolate chip cookies.") | ||
println("The recipe for ${recipe.name} is ${recipe.ingredients}") | ||
} |
24 changes: 24 additions & 0 deletions
24
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/TopAttraction.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class TopAttraction(val city: City, val attractionName: String, val description: String, val weather: Weather) | ||
|
||
@Serializable | ||
data class City(val name: String, val country: String) | ||
|
||
@Serializable | ||
data class Weather(val city: City, val temperature: Double, val description: String) | ||
|
||
suspend fun main() { | ||
val nearbyTopAttraction: TopAttraction = ai("Top attraction in Cádiz, Spain.") | ||
println( | ||
""" | ||
|The top attraction in ${nearbyTopAttraction.city.name} is ${nearbyTopAttraction.attractionName}. | ||
|Here's a brief description: ${nearbyTopAttraction.description}. | ||
|The weather in ${nearbyTopAttraction.city.name} is ${nearbyTopAttraction.weather.temperature} degrees Celsius and ${nearbyTopAttraction.weather.description}. | ||
|""".trimMargin() | ||
) | ||
} |
15 changes: 15 additions & 0 deletions
15
example/src/main/kotlin/com/xebia/functional/langchain4k/auto/TouristAttraction.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.xebia.functional.langchain4k.auto | ||
|
||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class TouristAttraction(val name: String, val location: String, val history: String) | ||
|
||
suspend fun main() { | ||
val statueOfLiberty: TouristAttraction = ai("Statue of Liberty location and history.") | ||
println( | ||
"""${statueOfLiberty.name} is located in ${statueOfLiberty.location} and has the following history: | ||
|${statueOfLiberty.history}""".trimMargin() | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<configuration> | ||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||
<encoder> | ||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||
</encoder> | ||
</appender> | ||
|
||
<root level="DEBUG"> | ||
<appender-ref ref="STDOUT" /> | ||
</root> | ||
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
plugins { | ||
id(libs.plugins.kotlin.js.get().pluginId) | ||
} | ||
|
||
group = "com.xebia.functional.langchain4k" | ||
version = "0.0.1-SNAPSHOT" | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
kotlin { | ||
js(IR) { | ||
nodejs() | ||
} | ||
|
||
sourceSets { | ||
val main by getting { | ||
dependencies { | ||
implementation(rootProject) | ||
} | ||
} | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
nodejs-commandexecutor/src/main/kotlin/com/xebia/functional/agents/JsWikipediaAgent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.xebia.functional.agents | ||
|
||
import com.xebia.functional.auto.agents.Agent | ||
import com.xebia.functional.auto.agents.WikipediaResult | ||
import com.xebia.functional.auto.agents.wikipedia | ||
import com.xebia.functional.io.CommandExecutor | ||
import com.xebia.functional.io.SYSTEM | ||
|
||
fun Agent.Companion.wikipedia(): Agent<WikipediaResult> = | ||
Agent.wikipedia(CommandExecutor.SYSTEM) |
49 changes: 49 additions & 0 deletions
49
nodejs-commandexecutor/src/main/kotlin/com/xebia/functional/io/NodeCommandExecutor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.xebia.functional.io | ||
|
||
import kotlin.coroutines.resume | ||
import kotlin.coroutines.resumeWithException | ||
import kotlin.coroutines.suspendCoroutine | ||
|
||
private external val child_process: dynamic | ||
private external val os: dynamic | ||
|
||
private open external class ExecOptions { | ||
var cwd: String | ||
} | ||
|
||
val CommandExecutor.Companion.SYSTEM | ||
get() = NodeCommandExecutor | ||
|
||
object NodeCommandExecutor : CommandExecutor { | ||
override suspend fun executeCommandAndCaptureOutput(command: List<String>, options: ExecuteCommandOptions): String { | ||
val commandToExecute = command.joinToString(separator = " ") { arg -> | ||
if (arg.contains(" ")) "'$arg'" else arg | ||
} | ||
val redirect = if (options.redirectStderr) "2>&1 " else "" | ||
val execOptions = object : ExecOptions() { | ||
init { | ||
cwd = options.directory | ||
} | ||
} | ||
return suspendCoroutine { continuation -> | ||
child_process.exec("$commandToExecute $redirect", execOptions) { error, stdout, stderr -> | ||
if (error != null) { | ||
println(stderr) | ||
continuation.resumeWithException(error) | ||
} else { | ||
continuation.resume(if (options.trim) stdout.trim() else stdout) | ||
} | ||
} | ||
Unit | ||
} | ||
} | ||
|
||
override suspend fun pwd(options: ExecuteCommandOptions): String = | ||
// https://nodejs.org/api/os.html | ||
when (os.platform()) { | ||
"win32" -> executeCommandAndCaptureOutput(listOf("echo", "%cd%"), options).trim() | ||
else -> executeCommandAndCaptureOutput(listOf("pwd"), options).trim() | ||
} | ||
|
||
override suspend fun findExecutable(executable: String): String = executable | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,4 +6,5 @@ pluginManagement { | |
|
||
} | ||
rootProject.name = "langchain4k" | ||
|
||
include("nodejs-commandexecutor") | ||
include("example") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.xebia.functional.auto | ||
|
||
import com.xebia.functional.auto.agents.Agent | ||
import com.xebia.functional.auto.model.* | ||
|
||
tailrec suspend fun solveObjective( | ||
task: Task, | ||
maxAttempts: Int = 5, | ||
previousSolutions: List<Solution> = emptyList(), | ||
agents: List<Agent<*>> = emptyList() | ||
): Solution = if (maxAttempts <= 0) { | ||
Solution(-1, task, result = "Exceeded maximum attempts", accomplishesObjective = false) | ||
} else { | ||
logger.debug { "Solving objective: ${task.objective} with agents $agents" } | ||
val contexts = agents.map { it.context(task, previousSolutions) } | ||
logger.debug { "Contexts: $contexts" } | ||
val ctx = AIContext(task, previousSolutions, contexts) | ||
val result: Solution = ctx.solution() | ||
logger.debug { "Solved: ${result.accomplishesObjective}" } | ||
if (result.accomplishesObjective) { | ||
logger.debug { "Solution accomplishes objective, proceeding to verification" } | ||
val verification: Verification = ctx.verify(result) | ||
if (verification.solvesTheProblemForReal) { | ||
logger.debug { "Solution verified: ${verification.solution.result} accepted: ${verification.solution.accomplishesObjective}" } | ||
result | ||
} else { | ||
val refinedTask: Task = ctx.refineTask() | ||
logger.debug { "Refined task: ${refinedTask.objective}" } | ||
solveObjective(refinedTask, maxAttempts - 1, previousSolutions + result) | ||
} | ||
} else { | ||
val refinedTask: Task = ctx.refineTask() | ||
logger.debug { "Refined task: ${refinedTask.objective}" } | ||
solveObjective(refinedTask, maxAttempts - 1, previousSolutions + result) | ||
} | ||
} | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package com.xebia.functional.auto | ||
|
||
import arrow.core.getOrElse | ||
import arrow.core.raise.catch | ||
import arrow.core.raise.either | ||
import arrow.fx.coroutines.resourceScope | ||
import com.xebia.functional.auto.agents.Agent | ||
import com.xebia.functional.auto.model.Task | ||
import com.xebia.functional.auto.serialization.buildJsonSchema | ||
import com.xebia.functional.embeddings.OpenAIEmbeddings | ||
import com.xebia.functional.env.OpenAIConfig | ||
import com.xebia.functional.llm.openai.* | ||
import com.xebia.functional.vectorstores.LocalVectorStore | ||
import com.xebia.functional.vectorstores.VectorStore | ||
import io.github.oshai.KotlinLogging | ||
import io.ktor.client.engine.HttpClientEngine | ||
import kotlinx.serialization.DeserializationStrategy | ||
import kotlinx.serialization.descriptors.SerialDescriptor | ||
import kotlinx.serialization.descriptors.serialDescriptor | ||
import kotlinx.serialization.json.Json | ||
import kotlinx.serialization.json.JsonObject | ||
import kotlinx.serialization.serializer | ||
import kotlin.time.ExperimentalTime | ||
|
||
@PublishedApi | ||
internal val logger = KotlinLogging.logger("AutoAI") | ||
|
||
val json = Json { | ||
ignoreUnknownKeys = true | ||
isLenient = true | ||
} | ||
|
||
@OptIn(ExperimentalTime::class) | ||
suspend inline fun <reified A> ai( | ||
prompt: String, | ||
engine: HttpClientEngine? = null, | ||
agents: List<Agent<*>> = emptyList(), | ||
auto: Boolean = false, | ||
): A { | ||
val descriptor = serialDescriptor<A>() | ||
val jsonSchema = buildJsonSchema(descriptor) | ||
return resourceScope { | ||
either { | ||
val openAIConfig = OpenAIConfig() | ||
val openAiClient = KtorOpenAIClient(openAIConfig, engine) | ||
val embeddings = OpenAIEmbeddings(openAIConfig, openAiClient, logger) | ||
val vectorStore = LocalVectorStore(embeddings) | ||
ai(prompt, descriptor, serializer<A>(), jsonSchema, openAiClient, vectorStore, agents, auto) | ||
}.getOrElse { throw IllegalStateException(it.joinToString()) } | ||
} | ||
} | ||
|
||
suspend fun <A> ai( | ||
prompt: String, | ||
descriptor: SerialDescriptor, | ||
deserializationStrategy: DeserializationStrategy<A>, | ||
jsonSchema: JsonObject, | ||
openAIClient: OpenAIClient, | ||
vectorStore: VectorStore, | ||
agents: List<Agent<*>> = emptyList(), | ||
auto: Boolean = false, | ||
): A { | ||
val augmentedPrompt = """ | ||
|Objective: $prompt | ||
|Instructions: Use the following JSON schema to produce the result on json format | ||
|JSON Schema:$jsonSchema | ||
|Return exactly the JSON response and nothing else | ||
""".trimMargin() | ||
val result = if (auto) { | ||
logger.debug { "Solving objective in auto reasoning mode: ${agents}\n$prompt" } | ||
val resolutionContext = solveObjective(Task(-1, prompt, emptyList()), agents = agents).result | ||
val promptWithContext = """ | ||
|$resolutionContext | ||
| | ||
|Given this information solve the objective: | ||
| | ||
|$augmentedPrompt | ||
""".trimMargin() | ||
openAIChatCall(openAIClient, promptWithContext) | ||
} else { | ||
logger.debug { "Solving objective without agents\n$prompt" } | ||
openAIChatCall(openAIClient, augmentedPrompt) | ||
} | ||
return catch({ | ||
json.decodeFromString(deserializationStrategy, result) | ||
}) { e -> | ||
val fixJsonPrompt = """ | ||
|Result: $result | ||
|Exception: ${e.message} | ||
|Objective: $prompt | ||
|Instructions: Use the following JSON schema to produce the result on valid json format avoiding the exception. | ||
|JSON Schema:$jsonSchema | ||
""".trimMargin() | ||
logger.debug { "Attempting to Fix JSON due to error: ${e.message}" } | ||
|
||
//here we should retry and handle errors, when we are executing the `ai` function again it might fail and it eventually crashes | ||
//we should handle this and retry | ||
ai(fixJsonPrompt, descriptor, deserializationStrategy, jsonSchema, openAIClient, vectorStore) | ||
.also { logger.debug { "Fixed JSON: $it" } } | ||
} | ||
} | ||
|
||
private suspend fun openAIChatCall( | ||
openAIClient: OpenAIClient, | ||
promptWithContext: String | ||
): String { | ||
val res = chatCompletionResponse(openAIClient, promptWithContext, "gpt-3.5-turbo", "AI_Value_Generator") | ||
val msg = res.choices.firstOrNull()?.message?.content | ||
requireNotNull(msg) { "No message found in result: $res" } | ||
return msg | ||
} | ||
|
||
private suspend fun chatCompletionResponse( | ||
openAIClient: OpenAIClient, | ||
prompt: String, | ||
model: String, | ||
user: String | ||
): ChatCompletionResponse { | ||
val completionRequest = ChatCompletionRequest( | ||
model = model, | ||
messages = listOf(Message(Role.system.name, prompt, user)), | ||
user = user | ||
) | ||
return openAIClient.createChatCompletion(completionRequest) | ||
} |
10 changes: 10 additions & 0 deletions
10
src/commonMain/kotlin/com/xebia/functional/auto/agents/Agent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.xebia.functional.auto.agents | ||
|
||
import com.xebia.functional.auto.model.Solution | ||
import com.xebia.functional.auto.model.Task | ||
|
||
interface Agent<out A> { | ||
suspend fun context(task: Task, previousSolutions: List<Solution>): AgentContext<A> | ||
|
||
companion object | ||
} |
21 changes: 21 additions & 0 deletions
21
src/commonMain/kotlin/com/xebia/functional/auto/agents/AgentContext.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.xebia.functional.auto.agents | ||
|
||
import com.xebia.functional.auto.model.AIContext | ||
import com.xebia.functional.auto.model.Solution | ||
import com.xebia.functional.auto.model.Task | ||
import com.xebia.functional.auto.model.previousSolutionsContext | ||
|
||
data class AgentContext<out A>( | ||
val task: Task, val previousSolutions: List<Solution>, val value: A, val output: String | ||
) | ||
|
||
internal fun AIContext.additionalContext(): String = | ||
if (agentContexts.isEmpty()) previousSolutionsContext() | ||
else """|${previousSolutionsContext()} | ||
| | ||
|Additional context provided by other agents for this context is shown below and delimited | ||
|by a line of dashes | ||
|----------------------------------------------------------------------- | ||
|${agentContexts.joinToString("\n") { "- ${it.task.objective}\n\tresult:${it.output}\n\t" }}. | ||
|----------------------------------------------------------------------- | ||
|""".trimMargin() |
49 changes: 49 additions & 0 deletions
49
src/commonMain/kotlin/com/xebia/functional/auto/agents/WikipediaAgent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.xebia.functional.auto.agents | ||
|
||
import com.xebia.functional.auto.* | ||
import com.xebia.functional.auto.model.Solution | ||
import com.xebia.functional.auto.model.Task | ||
import com.xebia.functional.io.CommandExecutor | ||
import com.xebia.functional.io.ExecuteCommandOptions | ||
import io.ktor.http.* | ||
import kotlinx.serialization.Serializable | ||
import okio.FileSystem | ||
|
||
@Serializable | ||
data class WikipediaResult(val command: String, val description: String) | ||
|
||
fun Agent.Companion.wikipedia(executor: CommandExecutor): Agent<WikipediaResult> = object : Agent<WikipediaResult> { | ||
override suspend fun context(task: Task, previousSolutions: List<Solution>): AgentContext<WikipediaResult> { | ||
val curlCommand = listOf( | ||
"curl", | ||
"-s", | ||
"https://en.wikipedia.org/w/api.php?action=query&format=json&list=search&srsearch=${task.objective.encodeURLQueryComponent()}" | ||
) | ||
val result = executor.executeCommandAndCaptureOutput( | ||
curlCommand, | ||
ExecuteCommandOptions( | ||
directory = FileSystem.SYSTEM_TEMPORARY_DIRECTORY.toString(), | ||
abortOnError = true, | ||
redirectStderr = true, | ||
trim = true | ||
) | ||
) | ||
val summarized: WikipediaResult = ai( | ||
""" | ||
You are an AI Agent in charge of extracting relevant information for objective: | ||
${task.objective} | ||
Instructions: | ||
- Extract the relevant information from the following output extracted by command: | ||
$curlCommand | ||
- The output is: | ||
---------------- | ||
$result | ||
---------------- | ||
- If no relevant information is found, return the following: | ||
<No relevant information found> | ||
""".trimIndent() | ||
) | ||
logger.debug { "WikipediaAgent: $summarized" } | ||
return AgentContext(task, previousSolutions, summarized, summarized.description) | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/commonMain/kotlin/com/xebia/functional/auto/model/AIContext.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.xebia.functional.auto.model | ||
|
||
import com.xebia.functional.auto.agents.AgentContext | ||
|
||
data class AIContext( | ||
val currentTask: Task, val previousSolutions: List<Solution>, val agentContexts: List<AgentContext<*>> | ||
) |
26 changes: 26 additions & 0 deletions
26
src/commonMain/kotlin/com/xebia/functional/auto/model/Solution.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.xebia.functional.auto.model | ||
|
||
import com.xebia.functional.auto.agents.additionalContext | ||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Solution( | ||
val id: Int, val task: Task, val result: String, val accomplishesObjective: Boolean | ||
) | ||
|
||
suspend fun AIContext.solution(): Solution = | ||
ai( | ||
"""|You are an AI who performs one task based on the following objective: | ||
|${currentTask.objective} | ||
| | ||
|${additionalContext()} | ||
|If you can't solve the objective, use `false` for `accomplishesObjective` in the returned response. | ||
""".trimMargin() | ||
) | ||
|
||
internal fun AIContext.previousSolutionsContext(): String = | ||
if (previousSolutions.isEmpty()) "" | ||
else """|Take into account these previously attempted tasks: | ||
|${previousSolutions.joinToString("\n") { "- ${it.task.objective}\n\tresult:${it.result}\n\tAccomplishes Objective: ${it.accomplishesObjective}" }}. | ||
""".trimMargin() |
22 changes: 22 additions & 0 deletions
22
src/commonMain/kotlin/com/xebia/functional/auto/model/Task.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.xebia.functional.auto.model | ||
|
||
import com.xebia.functional.auto.agents.additionalContext | ||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Task( | ||
val id: Int, val objective: String, val instructions: List<String> | ||
) | ||
|
||
suspend fun AIContext.refineTask(): Task = ai( | ||
"""|You are an AI who refines a task based on the following objective: | ||
|${currentTask.objective} | ||
|We have attempted to solve the with the current solution | ||
|but we are not sure if it's successful. | ||
| | ||
|${additionalContext()} | ||
| | ||
|Please refine the following task: ${currentTask.objective} to make it more specific, so that it can be solved. | ||
""".trimMargin() | ||
) |
21 changes: 21 additions & 0 deletions
21
src/commonMain/kotlin/com/xebia/functional/auto/model/Verification.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.xebia.functional.auto.model | ||
|
||
import com.xebia.functional.auto.agents.additionalContext | ||
import com.xebia.functional.auto.ai | ||
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class Verification(val id: Int, val solution: Solution, val solvesTheProblemForReal: Boolean) | ||
|
||
suspend fun AIContext.verify(result: Solution): Verification = ai( | ||
"""|You are an AI who verifies an objective has been accomplished for one task based on the following objective: | ||
|We have attempted to solve the following task objective: | ||
|${currentTask.objective} | ||
|We came up with the current solution, but we are not sure if it's successful. | ||
|Please verify that the following solution: ${result.result} accomplishes the objective. | ||
|Be very critical until you are sure that the solution solves the objective. | ||
| | ||
|${additionalContext()} | ||
| | ||
""".trimMargin() | ||
) |
510 changes: 510 additions & 0 deletions
510
src/commonMain/kotlin/com/xebia/functional/auto/serialization/JsonSchema.kt
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/commonMain/kotlin/com/xebia/functional/io/CommandExecutor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.xebia.functional.io | ||
|
||
|
||
data class ExecuteCommandOptions( | ||
val directory: String, | ||
val abortOnError: Boolean, | ||
val redirectStderr: Boolean, | ||
val trim: Boolean | ||
) | ||
|
||
enum class Platform { | ||
LINUX, MACOS, WINDOWS, | ||
} | ||
|
||
interface CommandExecutor { | ||
suspend fun executeCommandAndCaptureOutput( | ||
command: List<String>, | ||
options: ExecuteCommandOptions | ||
): String | ||
|
||
suspend fun pwd(options: ExecuteCommandOptions): String | ||
|
||
suspend fun findExecutable(executable: String): String | ||
|
||
companion object | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/commonMain/kotlin/com/xebia/functional/vectorstores/LocalVectorStore.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package com.xebia.functional.vectorstores | ||
|
||
import com.xebia.functional.Document | ||
import com.xebia.functional.embeddings.Embedding | ||
import com.xebia.functional.embeddings.Embeddings | ||
import com.xebia.functional.llm.openai.EmbeddingModel | ||
import com.xebia.functional.llm.openai.RequestConfig | ||
import kotlinx.uuid.UUID | ||
import kotlinx.uuid.generateUUID | ||
import kotlin.math.sqrt | ||
import kotlinx.coroutines.sync.Mutex | ||
import kotlinx.coroutines.sync.withLock | ||
|
||
class LocalVectorStore(private val embeddings: Embeddings) : VectorStore { | ||
|
||
private val requestConfig = RequestConfig( | ||
EmbeddingModel.TextEmbeddingAda002, | ||
RequestConfig.Companion.User("user") | ||
) | ||
|
||
private val mutex: Mutex = Mutex() | ||
private val documents: MutableList<Document> = mutableListOf() | ||
private val documentEmbeddings: MutableMap<Document, Embedding> = mutableMapOf() | ||
|
||
override suspend fun addTexts(texts: List<String>): List<DocumentVectorId> { | ||
val embeddingsList = embeddings.embedDocuments(texts, chunkSize = null, requestConfig = requestConfig) | ||
return texts.zip(embeddingsList) { text, embedding -> | ||
val document = Document(text) | ||
mutex.withLock { | ||
documents.add(document) | ||
documentEmbeddings[document] = embedding | ||
} | ||
DocumentVectorId(UUID.generateUUID()) | ||
} | ||
} | ||
|
||
override suspend fun addDocuments(documents: List<Document>): List<DocumentVectorId> = | ||
addTexts(documents.map(Document::content)) | ||
|
||
override suspend fun similaritySearch(query: String, limit: Int): List<Document> { | ||
val queryEmbedding = embeddings.embedQuery(query, requestConfig = requestConfig).firstOrNull() | ||
return queryEmbedding?.let { | ||
similaritySearchByVector(it, limit) | ||
}.orEmpty() | ||
} | ||
|
||
override suspend fun similaritySearchByVector(embedding: Embedding, limit: Int): List<Document> = | ||
documents.mapNotNull { document -> | ||
mutex.withLock { documentEmbeddings[document]?.cosineSimilarity(embedding) }?.let { | ||
document to it | ||
} | ||
}.sortedByDescending { (_, similarity) -> similarity } | ||
.take(limit) | ||
.map { (document, _) -> document } | ||
|
||
private fun Embedding.cosineSimilarity(other: Embedding): Double { | ||
val dotProduct = this.data.zip(other.data).sumOf { (a, b) -> (a * b).toDouble() } | ||
val magnitudeA = sqrt(this.data.sumOf { (it * it).toDouble() }) | ||
val magnitudeB = sqrt(other.data.sumOf { (it * it).toDouble() }) | ||
return dotProduct / (magnitudeA * magnitudeB) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/jvmMain/kotlin/com/xebia/functional/auto/agents/JvmWikipediaAgent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.xebia.functional.auto.agents | ||
|
||
import com.xebia.functional.io.CommandExecutor | ||
import com.xebia.functional.io.SYSTEM | ||
|
||
fun Agent.Companion.wikipedia(): Agent<WikipediaResult> = | ||
Agent.wikipedia(CommandExecutor.SYSTEM) |
90 changes: 90 additions & 0 deletions
90
src/jvmMain/kotlin/com/xebia/functional/io/JvmCommandExecutor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package com.xebia.functional.io | ||
|
||
import kotlinx.coroutines.runBlocking | ||
import java.io.File | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.runInterruptible | ||
import kotlinx.coroutines.withContext | ||
|
||
val CommandExecutor.Companion.SYSTEM: CommandExecutor | ||
get() = JvmCommandExecutor | ||
|
||
object JvmCommandExecutor : CommandExecutor { | ||
|
||
// TODO Remove RunBlocking | ||
private val platform: Platform by lazy { | ||
val osName = System.getProperty("os.name").lowercase() | ||
|
||
when { | ||
osName.startsWith("windows") -> { | ||
val uname = runBlocking { | ||
try { | ||
executeCommandAndCaptureOutput( | ||
listOf("where", "uname"), | ||
ExecuteCommandOptions( | ||
directory = ".", | ||
abortOnError = true, | ||
redirectStderr = false, | ||
trim = true, | ||
), | ||
) | ||
executeCommandAndCaptureOutput( | ||
listOf("uname", "-a"), | ||
ExecuteCommandOptions( | ||
directory = ".", | ||
abortOnError = true, | ||
redirectStderr = true, | ||
trim = true, | ||
), | ||
) | ||
} catch (e: Exception) { | ||
"" | ||
} | ||
} | ||
// if (uname.isNotBlank()) println("uname: $uname") | ||
when { | ||
uname.startsWith("MSYS") -> Platform.LINUX | ||
uname.startsWith("MINGW") -> Platform.LINUX | ||
uname.startsWith("CYGWIN") -> Platform.LINUX | ||
else -> Platform.WINDOWS | ||
} // .also { println("platform is $it") } | ||
} | ||
|
||
osName.startsWith("linux") -> Platform.LINUX | ||
osName.startsWith("mac") -> Platform.MACOS | ||
osName.startsWith("darwin") -> Platform.MACOS | ||
else -> error("unknown osName: $osName") | ||
} | ||
} | ||
|
||
|
||
override suspend fun executeCommandAndCaptureOutput(command: List<String>, options: ExecuteCommandOptions): String = | ||
withContext(Dispatchers.IO) { | ||
val process = ProcessBuilder().apply { | ||
command(command.filter { it.isNotBlank() }) | ||
directory(File(options.directory)) | ||
}.start() | ||
val stdout = process.inputStream.bufferedReader().use { it.readText() } | ||
val stderr = process.errorStream.bufferedReader().use { it.readText() } | ||
val exitCode = runInterruptible { process.waitFor() } | ||
if (options.abortOnError) assert(exitCode == 0) | ||
val output = if (stderr.isBlank()) stdout else "$stdout $stderr" | ||
if (options.trim) output.trim() else output | ||
} | ||
|
||
override suspend fun pwd(options: ExecuteCommandOptions): String = | ||
File(".").absolutePath | ||
|
||
override suspend fun findExecutable(executable: String): String = | ||
when (platform) { | ||
Platform.WINDOWS -> executeCommandAndCaptureOutput( | ||
listOf("where", executable), | ||
ExecuteCommandOptions(".", true, false, true) | ||
) | ||
|
||
else -> executeCommandAndCaptureOutput( | ||
listOf("which", executable), | ||
ExecuteCommandOptions(".", true, false, true) | ||
) | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/linuxX64Main/kotlin/com/xebia/functional/auto/agents/LinuxWikipediaAgent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.xebia.functional.auto.agents | ||
|
||
import com.xebia.functional.io.CommandExecutor | ||
import com.xebia.functional.io.SYSTEM | ||
|
||
fun Agent.Companion.wikipedia(): Agent<WikipediaResult> = | ||
Agent.wikipedia(CommandExecutor.SYSTEM) |
48 changes: 48 additions & 0 deletions
48
src/linuxX64Main/kotlin/com/xebia/functional/io/LinuxCommandExecutor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.xebia.functional.io | ||
|
||
|
||
import kotlinx.cinterop.refTo | ||
import kotlinx.cinterop.toKString | ||
import platform.posix.* | ||
|
||
val CommandExecutor.Companion.SYSTEM: CommandExecutor | ||
get() = LinuxCommandExecutor | ||
|
||
object LinuxCommandExecutor : CommandExecutor { | ||
|
||
/** | ||
* https://stackoverflow.com/questions/57123836/kotlin-native-execute-command-and-get-the-output | ||
*/ | ||
override suspend fun executeCommandAndCaptureOutput( | ||
command: List<String>, | ||
options: ExecuteCommandOptions | ||
): String { | ||
chdir(options.directory) | ||
val commandToExecute = command.joinToString(separator = " ") { arg -> | ||
if (arg.contains(" ")) "'$arg'" else arg | ||
} | ||
val redirect = if (options.redirectStderr) " 2>&1 " else "" | ||
val fp = popen("$commandToExecute $redirect", "r") ?: error("Failed to run command: $command") | ||
|
||
val stdout = buildString { | ||
val buffer = ByteArray(4096) | ||
while (true) { | ||
val input = fgets(buffer.refTo(0), buffer.size, fp) ?: break | ||
append(input.toKString()) | ||
} | ||
} | ||
|
||
val status = pclose(fp) | ||
if (status != 0 && options.abortOnError) { | ||
println(stdout) | ||
throw Exception("Command `$command` failed with status $status${if (options.redirectStderr) ": $stdout" else ""}") | ||
} | ||
|
||
return if (options.trim) stdout.trim() else stdout | ||
} | ||
|
||
override suspend fun pwd(options: ExecuteCommandOptions): String = | ||
executeCommandAndCaptureOutput(listOf("pwd"), options).trim() | ||
|
||
override suspend fun findExecutable(executable: String): String = executable | ||
} |
7 changes: 7 additions & 0 deletions
7
src/macosX64Main/kotlin/com/xebia/functional/auto/agents/MacOsWikipediaAgent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.xebia.functional.auto.agents | ||
|
||
import com.xebia.functional.io.CommandExecutor | ||
import com.xebia.functional.io.SYSTEM | ||
|
||
fun Agent.Companion.wikipedia(): Agent<WikipediaResult> = | ||
Agent.wikipedia(CommandExecutor.SYSTEM) |
45 changes: 45 additions & 0 deletions
45
src/macosX64Main/kotlin/com/xebia/functional/io/MacosCommandExecutor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.xebia.functional.io | ||
|
||
import kotlinx.cinterop.refTo | ||
import kotlinx.cinterop.toKString | ||
import platform.posix.* | ||
|
||
val CommandExecutor.Companion.SYSTEM: MacosCommandExecutor | ||
get() = MacosCommandExecutor | ||
|
||
object MacosCommandExecutor : CommandExecutor { | ||
|
||
/** | ||
* https://stackoverflow.com/questions/57123836/kotlin-native-execute-command-and-get-the-output | ||
*/ | ||
override suspend fun executeCommandAndCaptureOutput(command: List<String>, options: ExecuteCommandOptions): String { | ||
chdir(options.directory) | ||
val commandToExecute = command.joinToString(separator = " ") { arg -> | ||
if (arg.contains(" ")) "'$arg'" else arg | ||
} | ||
val redirect = if (options.redirectStderr) " 2>&1 " else "" | ||
val fp = popen("$commandToExecute $redirect", "r") ?: error("Failed to run command: $command") | ||
|
||
val stdout = buildString { | ||
val buffer = ByteArray(4096) | ||
while (true) { | ||
val input = fgets(buffer.refTo(0), buffer.size, fp) ?: break | ||
append(input.toKString()) | ||
} | ||
} | ||
|
||
val status = pclose(fp) | ||
if (status != 0 && options.abortOnError) { | ||
println(stdout) | ||
throw Exception("Command `$command` failed with status $status${if (options.redirectStderr) ": $stdout" else ""}") | ||
} | ||
|
||
return if (options.trim) stdout.trim() else stdout | ||
} | ||
|
||
override suspend fun pwd(options: ExecuteCommandOptions): String = | ||
executeCommandAndCaptureOutput(listOf("pwd"), options).trim() | ||
|
||
override suspend fun findExecutable(executable: String): String = | ||
executable | ||
} |
7 changes: 7 additions & 0 deletions
7
src/mingwX64Main/kotlin/com/xebia/functional/auto/agents/WindowsWikipediaAgents.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.xebia.functional.auto.agents | ||
|
||
import com.xebia.functional.io.CommandExecutor | ||
import com.xebia.functional.io.SYSTEM | ||
|
||
fun Agent.Companion.wikipedia(): Agent<WikipediaResult> = | ||
Agent.wikipedia(CommandExecutor.SYSTEM) |
88 changes: 88 additions & 0 deletions
88
src/mingwX64Main/kotlin/com/xebia/functional/io/WindowsCommandExecutor.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package com.xebia.functional.io | ||
|
||
import kotlinx.cinterop.refTo | ||
import kotlinx.cinterop.toKString | ||
import kotlinx.coroutines.runBlocking | ||
import platform.posix._pclose | ||
import platform.posix._popen | ||
import platform.posix.chdir | ||
import platform.posix.fgets | ||
|
||
val CommandExecutor.Companion.SYSTEM: CommandExecutor | ||
get() = WindowsCommandExecutor | ||
|
||
object WindowsCommandExecutor : CommandExecutor { | ||
// TODO Remove RunBlocking | ||
private val platform: Platform by lazy { | ||
val uname = runBlocking { | ||
try { | ||
executeCommandAndCaptureOutput( | ||
listOf("where", "uname"), | ||
ExecuteCommandOptions( | ||
directory = ".", | ||
abortOnError = true, | ||
redirectStderr = false, | ||
trim = true, | ||
), | ||
) | ||
executeCommandAndCaptureOutput( | ||
listOf("uname", "-a"), | ||
ExecuteCommandOptions( | ||
directory = ".", | ||
abortOnError = true, | ||
redirectStderr = true, | ||
trim = true, | ||
), | ||
) | ||
} catch (e: Exception) { | ||
"" | ||
} | ||
} | ||
// if (uname.isNotBlank()) println("uname: $uname") | ||
when { | ||
uname.startsWith("MSYS") -> Platform.LINUX | ||
uname.startsWith("MINGW") -> Platform.LINUX | ||
uname.startsWith("CYGWIN") -> Platform.LINUX | ||
else -> Platform.WINDOWS | ||
}//.also { println("platform is $it") } | ||
} | ||
|
||
/** | ||
* https://stackoverflow.com/questions/57123836/kotlin-native-execute-command-and-get-the-output | ||
*/ | ||
override suspend fun executeCommandAndCaptureOutput(command: List<String>, options: ExecuteCommandOptions): String { | ||
chdir(options.directory) | ||
val commandToExecute = command.joinToString(separator = " ") { arg -> | ||
if (arg.contains(" ") || arg.contains("%")) "\"$arg\"" else arg | ||
} | ||
println("executing: $commandToExecute") | ||
val redirect = if (options.redirectStderr) " 2>&1 " else "" | ||
val fp = _popen("$commandToExecute $redirect", "r") ?: error("Failed to run command: $command") | ||
|
||
val stdout = buildString { | ||
val buffer = ByteArray(4096) | ||
while (true) { | ||
val input = fgets(buffer.refTo(0), buffer.size, fp) ?: break | ||
append(input.toKString()) | ||
} | ||
} | ||
|
||
val status = _pclose(fp) | ||
if (status != 0 && options.abortOnError) { | ||
println(stdout) | ||
println("failed to run: $commandToExecute") | ||
throw Exception("Command `$command` failed with status $status${if (options.redirectStderr) ": $stdout" else ""}") | ||
} | ||
|
||
return if (options.trim) stdout.trim() else stdout | ||
} | ||
|
||
|
||
override suspend fun pwd(options: ExecuteCommandOptions): String = when (platform) { | ||
Platform.WINDOWS -> executeCommandAndCaptureOutput(listOf("echo", "%cd%"), options).trim('"', ' ') | ||
else -> executeCommandAndCaptureOutput(listOf("pwd"), options).trim() | ||
} | ||
|
||
override suspend fun findExecutable(executable: String): String = | ||
executable | ||
} |