2525import  org .springframework .ai .model .ApiKey ;
2626import  org .springframework .ai .model .NoopApiKey ;
2727import  org .springframework .ai .model .SimpleApiKey ;
28+ import  org .springframework .ai .moderation .Categories ;
29+ import  org .springframework .ai .moderation .CategoryScores ;
2830import  org .springframework .ai .openai .api .common .OpenAiApiConstants ;
2931import  org .springframework .ai .retry .RetryUtils ;
3032import  org .springframework .http .HttpHeaders ;
4244 * @author Ahmed Yousri 
4345 * @author Ilayaperumal Gopinathan 
4446 * @author Filip Hrisafov 
47+  * @author lambochen 
4548 * @see <a href= 
4649 * "https://platform.openai.com/docs/api-reference/moderations">https://platform.openai.com/docs/api-reference/moderations</a> 
4750 */ 
@@ -55,6 +58,8 @@ public class OpenAiModerationApi {
5558
5659	private  final  ObjectMapper  objectMapper ;
5760
61+ 	private  final  String  moderationPath ;
62+ 
5863	/** 
5964	 * Create a new OpenAI Moderation API with the provided base URL. 
6065	 * @param baseUrl the base URL for the OpenAI API. 
@@ -63,31 +68,47 @@ public class OpenAiModerationApi {
6368	 */ 
6469	public  OpenAiModerationApi (String  baseUrl , ApiKey  apiKey , MultiValueMap <String , String > headers ,
6570			RestClient .Builder  restClientBuilder , ResponseErrorHandler  responseErrorHandler ) {
71+ 		this (baseUrl , OpenAiApiConstants .DEFAULT_MODERATION_PATH , apiKey , headers , restClientBuilder ,
72+ 				responseErrorHandler );
73+ 	}
6674
75+ 	/** 
76+ 	 * Create a new OpenAI Moderation API with the provided base URL. 
77+ 	 * @param baseUrl the base URL for the OpenAI API. 
78+ 	 * @param apiKey OpenAI apiKey. 
79+ 	 * @param restClientBuilder the rest client builder to use. 
80+ 	 * @param moderationPath the moderation path to use. 
81+ 	 */ 
82+ 	public  OpenAiModerationApi (String  baseUrl , String  moderationPath , ApiKey  apiKey ,
83+ 			MultiValueMap <String , String > headers , RestClient .Builder  restClientBuilder ,
84+ 			ResponseErrorHandler  responseErrorHandler ) {
85+ 		Assert .hasText (moderationPath , "moderationPath cannot be null or empty" );
86+ 
87+ 		this .moderationPath  = moderationPath ;
6788		this .objectMapper  = new  ObjectMapper ().configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false );
6889
6990		// @formatter:off 
7091		this .restClient  = restClientBuilder .clone ()
71- 			.baseUrl (baseUrl )
72- 			.defaultHeaders (h  -> {
73- 				h .setContentType (MediaType .APPLICATION_JSON );
74- 				h .addAll (headers );
75- 			})
76- 			.defaultStatusHandler (responseErrorHandler )
77- 			.defaultRequest (requestHeadersSpec  -> {
78- 				if  (!(apiKey  instanceof  NoopApiKey )) {
79- 					requestHeadersSpec .header (HttpHeaders .AUTHORIZATION , "Bearer "  + apiKey .getValue ());
80- 				}
81- 			})
82- 			.build (); // @formatter:on 
92+ 				 .baseUrl (baseUrl )
93+ 				 .defaultHeaders (h  -> {
94+ 					 h .setContentType (MediaType .APPLICATION_JSON );
95+ 					 h .addAll (headers );
96+ 				 })
97+ 				 .defaultStatusHandler (responseErrorHandler )
98+ 				 .defaultRequest (requestHeadersSpec  -> {
99+ 					 if  (!(apiKey  instanceof  NoopApiKey )) {
100+ 						 requestHeadersSpec .header (HttpHeaders .AUTHORIZATION , "Bearer "  + apiKey .getValue ());
101+ 					 }
102+ 				 })
103+ 				 .build (); // @formatter:on 
83104	}
84105
85106	public  ResponseEntity <OpenAiModerationResponse > createModeration (OpenAiModerationRequest  openAiModerationRequest ) {
86107		Assert .notNull (openAiModerationRequest , "Moderation request cannot be null." );
87108		Assert .hasLength (openAiModerationRequest .prompt (), "Prompt cannot be empty." );
88109
89110		return  this .restClient .post ()
90- 			.uri ("v1/moderations" )
111+ 			.uri (this . moderationPath )
91112			.body (openAiModerationRequest )
92113			.retrieve ()
93114			.toEntity (OpenAiModerationResponse .class );
@@ -176,6 +197,8 @@ public static class Builder {
176197
177198		private  String  baseUrl  = OpenAiApiConstants .DEFAULT_BASE_URL ;
178199
200+ 		private  String  moderationPath  = OpenAiApiConstants .DEFAULT_MODERATION_PATH ;
201+ 
179202		private  ApiKey  apiKey ;
180203
181204		private  MultiValueMap <String , String > headers  = new  LinkedMultiValueMap <>();
@@ -190,6 +213,12 @@ public Builder baseUrl(String baseUrl) {
190213			return  this ;
191214		}
192215
216+ 		public  Builder  moderationPath (String  moderationPath ) {
217+ 			Assert .hasText (moderationPath , "moderationPath cannot be null or empty" );
218+ 			this .moderationPath  = moderationPath ;
219+ 			return  this ;
220+ 		}
221+ 
193222		public  Builder  apiKey (ApiKey  apiKey ) {
194223			Assert .notNull (apiKey , "apiKey cannot be null" );
195224			this .apiKey  = apiKey ;
@@ -222,8 +251,8 @@ public Builder responseErrorHandler(ResponseErrorHandler responseErrorHandler) {
222251
223252		public  OpenAiModerationApi  build () {
224253			Assert .notNull (this .apiKey , "apiKey must be set" );
225- 			return  new  OpenAiModerationApi (this .baseUrl , this .apiKey , this .headers , this .restClientBuilder ,
226- 					this .responseErrorHandler );
254+ 			return  new  OpenAiModerationApi (this .baseUrl , this .moderationPath , this .apiKey , this .headers ,
255+ 					this .restClientBuilder ,  this . responseErrorHandler );
227256		}
228257
229258	}
0 commit comments