Skip to content

提示 API

提示 API (Prompt API) 提供了一套全面的工具包,用於在生產環境應用程式中與大型語言模型 (LLMs) 互動。它提供:

  • 具有型別安全的 Kotlin DSL,用於建立結構化提示。
  • 多供應商支援,支援 OpenAI、Anthropic、Google 及其他 LLM 供應商。
  • 生產功能,例如重試邏輯、錯誤處理和逾時設定。
  • 多模態功能,用於處理文字、圖像、音訊和文件。

架構概覽

提示 API 由三個主要層組成:

  • LLM 用戶端:針對特定供應商 (OpenAI、Anthropic 等) 的低階介面。
  • 裝飾器:可選的包裝器,用於新增重試邏輯等功能。
  • 提示執行器:管理用戶端生命週期並簡化使用方式的高階抽象層。

建立提示

提示 API 使用 Kotlin DSL 建立提示。它支援以下類型的訊息:

  • system:設定 LLM 的上下文和指令。
  • user:代表使用者輸入。
  • assistant:代表 LLM 回應。

以下是一個簡單的提示範例:

kotlin
val prompt = prompt("prompt_name", LLMParams()) {
    // Add a system message to set the context
    system("You are a helpful assistant.")

    // Add a user message
    user("Tell me about Kotlin")

    // You can also add assistant messages for few-shot examples
    assistant("Kotlin is a modern programming language...")

    // Add another user message
    user("What are its key features?")
}

多模態輸入

