Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions OpenAI_API/Model/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@ public Model()
/// </summary>
public static Model AdaTextEmbedding => new Model("text-embedding-ada-002") { OwnedBy = "openai" };

/// <summary>
/// Stable text moderation model that may provide lower accuracy compared to TextModerationLatest.
/// OpenAI states they will provide advanced notice before updating this model.
/// </summary>
public static Model TextModerationStable => new Model("text-moderation-stable") { OwnedBy = "openai" };

/// <summary>
/// The latest text moderation model. This model will be automatically upgraded over time.
/// </summary>
public static Model TextModerationLatest => new Model("text-moderation-latest") { OwnedBy = "openai" };


/// <summary>
/// Gets more details about this Model from the API, specifically properties such as <see cref="OwnedBy"/> and permissions.
Expand Down
51 changes: 51 additions & 0 deletions OpenAI_API/Moderations/ModerationEndpoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using OpenAI_API.Models;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace OpenAI_API.Moderations
{
/// <summary>
/// This endpoint classifies text against the OpenAI Content Policy
/// </summary>
public class ModerationEndpoint : EndpointBase
{
/// <summary>
/// This allows you to send request to the recommended model without needing to specify. OpenAI recommends using the <see cref="Model.TextModerationLatest"/> model
/// </summary>
public ModerationRequest DefaultModerationRequestArgs { get; set; } = new ModerationRequest() { Model = Model.TextModerationLatest };

/// <summary>
/// The name of the endpoint, which is the final path segment in the API URL. For example, "completions".
/// </summary>
protected override string Endpoint { get { return "moderations"; } }

/// <summary>
/// Constructor of the api endpoint. Rather than instantiating this yourself, access it through an instance of <see cref="OpenAIAPI"/> as <see cref="OpenAIAPI.Moderations"/>.
/// </summary>
/// <param name="api"></param>
internal ModerationEndpoint(OpenAIAPI api) : base(api) { }

/// <summary>
/// Ask the API to classify the text using the default model.
/// </summary>
/// <param name="input">Text to classify</param>
/// <returns>Asynchronously returns the classification result</returns>
public async Task<ModerationResult> CreateModerationAsync(string input)
{
ModerationRequest req = new ModerationRequest(DefaultModerationRequestArgs.Model, input);
return await CreateModerationAsync(req);
}

/// <summary>
/// Ask the API to classify the text using a custom request.
/// </summary>
/// <param name="request">Request to send to the API</param>
/// <returns>Asynchronously returns the classification result</returns>
public async Task<ModerationResult> CreateModerationAsync(ModerationRequest request)
{
return await HttpPost<ModerationResult>(postData: request);
}
}
}
55 changes: 55 additions & 0 deletions OpenAI_API/Moderations/ModerationRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Newtonsoft.Json;
using OpenAI_API.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace OpenAI_API.Moderations
{
/// <summary>
/// Represents a request to the Moderations API.
/// </summary>
public class ModerationRequest
{
/// <summary>
/// Which Moderation model to use for this request
/// </summary>
[JsonProperty("model")]
public string Model { get; set; }

/// <summary>
/// Main text to classify
/// </summary>
[JsonProperty("input")]
public string Input { get; set; }

/// <summary>
/// Cretes a new, empty <see cref="ModerationRequest"/>
/// </summary>
public ModerationRequest()
{

}

/// <summary>
/// Creates a new <see cref="ModerationRequest"/> with the specified parameters
/// </summary>
/// <param name="model">The model to use. You can use <see cref="ModelsEndpoint.GetModelsAsync()"/> to see all of your available models, or use a standard model like <see cref="Model.TextModerationLatest"/>.</param>
/// <param name="input">The prompt to classify</param>
public ModerationRequest(Model model, string input)
{
Model = model;
this.Input = input;
}

/// <summary>
/// Creates a new <see cref="ModerationRequest"/> with the specified input and the <see cref="Model.TextModerationLatest"/> model.
/// </summary>
/// <param name="input">The prompt to classify</param>
public ModerationRequest(string input)
{
Model = OpenAI_API.Models.Model.TextModerationLatest;
this.Input = input;
}
}
}
153 changes: 153 additions & 0 deletions OpenAI_API/Moderations/ModerationResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;

