Skip to content

提示词 API

Prompt API 提供了一个全面的工具包,用于在生产应用程序中与大语言模型 (LLM) 进行交互。它提供:

  • 结合类型安全的 Kotlin DSL 用于创建结构化提示词
  • 对 OpenAI、Anthropic、Google 及其他 LLM 提供方提供多提供方支持
  • 生产特性,例如重试逻辑、错误处理和超时配置
  • 用于处理文本、图像、音频和文档的多模态能力

架构概览

Prompt API 由三个主要层组成:

  1. LLM 客户端 - 连接特定提供方(OpenAI、Anthropic 等)的底层接口
  2. 装饰器 - 可选的包装器,用于添加重试逻辑等功能
  3. 提示词执行器 - 管理客户端生命周期并简化使用的高级抽象

创建提示词

Prompt API 使用 Kotlin DSL 创建提示词。它支持以下消息类型:

  • system: 设置 LLM 的上下文和指令。
  • user: 表示用户输入。
  • assistant: 表示 LLM 响应。

这是一个简单提示词的示例:

kotlin
val prompt = prompt("prompt_name", LLMParams()) {
    // 添加 system 消息以设置上下文
    system("You are a helpful assistant.")

    // 添加 user 消息
    user("Tell me about Kotlin")

    // 你还可以添加 assistant 消息用于少样本示例
    assistant("Kotlin is a modern programming language...")

    // 再添加一条 user 消息
    user("What are its key features?")
}

执行提示词

要使用特定的 LLM 执行提示词,你需要完成以下步骤:

  1. 创建相应的 LLM 客户端,用于处理你的应用程序与 LLM 提供方之间的连接。例如:
kotlin
// 创建一个 OpenAI 客户端
val client = OpenAILLMClient(apiKey)
  1. 调用 execute 方法,将提示词和 LLM 作为实参。
kotlin
// 执行提示词
val response = client.execute(
    prompt = prompt,
    model = OpenAIModels.Chat.GPT4o  // 你可以选择不同的模型
)

以下 LLM 客户端可用:

这是一个使用 Prompt API 的简单示例:

kotlin

fun main() {
    runBlocking {
        // 使用你的 API 密钥设置 OpenAI 客户端
        val token = System.getenv("OPENAI_API_KEY")
        val client = OpenAILLMClient(token)

        // 创建提示词
        val prompt = prompt("prompt_name", LLMParams()) {
            // 添加 system 消息以设置上下文
            system("You are a helpful assistant.")

            // 添加 user 消息
            user("Tell me about Kotlin")

            // 你还可以添加 assistant 消息用于少样本示例
            assistant("Kotlin is a modern programming language...")

            // 再添加一条 user 消息
            user("What are its key features?")
        }

        // 执行提示词并获取响应
        val response = client.execute(prompt = prompt, model = OpenAIModels.Chat.GPT4o)
        println(response)
    }
}

重试功能

与 LLM 提供方协同工作时,你可能会遇到瞬时错误,例如速率限制或临时服务不可用。RetryingLLMClient 装饰器为任何 LLM 客户端添加了自动重试逻辑。

基本用法

将任何现有客户端包装为具有重试能力:

kotlin
// 将任何客户端包装为具有重试能力
val client = OpenAILLMClient(apiKey)
val resilientClient = RetryingLLMClient(client)

// 现在,所有操作都将在瞬时错误时自动重试
val response = resilientClient.execute(prompt, OpenAIModels.Chat.GPT4o)

配置重试行为

Koog 提供了几种预定义的重试配置:

配置最大尝试次数初始延迟最大延迟用例
DISABLED1(无重试)--开发/测试
CONSERVATIVE32秒30秒正常生产使用
AGGRESSIVE5500毫秒20秒关键操作
PRODUCTION31秒20秒推荐默认值

直接使用它们或创建自定义配置:

kotlin
// 使用预定义配置
val conservativeClient = RetryingLLMClient(
    delegate = client,
    config = RetryConfig.CONSERVATIVE
)

// 或者创建自定义配置
val customClient = RetryingLLMClient(
    delegate = client,
    config = RetryConfig(
        maxAttempts = 5,
        initialDelay = 1.seconds,
        maxDelay = 30.seconds,
        backoffMultiplier = 2.0,
        jitterFactor = 0.2
    )
)

可重试错误模式

默认情况下,重试机制会识别常见的瞬时错误:

  • HTTP 状态码:429(速率限制)、500、502、503、504
  • 错误关键词:"rate limit"(速率限制)、"timeout"(超时)、"connection reset"(连接重置)、"overloaded"(过载)

你可以根据特定需求定义自定义模式:

