Fixed type design for JSON serialization & deserialization

This commit is contained in:
Thorsten Sommer 2024-07-10 19:26:59 +02:00
parent bc56b2d9b0
commit d0858a1707
Signed by: tsommer
GPG Key ID: 371BBA77A02C0108
5 changed files with 41 additions and 17 deletions

View File

@ -3,29 +3,35 @@ namespace AIStudio.Chat;
/// <summary> /// <summary>
/// Data structure for a chat thread. /// Data structure for a chat thread.
/// </summary> /// </summary>
/// <param name="name">The name of the chat thread.</param> public sealed class ChatThread
/// <param name="seed">The seed for the chat thread. Some providers use this to generate deterministic results.</param>
/// <param name="systemPrompt">The system prompt for the chat thread.</param>
/// <param name="blocks">The content blocks of the chat thread.</param>
public sealed class ChatThread(string name, int seed, string systemPrompt, IEnumerable<ContentBlock> blocks)
{ {
/// <summary>
/// The unique identifier of the chat thread.
/// </summary>
public Guid ChatId { get; init; }
/// <summary>
/// The unique identifier of the workspace.
/// </summary>
public Guid WorkspaceId { get; set; }
/// <summary> /// <summary>
/// The name of the chat thread. Usually generated by an AI model or manually edited by the user. /// The name of the chat thread. Usually generated by an AI model or manually edited by the user.
/// </summary> /// </summary>
public string Name { get; set; } = name; public string Name { get; init; } = string.Empty;
/// <summary> /// <summary>
/// The seed for the chat thread. Some providers use this to generate deterministic results. /// The seed for the chat thread. Some providers use this to generate deterministic results.
/// </summary> /// </summary>
public int Seed { get; set; } = seed; public int Seed { get; init; }
/// <summary> /// <summary>
/// The current system prompt for the chat thread. /// The current system prompt for the chat thread.
/// </summary> /// </summary>
public string SystemPrompt { get; set; } = systemPrompt; public string SystemPrompt { get; init; } = string.Empty;
/// <summary> /// <summary>
/// The content blocks of the chat thread. /// The content blocks of the chat thread.
/// </summary> /// </summary>
public List<ContentBlock> Blocks { get; init; } = blocks.ToList(); public List<ContentBlock> Blocks { get; init; } = [];
} }

View File

