Skip to content

Commit 0ab49d0

Browse files
authored
Merge pull request #146 from joreilly/ai
add basic koog ai agent to the project
2 parents e8620d2 + 07b9994 commit 0ab49d0

File tree

5 files changed

+130
-0
lines changed

5 files changed

+130
-0
lines changed

agents/build.gradle.kts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
plugins {
2+
alias(libs.plugins.kotlinJvm)
3+
application
4+
}
5+
6+
dependencies {
7+
implementation(libs.mcp.kotlin)
8+
implementation(libs.koin.core)
9+
implementation("ai.koog:koog-agents:0.2.1")
10+
implementation("org.slf4j:slf4j-simple:2.0.17")
11+
implementation(projects.composeApp)
12+
}
13+
14+
java {
15+
toolchain {
16+
languageVersion = JavaLanguageVersion.of(17)
17+
}
18+
}
19+
20+
application {
21+
mainClass = "MainKt"
22+
}
23+
24+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import ai.koog.agents.core.tools.annotations.LLMDescription
2+
import ai.koog.agents.core.tools.annotations.Tool
3+
import ai.koog.agents.core.tools.reflect.ToolSet
4+
import dev.johnoreilly.climatetrace.data.ClimateTraceRepository
5+
6+
7+
8+
@LLMDescription("Tools for getting climate emission information")
9+
class ClimateTraceTool : ToolSet {
10+
val climateTraceRepository = koin.get<ClimateTraceRepository>()
11+
12+
@Tool
13+
@LLMDescription("Get the list of countries")
14+
suspend fun getCountries(): List<String> {
15+
val countries = climateTraceRepository.fetchCountries()
16+
return countries.map { "${it.name}, ${it.alpha3}" }
17+
}
18+
19+
20+
@Tool(customName = "getEmissions")
21+
@LLMDescription("Get the emission data for a country for a particular year.")
22+
suspend fun getEmissions(
23+
@LLMDescription("country code") countryCode: String,
24+
@LLMDescription("year") year: String
25+
): List<String> {
26+
return climateTraceRepository.fetchCountryEmissionsInfo(countryCode, year).map {
27+
it.emissions.co2.toString()
28+
}
29+
}
30+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import ai.koog.agents.core.agent.AIAgent
2+
import ai.koog.agents.core.tools.ToolRegistry
3+
import ai.koog.agents.core.tools.reflect.asTools
4+
import ai.koog.agents.features.eventHandler.feature.handleEvents
5+
import ai.koog.agents.mcp.McpToolRegistryProvider
6+
import ai.koog.prompt.executor.clients.google.GoogleModels
7+
import ai.koog.prompt.executor.clients.openai.OpenAIModels
8+
import ai.koog.prompt.executor.llms.all.simpleGoogleAIExecutor
9+
import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor
10+
import kotlin.uuid.ExperimentalUuidApi
11+
import kotlin.uuid.Uuid
12+
13+
val openAIApiKey = ""
14+
val apiKeyGoogle = ""
15+
16+
17+
18+
@OptIn(ExperimentalUuidApi::class)
19+
suspend fun runKoogAgent() {
20+
val agent = AIAgent(
21+
executor = simpleOpenAIExecutor(openAIApiKey),
22+
//executor = simpleGoogleAIExecutor(apiKeyGoogle),
23+
llmModel = OpenAIModels.Chat.GPT4o,
24+
//llmModel = GoogleModels.Gemini1_5Pro,
25+
toolRegistry = createToolSetRegistry()
26+
) {
27+
handleEvents {
28+
onToolCall { tool: ai.koog.agents.core.tools.Tool<*, *>, toolArgs: ai.koog.agents.core.tools.Tool.Args ->
29+
println("Tool called: tool ${tool.name}, args $toolArgs")
30+
}
31+
32+
onAgentRunError { strategyName: String, sessionUuid: Uuid?, throwable: Throwable ->
33+
println("An error occurred: ${throwable.message}\n${throwable.stackTraceToString()}")
34+
}
35+
36+
onAgentFinished { strategyName, result ->
37+
println("Agent (strategy = $strategyName) finished with result: $result")
38+
}
39+
}
40+
}
41+
42+
agent.run(
43+
"""
44+
Get emission data for France, Germany for 2023 and 2024.
45+
Use units of millions for the emissions data.
46+
Also get best estimate of population for each country and show per-capita emissions.
47+
""".trimIndent()
48+
)
49+
}
50+
51+
52+
suspend fun createToolSetRegistry(): ToolRegistry {
53+
val processClimateTrace = ProcessBuilder("java", "-jar",
54+
"./mcp-server/build/libs/serverAll.jar", "--stdio"
55+
).start()
56+
val transportClimateTrace = McpToolRegistryProvider.defaultStdioTransport(processClimateTrace)
57+
val toolRegistryClimateTrace = McpToolRegistryProvider.fromTransport(transportClimateTrace)
58+
59+
val localToolSetRegistry = ToolRegistry { tools(ClimateTraceTool().asTools()) }
60+
61+
// Can use either local toolset or one based on MCP server
62+
//return toolRegistryClimateTrace
63+
return localToolSetRegistry
64+
}

agents/src/main/kotlin/main.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import dev.johnoreilly.climatetrace.di.initKoin
2+
import kotlinx.coroutines.runBlocking
3+
import kotlin.uuid.ExperimentalUuidApi
4+
5+
6+
val koin = initKoin(enableNetworkLogs = true).koin
7+
8+
@OptIn(ExperimentalUuidApi::class)
9+
fun main() = runBlocking{
10+
runKoogAgent()
11+
}

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
2323
rootProject.name = "ClimateTraceKMP"
2424
include(":composeApp")
2525
include(":mcp-server")
26+
include(":agents")

0 commit comments

Comments
 (0)