namespace OpenAI_API.Moderations
{
/// <summary>
/// Represents a moderation result returned by the Moderations API
/// </summary>
public class ModerationResult : ApiResultBase
{
/// <summary>
/// List of results returned from the Moderations API request
/// </summary>
[JsonProperty("results")]
public List<Result> Results { get; set; }

/// <summary>
/// The unique identifier associated with a moderation request
/// Consists of the prefix "modr-" followed by a randomly generated alphanumeric string
/// </summary>
[JsonProperty("id")]
public string Id { get; set; }
}

/// <summary>
/// The result generated by the Moderations API request
/// </summary>
public class Result
{
/// <summary>
/// A series of categories that the content could be flagged for
/// </summary>
[JsonProperty("categories")]
public Categories Categories { get; set; }

/// <summary>
/// Confidence scores for the different category flags
/// </summary>
[JsonProperty("category_scores")]
public CategoryScores CategoryScores { get; set; }

/// <summary>
/// True if the text was flagged in any of the categories
/// </summary>
[JsonProperty("flagged")]
public bool Flagged { get; set; }

}

/// <summary>
/// Series of boolean values indiciating what the text is flagged for
/// </summary>
public class Categories
{
/// <summary>
/// If the text contains hate speech
/// </summary>
[JsonProperty("hate")]
public bool Hate { get; set; }

/// <summary>
/// If the text contains hate / threatening speech
/// </summary>
[JsonProperty("hate/threatening")]
public bool HateThreatening { get; set; }
/// <summary>
/// If the text contains content about self-harm
/// </summary>
[JsonProperty("self-harm")]
public bool SelfHarm { get; set; }

/// <summary>
/// If the text contains sexual content
/// </summary>
[JsonProperty("sexual")]
public bool Sexual { get; set; }

/// <summary>
/// If the text contains sexual content featuring minors
/// </summary>
[JsonProperty("sexual/minors")]
public bool SexualMinors { get; set; }

/// <summary>
/// If the text contains violent content
/// </summary>
[JsonProperty("violence")]
public bool Violence { get; set; }

/// <summary>
/// If the text contains violent and graphic content
/// </summary>
[JsonProperty("violence/graphic")]
public bool ViolenceGraphic { get; set; }
}

/// <summary>
/// Confidence scores for the different category flags
/// </summary>
public class CategoryScores
{
/// <summary>
/// Confidence score indicating "hate" content is detected in the text
/// A value between 0 and 1, where 0 indicates low confidence
/// </summary>
[JsonProperty("hate")]
public double Hate { get; set; }

/// <summary>
/// Confidence score indicating "hate/threatening" content is detected in the text
/// A value between 0 and 1, where 0 indicates low confidence
/// </summary>
[JsonProperty("hate/threatening")]
public double HateThreatening { get; set; }

/// <summary>
/// Confidence score indicating "self-harm" content is detected in the text
/// A value between 0 and 1, where 0 indicates low confidence
/// </summary>
[JsonProperty("self-harm")]
public double SelfHarm { get; set; }

/// <summary>
/// Confidence score indicating "sexual" content is detected in the text
/// A value between 0 and 1, where 0 indicates low confidence
/// </summary>
[JsonProperty("sexual")]
public double Sexual { get; set; }

/// <summary>
/// Confidence score indicating "sexual/minors" content is detected in the text
/// A value between 0 and 1, where 0 indicates low confidence
/// </summary>
[JsonProperty("sexual/minors")]
public double SexualMinors { get; set; }

/// <summary>
/// Confidence score indicating "violence" content is detected in the text
/// A value between 0 and 1, where 0 indicates low confidence
/// </summary>
[JsonProperty("violence")]
public double Violence { get; set; }

/// <summary>
/// Confidence score indicating "violence/graphic" content is detected in the text
/// A value between 0 and 1, where 0 indicates low confidence
/// </summary>
[JsonProperty("violence/graphic")]
public double ViolenceGraphic { get; set; }
}
}
7 changes: 7 additions & 0 deletions OpenAI_API/OpenAIAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using OpenAI_API.Files;
using OpenAI_API.Images;
using OpenAI_API.Models;
using OpenAI_API.Moderations;
using System.Xml.Linq;

namespace OpenAI_API
Expand Down Expand Up @@ -40,6 +41,7 @@ public OpenAIAPI(APIAuthentication apiKeys = null)
Models = new ModelsEndpoint(this);
Files = new FilesEndpoint(this);
Embeddings = new EmbeddingEndpoint(this);
Moderations = new ModerationEndpoint(this);
ImageGenerations = new ImageGenerationEndpoint(this);
}

Expand Down Expand Up @@ -68,6 +70,11 @@ public static OpenAIAPI ForAzure(string YourResourceName, string deploymentId, A
/// </summary>
public EmbeddingEndpoint Embeddings { get; }

/// <summary>
/// Classify text against the OpenAI Content Policy.
/// </summary>
public ModerationEndpoint Moderations { get; }

/// <summary>
/// The API endpoint for querying available Engines/models
/// </summary>
Expand Down