last works ...
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using xModels.Base;
|
||||
|
||||
namespace xAiApi.AI.Models.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// Ai Ask Request Data Transfer Object ...
|
||||
/// </summary>
|
||||
public class XAiAskRequestDto : XBaseDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Provided Prompt for Ask ...
|
||||
/// </summary>
|
||||
[FromQuery]
|
||||
public string Prompt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ai Selected Project Id, Optional ...
|
||||
/// if null, Use Default Project for Authenticated User ...
|
||||
/// </summary>
|
||||
[FromQuery]
|
||||
public string ProjectId { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Ai Selected Conversation of Project, Optional ...
|
||||
/// if null, Create new Conversation in Selected Project ...
|
||||
/// </summary>
|
||||
[FromQuery]
|
||||
public string ConversationId { get; set; } = null;
|
||||
}
|
||||
}
|
||||
+26
-10
@@ -509,12 +509,17 @@ namespace xAiApi.AI.Services
|
||||
|
||||
//
|
||||
// Getting Response Message from LLM ...
|
||||
var chatResponseEnumerable = chatClient
|
||||
var chatStream = chatClient
|
||||
.GetStreamingResponseAsync(
|
||||
options: chatOptions,
|
||||
messages: requirements.ChatHistory,
|
||||
cancellationToken: cancellationToken
|
||||
);
|
||||
isValid = !chatStream.IsNull();
|
||||
if (!isValid)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
//
|
||||
// Create an Empty Message for ID ...
|
||||
@@ -531,31 +536,31 @@ namespace xAiApi.AI.Services
|
||||
saveChanges: true,
|
||||
item: responseMessage
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// Collecting Data through Enumeration ...
|
||||
// Loop through Async Enumerable ...
|
||||
string content = string.Empty;
|
||||
var sequence = DateTime.UtcNow.ToTimestamp();
|
||||
await foreach (var data in chatResponseEnumerable)
|
||||
await foreach(var msg in chatStream)
|
||||
{
|
||||
//
|
||||
// Crucially, check the cancellation token before continuing
|
||||
// Throwing OperationCanceledException is the standard way to signal cancellation.
|
||||
if (cancellationToken.CanBeCanceled)
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
//
|
||||
// Append recieved data to Content ...
|
||||
content += data;
|
||||
content += msg.Text;
|
||||
|
||||
//
|
||||
// Crate Message Update Model ...
|
||||
var item = new XAiMessageUpdateDto
|
||||
{
|
||||
Sequense = sequence,
|
||||
Content = data.Text,
|
||||
Content = msg.Text,
|
||||
Id = responseMessage.Id,
|
||||
OwnerId = userInfo.UserId,
|
||||
UpdatedAt = DateTime.UtcNow,
|
||||
@@ -586,6 +591,7 @@ namespace xAiApi.AI.Services
|
||||
}
|
||||
|
||||
//
|
||||
// End Async Enumerable ...
|
||||
yield break;
|
||||
}
|
||||
#endregion
|
||||
@@ -976,7 +982,10 @@ namespace xAiApi.AI.Services
|
||||
{
|
||||
//
|
||||
// Complete Chat History ...
|
||||
foreach (var msg in conversation.Messages)
|
||||
var orderedByTimeMessage = conversation.Messages
|
||||
.OrderBy(x => x.CreatedOn)
|
||||
.AsEnumerable();
|
||||
foreach (var msg in orderedByTimeMessage)
|
||||
{
|
||||
//
|
||||
result.ChatHistory.Add(
|
||||
@@ -1025,11 +1034,18 @@ namespace xAiApi.AI.Services
|
||||
XException.InvalidData.Throw();
|
||||
}
|
||||
|
||||
//
|
||||
// Update Conversation ...
|
||||
var conversationEntity = await aiConversationRepository
|
||||
.GetAsync(id: result.AiConversation.Id);
|
||||
conversation = mapper.Map<XAiConversationDto>(conversationEntity);
|
||||
result.AiConversation = conversation;
|
||||
|
||||
//
|
||||
result.ChatHistory.Add(
|
||||
new ChatMessage(
|
||||
content: prompt,
|
||||
role: XAiChatRole.User.ToChatRole()
|
||||
content: promptAiMessage.Content,
|
||||
role: promptAiMessage.Role.ToChatRole()
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -8,11 +8,13 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OpenAI.Realtime;
|
||||
using xAiApi.AI.Interfaces;
|
||||
using xAiApi.AI.Models.Dtos;
|
||||
using xAiApi.Base;
|
||||
using xAiModels.Models;
|
||||
using xCommons.Configurations;
|
||||
using xCommons.Extensions;
|
||||
using xCommons.Providers;
|
||||
using xExceptions.Constants;
|
||||
using xIdentityHelper;
|
||||
using xIdentityService.Constants;
|
||||
using xIdentityService.Interfaces;
|
||||
@@ -51,6 +53,62 @@ namespace xAiApi.Controllers.V1
|
||||
|
||||
//
|
||||
#region Actions ...
|
||||
/// <summary>
|
||||
/// As a Message from Ai ...
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("Ask")]
|
||||
[Authorize(Policy = XPolicies.EnabledUser)]
|
||||
public async Task<ActionResult<XAiMessageDto>> Ask(
|
||||
[FromQuery] XAiAskRequestDto request,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
//
|
||||
// Do ...
|
||||
try
|
||||
{
|
||||
//
|
||||
// Validate Model ...
|
||||
var isValid =
|
||||
ModelState.IsValid &&
|
||||
!request.IsNull() &&
|
||||
!request.Prompt.IsNullOrEmpty();
|
||||
if (!isValid)
|
||||
{
|
||||
XException.InvalidArgs.Throw();
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve User Info ...
|
||||
var userInfo = await GetUserInfo();
|
||||
|
||||
//
|
||||
// Retrieve Result ...
|
||||
var result = await aiService
|
||||
.Ask(
|
||||
userInfo: userInfo,
|
||||
prompt: request.Prompt,
|
||||
projectId: request.ProjectId,
|
||||
cancellationToken: cancellationToken,
|
||||
conversationId: request.ConversationId
|
||||
);
|
||||
|
||||
//
|
||||
return Ok(result.ToDynamicObject());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//
|
||||
var result = GetExceptionActionResult(ex);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// As a Message from Ai ...
|
||||
/// </summary>
|
||||
@@ -96,6 +154,98 @@ namespace xAiApi.Controllers.V1
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ask a Message from Ai using Streamin Pattern ...
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("AskStream")]
|
||||
[Authorize(Policy = XPolicies.EnabledUser)]
|
||||
public async Task AskStream(
|
||||
[FromQuery] XAiAskRequestDto request,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
//
|
||||
// Do ...
|
||||
try
|
||||
{
|
||||
//
|
||||
// Validate Model ...
|
||||
var isValid =
|
||||
ModelState.IsValid &&
|
||||
!request.IsNull() &&
|
||||
!request.Prompt.IsNullOrEmpty();
|
||||
if (!isValid)
|
||||
{
|
||||
XException.InvalidArgs.Throw();
|
||||
}
|
||||
|
||||
//
|
||||
// Adding Content Type ...
|
||||
Response.Headers
|
||||
.Append("Content-Type", "text/event-stream");
|
||||
|
||||
//
|
||||
// Retrieve User Info ...
|
||||
var userInfo = await GetUserInfo();
|
||||
|
||||
//
|
||||
// Access Async Enumerable ...
|
||||
var stream = aiService
|
||||
.AskStream(
|
||||
userInfo: userInfo,
|
||||
prompt: request.Prompt,
|
||||
projectId: request.ProjectId,
|
||||
cancellationToken: cancellationToken,
|
||||
conversationId: request.ConversationId
|
||||
);
|
||||
|
||||
//
|
||||
// Loop through Enumerable ...
|
||||
await foreach (var message in stream)
|
||||
{
|
||||
//
|
||||
// Converts Model to Json String ...
|
||||
var json = message.ToJSON();
|
||||
|
||||
//
|
||||
// Generates Json byte[] ...
|
||||
var bytes = json.ToBytes();
|
||||
|
||||
//
|
||||
// Write Bytes to Stream ...
|
||||
await Response.Body.WriteAsync(
|
||||
bytes,
|
||||
0,
|
||||
bytes.Length,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
//
|
||||
// Flushing Stream ...
|
||||
await Response.Body.FlushAsync(cancellationToken);
|
||||
}
|
||||
|
||||
//
|
||||
// Closing Connection ...
|
||||
await Response.Body.FlushAsync();
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ask a Message from Ai using Streamin Pattern ...
|
||||
/// </summary>
|
||||
/// <param name="prompt"></param>
|
||||
/// <param name="projectId"></param>
|
||||
/// <param name="conversationId"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("AskAIStream")]
|
||||
[Authorize(Policy = XPolicies.EnabledUser)]
|
||||
public async Task AskAIStream(
|
||||
@@ -124,6 +274,9 @@ namespace xAiApi.Controllers.V1
|
||||
conversationId: conversationId,
|
||||
cancellationToken: cancellationToken
|
||||
);
|
||||
|
||||
//
|
||||
// Loop through Enumerable ...
|
||||
await foreach (var message in stream)
|
||||
{
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user