除了在提示中提供文字訊息外,Koog 還允許您在 user 訊息中向 LLM 傳送圖像、音訊、視訊和檔案。 與標準的純文字提示一樣,您也可以使用提示建構的 DSL 結構將媒體新增至提示中。

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

    user {
        +"Describe these images"

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

文字提示內容

為了支援各種附件類型,並在提示中明確區分文字和檔案輸入,您將文字訊息放入使用者提示中專用的 content 參數中。 若要新增檔案輸入,請將其作為列表提供給 attachments 參數。

包含文字訊息和附件列表的使用者訊息的一般格式如下:

kotlin
user(
    content = "This is the user message",
    attachments = listOf(
        // Add attachments
    )
)

檔案附件

若要包含附件,請在 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 檔案。

上述每個類別都接受以下參數:

名稱資料類型必填說明
contentAttachmentContent提供的檔案內容來源。有關更多資訊,請參閱 AttachmentContent
formatString提供的檔案格式。例如,png
mimeTypeString僅限 Attachment.File提供的檔案 MIME 類型。例如,image/png
fileNameString提供的檔案名稱,包括副檔名。例如,screenshot.png

有關更多詳細資訊,請參閱 API 參考

AttachmentContent

AttachmentContent 定義了作為 LLM 輸入提供的內容的類型和來源。支援以下類別:

  • AttachmentContent.URL(val url: String)

    從指定的 URL 提供檔案內容。接受以下參數:

    名稱資料類型必填說明
    urlString提供的內容 URL。

    另請參閱 API 參考

  • AttachmentContent.Binary.Bytes(val data: ByteArray)

    以位元組陣列形式提供檔案內容。接受以下參數:

    名稱資料類型必填說明
    dataByteArray以位元組陣列形式提供的檔案內容。

    另請參閱 API 參考

  • AttachmentContent.Binary.Base64(val base64: String)

    提供編碼為 Base64 字串的檔案內容。接受以下參數:

    名稱資料類型必填說明
    base64String包含檔案資料的 Base64 字串。

    另請參閱 API 參考

  • AttachmentContent.PlainText(val text: String)

TIP

僅適用於附件類型為 Attachment.File

從純文字檔案(例如 text/plain MIME 類型)提供內容。接受以下參數:

名稱資料類型必填說明
textString檔案內容。

另請參閱 API 參考

混合附件內容

除了在單獨的提示或訊息中提供不同類型的附件外,您還可以在單一 user 訊息中提供多種和混合類型的附件,如下所示:

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

    user {
        +"Compare the image with the document content."

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

在 LLM 用戶端和提示執行器之間做選擇

使用提示 API 時,您可以透過 LLM 用戶端或提示執行器來執行提示。 若要在用戶端和執行器之間做選擇,請考慮以下因素:

  • 如果您使用單一 LLM 供應商且不需要進階生命週期管理,請直接使用 LLM 用戶端。若要了解更多資訊,請參閱 使用 LLM 用戶端執行提示
  • 如果您需要更進階的抽象層來管理 LLM 及其生命週期,或者您希望透過跨多個供應商的一致 API 執行提示並在它們之間動態切換,請使用提示執行器。 若要了解更多資訊,請參閱 使用提示執行器執行提示

!!!note LLM 用戶端和提示執行器都允許您串流回應、產生多個選擇並執行內容審核。 有關更多資訊,請參閱特定用戶端或執行器的 API 參考

使用 LLM 用戶端執行提示

如果您使用單一 LLM 供應商且不需要進階生命週期管理,則可以使用 LLM 用戶端來執行提示。 Koog 提供以下 LLM 用戶端:

若要使用 LLM 用戶端執行提示,請執行以下操作:

  1. 建立 LLM 用戶端,用於處理應用程式與 LLM 供應商之間的連線。例如:
kotlin
// Create an OpenAI client
val client = OpenAILLMClient(apiKey)
  1. 呼叫 execute 方法,並以提示和 LLM 作為引數。
kotlin
// Execute the prompt
val response = client.execute(
    prompt = prompt,
    model = OpenAIModels.Chat.GPT4o  // You can choose different models
)

以下是一個使用 OpenAI 用戶端執行提示的範例:

kotlin

fun main() {
    runBlocking {
        // Set up the OpenAI client with your API key
        val token = System.getenv("OPENAI_API_KEY")
        val client = OpenAILLMClient(token)

        // Create a prompt
        val prompt = prompt("prompt_name", LLMParams()) {
            // Add a system message to set the context
            system("You are a helpful assistant.")

            // Add a user message
            user("Tell me about Kotlin")

            // You can also add assistant messages for few-shot examples
            assistant("Kotlin is a modern programming language...")

            // Add another user message
            user("What are its key features?")
        }

        // Execute the prompt and get the response
        val response = client.execute(prompt = prompt, model = OpenAIModels.Chat.GPT4o)
        println(response)
    }
}

!!!note LLM 用戶端允許您串流回應、產生多個選擇並執行內容審核。 有關更多資訊,請參閱特定用戶端的 API 參考。 若要深入了解內容審核,請參閱 內容審核

使用提示執行器執行提示

雖然 LLM 用戶端提供對供應商的直接存取,但提示執行器提供更高層次的抽象,可簡化常見的使用案例並處理用戶端生命週期管理。 當您希望達成以下目標時,它們是理想的選擇:

  • 快速建立原型,而無需管理用戶端配置。
  • 透過統一介面與多個供應商協同運作。
  • 在大型應用程式中簡化依賴注入。
  • 抽象化供應商特定細節。

執行器類型

Koog 提供兩種主要的提示執行器:

名稱
說明
SingleLLMPromptExecutor包裝單一供應商的單一 LLM 用戶端。如果您的代理程式僅需要在單一 LLM 供應商內的不同模型之間切換,請使用此執行器。
MultiLLMPromptExecutor透過供應商路由到多個 LLM 用戶端,並為每個供應商提供可選的備用方案,以在請求的供應商不可用時使用。如果您的代理程式需要在不同供應商的模型之間切換,請使用此執行器。

這些是 PromtExecutor 介面的實作,用於使用 LLM 執行提示。

建立單一供應商執行器

若要為特定的 LLM 供應商建立提示執行器,請執行以下操作:

  1. 設定特定供應商的 LLM 用戶端,並提供對應的 API 金鑰:
kotlin
val openAIClient = OpenAILLMClient(System.getenv("OPENAI_API_KEY"))
  1. 使用 SingleLLMPromptExecutor 建立提示執行器:
kotlin
val promptExecutor = SingleLLMPromptExecutor(openAIClient)

建立多供應商執行器

若要建立可與多個 LLM 供應商協同運作的提示執行器,請執行以下操作:

  1. 設定所需 LLM 供應商的用戶端,並提供對應的 API 金鑰:
kotlin
val openAIClient = OpenAILLMClient(System.getenv("OPENAI_KEY"))
val ollamaClient = OllamaClient()
  1. 將已設定的用戶端傳遞給 MultiLLMPromptExecutor 類別建構函式,以建立一個具有多個 LLM 供應商的提示執行器:
kotlin
val multiExecutor = MultiLLMPromptExecutor(
    LLMProvider.OpenAI to openAIClient,
    LLMProvider.Ollama to ollamaClient
)

預定義提示執行器

為了更快速地設定,Koog 為常見供應商提供了以下即用型執行器實作:

  • 單一供應商執行器,返回設定有特定 LLM 用戶端的 SingleLLMPromptExecutor

    • simpleOpenAIExecutor 用於使用 OpenAI 模型執行提示。
    • simpleAzureOpenAIExecutor 用於使用 Azure OpenAI Service 執行提示。
    • simpleAnthropicExecutor 用於使用 Anthropic 模型執行提示。
    • simpleGoogleAIExecutor 用於使用 Google 模型執行提示。
    • simpleOpenRouterExecutor 用於使用 OpenRouter 執行提示。
    • simpleOllamaExecutor 用於使用 Ollama 執行提示。
  • 多供應商執行器:

    • DefaultMultiLLMPromptExecutorMultiLLMPromptExecutor 的實作,支援 OpenAI、Anthropic 和 Google 供應商。

以下是一個建立預定義單一和多供應商執行器的範例:

kotlin
// Create an OpenAI executor
val promptExecutor = simpleOpenAIExecutor("OPENAI_KEY")

// Create a DefaultMultiLLMPromptExecutor with OpenAI, Anthropic, and Google LLM clients
val openAIClient = OpenAILLMClient("OPENAI_KEY")
val anthropicClient = AnthropicLLMClient("ANTHROPIC_KEY")
val googleClient = GoogleLLMClient("GOOGLE_KEY")
val multiExecutor = DefaultMultiLLMPromptExecutor(openAIClient, anthropicClient, googleClient)

執行提示

提示執行器提供了使用各種功能執行提示的方法,例如串流、多重選擇產生和內容審核。

以下是一個如何使用 execute 方法執行帶有特定 LLM 的提示的範例:

kotlin
// Execute a prompt
val response = promptExecutor.execute(
    prompt = prompt,
    model = OpenAIModels.Chat.GPT4o
)

這將使用 GPT4o 模型執行提示並返回回應。

!!!note 提示執行器允許您串流回應、產生多個選擇並執行內容審核。 有關更多資訊,請參閱特定執行器的 API 參考。 若要深入了解內容審核,請參閱 內容審核

快取提示執行器

對於重複的請求,您可以快取 LLM 回應以最佳化效能並降低成本。 Koog 提供了 CachedPromptExecutor,它是 PromptExecutor 的一個包裝器,可新增快取功能。 它允許您儲存先前執行提示的回應,並在再次執行相同提示時擷取它們。

若要建立快取提示執行器,請執行以下操作:

  1. 建立您要快取回應的提示執行器:
kotlin
val client = OpenAILLMClient(System.getenv("OPENAI_API_KEY"))
val promptExecutor = SingleLLMPromptExecutor(client)
  1. 使用所需的快取建立 CachedPromptExecutor 實例,並提供建立的提示執行器:
kotlin
val cachedExecutor = CachedPromptExecutor(
    cache = FilePromptCache(Path("/cache_directory")),
    nested = promptExecutor
)
  1. 使用所需的提示和模型執行快取提示執行器:
kotlin
val response = cachedExecutor.execute(prompt, OpenAIModels.Chat.GPT4o)

現在,您可以多次使用相同的模型執行相同的提示,回應將從快取中擷取。

!!!note * 如果您使用快取提示執行器呼叫 executeStreaming(),它會以單一區塊產生回應。 * 如果您使用快取提示執行器呼叫 moderate(),它會將請求轉發給巢狀提示執行器,並且不使用快取。 * 不支援快取多重選擇回應。

重試功能

在使用 LLM 供應商時,您可能會遇到暫時性錯誤,例如速率限制或暫時性服務不可用。RetryingLLMClient 裝飾器會為任何 LLM 用戶端新增自動重試邏輯。

基本用法

將任何現有的用戶端包裝上重試功能:

kotlin
// Wrap any client with retry capability
val client = OpenAILLMClient(apiKey)
val resilientClient = RetryingLLMClient(client)

// Now all operations will automatically retry on transient errors
val response = resilientClient.execute(prompt, OpenAIModels.Chat.GPT4o)

配置重試行為

Koog 提供多種預設重試配置:

配置最大嘗試次數初始延遲最大延遲使用案例
DISABLED1 (不重試)--開發與測試
CONSERVATIVE32s30s正常生產用途
AGGRESSIVE5500ms20s關鍵操作
PRODUCTION31s20s推薦預設值

您可以直接使用它們,或建立自訂配置:

kotlin
// Use the predefined configuration
val conservativeClient = RetryingLLMClient(
    delegate = client,
    config = RetryConfig.CONSERVATIVE
)

// Or create a custom configuration
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:閘道逾時
    • 529:Anthropic 超載
  • 錯誤關鍵字

    • rate limit (速率限制)
    • too many requests (請求過多)
    • request timeout (請求逾時)
    • connection timeout (連線逾時)
    • read timeout (讀取逾時)
    • write timeout (寫入逾時)
    • connection reset by peer (對等連線重設)
    • connection refused (連線遭拒)
    • temporarily unavailable (暫時不可用)
    • service unavailable (服務不可用)

您可以針對您的特定需求定義自訂模式:

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
        }
    )
)

