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 providers with records
This commit is contained in:
15 files changed
+111
-32
No files matched your search
@@ -152,9 +152,9 @@ public sealed class AnthropicMessageStreamAccumulator
|
||||
this.unparsableToolArguments[builder.ToolUseId] = builder.UnparsableToolArguments;
|
||||
}
|
||||
|
||||
private static JsonElement EmptyTextBlock() => JsonSerializer.SerializeToElement(new
|
||||
private static JsonElement EmptyTextBlock()
|
||||
{
|
||||
type = "text",
|
||||
text = string.Empty,
|
||||
});
|
||||
using var document = JsonDocument.Parse("""{"type":"text","text":""}""");
|
||||
return document.RootElement.Clone();
|
||||
}
|
||||
}
|
||||
@@ -1377,7 +1377,7 @@ public abstract class BaseProvider : IProvider, ISecretId
|
||||
if (runnableTools.Count > 0)
|
||||
{
|
||||
var adapter = new ChatCompletionToolCallingAdapter<TRequest>(requestFactory, systemPrompt, apiParameters,
|
||||
runnableTools.Select(x => ProviderToolAdapters.ToChatCompletionTool(x.Definition, enforcesStrictToolSchemas)).ToList(), mayAskForSequentialToolCalls, runnableTools,
|
||||
runnableTools.Select(x => (object)ProviderToolAdapters.ToChatCompletionTool(x.Definition, enforcesStrictToolSchemas)).ToList(), mayAskForSequentialToolCalls, runnableTools,
|
||||
(requestDto, requestToken) => this.StreamChatCompletionRequest(requestDto, providerName, requestPath, requestedSecret, requestHeadersAction, requestToken),
|
||||
ChatCompletionSourceReader.Read<TDelta, TAnnotation>,
|
||||
this.logger);
|
||||
@@ -1662,13 +1662,7 @@ public abstract class BaseProvider : IProvider, ISecretId
|
||||
modelName = "placeholder";
|
||||
|
||||
// Prepare the HTTP embedding request:
|
||||
var payload = new
|
||||
{
|
||||
model = modelName,
|
||||
input = texts,
|
||||
encoding_format = "float"
|
||||
};
|
||||
|
||||
var payload = new EmbeddingRequest(modelName, texts);
|
||||
var embeddingRequest = JsonSerializer.Serialize(payload, JSON_SERIALIZER_OPTIONS);
|
||||
using var request = new HttpRequestMessage(HttpMethod.Post, host.EmbeddingURL());
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace AIStudio.Provider;
|
||||
|
||||
/// <summary>
|
||||
/// A request for embeddings, in the shape of the OpenAI API, which most providers take.
|
||||
/// </summary>
|
||||
/// <param name="Model">The name of the embedding model.</param>
|
||||
/// <param name="Input">The texts to embed.</param>
|
||||
public sealed record EmbeddingRequest(string Model, IList<string> Input)
|
||||
{
|
||||
/// <summary>
|
||||
/// Asks for the vectors as numbers, instead of as base64.
|
||||
/// </summary>
|
||||
public string EncodingFormat => "float";
|
||||
}
|
||||
@@ -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))]));
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace AIStudio.Provider.OpenAI;
|
||||
|
||||
/// <summary>
|
||||
/// The function a tool of a Chat Completions compatible API offers to the model.
|
||||
/// </summary>
|
||||
public sealed record ChatCompletionFunctionDeclaration
|
||||
{
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
public string Description { get; init; } = string.Empty;
|
||||
|
||||
public JsonElement Parameters { get; init; }
|
||||
|
||||
public bool Strict { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace AIStudio.Provider.OpenAI;
|
||||
|
||||
/// <summary>
|
||||
/// The function tool definition shape expected by Chat Completions compatible APIs, with the function nested.
|
||||
/// </summary>
|
||||
public sealed record ChatCompletionFunctionTool
|
||||
{
|
||||
public string Type { get; init; } = "function";
|
||||
|
||||
public ChatCompletionFunctionDeclaration Function { get; init; } = new();
|
||||
}
|
||||
@@ -24,19 +24,18 @@ public static class ProviderToolAdapters
|
||||
/// </summary>
|
||||
/// <param name="definition">The tool to describe.</param>
|
||||
/// <param name="hostEnforcesStrict">Whether the host binds the model's tool calls to a strict schema. Only then is the tool sent in strict mode.</param>
|
||||
public static object ToChatCompletionTool(ToolDefinition definition, bool hostEnforcesStrict)
|
||||
public static ChatCompletionFunctionTool ToChatCompletionTool(ToolDefinition definition, bool hostEnforcesStrict)
|
||||
{
|
||||
var isStrict = definition.Function.Strict && hostEnforcesStrict;
|
||||
return new
|
||||
return new()
|
||||
{
|
||||
type = "function",
|
||||
function = new
|
||||
Function = new()
|
||||
{
|
||||
name = definition.Function.Name,
|
||||
description = definition.Function.DescriptionForLLM,
|
||||
parameters = ToOpenAIParameters(definition, isStrict),
|
||||
strict = isStrict,
|
||||
}
|
||||
Name = definition.Function.Name,
|
||||
Description = definition.Function.DescriptionForLLM,
|
||||
Parameters = ToOpenAIParameters(definition, isStrict),
|
||||
Strict = isStrict,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"model":"embedding-model","input":["The first text.","The second text."],"encoding_format":"float"}
|
||||
@@ -0,0 +1 @@
|
||||
{"content":{"parts":[{"text":"The first text."},{"text":"The second text."}]},"task_type":"SEMANTIC_SIMILARITY"}
|
||||
@@ -22,6 +22,8 @@ public sealed class JsonGoldenRequestTests
|
||||
yield return new("chat-completion-request.json", JsonSampleRequests.ChatCompletion, ProviderJsonOptions.OPTIONS);
|
||||
yield return new("responses-request.json", JsonSampleRequests.Responses, ProviderJsonOptions.OPTIONS);
|
||||
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);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GoldenRequests))]
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Text.Json;
|
||||
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Provider.Anthropic;
|
||||
using AIStudio.Provider.Google;
|
||||
using AIStudio.Provider.OpenAI;
|
||||
using AIStudio.Tools.ToolCallingSystem;
|
||||
|
||||
@@ -91,6 +92,16 @@ public static class JsonSampleRequests
|
||||
AdditionalApiParameters = ApiParameters(),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A request for embeddings in the shape of the OpenAI API.
|
||||
/// </summary>
|
||||
public static EmbeddingRequest Embedding() => new("embedding-model", ["The first text.", "The second text."]);
|
||||
|
||||
/// <summary>
|
||||
/// A request for an embedding to the Gemini API.
|
||||
/// </summary>
|
||||
public static GoogleEmbeddingRequest GoogleEmbedding() => GoogleEmbeddingRequest.Of(["The first text.", "The second text."]);
|
||||
|
||||
private static List<IMessageBase> Messages() =>
|
||||
[
|
||||
new TextMessage("You answer briefly.", "system"),
|
||||
|
||||
@@ -28,6 +28,8 @@ public static partial class JsonTestRoots
|
||||
yield return CaseWithNamespace(typeof(ChatCompletionAPIRequest), options);
|
||||
yield return CaseWithNamespace(typeof(ResponsesAPIRequest), options);
|
||||
yield return CaseWithNamespace(typeof(ChatRequest), options);
|
||||
yield return CaseWithNamespace(typeof(EmbeddingRequest), options);
|
||||
yield return CaseWithNamespace(typeof(GoogleEmbeddingRequest), options);
|
||||
|
||||
//
|
||||
// The messages and their parts, which converters write as the type they are of:
|
||||
@@ -43,7 +45,7 @@ public static partial class JsonTestRoots
|
||||
foreach (var type in new[] { typeof(string), typeof(int), typeof(long), typeof(double), typeof(decimal), typeof(bool), typeof(Dictionary<string, object>), typeof(List<object>), typeof(JsonElement) })
|
||||
yield return Case(new(type, options), "value of a request");
|
||||
|
||||
yield return Case(new(ProviderToolAdapters.ToChatCompletionTool(JsonSampleRequests.Tool(), hostEnforcesStrict: true).GetType(), options), "tool of a Chat Completions API");
|
||||
yield return CaseWithNamespace(typeof(ChatCompletionFunctionTool), options);
|
||||
yield return CaseWithNamespace(typeof(ResponsesFunctionTool), options);
|
||||
yield return CaseWithNamespace(typeof(ResponsesFunctionCallOutputItem), options);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user