Add moderation support (#24)

Adding support for the new Moderations api https://beta.openai.com/docs/guides/moderation

Fixes https://github.com/TheoKanning/openai-java/issues/20
This commit is contained in:
Theo Kanning 2022-08-19 10:32:33 -05:00 committed by GitHub
parent 77219d497b
commit d1f274800a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 195 additions and 7 deletions

View File

@ -12,12 +12,13 @@ as well as an example project using the client.
- [Engines](https://beta.openai.com/docs/api-reference/engines)
- [Completions](https://beta.openai.com/docs/api-reference/completions)
- [Edits](https://beta.openai.com/docs/api-reference/edits)
- [Embeddings](https://beta.openai.com/docs/api-reference/embeddings)
- [Searches](https://beta.openai.com/docs/api-reference/searches)
- [Classifications](https://beta.openai.com/docs/api-reference/classifications)
- [Answers](https://beta.openai.com/docs/api-reference/answers)
- [Files](https://beta.openai.com/docs/api-reference/files)
- [Fine-tunes](https://beta.openai.com/docs/api-reference/fine-tunes)
- [Embeddings](https://beta.openai.com/docs/api-reference/embeddings)
- [Moderations](https://beta.openai.com/docs/api-reference/moderations)
## Usage

View File

@ -2,6 +2,7 @@ apply plugin: 'java-library'
apply plugin: "com.vanniktech.maven.publish"
dependencies {
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.0'
compileOnly 'org.projectlombok:lombok:1.18.12'
annotationProcessor 'org.projectlombok:lombok:1.18.12'
}

View File

@ -0,0 +1,30 @@
package com.theokanning.openai.moderation;
import lombok.Data;
/**
* An object containing the moderation data for a single input string
*
* https://beta.openai.com/docs/api-reference/moderations/create
*/
@Data
public class Moderation {
/**
* Set to true if the model classifies the content as violating OpenAI's content policy, false otherwise
*/
boolean flagged;
/**
* Object containing per-category binary content policy violation flags.
* For each category, the value is true if the model flags the corresponding category as violated, false otherwise.
*/
ModerationCategories categories;
/**
* Object containing per-category raw scores output by the model, denoting the model's confidence that the
* input violates the OpenAI's policy for the category.
* The value is between 0 and 1, where higher values denote higher confidence.
* The scores should not be interpreted as probabilities.
*/
ModerationCategoryScores categoryScores;
}

View File

@ -0,0 +1,34 @@
package com.theokanning.openai.moderation;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.theokanning.openai.completion.CompletionChoice;
import lombok.Data;
import java.util.List;
/**
* An object containing the flags for each moderation category
*
* https://beta.openai.com/docs/api-reference/moderations/create
*/
@Data
public class ModerationCategories {
boolean hate;
@JsonProperty("hate/threatening")
boolean hateThreatening;
@JsonProperty("self-harm")
boolean selfHarm;
boolean sexual;
@JsonProperty("sexual/minors")
boolean sexualMinors;
boolean violence;
@JsonProperty("violence/graphic")
boolean violenceGraphic;
}

View File

@ -0,0 +1,31 @@
package com.theokanning.openai.moderation;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* An object containing the scores for each moderation category
*
* https://beta.openai.com/docs/api-reference/moderations/create
*/
@Data
public class ModerationCategoryScores {
double hate;
@JsonProperty("hate/threatening")
double hateThreatening;
@JsonProperty("self-harm")
double selfHarm;
double sexual;
@JsonProperty("sexual/minors")
double sexualMinors;
double violence;
@JsonProperty("violence/graphic")
double violenceGraphic;
}

View File

@ -0,0 +1,28 @@
package com.theokanning.openai.moderation;
import lombok.*;
import java.util.List;
/**
* A request for OpenAi to detect if text violates OpenAi's content policy.
*
* https://beta.openai.com/docs/api-reference/moderations/create
*/
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ModerationRequest {
/**
* The input text to classify.
*/
@NonNull
String input;
/**
* The name of the model to use, defaults to text-moderation-stable.
*/
String model;
}

View File

@ -0,0 +1,28 @@
package com.theokanning.openai.moderation;
import lombok.Data;
import java.util.List;
/**
* An object containing a response from the moderation api
*
* https://beta.openai.com/docs/api-reference/moderations/create
*/
@Data
public class ModerationResult {
/**
* A unique id assigned to this moderation.
*/
String id;
/**
* The GPT-3 model used.
*/
String model;
/**
* A list of moderation scores.
*/
List<Moderation> results;
}

View File

@ -15,6 +15,8 @@ import com.theokanning.openai.file.File;
import com.theokanning.openai.finetune.FineTuneEvent;
import com.theokanning.openai.finetune.FineTuneRequest;
import com.theokanning.openai.finetune.FineTuneResult;
import com.theokanning.openai.moderation.ModerationRequest;
import com.theokanning.openai.moderation.ModerationResult;
import com.theokanning.openai.search.SearchRequest;
import com.theokanning.openai.search.SearchResult;
import io.reactivex.Single;
@ -36,6 +38,9 @@ public interface OpenAiApi {
@POST("/v1/engines/{engine_id}/edits")
Single<EditResult> createEdit(@Path("engine_id") String engineId, @Body EditRequest request);
@POST("/v1/engines/{engine_id}/embeddings")
Single<EmbeddingResult> createEmbeddings(@Path("engine_id") String engineId, @Body EmbeddingRequest request);
@POST("/v1/engines/{engine_id}/search")
Single<OpenAiResponse<SearchResult>> search(@Path("engine_id") String engineId, @Body SearchRequest request);
@ -79,8 +84,6 @@ public interface OpenAiApi {
@DELETE("/v1/models/{fine_tune_id}")
Single<DeleteResult> deleteFineTune(@Path("fine_tune_id") String fineTuneId);
@POST("/v1/engines/{engine_id}/embeddings")
Single<EmbeddingResult> createEmbeddings(@Path("engine_id") String engineId, @Body EmbeddingRequest request);
@POST("/v1/moderations")
Single<ModerationResult> createModeration(@Body ModerationRequest request);
}

View File

@ -19,6 +19,8 @@ import com.theokanning.openai.file.File;
import com.theokanning.openai.finetune.FineTuneEvent;
import com.theokanning.openai.finetune.FineTuneRequest;
import com.theokanning.openai.finetune.FineTuneResult;
import com.theokanning.openai.moderation.ModerationRequest;
import com.theokanning.openai.moderation.ModerationResult;
import com.theokanning.openai.search.SearchRequest;
import com.theokanning.openai.search.SearchResult;
import okhttp3.*;
@ -92,6 +94,10 @@ public class OpenAiService {
return api.createEdit(engineId, request).blockingGet();
}
public EmbeddingResult createEmbeddings(String engineId, EmbeddingRequest request) {
return api.createEmbeddings(engineId, request).blockingGet();
}
public List<SearchResult> search(String engineId, SearchRequest request) {
return api.search(engineId, request).blockingGet().data;
}
@ -153,7 +159,7 @@ public class OpenAiService {
return api.deleteFineTune(fineTuneId).blockingGet();
}
public EmbeddingResult createEmbeddings(String engineId, EmbeddingRequest request) {
return api.createEmbeddings(engineId, request).blockingGet();
public ModerationResult createModeration(ModerationRequest request) {
return api.createModeration(request).blockingGet();
}
}

View File

@ -0,0 +1,26 @@
package com.theokanning.openai;
import com.theokanning.openai.moderation.ModerationRequest;
import com.theokanning.openai.moderation.Moderation;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ModerationTest {
String token = System.getenv("OPENAI_TOKEN");
OpenAiService service = new OpenAiService(token);
@Test
void createModeration() {
ModerationRequest moderationRequest = ModerationRequest.builder()
.input("I want to kill them")
.model("text-moderation-latest")
.build();
Moderation moderationScore = service.createModeration(moderationRequest).getResults().get(0);
assertTrue(moderationScore.isFlagged());
}
}