This commit is contained in:
2026-04-24 22:06:13 +03:30
parent e49c273171
commit bb5dc64a7d
11 changed files with 682 additions and 59 deletions
+11
View File
@@ -8,6 +8,17 @@ namespace xAiApi.AI.Configuration
/// <value></value>
public string Url { get; set; }
/// <summary>
/// a System Message to Introduce Model ...
/// </summary>
public string Introduction { get; set; }
/// <summary>
/// Model Name ...
/// </summary>
/// <value></value>
public string Model { get; set; }
/// <summary>
/// Text Generator Model Name ...
/// </summary>
+17
View File
@@ -0,0 +1,17 @@
using xExceptions.Attributes;
namespace xAiApi.AI.Constants
{
/// <summary>
/// Several Ai Projects Type ...
/// </summary>
public enum XAiProjectEnum
{
[StringValue("None")]
None,
[StringValue("Default")]
Default,
[StringValue("Custom")]
Custom
}
}
+68 -17
View File
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using xAiApi.AI.Configuration;
using xAiApi.AI.Models.Entities;
using xAiModels.Models;
using xIdentityModels.Models;
@@ -15,10 +17,11 @@ namespace xAiApi.AI.Interfaces
public interface IXAiProvider
{
/// <summary>
/// Ai Service for Getting Features ...
/// Configuration ...
/// </summary>
IXAIService AiService { get; }
/// <value></value>
public XAiApiConfiguration Configuration { get; }
//
#region Helpers ...
/// <summary>
@@ -26,91 +29,135 @@ namespace xAiApi.AI.Interfaces
/// <see cref="XAiProjectDto"/>
/// </summary>
/// <param name="entity"><see cref="XAiProject"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XAiProjectDto> ToDto(XAiProject entity);
Task<XAiProjectDto> ToDto(
XAiProject entity,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts Entity to Dto ...
/// <see cref="XAiMessageDto"/>
/// </summary>
/// <param name="entity"><see cref="XAiMessage"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XAiMessageDto> ToDto(XAiMessage entity);
Task<XAiMessageDto> ToDto(
XAiMessage entity,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts Entity to Dto ...
/// <see cref="XAiConversationDto"/>
/// </summary>
/// <param name="entity"><see cref="XAiConversation"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XAiConversationDto> ToDto(XAiConversation entity);
Task<XAiConversationDto> ToDto(
XAiConversation entity,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts a List of Entities to Dtos ...
/// <see cref="XAiProjectDto"/>
/// </summary>
/// <param name="entities"><see cref="XAiProject"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XAiProjectDto>> ToDtos(IEnumerable<XAiProject> entities);
Task<IEnumerable<XAiProjectDto>> ToDtos(
IEnumerable<XAiProject> entities,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts a List of Entities to Dtos ...
/// <see cref="XAiMessageDto"/>
/// </summary>
/// <param name="entities"><see cref="XAiMessage"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XAiMessageDto>> ToDtos(IEnumerable<XAiMessage> entities);
Task<IEnumerable<XAiMessageDto>> ToDtos(
IEnumerable<XAiMessage> entities,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts a List of Entities to Dtos ...
/// <see cref="XAiConversationDto"/>
/// </summary>
/// <param name="entities"><see cref="XAiConversation"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IEnumerable<XAiConversationDto>> ToDtos(IEnumerable<XAiConversation> entities);
Task<IEnumerable<XAiConversationDto>> ToDtos(
IEnumerable<XAiConversation> entities,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts a QueryResult of Entities to Dtos ...
/// <see cref="XAiProjectDto"/>
/// </summary>
/// <param name="queryResult"><see cref="XAiProject"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<XAiProjectDto>> ToDtoQueryResult(XQueryResult<XAiProject> queryResult);
Task<XQueryResult<XAiProjectDto>> ToDtoQueryResult(
XQueryResult<XAiProject> queryResult,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts a QueryResult of Entities to Dtos ...
/// <see cref="XAiMessageDto"/>
/// </summary>
/// <param name="queryResult"><see cref="XAiMessage"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<XAiMessageDto>> ToDtoQueryResult(XQueryResult<XAiMessage> queryResult);
Task<XQueryResult<XAiMessageDto>> ToDtoQueryResult(
XQueryResult<XAiMessage> queryResult,
CancellationToken cancellationToken = default
);
/// <summary>
/// Converts a QueryResult of Entities to Dtos ...
/// <see cref="XAiConversationDto"/>
/// </summary>
/// <param name="queryResult"><see cref="XAiConversation"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XQueryResult<XAiConversationDto>> ToDtoQueryResult(XQueryResult<XAiConversation> queryResult);
Task<XQueryResult<XAiConversationDto>> ToDtoQueryResult(
XQueryResult<XAiConversation> queryResult,
CancellationToken cancellationToken = default
);
/// <summary>
/// Check Permission for Ai Actions ...
/// </summary>
/// <param name="projectId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> HasPermission(
XUserClaimsInfoDto userInfo
string projectId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
/// <summary>
/// Prepare Prompt ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="projectId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<string> PreparePrompt(
string prompt,
XUserClaimsInfoDto userInfo
string projectId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
#endregion
@@ -118,13 +165,17 @@ namespace xAiApi.AI.Interfaces
/// Ask a Question ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="projectId"></param>
/// <param name="conversationId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<XAiMessageDto> Ask(
string prompt,
Guid conversationId,
XUserClaimsInfoDto userInfo
string projectId = null,
string conversationId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
);
}
}
+541 -38
View File
@@ -1,10 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
using Microsoft.SemanticKernel.ChatCompletion;
using OllamaSharp;
using xAiApi.AI.Configuration;
using xAiApi.AI.Constants;
using xAiApi.AI.Extensions;
using xAiApi.AI.Interfaces;
using xAiApi.AI.Interfaces.Entities;
using xAiApi.AI.Models.Entities;
using xAiModels.Constants;
using xAiModels.Extensions;
using xAiModels.Models;
using xCommons.Extensions;
using xExceptions.Constants;
@@ -15,20 +24,77 @@ using xModels.Dtos;
namespace xAiApi.AI.Services
{
/// <summary>
/// Provide Ai Capabilities Using AI Service ...
/// using User Data Info ...
/// </summary>
public class XAiProvider : IXAiProvider
{
/// <summary>
/// Configuration ...
/// </summary>
/// <value></value>
public XAiApiConfiguration Configuration { get; }
//
public IXAIService AiService { get; }
private readonly IChatClient chatClient;
private readonly ChatOptions chatOptions;
private readonly IXIdentityProvider identityProvider;
private readonly IXAiProjectRepository aiProjectRepository;
private readonly IXAiMessageRepository aiMessagetRepository;
private readonly IXAiConversationRepository aiConversationRepository;
public XAiProvider(
IXAIService aiService,
IXIdentityProvider identityProvider
XAiApiConfiguration configuration,
IXIdentityProvider identityProvider,
IXAiProjectRepository aiProjectRepository,
IXAiMessageRepository aiMessagetRepository,
IXAiConversationRepository aiConversationRepository
)
{
//
AiService = aiService;
Configuration = configuration;
//
this.identityProvider = identityProvider;
this.aiProjectRepository = aiProjectRepository;
this.aiMessagetRepository = aiMessagetRepository;
this.aiConversationRepository = aiConversationRepository;
//
// Prepare Chat Model ...
chatClient = new ChatClientBuilder(new OllamaApiClient(
new Uri(configuration.Url),
configuration.Model
))
// .UseFunctionInvocation()
.Build();
//
// Configuring Chant Options ...
chatOptions = new ChatOptions()
{
//
// Preparing Tools ...
// Tools = [
// //
// // Tempreature Tool ...
// AIFunctionFactory.Create((string location, string unit) => {
// //
// var temp = Random.Shared.Next(5, 20);
// var cond = Random.Shared.Next(0, 1) == 0 ? "sunny" : "rainy";
// //
// var result = $"The weather is {temp} degrees C and {cond}.";
// //
// return result;
// },
// "get_current_weather",
// "Get the current weather in given location"
// )
// ],
};
}
//
@@ -38,8 +104,12 @@ namespace xAiApi.AI.Services
/// <see cref="XAiProjectDto"/>
/// </summary>
/// <param name="entity"><see cref="XAiProject"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XAiProjectDto> ToDto(XAiProject entity)
public async Task<XAiProjectDto> ToDto(
XAiProject entity,
CancellationToken cancellationToken = default
)
{
//
XAiProjectDto result = null;
@@ -51,11 +121,18 @@ namespace xAiApi.AI.Services
result = entity.ToDto();
if (!entity.OwnerId.IsNullOrEmpty())
{
result.Owner = await GetPerson(entity.OwnerId);
//
result.Owner = await GetPerson(
entity.OwnerId,
cancellationToken
);
}
//
result.Conversations = await ToDtos(entity.Conversations);
result.Conversations = await ToDtos(
entity.Conversations,
cancellationToken
);
}
//
@@ -67,8 +144,12 @@ namespace xAiApi.AI.Services
/// <see cref="XAiMessageDto"/>
/// </summary>
/// <param name="entity"><see cref="XAiMessage"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XAiMessageDto> ToDto(XAiMessage entity)
public async Task<XAiMessageDto> ToDto(
XAiMessage entity,
CancellationToken cancellationToken = default
)
{
//
XAiMessageDto result = null;
@@ -80,11 +161,18 @@ namespace xAiApi.AI.Services
result = entity.ToDto();
if (!entity.OwnerId.IsNullOrEmpty())
{
result.Owner = await GetPerson(entity.OwnerId);
//
result.Owner = await GetPerson(
entity.OwnerId,
cancellationToken
);
}
//
result.Conversation = await ToDto(entity.Conversation);
result.Conversation = await ToDto(
entity.Conversation,
cancellationToken
);
}
//
@@ -96,8 +184,12 @@ namespace xAiApi.AI.Services
/// <see cref="XAiConversationDto"/>
/// </summary>
/// <param name="entity"><see cref="XAiConversation"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XAiConversationDto> ToDto(XAiConversation entity)
public async Task<XAiConversationDto> ToDto(
XAiConversation entity,
CancellationToken cancellationToken = default
)
{
//
XAiConversationDto result = null;
@@ -109,12 +201,24 @@ namespace xAiApi.AI.Services
result = entity.ToDto();
if (!entity.OwnerId.IsNullOrEmpty())
{
result.Owner = await GetPerson(entity.OwnerId);
//
result.Owner = await GetPerson(
entity.OwnerId,
cancellationToken
);
}
//
result.Project = await ToDto(entity.Project);
result.Messages = await ToDtos(entity.Messages);
result.Project = await ToDto(
entity.Project,
cancellationToken
);
//
result.Messages = await ToDtos(
entity.Messages,
cancellationToken
);
}
//
@@ -126,18 +230,25 @@ namespace xAiApi.AI.Services
/// <see cref="XAiProjectDto"/>
/// </summary>
/// <param name="entities"><see cref="XAiProject"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XAiProjectDto>> ToDtos(IEnumerable<XAiProject> entities)
public async Task<IEnumerable<XAiProjectDto>> ToDtos(
IEnumerable<XAiProject> entities,
CancellationToken cancellationToken = default
)
{
//
IList<XAiProjectDto> list = new List<XAiProjectDto>();
//
var enumerable = entities.ToAsyncEnumerable();
var enumerable = entities.ToAsyncEnumerable(cancellationToken);
await foreach (var entity in enumerable)
{
//
var dto = await ToDto(entity);
var dto = await ToDto(
entity,
cancellationToken
);
if (!dto.IsNullOrDefault())
{
list.Add(dto);
@@ -153,18 +264,25 @@ namespace xAiApi.AI.Services
/// <see cref="XAiMessageDto"/>
/// </summary>
/// <param name="entities"><see cref="XAiMessage"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XAiMessageDto>> ToDtos(IEnumerable<XAiMessage> entities)
public async Task<IEnumerable<XAiMessageDto>> ToDtos(
IEnumerable<XAiMessage> entities,
CancellationToken cancellationToken = default
)
{
//
IList<XAiMessageDto> list = new List<XAiMessageDto>();
//
var enumerable = entities.ToAsyncEnumerable();
var enumerable = entities.ToAsyncEnumerable(cancellationToken);
await foreach (var entity in enumerable)
{
//
var dto = await ToDto(entity);
var dto = await ToDto(
entity,
cancellationToken
);
if (!dto.IsNullOrDefault())
{
list.Add(dto);
@@ -180,18 +298,25 @@ namespace xAiApi.AI.Services
/// <see cref="XAiConversationDto"/>
/// </summary>
/// <param name="entities"><see cref="XAiConversation"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IEnumerable<XAiConversationDto>> ToDtos(IEnumerable<XAiConversation> entities)
public async Task<IEnumerable<XAiConversationDto>> ToDtos(
IEnumerable<XAiConversation> entities,
CancellationToken cancellationToken = default
)
{
//
IList<XAiConversationDto> list = new List<XAiConversationDto>();
//
var enumerable = entities.ToAsyncEnumerable();
var enumerable = entities.ToAsyncEnumerable(cancellationToken);
await foreach (var entity in enumerable)
{
//
var dto = await ToDto(entity);
var dto = await ToDto(
entity,
cancellationToken
);
if (!dto.IsNullOrDefault())
{
list.Add(dto);
@@ -207,8 +332,12 @@ namespace xAiApi.AI.Services
/// <see cref="XAiProjectDto"/>
/// </summary>
/// <param name="queryResult"><see cref="XAiProject"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<XAiProjectDto>> ToDtoQueryResult(XQueryResult<XAiProject> queryResult)
public async Task<XQueryResult<XAiProjectDto>> ToDtoQueryResult(
XQueryResult<XAiProject> queryResult,
CancellationToken cancellationToken = default
)
{
//
var result = new XQueryResult<XAiProjectDto>();
@@ -228,7 +357,11 @@ namespace xAiApi.AI.Services
//
if (queryResult.Items.HasChild())
{
result.Items = await ToDtos(queryResult.Items);
//
result.Items = await ToDtos(
queryResult.Items,
cancellationToken
);
}
}
@@ -241,8 +374,12 @@ namespace xAiApi.AI.Services
/// <see cref="XAiMessageDto"/>
/// </summary>
/// <param name="queryResult"><see cref="XAiMessage"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<XAiMessageDto>> ToDtoQueryResult(XQueryResult<XAiMessage> queryResult)
public async Task<XQueryResult<XAiMessageDto>> ToDtoQueryResult(
XQueryResult<XAiMessage> queryResult,
CancellationToken cancellationToken = default
)
{
//
var result = new XQueryResult<XAiMessageDto>();
@@ -262,7 +399,11 @@ namespace xAiApi.AI.Services
//
if (queryResult.Items.HasChild())
{
result.Items = await ToDtos(queryResult.Items);
//
result.Items = await ToDtos(
queryResult.Items,
cancellationToken
);
}
}
@@ -275,8 +416,12 @@ namespace xAiApi.AI.Services
/// <see cref="XAiConversationDto"/>
/// </summary>
/// <param name="queryResult"><see cref="XAiConversation"/></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<XQueryResult<XAiConversationDto>> ToDtoQueryResult(XQueryResult<XAiConversation> queryResult)
public async Task<XQueryResult<XAiConversationDto>> ToDtoQueryResult(
XQueryResult<XAiConversation> queryResult,
CancellationToken cancellationToken = default
)
{
//
var result = new XQueryResult<XAiConversationDto>();
@@ -296,7 +441,11 @@ namespace xAiApi.AI.Services
//
if (queryResult.Items.HasChild())
{
result.Items = await ToDtos(queryResult.Items);
//
result.Items = await ToDtos(
queryResult.Items,
cancellationToken
);
}
}
@@ -307,27 +456,60 @@ namespace xAiApi.AI.Services
/// <summary>
/// Check Permission for Ai Actions ...
/// </summary>
/// <param name="projectId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> HasPermission(XUserClaimsInfoDto userInfo)
public async Task<bool> HasPermission(
string projectId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
var result = true;
var result =
!userInfo.IsNullOrDefault() &&
!userInfo.UserId.IsNullOrEmpty();
if (!result)
{
return result;
}
//
// TODO: Complete this ...
try
{
//
var person = await GetPerson(
ownerId: userInfo.UserId,
cancellationToken: cancellationToken
);
//
result = !person.IsNullOrDefault();
}
catch
{
result = false;
}
//
return await Task.FromResult(result);
return result;
}
/// <summary>
/// Prepare Prompt ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="projectId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<string> PreparePrompt(string prompt, XUserClaimsInfoDto userInfo)
public async Task<string> PreparePrompt(
string prompt,
string projectId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
var result = prompt;
@@ -344,15 +526,135 @@ namespace xAiApi.AI.Services
/// Ask a Question ...
/// </summary>
/// <param name="prompt"></param>
/// <param name="projectId"></param>
/// <param name="conversationId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<XAiMessageDto> Ask(
public async Task<XAiMessageDto> Ask(
string prompt,
Guid conversationId,
XUserClaimsInfoDto userInfo
string projectId = null,
string conversationId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Access Project ...
var project = await GetProject(
userInfo: userInfo,
projectId: projectId,
cancellationToken: cancellationToken
);
var isValid = !project.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Check Project is Default Project or not ...
var isDefaultProject = project.Title == XAiProjectEnum.Default.GetStringValue();
//
// Access Conversation ...
var conversation = await GetConversation(
userInfo: userInfo,
projectId: projectId,
conversationId: conversationId,
cancellationToken: cancellationToken
);
isValid = !conversation.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Check First Question or not ...
var isFirstConversation = !conversation.Messages.HasChild();
//
// Check Permissions ...
isValid = await HasPermission(
userInfo: userInfo,
projectId: projectId,
cancellationToken: cancellationToken
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
// Preparing Chat History ...
IList<ChatMessage> chatHistory = null;
//
// Check if First Question ...
if (isFirstConversation)
{
//
// Add Introduction Prompt ...
chatHistory.Add(
new ChatMessage(
content: Configuration.Introduction,
role: XAiChatRole.System.ToChatRole()
)
);
//
// Add Project Prompt, if not Default Project ...
if (!isDefaultProject)
{
//
chatHistory.Add(
new ChatMessage(
content: project.Prompt,
role: XAiChatRole.System.ToChatRole()
)
);
}
}
else
{
//
// Complete Chat History ...
// TODO: Complete this ...
}
//
// Prepare Prompt ...
prompt = await PreparePrompt(
prompt: prompt,
userInfo: userInfo,
projectId: projectId,
cancellationToken: cancellationToken
);
if (chatHistory.IsNull())
{
chatHistory = new List<ChatMessage>();
}
chatHistory.Add(
new ChatMessage(
content: prompt,
role: XAiChatRole.User.ToChatRole()
)
);
//
// Getting Response Message from LLM ...
var chatResult = await chatClient
.GetResponseAsync(
options: chatOptions,
messages: chatHistory,
cancellationToken: cancellationToken
);
//
// TODO: Handle Here ...
//
throw new NotImplementedException();
}
@@ -363,8 +665,12 @@ namespace xAiApi.AI.Services
/// <see cref="XPersonDto"/>
/// </summary>
/// <param name="ownerId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<XPersonDto> GetPerson(string ownerId)
private async Task<XPersonDto> GetPerson(
string ownerId,
CancellationToken cancellationToken = default
)
{
//
XPersonDto result = null;
@@ -390,6 +696,203 @@ namespace xAiApi.AI.Services
//
return result;
}
/// <summary>
/// Retrieve Specified Project or Default ...
/// </summary>
/// <param name="projectId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<XAiProjectDto> GetProject(
string projectId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Validate UserInfo ...
var isValid =
!userInfo.IsNullOrDefault() &&
!userInfo.UserId.IsNullOrEmpty();
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
// Check UserInfo ...
var personDto = await GetPerson(
ownerId: userInfo.UserId,
cancellationToken: cancellationToken
);
isValid = !personDto.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
XAiProject project = null;
//
// Check Default Project is Exists or not ...
var defaultProject = await aiProjectRepository.FindOneAsync(
containsDetail: true,
ignoreSoftDeleteds: true,
whereClause: x =>
x.OwnerId == userInfo.UserId &&
x.Title == XAiProjectEnum.Default.GetStringValue()
);
var isExists = !defaultProject.IsNullOrDefault();
if (!isExists)
{
//
// Create Default Project ...
defaultProject = new XAiProject
{
Prompt = string.Empty,
OwnerId = userInfo.UserId,
Description = string.Empty,
CreatedOn = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
Title = XAiProjectEnum.Default.GetStringValue(),
};
//
defaultProject = await aiProjectRepository.AddAsync(
saveChanges: true,
item: defaultProject
);
//
isExists = !defaultProject.IsNullOrDefault();
}
//
// Validate Project ID ...
if (projectId.IsNullOrEmpty())
{
//
// Default Project ...
project = defaultProject;
projectId = defaultProject.Id.ToString();
}
else
{
//
// Special Project ...
project = await aiProjectRepository.FindOneAsync(
containsDetail: false,
ignoreSoftDeleteds: true,
whereClause: x =>
x.Id.ToString() == projectId &&
x.OwnerId == userInfo.UserId
);
isExists = !project.IsNullOrDefault();
if (!isExists)
{
//
// If Not Exists Use Default ...
project = defaultProject;
}
}
//
// Converts to Dto ...
var result = await ToDto(
entity: project,
cancellationToken: cancellationToken
);
//
return result;
}
/// <summary>
/// Retrieve Conversation for Asking ...
/// </summary>
/// <param name="projectId"></param>
/// <param name="conversationId"></param>
/// <param name="userInfo"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<XAiConversationDto> GetConversation(
string projectId = null,
string conversationId = null,
XUserClaimsInfoDto userInfo = null,
CancellationToken cancellationToken = default
)
{
//
// Validate User Info ...
var isValid = await HasPermission(
userInfo: userInfo,
projectId: projectId,
cancellationToken: cancellationToken
);
if (!isValid)
{
XException.NotAllowed.Throw();
}
//
var project = await GetProject(
userInfo: userInfo,
projectId: projectId,
cancellationToken: cancellationToken
);
isValid = !project.IsNullOrDefault();
if (!isValid)
{
XException.NotFound.Throw();
}
//
// Check Conversation Exists ...
var result =
project.Conversations
.FirstOrDefault(x =>
x.OwnerId == userInfo.UserId &&
x.Id.ToString() == conversationId
);
var isExists =
!result.IsNullOrDefault() &&
!conversationId.IsNullOrEmpty();
if (!isExists)
{
//
var title = $"Conversation {Guid.NewGuid()}";
var conversationEntity = new XAiConversation
{
Title = title,
ProjectId = project.Id,
OwnerId = userInfo.UserId,
CreatedOn = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
};
//
conversationEntity = await aiConversationRepository.AddAsync(
saveChanges: true,
item: conversationEntity
);
isExists = !conversationEntity.IsNullOrDefault();
if (!isExists)
{
XException.NotFound.Throw();
}
//
result = await ToDto(
entity: conversationEntity,
cancellationToken: cancellationToken
);
}
//
return result;
}
#endregion
}
}
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using xAiApi.AI.Interfaces.Entities;
using xAiApi.AI.Models.Entities;
using xDataService.Configuration;
@@ -9,6 +10,11 @@ using xDataService.Interfaces;
namespace xAiApi.Data.Repositories.Ef
{
/// <summary>
/// a Repository Pattern Implementation for
/// manipulating AiConversations ...
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public class XAiConversationEfRepository<TDbContext> : XBaseEFRepository<XAiConversation, Guid, XAiApiDbContext>, IXAiConversationRepository
where TDbContext : XDbContext
{
@@ -28,7 +34,10 @@ namespace xAiApi.Data.Repositories.Ef
public override IQueryable<XAiConversation> GetFullDbSet()
{
return dbSet;
//
return dbSet
.Include(x => x.Project)
.Include(x => x.Messages);
}
//
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using xAiApi.AI.Interfaces.Entities;
using xAiApi.AI.Models.Entities;
using xDataService.Configuration;
@@ -9,6 +10,11 @@ using xDataService.Interfaces;
namespace xAiApi.Data.Repositories.Ef
{
/// <summary>
/// a Repository Pattern Implementation for
/// manipulating AiMessage ...
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public class XAiMessageEfRepository<TDbContext> : XBaseEFRepository<XAiMessage, Guid, XAiApiDbContext>, IXAiMessageRepository
where TDbContext : XDbContext
{
@@ -28,7 +34,9 @@ namespace xAiApi.Data.Repositories.Ef
public override IQueryable<XAiMessage> GetFullDbSet()
{
return dbSet;
//
return dbSet
.Include(x => x.Conversation);
}
//
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using xAiApi.AI.Interfaces.Entities;
using xAiApi.AI.Models.Entities;
using xDataService.Configuration;
@@ -9,6 +10,11 @@ using xDataService.Interfaces;
namespace xAiApi.Data.Repositories.Ef
{
/// <summary>
/// a Repository Pattern Implementation for
/// manipulating AiProjects ...
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
public class XAiProjectEfRepository<TDbContext> : XBaseEFRepository<XAiProject, Guid, XAiApiDbContext>, IXAiProjectRepository
where TDbContext : XDbContext
{
@@ -28,7 +34,9 @@ namespace xAiApi.Data.Repositories.Ef
public override IQueryable<XAiProject> GetFullDbSet()
{
return dbSet;
//
return dbSet
.Include(x => x.Conversations);
}
//
@@ -10,6 +10,10 @@ using xDataService.MongoRepositories;
namespace xAiApi.Data.Repositories.Mongo
{
/// <summary>
/// a Repository Pattern Implementation for
/// manipulating AiConversations ...
/// </summary>
public class XAiConversationMongoRepository : XBaseMongoRepository<XAiConversation, Guid>, IXAiConversationRepository
{
//
@@ -10,6 +10,10 @@ using xDataService.MongoRepositories;
namespace xAiApi.Data.Repositories.Mongo
{
/// <summary>
/// a Repository Pattern Implementation for
/// manipulating AiMessage ...
/// </summary>
public class XAiMessageMongoRepository : XBaseMongoRepository<XAiMessage, Guid>, IXAiMessageRepository
{
//
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using xAiApi.AI.Interfaces.Entities;
@@ -10,6 +11,10 @@ using xDataService.MongoRepositories;
namespace xAiApi.Data.Repositories.Mongo
{
/// <summary>
/// a Repository Pattern Implementation for
/// manipulating AiProjects ...
/// </summary>
public class XAiProjectMongoRepository : XBaseMongoRepository<XAiProject, Guid>, IXAiProjectRepository
{
//
@@ -28,6 +33,7 @@ namespace xAiApi.Data.Repositories.Mongo
public override IMongoQueryable<XAiProject> GetFullDbSet()
{
//
return collection
.AsQueryable();
}
+3 -1
View File
@@ -9,7 +9,9 @@
],
"AiApiServiceConfiguration": {
"Url":"http://localhost:11434",
"TextModel": "gemma3:1b"
"Model": "gemma3:1b",
"TextModel": "gemma3:1b",
"Introduction": "Your Name is xSaherElm AI, you extends by SaherElm IT Center, your trainer is Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com), you are an ai assistant which acts as a senior Software Architecture, senior Software Developer and Senior Trader"
},
"IdentityServiceConfiguration": {
"Authority": "https://localhost:4001",