CtrlK
CommunityDocumentationLog inGet started
Tessl Logo

tessl/maven-com-embabel-agent--embabel-agent-common

Common AI framework utilities for the Embabel Agent system including LLM configuration, output converters, prompt contributors, and embedding service abstractions.

Overview
Eval results
Files

prompt-system.mddocs/supporting/

Prompt System

Pluggable system for contributing content to prompts at different locations with role-based identification.

Core Interfaces

PromptContributor

Objects that contribute to prompts with fixed or dynamic content.

interface PromptContributor : PromptElement {
    fun promptContribution(): PromptContribution
    fun contribution(): String

    companion object {
        @JvmStatic
        @JvmOverloads
        fun fixed(
            content: String,
            role: String? = null,
            location: PromptContributionLocation = PromptContributionLocation.BEGINNING
        ): PromptContributor

        @JvmStatic
        @JvmOverloads
        fun dynamic(
            contributionMaker: () -> String,
            role: String? = null,
            location: PromptContributionLocation = PromptContributionLocation.BEGINNING
        ): PromptContributor
    }
}

Basic Usage:

// Fixed content
val fixedContributor = PromptContributor.fixed(
    content = "You are a helpful AI assistant.",
    role = "system_prompt",
    location = PromptContributionLocation.BEGINNING
)

// Dynamic content
val dynamicContributor = PromptContributor.dynamic(
    contributionMaker = {
        val currentTime = LocalDateTime.now()
        "Current time: $currentTime"
    },
    role = "timestamp",
    location = PromptContributionLocation.BEGINNING
)

// Use contributors
val contribution1 = fixedContributor.promptContribution()
println(contribution1.content)

PromptContribution

Data class representing a single prompt contribution.

data class PromptContribution(
    val content: String,
    val location: PromptContributionLocation,
    val role: String?
) {
    companion object {
        const val KNOWLEDGE_CUTOFF_ROLE = "knowledge_cutoff"
        const val CURRENT_DATE_ROLE = "current_date"
    }
}

PromptContributionLocation

Where contributions are inserted in the prompt.

enum class PromptContributionLocation {
    BEGINNING,
    END
}

Usage:

// Beginning contributions (system instructions)
val systemPrompt = PromptContributor.fixed(
    "You are an expert programmer.",
    "system",
    PromptContributionLocation.BEGINNING
)

// End contributions (formatting instructions)
val formatPrompt = PromptContributor.fixed(
    "Respond in JSON format.",
    "format",
    PromptContributionLocation.END
)

PromptElement

Base interface for prompt-related elements.

interface PromptElement {
    val role: String?
    val promptContributionLocation: PromptContributionLocation
}

PromptContributorConsumer

Interface for objects that consume prompt contributors.

interface PromptContributorConsumer {
    val promptContributors: List<PromptContributor>
}

Usage:

class MyPromptBuilder : PromptContributorConsumer {
    override val promptContributors = listOf(
        CurrentDate(),
        PromptContributor.fixed(
            "Be helpful and concise.",
            "instruction",
            PromptContributionLocation.BEGINNING
        )
    )

    fun buildPrompt(userMessage: String): String {
        val beginningContribs = promptContributors
            .filter { it.promptContributionLocation == PromptContributionLocation.BEGINNING }
            .joinToString("\n") { it.contribution() }

        val endContribs = promptContributors
            .filter { it.promptContributionLocation == PromptContributionLocation.END }
            .joinToString("\n") { it.contribution() }

        return """
            $beginningContribs

            $userMessage

            $endContribs
        """.trimIndent()
    }
}

Built-in Contributors

CurrentDate

Contributes current date to prompts.

class CurrentDate(
    val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
) : PromptContributor {
    override val role: String = PromptContribution.CURRENT_DATE_ROLE
    override val promptContributionLocation: PromptContributionLocation =
        PromptContributionLocation.BEGINNING
}

Usage:

import java.time.format.DateTimeFormatter

