openai_fork/
moderations.rs1use super::{openai_post, ApiResponseOrError};
4use derive_builder::Builder;
5use serde::{Deserialize, Serialize};
6
7#[derive(Deserialize, Clone, Debug)]
8pub struct Moderation {
9 pub id: String,
10 pub model: String,
11 pub results: Vec<ModerationResult>,
12}
13
14#[derive(Deserialize, Clone, Debug)]
15pub struct ModerationResult {
16 pub flagged: bool,
17 pub categories: Categories,
18 pub category_scores: CategoryScores,
19}
20
21#[derive(Deserialize, Clone, Copy, Debug)]
22pub struct Categories {
23 pub hate: bool,
24 #[serde(rename = "hate/threatening")]
25 pub hate_threatening: bool,
26 #[serde(rename = "self-harm")]
27 pub self_harm: bool,
28 pub sexual: bool,
29 #[serde(rename = "sexual/minors")]
30 pub sexual_minors: bool,
31 pub violence: bool,
32 #[serde(rename = "violence/graphic")]
33 pub violence_graphic: bool,
34}
35
36#[derive(Deserialize, Clone, Debug)]
37pub struct CategoryScores {
38 pub hate: f64,
39 #[serde(rename = "hate/threatening")]
40 pub hate_threatening: f64,
41 #[serde(rename = "self-harm")]
42 pub self_harm: f64,
43 pub sexual: f64,
44 #[serde(rename = "sexual/minors")]
45 pub sexual_minors: f64,
46 pub violence: f64,
47 #[serde(rename = "violence/graphic")]
48 pub violence_graphic: f64,
49}
50
51#[derive(Serialize, Builder, Debug, Clone)]
52#[builder(pattern = "owned")]
53#[builder(name = "ModerationBuilder")]
54#[builder(setter(strip_option, into))]
55pub struct ModerationRequest {
56 pub input: String,
58 #[serde(skip_serializing_if = "Option::is_none")]
61 #[builder(default)]
62 pub model: Option<String>,
63}
64
65impl Moderation {
66 async fn create(request: &ModerationRequest) -> ApiResponseOrError<Self> {
67 openai_post("moderations", request).await
68 }
69
70 pub fn builder(input: impl Into<String>) -> ModerationBuilder {
71 ModerationBuilder::create_empty().input(input)
72 }
73}
74
75impl ModerationBuilder {
76 pub async fn create(self) -> ApiResponseOrError<Moderation> {
77 Moderation::create(&self.build().unwrap()).await
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::set_key;
85 use dotenvy::dotenv;
86 use std::env;
87
88 #[tokio::test]
89 async fn moderations() {
90 dotenv().ok();
91 set_key(env::var("OPENAI_KEY").unwrap());
92
93 let moderation = Moderation::builder("I want to kill them.")
94 .model("text-moderation-latest")
95 .create()
96 .await
97 .unwrap();
98
99 assert_eq!(
100 moderation.results.first().unwrap().categories.violence,
101 true
102 );
103 assert_eq!(moderation.results.first().unwrap().flagged, true);
104 }
105}