Generated the JSON contracts of providers, the runtime, and services at compile time (#1150)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-03 07:59:30 +01:00
1 parent e954881fda
commit 24e3c22db3
140 files changed
+1415 -292

No files matched your search

@@ -2,5 +2,5 @@
public sealed record GoogleEmbedding
{
public List<float>? Values { get; init; }
public List<float>? Values { get; set; }
}
@@ -0,0 +1,7 @@
namespace AIStudio.Provider.Google;
/// <summary>
/// The content of a request for an embedding to the Gemini API.
/// </summary>
/// <param name="Parts">The texts, each of them as a part of its own.</param>
public sealed record GoogleEmbeddingContent(IList<GoogleEmbeddingPart> Parts);
@@ -0,0 +1,7 @@
namespace AIStudio.Provider.Google;
/// <summary>
/// One text in a request for an embedding to the Gemini API.
/// </summary>
/// <param name="Text">The text to embed.</param>
public sealed record GoogleEmbeddingPart(string Text);
@@ -0,0 +1,22 @@
namespace AIStudio.Provider.Google;
/// <summary>
/// A request for an embedding to the Gemini API.
/// </summary>
/// <param name="Content">The texts to embed.</param>
public sealed record GoogleEmbeddingRequest(GoogleEmbeddingContent Content)
{
/// <summary>
/// Asks for vectors which tell how similar texts are.
/// </summary>
/// <remarks>
/// Written as task_type, like every other field of our requests. The API reads both its field names in
/// snake case and in camel case.
/// </remarks>
public string TaskType => "SEMANTIC_SIMILARITY";
/// <summary>
/// Creates the request for the given texts, each of them as a part of its own.
/// </summary>
public static GoogleEmbeddingRequest Of(IEnumerable<string> texts) => new(new GoogleEmbeddingContent([..texts.Select(text => new GoogleEmbeddingPart(text))]));
}
@@ -6,9 +6,13 @@ namespace AIStudio.Provider.Google;
public sealed record GoogleEmbeddingResponse
{
[JsonConverter(typeof(GoogleEmbeddingListConverter))]
public List<GoogleEmbedding>? Embedding { get; init; }
public List<GoogleEmbedding>? Embedding { get; set; }
private sealed class GoogleEmbeddingListConverter : JsonConverter<List<GoogleEmbedding>>
/// <remarks>
/// Internal rather than private: the JSON context of the providers has to reach the converter, else it reads
/// the embeddings without it.
/// </remarks>
internal sealed class GoogleEmbeddingListConverter : JsonConverter<List<GoogleEmbedding>>
{
public override List<GoogleEmbedding> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
@@ -92,16 +92,7 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, new Uri("https
}
// Prepare the Google Gemini embedding request:
var payload = new
{
content = new
{
parts = texts.Select(text => new { text }).ToArray()
},
taskType = "SEMANTIC_SIMILARITY"
};
var payload = GoogleEmbeddingRequest.Of(texts);
var embeddingRequest = JsonSerializer.Serialize(payload, JSON_SERIALIZER_OPTIONS);
var embedUrl = $"https://generativelanguage.googleapis.com/v1beta/models/{modelName}:embedContent";
using var request = new HttpRequestMessage(HttpMethod.Post, embedUrl);