kotlin
val config = RetryConfig(
    retryablePatterns = listOf(
        RetryablePattern.Status(429),           // 特定状态码
        RetryablePattern.Keyword("quota"),      // 错误消息中的关键词
        RetryablePattern.Regex(Regex("ERR_\\d+")), // 自定义正则表达式模式
        RetryablePattern.Custom { error ->      // 自定义逻辑
            error.contains("temporary") && error.length > 20
        }
    )
)

提示词执行器重试

使用提示词执行器时,在创建执行器之前包装底层客户端:

kotlin
// 具有重试功能的单提供方执行器
val resilientClient = RetryingLLMClient(
    OpenAILLMClient(System.getenv("OPENAI_API_KEY")),
    RetryConfig.PRODUCTION
)
val executor = SingleLLMPromptExecutor(resilientClient)

// 具有灵活客户端配置的多提供方执行器
val multiExecutor = MultiLLMPromptExecutor(
    LLMProvider.OpenAI to RetryingLLMClient(
        OpenAILLMClient(System.getenv("OPENAI_API_KEY")),
        RetryConfig.CONSERVATIVE
    ),
    LLMProvider.Anthropic to RetryingLLMClient(
        AnthropicLLMClient(System.getenv("ANTHROPIC_API_KEY")),
        RetryConfig.AGGRESSIVE  
    ),
    // Bedrock 客户端已内置 AWS SDK 重试功能
    LLMProvider.Bedrock to BedrockLLMClient(
        awsAccessKeyId = System.getenv("AWS_ACCESS_KEY_ID"),
        awsSecretAccessKey = System.getenv("AWS_SECRET_ACCESS_KEY"),
        awsSessionToken = System.getenv("AWS_SESSION_TOKEN"),
    ))

流式传输重试

流式传输操作可以选择性地重试(默认禁用):

kotlin
val config = RetryConfig(
    maxAttempts = 3
)

val client = RetryingLLMClient(baseClient, config)
val stream = client.executeStreaming(prompt, OpenAIModels.Chat.GPT4o)

注意:流式传输重试仅适用于在收到第一个 token 之前的连接失败。一旦流式传输开始,错误将直接传递以保留内容完整性。

超时配置

所有 LLM 客户端都支持超时配置,以防止请求挂起:

kotlin
val client = OpenAILLMClient(
    apiKey = apiKey,
    settings = OpenAIClientSettings(
        timeoutConfig = ConnectionTimeoutConfig(
            connectTimeoutMillis = 5000,    // 建立连接的 5 秒
            requestTimeoutMillis = 60000    // 整个请求的 60 秒
        )
    )
)

错误处理最佳实践

在生产环境中与 LLM 协同工作时:

  1. 始终将操作包装在 try-catch 块中以处理意外错误
  2. 记录带上下文的错误以便调试
  3. 为关键操作实施回退策略
  4. 监控重试模式以识别系统性问题

全面错误处理的示例:

kotlin
try {
    val response = resilientClient.execute(prompt, model)
    processResponse(response)
} catch (e: Exception) {
    logger.error("LLM operation failed", e)
    
    when {
        e.message?.contains("rate limit") == true -> {
            // 特别处理速率限制
            scheduleRetryLater()
        }
        e.message?.contains("invalid api key") == true -> {
            // 处理认证错误
            notifyAdministrator()
        }
        else -> {
            // 回退到备用解决方案
            useDefaultResponse()
        }
    }
}

多模态输入

除了在提示词中提供文本消息外,Koog 还允许你将图像、音频、视频和文件与 user 消息一同发送给 LLM。与标准的纯文本提示词一样,你也可以使用 DSL 结构来构建提示词并向其添加媒体。

kotlin
val prompt = prompt("multimodal_input") {
    system("You are a helpful assistant.")

    user {
        +"描述这些图像"

        attachments {
            image("https://example.com/test.png")
            image(Path("/User/koog/image.png"))
        }
    }
}

文本提示词内容

为了支持各种附件类型并在提示词中区分文本输入和文件输入,你可以将文本消息放在 user 提示词中一个专用的 content 形参中。要添加文件输入,请将它们作为列表提供给 attachments 形参。

包含文本消息和附件列表的 user 消息的通用格式如下:

kotlin
user(
    content = "This is the user message",
    attachments = listOf(
        // 添加附件
    )
)

文件附件

要包含附件,请将文件提供给 attachments 形参,格式如下:

kotlin
user(
    content = "Describe this image",
    attachments = listOf(
        Attachment.Image(
            content = AttachmentContent.URL("https://example.com/capture.png"),
            format = "png",
            mimeType = "image/png",
            fileName = "capture.png"
        )
    )
)