搭配提示執行器使用重試

使用提示執行器時,請在建立執行器之前,使用重試機制包裝底層 LLM 用戶端:

kotlin
// 帶有重試功能的單一供應商執行器
val resilientClient = RetryingLLMClient(
    OpenAILLMClient(System.getenv("OPENAI_KEY")),
    RetryConfig.PRODUCTION
)
val executor = SingleLLMPromptExecutor(resilientClient)

// 帶有靈活用戶端配置的多供應商執行器
val multiExecutor = MultiLLMPromptExecutor(
    LLMProvider.OpenAI to RetryingLLMClient(
        OpenAILLMClient(System.getenv("OPENAI_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)

!!!note 串流重試僅適用於在收到第一個 Token 之前的連線失敗。一旦串流開始,錯誤將直接傳遞,以保留內容完整性。

逾時設定

所有 LLM 用戶端都支援逾時設定,以防止掛起請求:

kotlin
val client = OpenAILLMClient(
    apiKey = apiKey,
    settings = OpenAIClientSettings(
        timeoutConfig = ConnectionTimeoutConfig(
            connectTimeoutMillis = 5000,    // 5 秒以建立連線
            requestTimeoutMillis = 60000    // 60 秒以完成整個請求
        )
    )
)

錯誤處理

在生產環境中處理 LLM 時,您需要實作錯誤處理策略:

  • 使用 try-catch 區塊來處理意外錯誤。
  • 記錄帶有上下文的錯誤,用於偵錯。
  • 實作備用策略,用於關鍵操作。
  • 監控重試模式,以識別重複或系統性問題。

以下是一個全面的錯誤處理範例:

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()
        }
    }
}