mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-11-03 23:47:21 +00:00
Replaced the anonymous request shapes of the runtime calls with records
This commit is contained in:
16 files changed
+65
-19
No files matched your search
@@ -0,0 +1,6 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>Request body used to count the tokens of a text in the Rust runtime.</summary>
|
||||
/// <param name="Text">The text to count.</param>
|
||||
/// <param name="TokenizerPath">Path of the tokenizer file to count with.</param>
|
||||
public sealed record CountTokensRequest(string Text, string TokenizerPath);
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>Request body used to delete the stored tokenizer of a model in the Rust runtime.</summary>
|
||||
/// <param name="ModelId">The model whose tokenizer gets deleted.</param>
|
||||
public sealed record DeleteTokenizerRequest(string ModelId);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>Request body used to prepare a local image for a model in the Rust runtime.</summary>
|
||||
/// <param name="Path">Absolute path of the image.</param>
|
||||
/// <param name="MaxBytes">The size the prepared image may have at most.</param>
|
||||
public sealed record PrepareImageForModelRequest(string Path, long MaxBytes);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>Request body used to check and optionally optimize a local image in the Rust runtime.</summary>
|
||||
/// <param name="Path">Absolute path of the image.</param>
|
||||
/// <param name="Optimize">Whether the maximum-edge policy and re-encoding are applied.</param>
|
||||
public sealed record PrepareImageRequest(string Path, bool Optimize);
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>Request body used to store a copy of a tokenizer file for a model in the Rust runtime.</summary>
|
||||
/// <param name="ModelId">The model the tokenizer belongs to.</param>
|
||||
/// <param name="FilePath">Absolute path of the tokenizer file.</param>
|
||||
public sealed record StoreTokenizerRequest(string ModelId, string FilePath);
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>Request body used to check a tokenizer file in the Rust runtime.</summary>
|
||||
/// <param name="FilePath">Absolute path of the tokenizer file.</param>
|
||||
public sealed record ValidateTokenizerRequest(string FilePath);
|
||||
@@ -20,7 +20,7 @@ public sealed partial class RustService
|
||||
bool optimize,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var response = await this.http.PostAsJsonAsync("/image/prepare", new { path, optimize }, JSON_OPTIONS, token);
|
||||
using var response = await this.http.PostAsJsonAsync("/image/prepare", new PrepareImageRequest(path, optimize), JSON_OPTIONS, token);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await response.Content.ReadFromJsonAsync<ImagePrepareResponse>(JSON_OPTIONS, token)
|
||||
@@ -44,7 +44,7 @@ public sealed partial class RustService
|
||||
{
|
||||
try
|
||||
{
|
||||
using var response = await this.http.PostAsJsonAsync("/image/prepare-for-model", new { path, maxBytes }, JSON_OPTIONS, token);
|
||||
using var response = await this.http.PostAsJsonAsync("/image/prepare-for-model", new PrepareImageForModelRequest(path, maxBytes), JSON_OPTIONS, token);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return await response.Content.ReadFromJsonAsync<PreparedModelImage>(JSON_OPTIONS, token)
|
||||
|
||||
@@ -15,9 +15,7 @@ public sealed partial class RustService : ITokenizerStorage
|
||||
|
||||
public async Task<TokenizerResponse> ValidateTokenizer(string filePath)
|
||||
{
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/validate", new {
|
||||
file_path = filePath,
|
||||
}, JSON_OPTIONS);
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/validate", new ValidateTokenizerRequest(filePath), JSON_OPTIONS);
|
||||
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
@@ -33,10 +31,7 @@ public sealed partial class RustService : ITokenizerStorage
|
||||
public async Task<TokenizerResponse> StoreTokenizer(string modelId, string filePath)
|
||||
{
|
||||
this.logger!.LogInformation($"Storing tokenizer for model '{modelId}' from file '{filePath}'");
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/store", new {
|
||||
model_id = modelId,
|
||||
file_path = filePath,
|
||||
}, JSON_OPTIONS);
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/store", new StoreTokenizerRequest(modelId, filePath), JSON_OPTIONS);
|
||||
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
@@ -50,9 +45,7 @@ public sealed partial class RustService : ITokenizerStorage
|
||||
public async Task<TokenizerResponse> DeleteTokenizer(string modelId)
|
||||
{
|
||||
this.logger!.LogInformation($"Deleting tokenizer for model '{modelId}'");
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/delete", new {
|
||||
model_id = modelId,
|
||||
}, JSON_OPTIONS);
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/delete", new DeleteTokenizerRequest(modelId), JSON_OPTIONS);
|
||||
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
@@ -71,10 +64,7 @@ public sealed partial class RustService : ITokenizerStorage
|
||||
|
||||
private async Task<TokenizerResponse?> GetTokenCount(string providerName, string tokenizerPath, string text, CancellationToken cancellationToken)
|
||||
{
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/count", new {
|
||||
text,
|
||||
tokenizer_path = tokenizerPath,
|
||||
}, JSON_OPTIONS, cancellationToken);
|
||||
var result = await this.http.PostAsJsonAsync("/tokenizer/count", new CountTokensRequest(text, tokenizerPath), JSON_OPTIONS, cancellationToken);
|
||||
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"text":"Count these tokens.","tokenizer_path":"/samples/tokenizer.json"}
|
||||
@@ -0,0 +1 @@
|
||||
{"model_id":"model-a"}
|
||||
@@ -0,0 +1 @@
|
||||
{"path":"/samples/picture.png","max_bytes":5242880}
|
||||
@@ -0,0 +1 @@
|
||||
{"path":"/samples/picture.png","optimize":true}
|
||||
@@ -0,0 +1 @@
|
||||
{"model_id":"model-a","file_path":"/samples/tokenizer.json"}
|
||||
@@ -0,0 +1 @@
|
||||
{"file_path":"/samples/tokenizer.json"}
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.Text.Json;
|
||||
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Tools.Rust;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
namespace AIStudio.Tests.Serialization;
|
||||
|
||||
@@ -9,9 +11,9 @@ namespace AIStudio.Tests.Serialization;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The files in the folder Fixtures were written with the contracts of reflection, before AI Studio got
|
||||
/// contracts of its own. A provider reads every byte of a request, and one which got written otherwise, e.g.,
|
||||
/// with a field under another name or without the tools, gets refused or misread. The requests are made up,
|
||||
/// see <see cref="JsonSampleRequests"/>.
|
||||
/// contracts of its own. A provider or the runtime reads every byte of a request, and one which got written
|
||||
/// otherwise, e.g., with a field under another name or without the tools, gets refused or misread. The requests
|
||||
/// are made up, see <see cref="JsonSampleRequests"/>.
|
||||
/// </remarks>
|
||||
[TestFixture]
|
||||
public sealed class JsonGoldenRequestTests
|
||||
@@ -24,6 +26,14 @@ public sealed class JsonGoldenRequestTests
|
||||
yield return new("anthropic-messages-request.json", () => JsonSampleRequests.Anthropic(), ProviderJsonOptions.OPTIONS);
|
||||
yield return new("embedding-request.json", JsonSampleRequests.Embedding, ProviderJsonOptions.OPTIONS);
|
||||
yield return new("google-embedding-request.json", JsonSampleRequests.GoogleEmbedding, ProviderJsonOptions.OPTIONS);
|
||||
|
||||
// The requests to the runtime which were anonymous types once:
|
||||
yield return new("runtime-validate-tokenizer-request.json", () => new ValidateTokenizerRequest("/samples/tokenizer.json"), RustService.JSON_OPTIONS);
|
||||
yield return new("runtime-store-tokenizer-request.json", () => new StoreTokenizerRequest("model-a", "/samples/tokenizer.json"), RustService.JSON_OPTIONS);
|
||||
yield return new("runtime-delete-tokenizer-request.json", () => new DeleteTokenizerRequest("model-a"), RustService.JSON_OPTIONS);
|
||||
yield return new("runtime-count-tokens-request.json", () => new CountTokensRequest("Count these tokens.", "/samples/tokenizer.json"), RustService.JSON_OPTIONS);
|
||||
yield return new("runtime-prepare-image-request.json", () => new PrepareImageRequest("/samples/picture.png", true), RustService.JSON_OPTIONS);
|
||||
yield return new("runtime-prepare-image-for-model-request.json", () => new PrepareImageForModelRequest("/samples/picture.png", 5_242_880), RustService.JSON_OPTIONS);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GoldenRequests))]
|
||||
|
||||
@@ -31,6 +31,12 @@ public static partial class JsonTestRoots
|
||||
yield return Case(new(typeof(SetInterfaceSizeRequest), options));
|
||||
yield return Case(new(typeof(CreateMediaJobRequest), options));
|
||||
yield return Case(new(typeof(LogEventRequest), options));
|
||||
yield return Case(new(typeof(ValidateTokenizerRequest), options));
|
||||
yield return Case(new(typeof(StoreTokenizerRequest), options));
|
||||
yield return Case(new(typeof(DeleteTokenizerRequest), options));
|
||||
yield return Case(new(typeof(CountTokensRequest), options));
|
||||
yield return Case(new(typeof(PrepareImageRequest), options));
|
||||
yield return Case(new(typeof(PrepareImageForModelRequest), options));
|
||||
|
||||
// Every request of the vector store:
|
||||
foreach (var type in typeof(QdrantEdgeClientImplementation).GetNestedTypes(BindingFlags.NonPublic).Where(type => type.Name.EndsWith("Request", StringComparison.Ordinal)).OrderBy(type => type.Name, StringComparer.Ordinal))
|
||||
|
||||
Reference in new issue
Block a user