Skip to content

Commit 1265387

Browse files
committed
Fixes #97: adds user names to chat, support multiple inputs for moderation
1 parent d4b0eed commit 1265387

File tree

5 files changed

+245
-66
lines changed

5 files changed

+245
-66
lines changed

OpenAI_API/Chat/ChatMessage.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,11 @@ public ChatMessageRole Role
5353
/// </summary>
5454
[JsonProperty("content")]
5555
public string Content { get; set; }
56+
57+
/// <summary>
58+
/// An optional name of the user in a multi-user chat
59+
/// </summary>
60+
[JsonProperty("name")]
61+
public string Name { get; set; }
5662
}
5763
}

OpenAI_API/Chat/Conversation.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ public void AppendMessage(ChatMessage message)
9191
/// </summary>
9292
/// <param name="content">Text content generated by the end users of an application, or set by a developer as an instruction</param>
9393
public void AppendUserInput(string content) => this.AppendMessage(new ChatMessage(ChatMessageRole.User, content));
94+
95+
/// <summary>
96+
/// Creates and appends a <see cref="ChatMessage"/> to the chat hstory with the Role of <see cref="ChatMessageRole.User"/>. The user messages help instruct the assistant. They can be generated by the end users of an application, or set by a developer as an instruction.
97+
/// </summary>
98+
/// <param name="userName">The name of the user in a multi-user chat</param>
99+
/// <param name="content">Text content generated by the end users of an application, or set by a developer as an instruction</param>
100+
public void AppendUserInputWithName(string userName, string content) => this.AppendMessage(new ChatMessage(ChatMessageRole.User, content) { Name = userName });
101+
102+
94103
/// <summary>
95104
/// Creates and appends a <see cref="ChatMessage"/> to the chat hstory with the Role of <see cref="ChatMessageRole.System"/>. The system message helps set the behavior of the assistant.
96105
/// </summary>

OpenAI_API/Moderation/ModerationRequest.cs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using OpenAI_API.Models;
33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
56
using System.Reflection;
67
using System.Text;
78

@@ -22,8 +23,27 @@ public class ModerationRequest
2223
/// <summary>
2324
/// The input text to classify
2425
/// </summary>
26+
[JsonIgnore]
27+
public string Input
28+
{
29+
get
30+
{
31+
if (Inputs == null)
32+
return null;
33+
else
34+
return Inputs.FirstOrDefault();
35+
}
36+
set
37+
{
38+
Inputs = new string[] { value };
39+
}
40+
}
41+
42+
/// <summary>
43+
/// An array of inputs to classify
44+
/// </summary>
2545
[JsonProperty("input")]
26-
public string Input { get; set; }
46+
public string[] Inputs { get; set; }
2747

2848
/// <summary>
2949
/// Cretes a new, empty <see cref="ModerationRequest"/>
@@ -45,13 +65,24 @@ public ModerationRequest(string input, Model model)
4565
}
4666

4767
/// <summary>
48-
/// Creates a new <see cref="ModerationRequest"/> with the specified input and the <see cref="Model.TextModerationLatest"/> model.
68+
/// Creates a new <see cref="ModerationRequest"/> with the specified parameters
4969
/// </summary>
50-
/// <param name="input">The prompt to classify</param>
51-
public ModerationRequest(string input)
70+
/// <param name="inputs">An array of prompts to classify</param>
71+
/// <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>
72+
public ModerationRequest(string[] inputs, Model model)
73+
{
74+
Model = model;
75+
this.Inputs = inputs;
76+
}
77+
78+
/// <summary>
79+
/// Creates a new <see cref="ModerationRequest"/> with the specified input(s) and the <see cref="Model.TextModerationLatest"/> model.
80+
/// </summary>
81+
/// <param name="input">One or more prompts to classify</param>
82+
public ModerationRequest(params string[] input)
5283
{
5384
Model = OpenAI_API.Models.Model.TextModerationLatest;
54-
this.Input = input;
85+
this.Inputs = input;
5586
}
5687
}
5788
}