// Default format
val currentDate = CurrentDate()
val contribution = currentDate.promptContribution()
println(contribution.content) // "Current date: 2026-02-06\n"

// Custom format
val customDate = CurrentDate(
    DateTimeFormatter.ofPattern("MMMM dd, yyyy")
)
val customContribution = customDate.promptContribution()
println(customContribution.content) // "Current date: February 06, 2026\n"

KnowledgeCutoffDate

Contributes knowledge cutoff date information.

class KnowledgeCutoffDate(
    val date: LocalDate,
    val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM")
) : PromptContributor {
    override val role: String = PromptContribution.KNOWLEDGE_CUTOFF_ROLE
    override val promptContributionLocation: PromptContributionLocation =
        PromptContributionLocation.BEGINNING
}

Usage:

import java.time.LocalDate
import java.time.format.DateTimeFormatter

// Default format
val cutoff = KnowledgeCutoffDate(
    date = LocalDate.of(2023, 4, 1)
)
val contribution = cutoff.promptContribution()
println(contribution.content) // "Knowledge cutoff: 2023-04\n"

// Custom format
val customCutoff = KnowledgeCutoffDate(
    date = LocalDate.of(2023, 4, 1),
    formatter = DateTimeFormatter.ofPattern("MMMM yyyy")
)

Custom Contributors

Create custom contributors by implementing the interface.

class TemperatureContributor(
    private val location: String
) : PromptContributor {
    override val role = "weather"
    override val promptContributionLocation = PromptContributionLocation.BEGINNING

    override fun contribution(): String {
        val temp = fetchCurrentTemperature(location)
        return "Current temperature in $location: ${temp}°C"
    }
}

val weatherContributor = TemperatureContributor("New York")

Prompt Assembly

Assemble prompts from contributors.

fun assemblePrompt(
    contributors: List<PromptContributor>,
    userMessage: String
): String {
    val beginning = contributors
        .filter { it.promptContributionLocation == PromptContributionLocation.BEGINNING }
        .map { it.promptContribution() }
        .sortedBy { it.role }
        .joinToString("\n\n") { it.content }

    val end = contributors
        .filter { it.promptContributionLocation == PromptContributionLocation.END }
        .map { it.promptContribution() }
        .sortedBy { it.role }
        .joinToString("\n\n") { it.content }

    return buildString {
        if (beginning.isNotEmpty()) {
            appendLine(beginning)
            appendLine()
        }
        appendLine(userMessage)
        if (end.isNotEmpty()) {
            appendLine()
            appendLine(end)
        }
    }.trim()
}

// Usage
val contributors = listOf(
    CurrentDate(),
    KnowledgeCutoffDate(LocalDate.of(2023, 4, 1)),
    PromptContributor.fixed(
        "Respond in a professional tone.",
        "tone",
        PromptContributionLocation.BEGINNING
    ),
    PromptContributor.fixed(
        "Format your response as JSON.",
        "format",
        PromptContributionLocation.END
    )
)

val prompt = assemblePrompt(contributors, "What is the weather today?")

Spring Integration

import org.springframework.stereotype.Component

@Component
class SystemPromptContributor : PromptContributor {
    override val role = "system"
    override val promptContributionLocation = PromptContributionLocation.BEGINNING

    override fun contribution(): String {
        return "You are a helpful AI assistant specialized in programming."
    }
}

@Service
class PromptService(
    private val contributors: List<PromptContributor>
) {
    fun buildPrompt(userInput: String): String {
        return assemblePrompt(contributors, userInput)
    }
}

Design Patterns

  • Strategy Pattern: Different contributors implement different contribution strategies
  • Template Method Pattern: PromptContributor defines the template, implementations provide content
  • Factory Pattern: Companion object factory methods create contributors
  • Decorator Pattern: Contributors can wrap and enhance base prompt content
tessl i tessl/maven-com-embabel-agent--embabel-agent-common@0.3.1

docs

index.md

quick-reference.md

README.md

tile.json