mirror of https://github.com/hykilpikonna/AquaDX
[+] Safety moderation
parent
5ba64483fb
commit
60661757c6
|
@ -0,0 +1,71 @@
|
|||
package icu.samnyan.aqua.net
|
||||
|
||||
import ext.HTTP
|
||||
import ext.async
|
||||
import ext.toJson
|
||||
import icu.samnyan.aqua.net.games.BaseEntity
|
||||
import io.ktor.client.call.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
import jakarta.persistence.Entity
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Service
|
||||
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "aqua-net.openai")
|
||||
class OpenAIConfig {
|
||||
var apiKey: String = ""
|
||||
}
|
||||
|
||||
@Entity
|
||||
class AquaNetSafety : BaseEntity() {
|
||||
var content: String = ""
|
||||
var safe: Boolean = false
|
||||
}
|
||||
|
||||
interface AquaNetSafetyRepo : JpaRepository<AquaNetSafety, Long> {
|
||||
fun findByContent(content: String): AquaNetSafety?
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class OpenAIResp<T>(
|
||||
val id: String,
|
||||
val model: String,
|
||||
val results: List<T>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class OpenAIMod(
|
||||
val flagged: Boolean,
|
||||
val categories: Map<String, Boolean>,
|
||||
val categoryScores: Map<String, Double>,
|
||||
)
|
||||
|
||||
@Service
|
||||
class AquaNetSafetyService(
|
||||
val safety: AquaNetSafetyRepo,
|
||||
val openAIConfig: OpenAIConfig
|
||||
) {
|
||||
suspend fun isSafe(content: String): Boolean {
|
||||
if (content.isBlank()) return true
|
||||
|
||||
async { safety.findByContent(content) }?.let { return it.safe }
|
||||
|
||||
// Query OpenAI
|
||||
HTTP.post("https://api.openai.com/v1/moderations") {
|
||||
header("Authorization", "Bearer ${openAIConfig.apiKey}")
|
||||
header("Content-Type", "application/json")
|
||||
setBody(mapOf("input" to content).toJson())
|
||||
}.let {
|
||||
if (!it.status.isSuccess()) return true
|
||||
val body = it.body<OpenAIResp<OpenAIMod>>()
|
||||
return AquaNetSafety().apply {
|
||||
this.content = content
|
||||
this.safe = !body.results.first().flagged
|
||||
}.also { safety.save(it) }.safe
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE aqua_net_safety
|
||||
(
|
||||
id BIGINT AUTO_INCREMENT NOT NULL,
|
||||
content VARCHAR(255) NOT NULL,
|
||||
safe BIT(1) NOT NULL,
|
||||
CONSTRAINT pk_aqua_net_safety PRIMARY KEY (id),
|
||||
CONSTRAINT uq_aqua_net_safety_content UNIQUE (content)
|
||||
);
|
Loading…
Reference in New Issue