mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-05-21 11:12:17 +00:00
First version of the refactoring of ChatRequests
This commit is contained in:
parent
075e078fde
commit
42f4f46523
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -24,52 +22,30 @@ public sealed class ProviderAlibabaCloud() : BaseProvider(LLMProviders.ALIBABA_C
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"AlibabaCloud",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
// Prepare the system prompt:
|
async (systemPrompt, apiParameters) =>
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
// Build the list of messages:
|
||||||
Role = "system",
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the AlibabaCloud HTTP chat request:
|
|
||||||
var alibabaCloudChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
return new ChatCompletionAPIRequest
|
||||||
{
|
{
|
||||||
// Build the HTTP post request:
|
Model = chatModel.Id,
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Build the messages:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the content:
|
Stream = true,
|
||||||
request.Content = new StringContent(alibabaCloudChatRequest, Encoding.UTF8, "application/json");
|
AdditionalApiParameters = apiParameters
|
||||||
return request;
|
};
|
||||||
}
|
},
|
||||||
|
token: token))
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>("AlibabaCloud", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,4 +159,4 @@ public sealed class ProviderAlibabaCloud() : BaseProvider(LLMProviders.ALIBABA_C
|
|||||||
return modelResponse.Data.Where(model => prefixes.Any(prefix => model.Id.StartsWith(prefix, StringComparison.InvariantCulture)));
|
return modelResponse.Data.Where(model => prefixes.Any(prefix => model.Id.StartsWith(prefix, StringComparison.InvariantCulture)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -565,6 +565,78 @@ public abstract class BaseProvider : IProvider, ISecretId
|
|||||||
streamReader.Dispose();
|
streamReader.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Streams the chat completion from an OpenAI-compatible provider using the Chat Completion API.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="providerName">The provider name for logging and error reporting.</param>
|
||||||
|
/// <param name="chatModel">The selected chat model.</param>
|
||||||
|
/// <param name="chatThread">The current chat thread.</param>
|
||||||
|
/// <param name="settingsManager">The settings manager.</param>
|
||||||
|
/// <param name="requestFactory">Builds the provider-specific request body.</param>
|
||||||
|
/// <param name="storeType">The secret store type.</param>
|
||||||
|
/// <param name="isTryingSecret">Whether the API key is optional.</param>
|
||||||
|
/// <param name="systemPromptRole">The system prompt role to use.</param>
|
||||||
|
/// <param name="requestPath">The request path, relative to the provider base URL.</param>
|
||||||
|
/// <param name="headersAction">Optional additional headers to add.</param>
|
||||||
|
/// <param name="token">The cancellation token.</param>
|
||||||
|
/// <typeparam name="TRequest">The request DTO type.</typeparam>
|
||||||
|
/// <typeparam name="TDelta">The delta stream line type.</typeparam>
|
||||||
|
/// <typeparam name="TAnnotation">The annotation stream line type.</typeparam>
|
||||||
|
/// <returns>The streamed content chunks.</returns>
|
||||||
|
protected async IAsyncEnumerable<ContentStreamChunk> StreamOpenAICompatibleChatCompletion<TRequest, TDelta, TAnnotation>(
|
||||||
|
string providerName,
|
||||||
|
Model chatModel,
|
||||||
|
ChatThread chatThread,
|
||||||
|
SettingsManager settingsManager,
|
||||||
|
Func<TextMessage, IDictionary<string, object>, Task<TRequest>> requestFactory,
|
||||||
|
SecretStoreType storeType = SecretStoreType.LLM_PROVIDER,
|
||||||
|
bool isTryingSecret = false,
|
||||||
|
string systemPromptRole = "system",
|
||||||
|
string requestPath = "chat/completions",
|
||||||
|
Action<HttpRequestHeaders>? headersAction = null,
|
||||||
|
[EnumeratorCancellation] CancellationToken token = default)
|
||||||
|
where TDelta : IResponseStreamLine
|
||||||
|
where TAnnotation : IAnnotationStreamLine
|
||||||
|
{
|
||||||
|
// Get the API key:
|
||||||
|
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, storeType, isTrying: isTryingSecret);
|
||||||
|
if(!requestedSecret.Success && !isTryingSecret)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
// Prepare the system prompt:
|
||||||
|
var systemPrompt = new TextMessage
|
||||||
|
{
|
||||||
|
Role = systemPromptRole,
|
||||||
|
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse the API parameters:
|
||||||
|
var apiParameters = this.ParseAdditionalApiParameters();
|
||||||
|
|
||||||
|
// Prepare the provider HTTP chat request:
|
||||||
|
var providerChatRequest = JsonSerializer.Serialize(await requestFactory(systemPrompt, apiParameters), JSON_SERIALIZER_OPTIONS);
|
||||||
|
|
||||||
|
async Task<HttpRequestMessage> RequestBuilder()
|
||||||
|
{
|
||||||
|
// Build the HTTP post request:
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Post, requestPath);
|
||||||
|
|
||||||
|
// Set the authorization header:
|
||||||
|
if (requestedSecret.Success)
|
||||||
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
||||||
|
|
||||||
|
// Set provider-specific headers:
|
||||||
|
headersAction?.Invoke(request.Headers);
|
||||||
|
|
||||||
|
// Set the content:
|
||||||
|
request.Content = new StringContent(providerChatRequest, Encoding.UTF8, "application/json");
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
await foreach (var content in this.StreamChatCompletionInternal<TDelta, TAnnotation>(providerName, RequestBuilder, token))
|
||||||
|
yield return content;
|
||||||
|
}
|
||||||
|
|
||||||
protected async Task<string> PerformStandardTranscriptionRequest(RequestedSecret requestedSecret, Model transcriptionModel, string audioFilePath, Host host = Host.NONE, CancellationToken token = default)
|
protected async Task<string> PerformStandardTranscriptionRequest(RequestedSecret requestedSecret, Model transcriptionModel, string audioFilePath, Host host = Host.NONE, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -24,52 +22,30 @@ public sealed class ProviderDeepSeek() : BaseProvider(LLMProviders.DEEP_SEEK, "h
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"DeepSeek",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
// Prepare the system prompt:
|
async (systemPrompt, apiParameters) =>
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
// Build the list of messages:
|
||||||
Role = "system",
|
var messages = await chatThread.Blocks.BuildMessagesUsingDirectImageUrlAsync(this.Provider, chatModel);
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingDirectImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the DeepSeek HTTP chat request:
|
|
||||||
var deepSeekChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
return new ChatCompletionAPIRequest
|
||||||
{
|
{
|
||||||
// Build the HTTP post request:
|
Model = chatModel.Id,
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Build the messages:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the content:
|
Stream = true,
|
||||||
request.Content = new StringContent(deepSeekChatRequest, Encoding.UTF8, "application/json");
|
AdditionalApiParameters = apiParameters
|
||||||
return request;
|
};
|
||||||
}
|
},
|
||||||
|
token: token))
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>("DeepSeek", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,4 +120,4 @@ public sealed class ProviderDeepSeek() : BaseProvider(LLMProviders.DEEP_SEEK, "h
|
|||||||
var modelResponse = await response.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
var modelResponse = await response.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
||||||
return modelResponse.Data;
|
return modelResponse.Data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace AIStudio.Provider.Fireworks;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The Fireworks chat request model.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Model">Which model to use for chat completion.</param>
|
|
||||||
/// <param name="Messages">The chat messages.</param>
|
|
||||||
/// <param name="Stream">Whether to stream the chat completion.</param>
|
|
||||||
public readonly record struct ChatRequest(
|
|
||||||
string Model,
|
|
||||||
IList<IMessageBase> Messages,
|
|
||||||
bool Stream
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Attention: The "required" modifier is not supported for [JsonExtensionData].
|
|
||||||
[JsonExtensionData]
|
|
||||||
public IDictionary<string, object> AdditionalApiParameters { get; init; } = new Dictionary<string, object>();
|
|
||||||
}
|
|
||||||
@ -1,7 +1,4 @@
|
|||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -24,53 +21,31 @@ public class ProviderFireworks() : BaseProvider(LLMProviders.FIREWORKS, "https:/
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ResponseStreamLine, ChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"Fireworks",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
|
async (systemPrompt, apiParameters) =>
|
||||||
|
{
|
||||||
|
// Build the list of messages:
|
||||||
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
|
|
||||||
// Prepare the system prompt:
|
return new ChatCompletionAPIRequest
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
Model = chatModel.Id,
|
||||||
Role = "system",
|
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the Fireworks HTTP chat request:
|
|
||||||
var fireworksChatRequest = JsonSerializer.Serialize(new ChatRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
// Right now, we only support streaming completions:
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
// Build the messages:
|
||||||
{
|
// - First of all the system prompt
|
||||||
// Build the HTTP post request:
|
// - Then none-empty user and AI messages
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the authorization header:
|
// Right now, we only support streaming completions:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
Stream = true,
|
||||||
|
AdditionalApiParameters = apiParameters
|
||||||
// Set the content:
|
};
|
||||||
request.Content = new StringContent(fireworksChatRequest, Encoding.UTF8, "application/json");
|
},
|
||||||
return request;
|
token: token))
|
||||||
}
|
|
||||||
|
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ResponseStreamLine, ChatCompletionAnnotationStreamLine>("Fireworks", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,4 +101,4 @@ public class ProviderFireworks() : BaseProvider(LLMProviders.FIREWORKS, "https:/
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -24,52 +22,30 @@ public sealed class ProviderGWDG() : BaseProvider(LLMProviders.GWDG, "https://ch
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"GWDG",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
// Prepare the system prompt:
|
async (systemPrompt, apiParameters) =>
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
// Build the list of messages:
|
||||||
Role = "system",
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the GWDG HTTP chat request:
|
|
||||||
var gwdgChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
return new ChatCompletionAPIRequest
|
||||||
{
|
{
|
||||||
// Build the HTTP post request:
|
Model = chatModel.Id,
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Build the messages:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the content:
|
Stream = true,
|
||||||
request.Content = new StringContent(gwdgChatRequest, Encoding.UTF8, "application/json");
|
AdditionalApiParameters = apiParameters
|
||||||
return request;
|
};
|
||||||
}
|
},
|
||||||
|
token: token))
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>("GWDG", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,4 +128,4 @@ public sealed class ProviderGWDG() : BaseProvider(LLMProviders.GWDG, "https://ch
|
|||||||
var modelResponse = await response.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
var modelResponse = await response.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
||||||
return modelResponse.Data;
|
return modelResponse.Data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace AIStudio.Provider.Google;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The Google chat request model.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Model">Which model to use for chat completion.</param>
|
|
||||||
/// <param name="Messages">The chat messages.</param>
|
|
||||||
/// <param name="Stream">Whether to stream the chat completion.</param>
|
|
||||||
public readonly record struct ChatRequest(
|
|
||||||
string Model,
|
|
||||||
IList<IMessageBase> Messages,
|
|
||||||
bool Stream
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Attention: The "required" modifier is not supported for [JsonExtensionData].
|
|
||||||
[JsonExtensionData]
|
|
||||||
public IDictionary<string, object> AdditionalApiParameters { get; init; } = new Dictionary<string, object>();
|
|
||||||
}
|
|
||||||
@ -24,53 +24,31 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, "https://gener
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"Google",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
|
async (systemPrompt, apiParameters) =>
|
||||||
|
{
|
||||||
|
// Build the list of messages:
|
||||||
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
|
|
||||||
// Prepare the system prompt:
|
return new ChatCompletionAPIRequest
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
Model = chatModel.Id,
|
||||||
Role = "system",
|
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the Google HTTP chat request:
|
|
||||||
var geminiChatRequest = JsonSerializer.Serialize(new ChatRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
// Right now, we only support streaming completions:
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
// Build the messages:
|
||||||
{
|
// - First of all the system prompt
|
||||||
// Build the HTTP post request:
|
// - Then none-empty user and AI messages
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the authorization header:
|
// Right now, we only support streaming completions:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
Stream = true,
|
||||||
|
AdditionalApiParameters = apiParameters
|
||||||
// Set the content:
|
};
|
||||||
request.Content = new StringContent(geminiChatRequest, Encoding.UTF8, "application/json");
|
},
|
||||||
return request;
|
token: token))
|
||||||
}
|
|
||||||
|
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>("Google", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,4 +234,4 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, "https://gener
|
|||||||
? modelId["models/".Length..]
|
? modelId["models/".Length..]
|
||||||
: modelId;
|
: modelId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,10 +13,11 @@ public readonly record struct ChatRequest(
|
|||||||
string Model,
|
string Model,
|
||||||
IList<IMessageBase> Messages,
|
IList<IMessageBase> Messages,
|
||||||
bool Stream,
|
bool Stream,
|
||||||
int Seed
|
[property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
int? Seed
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Attention: The "required" modifier is not supported for [JsonExtensionData].
|
// Attention: The "required" modifier is not supported for [JsonExtensionData].
|
||||||
[JsonExtensionData]
|
[JsonExtensionData]
|
||||||
public IDictionary<string, object> AdditionalApiParameters { get; init; } = new Dictionary<string, object>();
|
public IDictionary<string, object> AdditionalApiParameters { get; init; } = new Dictionary<string, object>();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -24,53 +22,34 @@ public class ProviderGroq() : BaseProvider(LLMProviders.GROQ, "https://api.groq.
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatRequest, ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"Groq",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
|
async (systemPrompt, apiParameters) =>
|
||||||
|
{
|
||||||
|
var seed = TryPopIntParameter(apiParameters, "seed", out var parsedSeed) ? parsedSeed : (int?)null;
|
||||||
|
|
||||||
// Prepare the system prompt:
|
// Build the list of messages:
|
||||||
var systemPrompt = new TextMessage
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
{
|
|
||||||
Role = "system",
|
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the OpenAI HTTP chat request:
|
|
||||||
var groqChatRequest = JsonSerializer.Serialize(new ChatRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
// Right now, we only support streaming completions:
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
return new ChatRequest
|
||||||
{
|
{
|
||||||
// Build the HTTP post request:
|
Model = chatModel.Id,
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Build the messages:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the content:
|
// Right now, we only support streaming completions:
|
||||||
request.Content = new StringContent(groqChatRequest, Encoding.UTF8, "application/json");
|
Stream = true,
|
||||||
return request;
|
Seed = seed,
|
||||||
}
|
AdditionalApiParameters = apiParameters
|
||||||
|
};
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>("Groq", RequestBuilder, token))
|
},
|
||||||
|
token: token))
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,4 +127,4 @@ public class ProviderGroq() : BaseProvider(LLMProviders.GROQ, "https://api.groq.
|
|||||||
!n.Id.StartsWith("distil-", StringComparison.OrdinalIgnoreCase) &&
|
!n.Id.StartsWith("distil-", StringComparison.OrdinalIgnoreCase) &&
|
||||||
!n.Id.Contains("-tts", StringComparison.OrdinalIgnoreCase));
|
!n.Id.Contains("-tts", StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -24,52 +22,30 @@ public sealed class ProviderHelmholtz() : BaseProvider(LLMProviders.HELMHOLTZ, "
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"Helmholtz",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
// Prepare the system prompt:
|
async (systemPrompt, apiParameters) =>
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
// Build the list of messages:
|
||||||
Role = "system",
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the Helmholtz HTTP chat request:
|
|
||||||
var helmholtzChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
return new ChatCompletionAPIRequest
|
||||||
{
|
{
|
||||||
// Build the HTTP post request:
|
Model = chatModel.Id,
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Build the messages:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the content:
|
Stream = true,
|
||||||
request.Content = new StringContent(helmholtzChatRequest, Encoding.UTF8, "application/json");
|
AdditionalApiParameters = apiParameters
|
||||||
return request;
|
};
|
||||||
}
|
},
|
||||||
|
token: token))
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>("Helmholtz", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,4 +127,4 @@ public sealed class ProviderHelmholtz() : BaseProvider(LLMProviders.HELMHOLTZ, "
|
|||||||
var modelResponse = await response.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
var modelResponse = await response.Content.ReadFromJsonAsync<ModelsResponse>(token);
|
||||||
return modelResponse.Data;
|
return modelResponse.Data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -29,52 +26,30 @@ public sealed class ProviderHuggingFace : BaseProvider
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"HuggingFace",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
|
async (systemPrompt, apiParameters) =>
|
||||||
|
{
|
||||||
|
// Build the list of messages:
|
||||||
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
|
|
||||||
// Prepare the system prompt:
|
return new ChatCompletionAPIRequest
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
Model = chatModel.Id,
|
||||||
Role = "system",
|
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var message = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the HuggingFace HTTP chat request:
|
|
||||||
var huggingfaceChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..message],
|
|
||||||
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
// Build the messages:
|
||||||
{
|
// - First of all the system prompt
|
||||||
// Build the HTTP post request:
|
// - Then none-empty user and AI messages
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the authorization header:
|
Stream = true,
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
AdditionalApiParameters = apiParameters
|
||||||
|
};
|
||||||
// Set the content:
|
},
|
||||||
request.Content = new StringContent(huggingfaceChatRequest, Encoding.UTF8, "application/json");
|
token: token))
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>("HuggingFace", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,4 +98,4 @@ public sealed class ProviderHuggingFace : BaseProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -22,58 +20,36 @@ public sealed class ProviderMistral() : BaseProvider(LLMProviders.MISTRAL, "http
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Provider.Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Provider.Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatRequest, ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"Mistral",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
|
async (systemPrompt, apiParameters) =>
|
||||||
|
{
|
||||||
|
var safePrompt = TryPopBoolParameter(apiParameters, "safe_prompt", out var parsedSafePrompt) && parsedSafePrompt;
|
||||||
|
var randomSeed = TryPopIntParameter(apiParameters, "random_seed", out var parsedRandomSeed) ? parsedRandomSeed : (int?)null;
|
||||||
|
|
||||||
// Prepare the system prompt:
|
// Build the list of messages:
|
||||||
var systemPrompt = new TextMessage
|
var messages = await chatThread.Blocks.BuildMessagesUsingDirectImageUrlAsync(this.Provider, chatModel);
|
||||||
{
|
|
||||||
Role = "system",
|
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
var safePrompt = TryPopBoolParameter(apiParameters, "safe_prompt", out var parsedSafePrompt) && parsedSafePrompt;
|
|
||||||
var randomSeed = TryPopIntParameter(apiParameters, "random_seed", out var parsedRandomSeed) ? parsedRandomSeed : (int?)null;
|
|
||||||
|
|
||||||
// Build the list of messages:
|
return new ChatRequest
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingDirectImageUrlAsync(this.Provider, chatModel);
|
{
|
||||||
|
Model = chatModel.Id,
|
||||||
// Prepare the Mistral HTTP chat request:
|
|
||||||
var mistralChatRequest = JsonSerializer.Serialize(new ChatRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
// Right now, we only support streaming completions:
|
|
||||||
Stream = true,
|
|
||||||
RandomSeed = randomSeed,
|
|
||||||
SafePrompt = safePrompt,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
|
// Build the messages:
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
// - First of all the system prompt
|
||||||
{
|
// - Then none-empty user and AI messages
|
||||||
// Build the HTTP post request:
|
Messages = [systemPrompt, ..messages],
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Right now, we only support streaming completions:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
Stream = true,
|
||||||
|
RandomSeed = randomSeed,
|
||||||
// Set the content:
|
SafePrompt = safePrompt,
|
||||||
request.Content = new StringContent(mistralChatRequest, Encoding.UTF8, "application/json");
|
AdditionalApiParameters = apiParameters
|
||||||
return request;
|
};
|
||||||
}
|
},
|
||||||
|
token: token))
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>("Mistral", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -27,57 +25,37 @@ public sealed class ProviderOpenRouter() : BaseProvider(LLMProviders.OPEN_ROUTER
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"OpenRouter",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
|
async (systemPrompt, apiParameters) =>
|
||||||
|
{
|
||||||
|
// Build the list of messages:
|
||||||
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
|
|
||||||
// Prepare the system prompt:
|
return new ChatCompletionAPIRequest
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
Model = chatModel.Id,
|
||||||
Role = "system",
|
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
// Build the messages:
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
// Build the list of messages:
|
Messages = [systemPrompt, ..messages],
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the OpenRouter HTTP chat request:
|
// Right now, we only support streaming completions:
|
||||||
var openRouterChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
Stream = true,
|
||||||
{
|
AdditionalApiParameters = apiParameters
|
||||||
Model = chatModel.Id,
|
};
|
||||||
|
},
|
||||||
// Build the messages:
|
headersAction: headers =>
|
||||||
// - First of all the system prompt
|
{
|
||||||
// - Then none-empty user and AI messages
|
// Set custom headers for project identification:
|
||||||
Messages = [systemPrompt, ..messages],
|
headers.Add("HTTP-Referer", PROJECT_WEBSITE);
|
||||||
|
headers.Add("X-Title", PROJECT_NAME);
|
||||||
// Right now, we only support streaming completions:
|
},
|
||||||
Stream = true,
|
token: token))
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
|
||||||
{
|
|
||||||
// Build the HTTP post request:
|
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
|
||||||
|
|
||||||
// Set custom headers for project identification:
|
|
||||||
request.Headers.Add("HTTP-Referer", PROJECT_WEBSITE);
|
|
||||||
request.Headers.Add("X-Title", PROJECT_NAME);
|
|
||||||
|
|
||||||
// Set the content:
|
|
||||||
request.Content = new StringContent(openRouterChatRequest, Encoding.UTF8, "application/json");
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>("OpenRouter", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,4 @@
|
|||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -33,51 +30,29 @@ public sealed class ProviderPerplexity() : BaseProvider(LLMProviders.PERPLEXITY,
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ResponseStreamLine, NoChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"Perplexity",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
// Prepare the system prompt:
|
async (systemPrompt, apiParameters) =>
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
// Build the list of messages:
|
||||||
Role = "system",
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the Perplexity HTTP chat request:
|
|
||||||
var perplexityChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
return new ChatCompletionAPIRequest
|
||||||
{
|
{
|
||||||
// Build the HTTP post request:
|
Model = chatModel.Id,
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Build the messages:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
// Set the content:
|
Messages = [systemPrompt, ..messages],
|
||||||
request.Content = new StringContent(perplexityChatRequest, Encoding.UTF8, "application/json");
|
Stream = true,
|
||||||
return request;
|
AdditionalApiParameters = apiParameters
|
||||||
}
|
};
|
||||||
|
},
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ResponseStreamLine, NoChatCompletionAnnotationStreamLine>("Perplexity", RequestBuilder, token))
|
token: token))
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,4 +103,4 @@ public sealed class ProviderPerplexity() : BaseProvider(LLMProviders.PERPLEXITY,
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private Task<IEnumerable<Model>> LoadModels() => Task.FromResult<IEnumerable<Model>>(KNOWN_MODELS);
|
private Task<IEnumerable<Model>> LoadModels() => Task.FromResult<IEnumerable<Model>>(KNOWN_MODELS);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace AIStudio.Provider.SelfHosted;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The chat request model.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Model">Which model to use for chat completion.</param>
|
|
||||||
/// <param name="Messages">The chat messages.</param>
|
|
||||||
/// <param name="Stream">Whether to stream the chat completion.</param>
|
|
||||||
public readonly record struct ChatRequest(
|
|
||||||
string Model,
|
|
||||||
IList<IMessageBase> Messages,
|
|
||||||
bool Stream
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Attention: The "required" modifier is not supported for [JsonExtensionData].
|
|
||||||
[JsonExtensionData]
|
|
||||||
public IDictionary<string, object> AdditionalApiParameters { get; init; } = new Dictionary<string, object>();
|
|
||||||
}
|
|
||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -25,58 +23,39 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Provider.Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Provider.Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER, isTrying: true);
|
"self-hosted provider",
|
||||||
|
chatModel,
|
||||||
// Prepare the system prompt:
|
chatThread,
|
||||||
var systemPrompt = new TextMessage
|
settingsManager,
|
||||||
{
|
async (systemPrompt, apiParameters) =>
|
||||||
Role = "system",
|
{
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
// Build the list of messages. The image format depends on the host:
|
||||||
};
|
// - Ollama uses the direct image URL format: { "type": "image_url", "image_url": "data:..." }
|
||||||
|
// - LM Studio, vLLM, and llama.cpp use the nested image URL format: { "type": "image_url", "image_url": { "url": "data:..." } }
|
||||||
// Parse the API parameters:
|
var messages = host switch
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
{
|
||||||
|
Host.OLLAMA => await chatThread.Blocks.BuildMessagesUsingDirectImageUrlAsync(this.Provider, chatModel),
|
||||||
|
_ => await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel),
|
||||||
|
};
|
||||||
|
|
||||||
// Build the list of messages. The image format depends on the host:
|
return new ChatCompletionAPIRequest
|
||||||
// - Ollama uses the direct image URL format: { "type": "image_url", "image_url": "data:..." }
|
{
|
||||||
// - LM Studio, vLLM, and llama.cpp use the nested image URL format: { "type": "image_url", "image_url": { "url": "data:..." } }
|
Model = chatModel.Id,
|
||||||
var messages = host switch
|
|
||||||
{
|
|
||||||
Host.OLLAMA => await chatThread.Blocks.BuildMessagesUsingDirectImageUrlAsync(this.Provider, chatModel),
|
|
||||||
_ => await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Prepare the OpenAI HTTP chat request:
|
|
||||||
var providerChatRequest = JsonSerializer.Serialize(new ChatRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
// Right now, we only support streaming completions:
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
// Build the messages:
|
||||||
{
|
// - First of all the system prompt
|
||||||
// Build the HTTP post request:
|
// - Then none-empty user and AI messages
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, host.ChatURL());
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the authorization header:
|
// Right now, we only support streaming completions:
|
||||||
if (requestedSecret.Success)
|
Stream = true,
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
AdditionalApiParameters = apiParameters
|
||||||
|
};
|
||||||
// Set the content:
|
},
|
||||||
request.Content = new StringContent(providerChatRequest, Encoding.UTF8, "application/json");
|
isTryingSecret: true,
|
||||||
return request;
|
requestPath: host.ChatURL(),
|
||||||
}
|
token: token))
|
||||||
|
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, ChatCompletionAnnotationStreamLine>("self-hosted provider", RequestBuilder, token))
|
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,4 +190,4 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide
|
|||||||
filterPhrases.All( filter => model.Id.Contains(filter, StringComparison.InvariantCulture)))
|
filterPhrases.All( filter => model.Id.Contains(filter, StringComparison.InvariantCulture)))
|
||||||
.Select(n => new Provider.Model(n.Id, null));
|
.Select(n => new Provider.Model(n.Id, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
using AIStudio.Chat;
|
using AIStudio.Chat;
|
||||||
using AIStudio.Provider.OpenAI;
|
using AIStudio.Provider.OpenAI;
|
||||||
@ -24,53 +22,31 @@ public sealed class ProviderX() : BaseProvider(LLMProviders.X, "https://api.x.ai
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
public override async IAsyncEnumerable<ContentStreamChunk> StreamChatCompletion(Model chatModel, ChatThread chatThread, SettingsManager settingsManager, [EnumeratorCancellation] CancellationToken token = default)
|
||||||
{
|
{
|
||||||
// Get the API key:
|
await foreach (var content in this.StreamOpenAICompatibleChatCompletion<ChatCompletionAPIRequest, ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>(
|
||||||
var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.LLM_PROVIDER);
|
"xAI",
|
||||||
if(!requestedSecret.Success)
|
chatModel,
|
||||||
yield break;
|
chatThread,
|
||||||
|
settingsManager,
|
||||||
// Prepare the system prompt:
|
async (systemPrompt, apiParameters) =>
|
||||||
var systemPrompt = new TextMessage
|
{
|
||||||
{
|
// Build the list of messages:
|
||||||
Role = "system",
|
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
||||||
Content = chatThread.PrepareSystemPrompt(settingsManager),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parse the API parameters:
|
|
||||||
var apiParameters = this.ParseAdditionalApiParameters();
|
|
||||||
|
|
||||||
// Build the list of messages:
|
|
||||||
var messages = await chatThread.Blocks.BuildMessagesUsingNestedImageUrlAsync(this.Provider, chatModel);
|
|
||||||
|
|
||||||
// Prepare the xAI HTTP chat request:
|
|
||||||
var xChatRequest = JsonSerializer.Serialize(new ChatCompletionAPIRequest
|
|
||||||
{
|
|
||||||
Model = chatModel.Id,
|
|
||||||
|
|
||||||
// Build the messages:
|
|
||||||
// - First of all the system prompt
|
|
||||||
// - Then none-empty user and AI messages
|
|
||||||
Messages = [systemPrompt, ..messages],
|
|
||||||
|
|
||||||
// Right now, we only support streaming completions:
|
|
||||||
Stream = true,
|
|
||||||
AdditionalApiParameters = apiParameters
|
|
||||||
}, JSON_SERIALIZER_OPTIONS);
|
|
||||||
|
|
||||||
async Task<HttpRequestMessage> RequestBuilder()
|
return new ChatCompletionAPIRequest
|
||||||
{
|
{
|
||||||
// Build the HTTP post request:
|
Model = chatModel.Id,
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
|
|
||||||
|
|
||||||
// Set the authorization header:
|
// Build the messages:
|
||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION));
|
// - First of all the system prompt
|
||||||
|
// - Then none-empty user and AI messages
|
||||||
|
Messages = [systemPrompt, ..messages],
|
||||||
|
|
||||||
// Set the content:
|
// Right now, we only support streaming completions:
|
||||||
request.Content = new StringContent(xChatRequest, Encoding.UTF8, "application/json");
|
Stream = true,
|
||||||
return request;
|
AdditionalApiParameters = apiParameters
|
||||||
}
|
};
|
||||||
|
},
|
||||||
await foreach (var content in this.StreamChatCompletionInternal<ChatCompletionDeltaStreamLine, NoChatCompletionAnnotationStreamLine>("xAI", RequestBuilder, token))
|
token: token))
|
||||||
yield return content;
|
yield return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,4 +134,4 @@ public sealed class ProviderX() : BaseProvider(LLMProviders.X, "https://api.x.ai
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user