@ -3,25 +3,22 @@ namespace AIStudio.Chat;
/// <summary> /// <summary>
/// A block of content in a chat thread. Might be any type of content, e.g., text, image, voice, etc. /// A block of content in a chat thread. Might be any type of content, e.g., text, image, voice, etc.
/// </summary> /// </summary>
/// <param name="time">Time when the content block was created.</param> public class ContentBlock
/// <param name="type">Type of the content block, e.g., text, image, voice, etc.</param>
/// <param name="content">The content of the block.</param>
public class ContentBlock(DateTimeOffset time, ContentType type, IContent content)
{ {
/// <summary> /// <summary>
/// Time when the content block was created. /// Time when the content block was created.
/// </summary> /// </summary>
public DateTimeOffset Time => time; public DateTimeOffset Time { get; init; }
/// <summary> /// <summary>
/// Type of the content block, e.g., text, image, voice, etc. /// Type of the content block, e.g., text, image, voice, etc.
/// </summary> /// </summary>
public ContentType ContentType => type; public ContentType ContentType { get; init; } = ContentType.NONE;
/// <summary> /// <summary>
/// The content of the block. /// The content of the block.
/// </summary> /// </summary>
public IContent Content => content; public IContent? Content { get; init; } = null;
/// <summary> /// <summary>
/// The role of the content block in the chat thread, e.g., user, AI, etc. /// The role of the content block in the chat thread, e.g., user, AI, etc.

View File

@ -1,3 +1,5 @@
using System.Text.Json.Serialization;
using AIStudio.Provider; using AIStudio.Provider;
using AIStudio.Settings; using AIStudio.Settings;
@ -11,15 +13,19 @@ public sealed class ContentImage : IContent
#region Implementation of IContent #region Implementation of IContent
/// <inheritdoc /> /// <inheritdoc />
[JsonIgnore]
public bool InitialRemoteWait { get; set; } = false; public bool InitialRemoteWait { get; set; } = false;
/// <inheritdoc /> /// <inheritdoc />
[JsonIgnore]
public bool IsStreaming { get; set; } = false; public bool IsStreaming { get; set; } = false;
/// <inheritdoc /> /// <inheritdoc />
[JsonIgnore]
public Func<Task> StreamingDone { get; set; } = () => Task.CompletedTask; public Func<Task> StreamingDone { get; set; } = () => Task.CompletedTask;
/// <inheritdoc /> /// <inheritdoc />
[JsonIgnore]
public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask; public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask;
/// <inheritdoc /> /// <inheritdoc />

View File

@ -1,3 +1,5 @@
using System.Text.Json.Serialization;
using AIStudio.Provider; using AIStudio.Provider;
using AIStudio.Settings; using AIStudio.Settings;
@ -17,14 +19,19 @@ public sealed class ContentText : IContent
#region Implementation of IContent #region Implementation of IContent
/// <inheritdoc /> /// <inheritdoc />
[JsonIgnore]
public bool InitialRemoteWait { get; set; } public bool InitialRemoteWait { get; set; }
/// <inheritdoc /> /// <inheritdoc />
// [JsonIgnore]
public bool IsStreaming { get; set; } public bool IsStreaming { get; set; }
/// <inheritdoc /> /// <inheritdoc />
[JsonIgnore]
public Func<Task> StreamingDone { get; set; } = () => Task.CompletedTask; public Func<Task> StreamingDone { get; set; } = () => Task.CompletedTask;
/// <inheritdoc />
[JsonIgnore]
public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask; public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask;
/// <inheritdoc /> /// <inheritdoc />

View File

@ -1,3 +1,5 @@
using System.Text.Json.Serialization;
using AIStudio.Provider; using AIStudio.Provider;
using AIStudio.Settings; using AIStudio.Settings;
@ -6,6 +8,8 @@ namespace AIStudio.Chat;
/// <summary> /// <summary>
/// The interface for any content in the chat. /// The interface for any content in the chat.
/// </summary> /// </summary>
[JsonDerivedType(typeof(ContentText), typeDiscriminator: "text")]
[JsonDerivedType(typeof(ContentImage), typeDiscriminator: "image")]
public interface IContent public interface IContent
{ {
/// <summary> /// <summary>
@ -13,22 +17,26 @@ public interface IContent
/// Does not indicate that the stream is finished; it only indicates that we are /// Does not indicate that the stream is finished; it only indicates that we are
/// waiting for the first response, i.e., wait for the remote to pick up the request. /// waiting for the first response, i.e., wait for the remote to pick up the request.
/// </summary> /// </summary>
[JsonIgnore]
public bool InitialRemoteWait { get; set; } public bool InitialRemoteWait { get; set; }
/// <summary> /// <summary>
/// Indicates whether the content is streaming right now. False, if the content is /// Indicates whether the content is streaming right now. False, if the content is
/// either static or the stream has finished. /// either static or the stream has finished.
/// </summary> /// </summary>
[JsonIgnore]
public bool IsStreaming { get; set; } public bool IsStreaming { get; set; }
/// <summary> /// <summary>
/// An action that is called when the content was changed during streaming. /// An action that is called when the content was changed during streaming.
/// </summary> /// </summary>
[JsonIgnore]
public Func<Task> StreamingEvent { get; set; } public Func<Task> StreamingEvent { get; set; }
/// <summary> /// <summary>
/// An action that is called when the streaming is done. /// An action that is called when the streaming is done.
/// </summary> /// </summary>
[JsonIgnore]
public Func<Task> StreamingDone { get; set; } public Func<Task> StreamingDone { get; set; }
/// <summary> /// <summary>