mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-03 22:47:21 +00:00
Generated the JSON contracts of the model answers and the Assistant Builder at compile time
This commit is contained in:
21 files changed
+150
-18
No files matched your search
@@ -19,10 +19,11 @@ public abstract class AgentBase(ILogger<AgentBase> logger, SettingsManager setti
|
||||
Time = DateTimeOffset.UtcNow,
|
||||
};
|
||||
|
||||
internal static readonly JsonSerializerOptions JSON_SERIALIZER_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_SERIALIZER_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
};
|
||||
TypeInfoResolver = AgentJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
protected DataSourceService DataSourceService { get; init; } = dataSourceService;
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using AIStudio.Agents.AssistantAudit;
|
||||
|
||||
namespace AIStudio.Agents;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads the answers of the agents, built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(List<SelectedDataSource>))]
|
||||
[JsonSerializable(typeof(RetrievalContextValidationResult))]
|
||||
[JsonSerializable(typeof(AssistantAuditResult))]
|
||||
internal sealed partial class AgentJsonContext : JsonSerializerContext;
|
||||
@@ -14,13 +14,14 @@ internal sealed class LauncherTextsResponse
|
||||
{
|
||||
public const string SCHEMA_VERSION_VALUE = "assistant_builder_launcher_texts_v1";
|
||||
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
AllowTrailingCommas = false,
|
||||
ReadCommentHandling = JsonCommentHandling.Disallow,
|
||||
MaxDepth = 8,
|
||||
};
|
||||
TypeInfoResolver = LauncherTextsResponseJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
public string SchemaVersion { get; set; } = string.Empty;
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.Builder;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads the answer of a model which names a direct chat launcher, built
|
||||
/// at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(LauncherTextsResponse))]
|
||||
internal sealed partial class LauncherTextsResponseJsonContext : JsonSerializerContext;
|
||||
@@ -4,13 +4,14 @@ namespace AIStudio.Assistants.Builder;
|
||||
|
||||
internal sealed partial class LuaResponse
|
||||
{
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
AllowTrailingCommas = false,
|
||||
ReadCommentHandling = JsonCommentHandling.Disallow,
|
||||
MaxDepth = 32,
|
||||
};
|
||||
TypeInfoResolver = LuaResponseJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
public static bool TryParse(string modelResponse, out LuaResponse response, out LuaResponseParseError error, out string technicalDetails)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.Builder;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads the answer of a model which writes an assistant plugin, built at
|
||||
/// compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(LuaResponse))]
|
||||
internal sealed partial class LuaResponseJsonContext : JsonSerializerContext;
|
||||
@@ -13,13 +13,14 @@ namespace AIStudio.Assistants.ERI;
|
||||
/// </remarks>
|
||||
internal sealed class ERIServerFileList
|
||||
{
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
AllowTrailingCommas = false,
|
||||
ReadCommentHandling = JsonCommentHandling.Disallow,
|
||||
MaxDepth = 8,
|
||||
};
|
||||
TypeInfoResolver = ERIServerFileListJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// The paths of the files, relative to the base directory.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.ERI;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads the files a model plans for an ERI server, built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(ERIServerFileList))]
|
||||
internal sealed partial class ERIServerFileListJsonContext : JsonSerializerContext;
|
||||
@@ -17,10 +17,11 @@ namespace AIStudio.Assistants.PromptOptimizer;
|
||||
|
||||
public partial class AssistantPromptOptimizer : AssistantBaseCore<SettingsDialogPromptOptimizer>
|
||||
{
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
};
|
||||
TypeInfoResolver = PromptOptimizationJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.PromptOptimizer;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads the answer of the prompt optimizer, built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(PromptOptimizationResult))]
|
||||
internal sealed partial class PromptOptimizationJsonContext : JsonSerializerContext;
|
||||
@@ -16,10 +16,11 @@ namespace AIStudio.Assistants.SWOTAnalysis;
|
||||
internal static class SwotAnalysisModeration
|
||||
{
|
||||
// Internal rather than private, so that a test can check the JSON the moderator gets:
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
};
|
||||
TypeInfoResolver = SwotModerationJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
public static string BuildSystemPrompt(string outputLanguageInstruction) =>
|
||||
$"""
|
||||
|
||||
@@ -8,13 +8,14 @@ namespace AIStudio.Assistants.SWOTAnalysis;
|
||||
/// </summary>
|
||||
internal static class SwotModelAnswer
|
||||
{
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
AllowTrailingCommas = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
RespectNullableAnnotations = true,
|
||||
};
|
||||
TypeInfoResolver = SwotModelAnswerJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// Reads the JSON object of a model answer into the given type, without checking its content.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.SWOTAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads the answers of the models which work on a SWOT analysis, built at
|
||||
/// compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(SwotCategoryAnalysisResult))]
|
||||
[JsonSerializable(typeof(SwotModerationResult))]
|
||||
internal sealed partial class SwotModelAnswerJsonContext : JsonSerializerContext;
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Assistants.SWOTAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json writes the preliminary results the moderator of a SWOT analysis gets,
|
||||
/// built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(Dictionary<string, SwotModerationCategoryInput>))]
|
||||
internal sealed partial class SwotModerationJsonContext : JsonSerializerContext;
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Tools.PowerPoint;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json reads the slides a model plans, built at compile time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(SlideDeckSpec.DeckDto))]
|
||||
internal sealed partial class SlideDeckJsonContext : JsonSerializerContext;
|
||||
@@ -7,7 +7,7 @@ namespace AIStudio.Tools.PowerPoint;
|
||||
|
||||
internal sealed partial record SlideDeckSpec
|
||||
{
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
@@ -15,7 +15,8 @@ internal sealed partial record SlideDeckSpec
|
||||
AllowTrailingCommas = true,
|
||||
ReadCommentHandling = JsonCommentHandling.Skip,
|
||||
MaxDepth = 16,
|
||||
};
|
||||
TypeInfoResolver = SlideDeckJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// The deepest list level a paragraph may have; PowerPoint knows nine, starting at 0.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AIStudio.Tools.Services;
|
||||
|
||||
/// <summary>
|
||||
/// The contracts with which System.Text.Json writes what the Assistant Builder hands to its models, built at compile
|
||||
/// time.
|
||||
/// </summary>
|
||||
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(AssistantBuilderDraftPromptData))]
|
||||
[JsonSerializable(typeof(AssistantBuilderGenerationPromptData))]
|
||||
[JsonSerializable(typeof(AssistantBuilderLauncherPromptData))]
|
||||
[JsonSerializable(typeof(AssistantBuilderRevisionPromptData))]
|
||||
internal sealed partial class AssistantBuilderPromptJsonContext : JsonSerializerContext;
|
||||
@@ -19,11 +19,12 @@ public sealed class AssistantPluginGenerationService(ToolRegistry toolRegistry,
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(AssistantPluginGenerationService).Namespace, nameof(AssistantPluginGenerationService));
|
||||
|
||||
// Internal rather than private, so that a test can check the JSON the models get:
|
||||
internal static readonly JsonSerializerOptions UNTRUSTED_PROMPT_JSON_OPTIONS = new()
|
||||
internal static readonly JsonSerializerOptions UNTRUSTED_PROMPT_JSON_OPTIONS = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
WriteIndented = true,
|
||||
};
|
||||
TypeInfoResolver = AssistantBuilderPromptJsonContext.Default,
|
||||
}.AsReadOnly();
|
||||
|
||||
private const string LUA_RESPONSE_SCHEMA_PATH = "Assistants/Builder/AssistantBuilderLuaResponse.schema.json";
|
||||
private const string DEFAULT_VERSION = "1.0.0";
|
||||
|
||||
@@ -22,6 +22,7 @@ public sealed class JsonContractTests
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.VisualBriefingHashed))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.VisualBriefingAnswers))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ModelAnswers))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ModelPrompts))]
|
||||
public void TheContractsMatchThoseOfReflection(JsonTestRoot root)
|
||||
{
|
||||
var baseline = JsonReflectionBaseline.Of(root.Options);
|
||||
|
||||
@@ -23,6 +23,8 @@ public sealed class JsonCoverageTests
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.VisualBriefingStored))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.VisualBriefingHashed))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.VisualBriefingAnswers))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ModelAnswers))]
|
||||
[TestCaseSource(typeof(JsonTestRoots), nameof(JsonTestRoots.ModelPrompts))]
|
||||
public void EveryContractComesFromSourceGeneration(JsonTestRoot root)
|
||||
{
|
||||
var typesWithoutGeneratedContract = JsonTypeGraph.Collect(root.Type, root.Options)
|
||||
|
||||
@@ -5,6 +5,7 @@ using AIStudio.Assistants.ERI;
|
||||
using AIStudio.Assistants.PromptOptimizer;
|
||||
using AIStudio.Assistants.SWOTAnalysis;
|
||||
using AIStudio.Tools.PowerPoint;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
namespace AIStudio.Tests.Serialization;
|
||||
|
||||
@@ -33,4 +34,20 @@ public static partial class JsonTestRoots
|
||||
yield return Case(new(typeof(ERIServerFileList), ERIServerFileList.JSON_OPTIONS));
|
||||
yield return Case(new(typeof(SlideDeckSpec.DeckDto), SlideDeckSpec.JSON_OPTIONS));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The JSON which the Assistant Builder and the moderation of a SWOT analysis put into their prompts.
|
||||
/// </summary>
|
||||
public static IEnumerable<TestCaseData> ModelPrompts()
|
||||
{
|
||||
TestHost.PrepareStaticState();
|
||||
|
||||
var untrusted = AssistantPluginGenerationService.UNTRUSTED_PROMPT_JSON_OPTIONS;
|
||||
yield return Case(new(typeof(AssistantBuilderDraftPromptData), untrusted));
|
||||
yield return Case(new(typeof(AssistantBuilderGenerationPromptData), untrusted));
|
||||
yield return Case(new(typeof(AssistantBuilderLauncherPromptData), untrusted));
|
||||
yield return Case(new(typeof(AssistantBuilderRevisionPromptData), untrusted));
|
||||
|
||||
yield return Case(new(typeof(Dictionary<string, SwotModerationCategoryInput>), SwotAnalysisModeration.JSON_OPTIONS));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user