-
-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Evgenii Khoroshev
committed
Nov 15, 2023
1 parent
5de096c
commit bcd1f7a
Showing
5 changed files
with
299 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using NUnit.Framework; | ||
using System.Collections.Generic; | ||
using System.Threading.Tasks; | ||
using OpenAI.Threads; | ||
|
||
namespace OpenAI.Tests | ||
{ | ||
internal class TestFixture_13_Theads : AbstractTestFixture | ||
{ | ||
[Test] | ||
public async Task Test_01_CreateThread() | ||
{ | ||
Assert.IsNotNull(OpenAIClient.ThreadsEndpoint); | ||
|
||
var request = new CreateThreadRequest | ||
{ | ||
Messages = new List<CreateThreadRequest.Message>() | ||
{ | ||
new CreateThreadRequest.Message("Test message") | ||
}, | ||
Metadata = new Dictionary<string, object> | ||
{ | ||
["text"] = "test" | ||
} | ||
}; | ||
|
||
var result = await OpenAIClient.ThreadsEndpoint.CreateThreadAsync(request); | ||
|
||
Assert.IsNotNull(result); | ||
Assert.AreEqual("thread", result.Object); | ||
|
||
Assert.IsNotNull(result.Metadata); | ||
Assert.Contains("text", result.Metadata.Keys); | ||
Assert.AreEqual("test", result.Metadata["text"]); | ||
} | ||
|
||
[Test] | ||
public async Task Test_02_RetrieveThread() | ||
{ | ||
Assert.IsNotNull(OpenAIClient.ThreadsEndpoint); | ||
|
||
var createThreadRequest = new CreateThreadRequest | ||
{ | ||
Metadata = new Dictionary<string, object> | ||
{ | ||
["text"] = "test" | ||
} | ||
}; | ||
|
||
var created = await OpenAIClient.ThreadsEndpoint.CreateThreadAsync(createThreadRequest); | ||
|
||
var retrieved = await OpenAIClient.ThreadsEndpoint.RetrieveThreadAsync(created.Id); | ||
|
||
Assert.IsNotNull(retrieved); | ||
Assert.AreEqual(created.Id, retrieved.Id); | ||
Assert.IsNotNull(retrieved.Metadata); | ||
Assert.Contains("text", retrieved.Metadata.Keys); | ||
Assert.AreEqual("test", retrieved.Metadata["text"]); | ||
} | ||
|
||
[Test] | ||
public async Task Test_03_ModifyThread() | ||
{ | ||
Assert.IsNotNull(OpenAIClient.ThreadsEndpoint); | ||
|
||
var created = await OpenAIClient.ThreadsEndpoint.CreateThreadAsync(new CreateThreadRequest()); | ||
|
||
var newMetadata = new Dictionary<string, object> | ||
{ | ||
["text"] = "test2" | ||
}; | ||
|
||
var modified = await OpenAIClient.ThreadsEndpoint.ModifyThreadAsync(created.Id, newMetadata); | ||
|
||
Assert.IsNotNull(modified); | ||
Assert.AreEqual(created.Id, modified.Id); | ||
Assert.IsNotNull(modified.Metadata); | ||
Assert.Contains("text", modified.Metadata.Keys); | ||
Assert.AreEqual("test2", modified.Metadata["text"]); | ||
} | ||
|
||
[Test] | ||
public async Task Test_04_DeleteThread() | ||
{ | ||
Assert.IsNotNull(OpenAIClient.ThreadsEndpoint); | ||
|
||
var created = await OpenAIClient.ThreadsEndpoint.CreateThreadAsync(new CreateThreadRequest()); | ||
|
||
var isDeleted = await OpenAIClient.ThreadsEndpoint.DeleteThreadAsync(created.Id); | ||
|
||
Assert.IsTrue(isDeleted); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
using System.Collections.Generic; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace OpenAI.Threads; | ||
|
||
public class CreateThreadRequest | ||
{ | ||
/// <summary> | ||
/// A list of messages to start the thread with. | ||
/// </summary> | ||
[JsonPropertyName("messages")] | ||
public List<Message> Messages { get; set; } = new(); | ||
|
||
/// <summary> | ||
/// Set of 16 key-value pairs that can be attached to an object. | ||
/// This can be useful for storing additional information about the object in a structured format. | ||
/// Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. | ||
/// </summary> | ||
[JsonPropertyName("metadata")] | ||
public Dictionary<string, object> Metadata { get; set; } | ||
|
||
public class Message | ||
{ | ||
public Message() { } | ||
|
||
public Message(string content) | ||
{ | ||
Content = content; | ||
} | ||
|
||
/// <summary> | ||
/// The role of the entity that is creating the message. Currently only user is supported. | ||
/// </summary> | ||
[JsonPropertyName("role")] | ||
public string Role { get; set; } = "user"; | ||
|
||
/// <summary> | ||
/// The content of the message. | ||
/// </summary> | ||
[JsonPropertyName("content")] | ||
public string Content { get; set; } | ||
|
||
/// <summary> | ||
/// A list of File IDs that the message should use. There can be a maximum of 10 files attached to a message. | ||
/// Useful for tools like retrieval and code_interpreter that can access and use files. | ||
/// </summary> | ||
[JsonPropertyName("file_ids")] | ||
public string[] FileIds { get; set; } | ||
|
||
/// <summary> | ||
/// Set of 16 key-value pairs that can be attached to an object. | ||
/// This can be useful for storing additional information about the object in a structured format. | ||
/// Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. | ||
/// </summary> | ||
[JsonPropertyName("metadata")] | ||
public Dictionary<string, string> Metadata { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Collections.Generic; | ||
using System.Text.Json.Serialization; | ||
|
||
namespace OpenAI.Threads; | ||
|
||
public class Thread | ||
{ | ||
/// <summary> | ||
/// The identifier, which can be referenced in API endpoints. | ||
/// </summary> | ||
[JsonPropertyName("id")] | ||
public string Id { get; set; } | ||
|
||
/// <summary> | ||
/// The object type, which is always thread. | ||
/// </summary> | ||
[JsonPropertyName("object")] | ||
public string Object { get; set; } = "thread"; | ||
|
||
/// <summary> | ||
/// The Unix timestamp (in seconds) for when the thread was created. | ||
/// </summary> | ||
/// <returns></returns> | ||
[JsonPropertyName("created_at")] | ||
public int CreatedAt { get; set; } | ||
|
||
/// <summary> | ||
/// Set of 16 key-value pairs that can be attached to an object. | ||
/// This can be useful for storing additional information about the object in a structured format. | ||
/// Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. | ||
/// </summary> | ||
[JsonPropertyName("metadata")] | ||
public Dictionary<string, string> Metadata { get; set; } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
using System.Collections.Generic; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using OpenAI.Extensions; | ||
|
||
namespace OpenAI.Threads; | ||
|
||
public class ThreadsEndpoint : BaseEndPoint | ||
{ | ||
public ThreadsEndpoint(OpenAIClient api) : base(api) | ||
{ | ||
} | ||
|
||
protected override string Root => "/threads"; | ||
|
||
/// <summary> | ||
/// Create a thread. | ||
/// </summary> | ||
/// <param name="request"></param> | ||
/// <param name="cancellationToken"></param> | ||
/// <returns>A thread object.</returns> | ||
public async Task<Thread> CreateThreadAsync(CreateThreadRequest request, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
var jsonContent = JsonSerializer.Serialize(request, OpenAIClient.JsonSerializationOptions) | ||
.ToJsonStringContent(EnableDebug); | ||
var response = await Api.Client.PostAsync(GetUrl(), jsonContent, cancellationToken).ConfigureAwait(false); | ||
var responseAsString = await response.ReadAsStringAsync(EnableDebug, cancellationToken).ConfigureAwait(false); | ||
var created = JsonSerializer.Deserialize<Thread>(responseAsString, OpenAIClient.JsonSerializationOptions); | ||
|
||
return created; | ||
} | ||
|
||
/// <summary> | ||
/// Retrieves a thread. | ||
/// </summary> | ||
/// <param name="threadId">The ID of the thread to retrieve.</param> | ||
/// <param name="cancellationToken"></param> | ||
/// <returns>The thread object matching the specified ID.</returns> | ||
public async Task<Thread> RetrieveThreadAsync(string threadId, CancellationToken cancellationToken = default) | ||
{ | ||
var response = await Api.Client.GetAsync(GetUrl($"/{threadId}"), cancellationToken).ConfigureAwait(false); | ||
var responseAsString = await response.ReadAsStringAsync(EnableDebug, cancellationToken).ConfigureAwait(false); | ||
var thread = JsonSerializer.Deserialize<Thread>(responseAsString, OpenAIClient.JsonSerializationOptions); | ||
|
||
return thread; | ||
} | ||
|
||
/// <summary> | ||
/// Modifies a thread. | ||
/// </summary> | ||
/// <param name="threadId">The ID of the thread to modify. Only the metadata can be modified.</param> | ||
/// <param name="metadata">Set of 16 key-value pairs that can be attached to an object. | ||
/// This can be useful for storing additional information about the object in a structured format. | ||
/// Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long.</param> | ||
/// <param name="cancellationToken"></param> | ||
/// <returns>The modified thread object matching the specified ID.</returns> | ||
public async Task<Thread> ModifyThreadAsync(string threadId, Dictionary<string, object> metadata, | ||
CancellationToken cancellationToken = default) | ||
{ | ||
var jsonContent = JsonSerializer.Serialize(new { metadata = metadata }, OpenAIClient.JsonSerializationOptions) | ||
.ToJsonStringContent(EnableDebug); | ||
var response = await Api.Client.PostAsync(GetUrl($"/{threadId}"), jsonContent, cancellationToken) | ||
.ConfigureAwait(false); | ||
var responseAsString = await response.ReadAsStringAsync(EnableDebug, cancellationToken).ConfigureAwait(false); | ||
var thread = JsonSerializer.Deserialize<Thread>(responseAsString, OpenAIClient.JsonSerializationOptions); | ||
|
||
return thread; | ||
} | ||
|
||
/// <summary> | ||
/// Delete a thread. | ||
/// </summary> | ||
/// <param name="threadId">The ID of the thread to delete.</param> | ||
/// <param name="cancellationToken"></param> | ||
/// <returns>True, if was successfully deleted.</returns> | ||
public async Task<bool> DeleteThreadAsync(string threadId, CancellationToken cancellationToken = default) | ||
{ | ||
var response = await Api.Client.DeleteAsync(GetUrl($"/{threadId}"), cancellationToken).ConfigureAwait(false); | ||
var responseAsString = await response.ReadAsStringAsync(EnableDebug, cancellationToken).ConfigureAwait(false); | ||
var status = | ||
JsonSerializer.Deserialize<DeletionStatus>(responseAsString, OpenAIClient.JsonSerializationOptions); | ||
|
||
return status.Deleted; | ||
} | ||
|
||
private sealed class DeletionStatus | ||
{ | ||
[JsonInclude] | ||
[JsonPropertyName("id")] | ||
public string Id { get; private set; } | ||
|
||
[JsonInclude] | ||
[JsonPropertyName("object")] | ||
public string Object { get; private set; } | ||
|
||
[JsonInclude] | ||
[JsonPropertyName("deleted")] | ||
public bool Deleted { get; private set; } | ||
} | ||
} |