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 ...
|
// Getting Response Message from LLM ...
|
||||||
var chatResponseEnumerable = chatClient
|
var chatStream = chatClient
|
||||||
.GetStreamingResponseAsync(
|
.GetStreamingResponseAsync(
|
||||||
options: chatOptions,
|
options: chatOptions,
|
||||||
messages: requirements.ChatHistory,
|
messages: requirements.ChatHistory,
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
|
isValid = !chatStream.IsNull();
|
||||||
|
if (!isValid)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create an Empty Message for ID ...
|
// Create an Empty Message for ID ...
|
||||||
@@ -531,31 +536,31 @@ namespace xAiApi.AI.Services
|
|||||||
saveChanges: true,
|
saveChanges: true,
|
||||||
item: responseMessage
|
item: responseMessage
|
||||||
);
|
);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Collecting Data through Enumeration ...
|
// Loop through Async Enumerable ...
|
||||||
string content = string.Empty;
|
string content = string.Empty;
|
||||||
var sequence = DateTime.UtcNow.ToTimestamp();
|
var sequence = DateTime.UtcNow.ToTimestamp();
|
||||||
await foreach (var data in chatResponseEnumerable)
|
await foreach(var msg in chatStream)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Crucially, check the cancellation token before continuing
|
// Crucially, check the cancellation token before continuing
|
||||||
// Throwing OperationCanceledException is the standard way to signal cancellation.
|
// Throwing OperationCanceledException is the standard way to signal cancellation.
|
||||||
if (cancellationToken.CanBeCanceled)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Append recieved data to Content ...
|
// Append recieved data to Content ...
|
||||||
content += data;
|
content += msg.Text;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Crate Message Update Model ...
|
// Crate Message Update Model ...
|
||||||
var item = new XAiMessageUpdateDto
|
var item = new XAiMessageUpdateDto
|
||||||
{
|
{
|
||||||
Sequense = sequence,
|
Sequense = sequence,
|
||||||
Content = data.Text,
|
Content = msg.Text,
|
||||||
Id = responseMessage.Id,
|
Id = responseMessage.Id,
|
||||||
OwnerId = userInfo.UserId,
|
OwnerId = userInfo.UserId,
|
||||||
UpdatedAt = DateTime.UtcNow,
|
UpdatedAt = DateTime.UtcNow,
|
||||||
@@ -586,6 +591,7 @@ namespace xAiApi.AI.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
// End Async Enumerable ...
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
@@ -976,7 +982,10 @@ namespace xAiApi.AI.Services
|
|||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Complete Chat History ...
|
// 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(
|
result.ChatHistory.Add(
|
||||||
@@ -1025,11 +1034,18 @@ namespace xAiApi.AI.Services
|
|||||||
XException.InvalidData.Throw();
|
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(
|
result.ChatHistory.Add(
|
||||||
new ChatMessage(
|
new ChatMessage(
|
||||||
content: prompt,
|
content: promptAiMessage.Content,
|
||||||
role: XAiChatRole.User.ToChatRole()
|
role: promptAiMessage.Role.ToChatRole()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ using Microsoft.Extensions.AI;
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using OpenAI.Realtime;
|
using OpenAI.Realtime;
|
||||||
using xAiApi.AI.Interfaces;
|
using xAiApi.AI.Interfaces;
|
||||||
|
using xAiApi.AI.Models.Dtos;
|
||||||
using xAiApi.Base;
|
using xAiApi.Base;
|
||||||
using xAiModels.Models;
|
using xAiModels.Models;
|
||||||
using xCommons.Configurations;
|
using xCommons.Configurations;
|
||||||
using xCommons.Extensions;
|
using xCommons.Extensions;
|
||||||
using xCommons.Providers;
|
using xCommons.Providers;
|
||||||
|
using xExceptions.Constants;
|
||||||
using xIdentityHelper;
|
using xIdentityHelper;
|
||||||
using xIdentityService.Constants;
|
using xIdentityService.Constants;
|
||||||
using xIdentityService.Interfaces;
|
using xIdentityService.Interfaces;
|
||||||
@@ -51,6 +53,62 @@ namespace xAiApi.Controllers.V1
|
|||||||
|
|
||||||
//
|
//
|
||||||
#region Actions ...
|
#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>
|
/// <summary>
|
||||||
/// As a Message from Ai ...
|
/// As a Message from Ai ...
|
||||||
/// </summary>
|
/// </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")]
|
[HttpGet("AskAIStream")]
|
||||||
[Authorize(Policy = XPolicies.EnabledUser)]
|
[Authorize(Policy = XPolicies.EnabledUser)]
|
||||||
public async Task AskAIStream(
|
public async Task AskAIStream(
|
||||||
@@ -124,6 +274,9 @@ namespace xAiApi.Controllers.V1
|
|||||||
conversationId: conversationId,
|
conversationId: conversationId,
|
||||||
cancellationToken: cancellationToken
|
cancellationToken: cancellationToken
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Loop through Enumerable ...
|
||||||
await foreach (var message in stream)
|
await foreach (var message in stream)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user