OpenAI_Tests/ChatEndpointTests.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using OpenAI_API.Chat;
33
using OpenAI_API.Completions;
44
using OpenAI_API.Models;
5+
using OpenAI_API.Moderation;
56
using System;
67
using System.Collections.Generic;
78
using System.Linq;
@@ -53,7 +54,45 @@ public void BasicCompletion()
5354
Assert.That(results.Choices.All(c => c.Message.Role.Equals(ChatMessageRole.Assistant)));
5455
Assert.That(results.Choices.All(c => c.Message.Content.Length > 1));
5556
}
57+
[Test]
58+
public void BasicCompletionWithNames()
59+
{
60+
var api = new OpenAI_API.OpenAIAPI();
5661

62+
Assert.IsNotNull(api.Chat);
63+
64+
var results = api.Chat.CreateChatCompletionAsync(new ChatRequest()
65+
{
66+
Model = Model.ChatGPTTurbo,
67+
Temperature = 0.1,
68+
MaxTokens = 5,
69+
Messages = new ChatMessage[] {
70+
new ChatMessage(ChatMessageRole.System, "You are the moderator in this workplace chat. Answer any questions asked of the participants."),
71+
new ChatMessage(ChatMessageRole.User, "Hello everyone") { Name="John"},
72+
new ChatMessage(ChatMessageRole.User, "Good morning all") { Name="Edward"},
73+
new ChatMessage(ChatMessageRole.User, "Is John here? Answer yes or no.") { Name = "Cindy" }
74+
}
75+
}).Result;
76+
Assert.IsNotNull(results);
77+
if (results.CreatedUnixTime.HasValue)
78+
{
79+
Assert.NotZero(results.CreatedUnixTime.Value);
80+
Assert.NotNull(results.Created);
81+
Assert.Greater(results.Created.Value, new DateTime(2018, 1, 1));
82+
Assert.Less(results.Created.Value, DateTime.Now.AddDays(1));
83+
}
84+
else
85+
{
86+
Assert.Null(results.Created);
87+
}
88+
Assert.NotNull(results.Object);
89+
Assert.NotNull(results.Choices);
90+
Assert.NotZero(results.Choices.Count);
91+
Assert.AreEqual(ChatMessageRole.Assistant, results.Choices[0].Message.Role);
92+
Assert.That(results.Choices.All(c => c.Message.Role.Equals(ChatMessageRole.Assistant)));
93+
Assert.That(results.Choices.All(c => c.Message.Content.Length > 1));
94+
Assert.That(results.ToString().ToLower().Contains("yes"));
95+
}
5796
[Test]
5897
public void SimpleCompletion()
5998
{
@@ -92,6 +131,7 @@ public void ChatBackAndForth(string model)
92131

93132
var chat = api.Chat.CreateConversation();
94133
chat.Model = model;
134+
chat.RequestParameters.Temperature = 0;
95135

96136
chat.AppendSystemMessage("You are a teacher who helps children understand if things are animals or not. If the user tells you an animal, you say \"yes\". If the user tells you something that is not an animal, you say \"no\". You only ever respond with \"yes\" or \"no\". You do not say anything else.");
97137
chat.AppendUserInput("Is this an animal? Cat");
@@ -110,6 +150,32 @@ public void ChatBackAndForth(string model)
110150
Assert.AreEqual("No", res.Trim());
111151
}
112152