attachments 形参接受一个文件输入列表,其中每个项都是以下某个类的实例:

  • Attachment.Image: 图像附件,例如 jpgpng 文件。
  • Attachment.Audio: 音频附件,例如 mp3wav 文件。
  • Attachment.Video: 视频附件,例如 mpgavi 文件。
  • Attachment.File: 文件附件,例如 pdftxt 文件。

上述每个类都接受以下形参:

名称数据类型必需描述
contentAttachmentContentYes所提供文件内容的源。有关更多信息,请参见 AttachmentContent
formatStringYes所提供文件的格式。例如,png
mimeTypeStringOnly for Attachment.File所提供文件的 MIME 类型。例如,image/png
fileNameStringNo所提供文件的名称,包括扩展名。例如,screenshot.png

AttachmentContent

AttachmentContent 定义了作为 LLM 输入提供的内容的类型和源。支持以下类:

AttachmentContent.URL(val url: String)

从指定的 URL 提供文件内容。接受以下形参:

名称数据类型必需描述
urlStringYes所提供内容的 URL。

AttachmentContent.Binary.Bytes(val data: ByteArray)

将文件内容作为字节数组提供。接受以下形参:

名称数据类型必需描述
dataByteArrayYes作为字节数组提供的文件内容。

AttachmentContent.Binary.Base64(val base64: String)

将文件内容编码为 Base64 字符串提供。接受以下形参:

名称数据类型必需描述
base64StringYes包含文件数据的 Base64 字符串。

AttachmentContent.PlainText(val text: String)

仅当附件类型为 Attachment.File 时适用。提供纯文本文件(例如 text/plain MIME 类型)的内容。接受以下形参:

名称数据类型必需描述
textStringYes文件的内容。

混合附件内容

除了在单独的提示词或消息中提供不同类型的附件外,你还可以在单个 user 消息中提供多种混合类型的附件,如下所示:

kotlin
val prompt = prompt("mixed_content") {
    system("You are a helpful assistant.")

    user {
        +"比较图像与文档内容。"

        attachments {
            image(Path("/User/koog/page.png"))
            binaryFile(Path("/User/koog/page.pdf"), "application/pdf")
        }
    }
}

提示词执行器

尽管 LLM 客户端提供了对提供方的直接访问,但 提示词执行器 提供了一种更高级的抽象,可以简化常见用例并处理客户端生命周期管理。它们在以下场景中非常适用:

  • 无需管理客户端配置即可快速原型化
  • 通过统一接口与多个提供方协同工作
  • 在大型应用程序中简化依赖注入
  • 抽象化提供方特有的细节

执行器类型

Koog 框架提供了几种提示词执行器:

  • 单提供方执行器

    • simpleOpenAIExecutor: 用于执行带有 OpenAI 模型的提示词。
    • simpleAnthropicExecutor: 用于执行带有 Anthropic 模型的提示词。
    • simpleGoogleExecutor: 用于执行带有 Google 模型的提示词。
    • simpleOpenRouterExecutor: 用于执行带有 OpenRouter 的提示词。
    • simpleOllamaExecutor: 用于执行带有 Ollama 的提示词。
  • 多提供方执行器

    • DefaultMultiLLMPromptExecutor: 用于与多个 LLM 提供方协同工作

创建单提供方执行器

要为特定的 LLM 提供方创建提示词执行器,请使用相应函数。例如,要创建 OpenAI 提示词执行器,你需要调用 simpleOpenAIExecutor 函数并提供与 OpenAI 服务进行认证所需的 API 密钥:

  1. 创建提示词执行器:
kotlin
// 创建一个 OpenAI 执行器
val promptExecutor = simpleOpenAIExecutor(apiToken)
  1. 使用特定的 LLM 执行提示词:
kotlin
// 执行提示词
val response = promptExecutor.execute(
    prompt = prompt,
    model = OpenAIModels.Chat.GPT4o
).single()

创建多提供方执行器

要创建与多个 LLM 提供方协同工作的提示词执行器,请完成以下步骤:

  1. 为所需的 LLM 提供方配置客户端,并提供相应的 API 密钥。例如:
kotlin
val openAIClient = OpenAILLMClient(System.getenv("OPENAI_KEY"))
val anthropicClient = AnthropicLLMClient(System.getenv("ANTHROPIC_KEY"))
val googleClient = GoogleLLMClient(System.getenv("GOOGLE_KEY"))
  1. 将配置好的客户端传递给 DefaultMultiLLMPromptExecutor 类构造函数,以创建具有多个 LLM 提供方的提示词执行器:
kotlin
val multiExecutor = DefaultMultiLLMPromptExecutor(openAIClient, anthropicClient, googleClient)
  1. 使用特定的 LLM 执行提示词:
kotlin
val response = multiExecutor.execute(
    prompt = prompt,
    model = OpenAIModels.Chat.GPT4o
).single()