public override suspend fun moderate()

in prompt/prompt-executor/prompt-executor-clients/prompt-executor-openai-client/src/commonMain/kotlin/ai/koog/prompt/executor/clients/openai/OpenAILLMClient.kt [445:516]


    public override suspend fun moderate(prompt: Prompt, model: LLModel): ModerationResult {
        logger.debug { "Moderating text and image content with model: $model" }

        model.requireCapability(LLMCapability.Moderation)

        require(prompt.messages.isNotEmpty()) { "Can't moderate an empty prompt" }

        val input = prompt.messages
            .map { message ->
                require(message.parts.all { it is ContentPart.Text || it is ContentPart.Image }) {
                    "Only image attachments are supported for moderation"
                }

                message.toMessageContent(model)
            }
            .let { contents ->
                /*
                 If all messages contain only text, merge it all in a single text input,
                 to support OpenAI-compatible providers that do not support attachments.

                 Otherwise create a single content instance with all the parts
                 */
                if (contents.all { it is OpenAIContent.Text }) {
                    val text = contents.joinToString(separator = "\n\n") { (it as OpenAIContent.Text).value }

                    OpenAIContent.Text(text)
                } else {
                    val parts = contents.flatMap { content ->
                        when (content) {
                            is OpenAIContent.Parts -> content.value
                            is OpenAIContent.Text -> listOf(OpenAIContentPart.Text(content.value))
                        }
                    }

                    OpenAIContent.Parts(parts)
                }
            }

        val request = OpenAIModerationRequest(
            input = input,
            model = model.id
        )

        val openAIResponse = withContext(Dispatchers.SuitableForIO) {
            try {
                httpClient.post(
                    path = settings.moderationsPath,
                    request = request,
                    requestBodyType = OpenAIModerationRequest::class,
                    responseType = OpenAIModerationResponse::class
                )
            } catch (e: CancellationException) {
                throw e
            } catch (e: Exception) {
                throw LLMClientException(
                    clientName = clientName,
                    message = e.message,
                    cause = e
                )
            }
        }

        if (openAIResponse.results.isEmpty()) {
            val exception = LLMClientException(clientName, "Empty results in OpenAI moderation response")
            logger.error(exception) { exception.message }
            throw exception
        }
        val result = openAIResponse.results.first()

        // Convert OpenAI categories to a map
        return convertModerationResult(result)
    }