153+
[Test]
154+
public void ChatWithNames()
155+
{
156+
var api = new OpenAI_API.OpenAIAPI();
157+
158+
var chat = api.Chat.CreateConversation();
159+
chat.RequestParameters.Temperature = 0;
160+
161+
chat.AppendSystemMessage("You are the moderator in this workplace chat. Answer any questions asked of the participants.");
162+
chat.AppendUserInputWithName("John", "Hello everyone");
163+
chat.AppendUserInputWithName("Edward", "Good morning all");
164+
chat.AppendUserInputWithName("Cindy", "Is John here? Answer yes or no.");
165+
chat.AppendExampleChatbotOutput("Yes");
166+
chat.AppendUserInputWithName("Cindy", "Is Monica here? Answer yes or no.");
167+
string res = chat.GetResponseFromChatbot().Result;
168+
Assert.NotNull(res);
169+
Assert.IsNotEmpty(res);
170+
Assert.That(res.ToLower().Contains("no"));
171+
chat.AppendUserInputWithName("Cindy", "Is Edward here? Answer yes or no.");
172+
res = chat.GetResponseFromChatbot().Result;
173+
Assert.NotNull(res);
174+
Assert.IsNotEmpty(res);
175+
Assert.That(res.ToLower().Contains("yes"));
176+
}
177+
178+
113179
[Test]
114180
public async Task StreamCompletionEnumerableAsync_ShouldStreamData()
115181
{

OpenAI_Tests/ModerationEndpointTests.cs

Lines changed: 128 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -6,71 +6,138 @@
66

77
namespace OpenAI_Tests
88
{
9-
public class ModerationEndpointTests
10-
{
11-
[SetUp]
12-
public void Setup()
13-
{
14-
OpenAI_API.APIAuthentication.Default = new OpenAI_API.APIAuthentication(Environment.GetEnvironmentVariable("TEST_OPENAI_SECRET_KEY"));
15-
}
16-
17-
[Test]
18-
public void NoViolations()
19-
{
20-
var api = new OpenAI_API.OpenAIAPI();
21-
22-
Assert.IsNotNull(api.Moderation);
23-
24-
var results = api.Moderation.CallModerationAsync(new ModerationRequest("Hello world")).Result;
25-
Assert.IsNotNull(results);
26-
if (results.CreatedUnixTime.HasValue)
27-
{
28-
Assert.NotZero(results.CreatedUnixTime.Value);
29-
Assert.NotNull(results.Created);
30-
Assert.Greater(results.Created.Value, new DateTime(2018, 1, 1));
9+
public class ModerationEndpointTests
10+
{
11+
[SetUp]
12+
public void Setup()
13+
{
14+
OpenAI_API.APIAuthentication.Default = new OpenAI_API.APIAuthentication(Environment.GetEnvironmentVariable("TEST_OPENAI_SECRET_KEY"));
15+
}
16+
17+
[Test]
18+
public void NoViolations()
19+
{
20+
var api = new OpenAI_API.OpenAIAPI();
21+
22+
Assert.IsNotNull(api.Moderation);
23+
24+
var results = api.Moderation.CallModerationAsync(new ModerationRequest("Hello world")).Result;
25+
Assert.IsNotNull(results);
26+
if (results.CreatedUnixTime.HasValue)
27+
{
28+
Assert.NotZero(results.CreatedUnixTime.Value);
29+
Assert.NotNull(results.Created);
30+
Assert.Greater(results.Created.Value, new DateTime(2018, 1, 1));
3131
Assert.Less(results.Created.Value, DateTime.Now.AddDays(1));
32-
} else
33-
{
34-
Assert.Null(results.Created);
3532
}
36-
Assert.NotNull(results.Results);
37-
Assert.NotZero(results.Results.Count);
38-
var result = results.Results[0];
39-
Assert.False(result.Flagged);
40-
Assert.Zero(result.FlaggedCategories.Count);
41-
Assert.Greater(result.HighestFlagScore, 0d);
42-
Assert.Null(result.MainContentFlag);
43-
}
44-
45-
[Test]
46-
public void ViolenceExample()
47-
{
48-
var api = new OpenAI_API.OpenAIAPI();
49-
50-
Assert.IsNotNull(api.Moderation);
51-
52-
var results = api.Moderation.CallModerationAsync("I want to kill them.").Result;
53-
Assert.IsNotNull(results);
54-
if (results.CreatedUnixTime.HasValue)
55-
{
56-
Assert.NotZero(results.CreatedUnixTime.Value);
57-
Assert.NotNull(results.Created);
58-
Assert.Greater(results.Created.Value, new DateTime(2018, 1, 1));
33+
else
34+
{
35+
Assert.Null(results.Created);
36+
}
37+
Assert.NotNull(results.Results);
38+
Assert.NotZero(results.Results.Count);
39+
var result = results.Results[0];
40+
Assert.False(result.Flagged);
41+
Assert.Zero(result.FlaggedCategories.Count);
42+
Assert.Greater(result.HighestFlagScore, 0d);
43+
Assert.Null(result.MainContentFlag);
44+
}
45+
46+
47+
[Test]
48+
public void MultipleInputs()
49+
{
50+
var api = new OpenAI_API.OpenAIAPI();
51+
52+
Assert.IsNotNull(api.Moderation);
53+
54+
var results = api.Moderation.CallModerationAsync(new ModerationRequest("Hello world", "Good morning")).Result;
55+
Assert.IsNotNull(results);
56+
if (results.CreatedUnixTime.HasValue)
57+
{
58+
Assert.NotZero(results.CreatedUnixTime.Value);
59+
Assert.NotNull(results.Created);
60+
Assert.Greater(results.Created.Value, new DateTime(2018, 1, 1));
5961
Assert.Less(results.Created.Value, DateTime.Now.AddDays(1));
60-
} else
61-
{
62-
Assert.Null(results.Created);
6362
}
64-
Assert.NotNull(results.Results);
65-
Assert.NotZero(results.Results.Count);
66-
var result = results.Results[0];
67-
Assert.True(result.Flagged);
68-
Assert.NotZero(result.FlaggedCategories.Count);
69-
Assert.Greater(result.HighestFlagScore, 0.5d);
70-
Assert.AreEqual("violence", result.MainContentFlag);
71-
Assert.AreEqual(result.HighestFlagScore, result.CategoryScores["violence"]);
72-
Assert.AreEqual("violence", result.FlaggedCategories.First());
63+
else
64+
{
65+
Assert.Null(results.Created);
66+
}
67+
Assert.NotNull(results.Results);
68+
Assert.AreEqual(2, results.Results.Count);
69+
foreach (var result in results.Results)
70+
{
71+
Assert.False(result.Flagged);
72+
Assert.Zero(result.FlaggedCategories.Count);
73+
Assert.Greater(result.HighestFlagScore, 0d);
74+
Assert.Null(result.MainContentFlag);
75+
}
76+
}
77+
78+
79+
80+
[Test]
81+
public void MultipleInputsFailing()
82+
{
83+
var api = new OpenAI_API.OpenAIAPI();
84+
85+
Assert.IsNotNull(api.Moderation);
86+
87+
var results = api.Moderation.CallModerationAsync(new ModerationRequest("You are going to die, you scum", "I want to kill them")).Result;
88+
Assert.IsNotNull(results);
89+
if (results.CreatedUnixTime.HasValue)
90+
{
91+
Assert.NotZero(results.CreatedUnixTime.Value);
92+
Assert.NotNull(results.Created);
93+
Assert.Greater(results.Created.Value, new DateTime(2018, 1, 1));
94+
Assert.Less(results.Created.Value, DateTime.Now.AddDays(1));
95+
}
96+
else
97+
{
98+
Assert.Null(results.Created);
99+
}
100+
Assert.NotNull(results.Results);
101+
Assert.AreEqual(2, results.Results.Count);
102+
foreach (var result in results.Results)
103+
{
104+
Assert.True(result.Flagged);
105+
Assert.NotZero(result.FlaggedCategories.Count);
106+
Assert.Greater(result.HighestFlagScore, 0.5d);
107+
Assert.NotNull(result.MainContentFlag);
108+
}
109+
}
110+
111+
[Test]
112+
public void ViolenceExample()
113+
{
114+
var api = new OpenAI_API.OpenAIAPI();
115+
116+
Assert.IsNotNull(api.Moderation);
117+
118+
var results = api.Moderation.CallModerationAsync("I want to kill them.").Result;
119+
Assert.IsNotNull(results);
120+
if (results.CreatedUnixTime.HasValue)
121+
{
122+
Assert.NotZero(results.CreatedUnixTime.Value);
123+
Assert.NotNull(results.Created);
124+
Assert.Greater(results.Created.Value, new DateTime(2018, 1, 1));
125+
Assert.Less(results.Created.Value, DateTime.Now.AddDays(1));
126+
}
127+
else
128+
{
129+
Assert.Null(results.Created);
130+
}
131+
Assert.NotNull(results.Results);
132+
Assert.NotZero(results.Results.Count);
133+
var result = results.Results[0];
134+
Assert.True(result.Flagged);
135+
Assert.NotZero(result.FlaggedCategories.Count);
136+
Assert.Greater(result.HighestFlagScore, 0.5d);
137+
Assert.AreEqual("violence", result.MainContentFlag);
138+
Assert.AreEqual(result.HighestFlagScore, result.CategoryScores["violence"]);
139+
Assert.AreEqual("violence", result.FlaggedCategories.First());
73140
}
74141

75-
}
142+
}
76143
}

0 commit comments

Comments
 (0)