feat: 完成ai message、session搭建
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class MessageDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public Guid SessionId { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string Role { get; set; }
|
||||
public decimal DeductCost { get; set; }
|
||||
public decimal TotalTokens { get; set; }
|
||||
public string ModelId { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Yi.Framework.Ddd.Application.Contracts;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class MessageGetListInput:PagedAllResultRequestDto
|
||||
{
|
||||
[Required]
|
||||
public Guid SessionId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class MessageInputDto
|
||||
{
|
||||
public string Content { get; set; }
|
||||
public string Role { get; set; }
|
||||
public decimal DeductCost { get; set; }
|
||||
public decimal TotalTokens { get; set; }
|
||||
public string ModelId { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -4,6 +4,8 @@ public class SendMessageInput
|
||||
{
|
||||
public List<Message> Messages { get; set; }
|
||||
public string Model { get; set; }
|
||||
|
||||
public Guid? SessionId{ get; set; }
|
||||
}
|
||||
|
||||
public class Message
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SessionDto : FullAuditedEntityDto<Guid>
|
||||
{
|
||||
public string SessionTitle { get; set; }
|
||||
public string SessionContent { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SessionGetListInput
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
|
||||
public class SessionInputDto
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public string SessionTitle { get; set; }
|
||||
public string SessionContent { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -6,21 +6,28 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using OpenAI.Chat;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Options;
|
||||
using Yi.Framework.AiHub.Domain.Managers;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
public class AiService : ApplicationService
|
||||
/// <summary>
|
||||
/// ai服务
|
||||
/// </summary>
|
||||
public class AiChatService : ApplicationService
|
||||
{
|
||||
private readonly AiGateWayOptions _options;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly AiMessageManager _aiMessageManager;
|
||||
|
||||
public AiService(IOptions<AiGateWayOptions> options, IHttpContextAccessor httpContextAccessor)
|
||||
public AiChatService(IOptions<AiGateWayOptions> options, IHttpContextAccessor httpContextAccessor,
|
||||
AiMessageManager aiMessageManager)
|
||||
{
|
||||
_options = options.Value;
|
||||
this._httpContextAccessor = httpContextAccessor;
|
||||
_aiMessageManager = aiMessageManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +82,7 @@ public class AiService : ApplicationService
|
||||
}
|
||||
|
||||
var gateWay = LazyServiceProvider.GetRequiredService<AiGateWayManager>();
|
||||
var completeChatResponse = gateWay.CompleteChatAsync(input.Model, history,cancellationToken);
|
||||
var completeChatResponse = gateWay.CompleteChatAsync(input.Model, history, cancellationToken);
|
||||
await using var writer = new StreamWriter(response.Body, Encoding.UTF8, leaveOpen: true);
|
||||
await foreach (var data in completeChatResponse)
|
||||
{
|
||||
@@ -88,10 +95,24 @@ public class AiService : ApplicationService
|
||||
await writer.WriteLineAsync($"data: {message}\n");
|
||||
await writer.FlushAsync(cancellationToken); // 确保立即推送数据
|
||||
}
|
||||
|
||||
|
||||
//断开连接
|
||||
await writer.WriteLineAsync($"data: done\n");
|
||||
await writer.FlushAsync(cancellationToken); // 确保立即推送数据
|
||||
|
||||
if (CurrentUser.IsAuthenticated && input.SessionId.HasValue)
|
||||
{
|
||||
// 等待接入token
|
||||
// await _aiMessageManager.CreateMessageAsync(CurrentUser.GetId(), input.SessionId.Value, new MessageInputDto
|
||||
// {
|
||||
// Content = null,
|
||||
// Role = null,
|
||||
// DeductCost = 0,
|
||||
// TotalTokens = 0,
|
||||
// ModelId = null,
|
||||
// Remark = null
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
using Yi.Framework.AiHub.Domain.Entities;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
public class MessageService : ApplicationService
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageAggregateRoot> _repository;
|
||||
|
||||
public MessageService(ISqlSugarRepository<MessageAggregateRoot> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询消息
|
||||
/// 需要会话id
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
public async Task<PagedResultDto<MessageDto>> GetListAsync(MessageGetListInput input)
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
var userId = CurrentUser.GetId();
|
||||
var entities = await _repository._DbQueryable
|
||||
.Where(x => x.SessionId == input.SessionId)
|
||||
.Where(x=>x.UserId == userId)
|
||||
.OrderByDescending(x => x.Id)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
return new PagedResultDto<MessageDto>(total, entities.Adapt<List<MessageDto>>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using Mapster;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
using Yi.Framework.AiHub.Domain.Entities;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Application.Services;
|
||||
|
||||
public class SessionService : CrudAppService<SessionAggregateRoot, SessionDto, Guid, SessionGetListInput>
|
||||
{
|
||||
private readonly ISqlSugarRepository<SessionAggregateRoot, Guid> _repository;
|
||||
public readonly ISqlSugarRepository<MessageAggregateRoot, Guid> _messageRepository;
|
||||
public SessionService(ISqlSugarRepository<SessionAggregateRoot, Guid> repository, ISqlSugarRepository<MessageAggregateRoot, Guid> messageRepository) : base(repository)
|
||||
{
|
||||
_repository = repository;
|
||||
_messageRepository = messageRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建会话
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
public override async Task<SessionDto> CreateAsync(SessionDto input)
|
||||
{
|
||||
var entity = await MapToEntityAsync(input);
|
||||
entity.UserId = CurrentUser.GetId();
|
||||
await _repository.InsertAsync(entity);
|
||||
return entity.Adapt<SessionDto>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 详情会话
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
public override Task<SessionDto> GetAsync(Guid id)
|
||||
{
|
||||
return base.GetAsync(id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编辑会话
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
public override Task<SessionDto> UpdateAsync(Guid id, SessionDto input)
|
||||
{
|
||||
return base.UpdateAsync(id, input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除会话
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
public override async Task DeleteAsync(Guid id)
|
||||
{
|
||||
await base.DeleteAsync(id);
|
||||
//对应的消息一起删除
|
||||
await _messageRepository.DeleteAsync(x => x.SessionId == id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询会话
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[Authorize]
|
||||
public override Task<PagedResultDto<SessionDto>> GetListAsync(SessionGetListInput input)
|
||||
{
|
||||
return base.GetListAsync(input);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities.Auditing;
|
||||
|
||||
namespace Yi.Framework.AiHub.Domain.Entities;
|
||||
|
||||
[SugarTable("Ai_Message")]
|
||||
[SugarIndex($"index_{{table}}_{nameof(UserId)}", $"{nameof(UserId)}", OrderByType.Asc)]
|
||||
public class MessageAggregateRoot : FullAuditedAggregateRoot<Guid>
|
||||
{
|
||||
public MessageAggregateRoot()
|
||||
{
|
||||
}
|
||||
|
||||
public MessageAggregateRoot(Guid userId, Guid sessionId, string content, string role, string modelId)
|
||||
{
|
||||
UserId = userId;
|
||||
SessionId = sessionId;
|
||||
Content = content;
|
||||
Role = role;
|
||||
ModelId = modelId;
|
||||
}
|
||||
|
||||
public Guid UserId { get; set; }
|
||||
public Guid SessionId { get; set; }
|
||||
public string Content { get; set; }
|
||||
public string Role { get; set; }
|
||||
public decimal DeductCost { get; set; }
|
||||
public decimal TotalTokens { get; set; }
|
||||
public string ModelId { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using SqlSugar;
|
||||
using Volo.Abp.Domain.Entities.Auditing;
|
||||
|
||||
namespace Yi.Framework.AiHub.Domain.Entities;
|
||||
|
||||
[SugarTable("Ai_Session")]
|
||||
[SugarIndex($"index_{{table}}_{nameof(UserId)}",$"{nameof(UserId)}", OrderByType.Asc)]
|
||||
public class SessionAggregateRoot : FullAuditedAggregateRoot<Guid>
|
||||
{
|
||||
public Guid UserId { get; set; }
|
||||
public string SessionTitle { get; set; }
|
||||
public string SessionContent { get; set; }
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Volo.Abp.Domain.Services;
|
||||
using Volo.Abp.Users;
|
||||
using Yi.Framework.AiHub.Application.Contracts.Dtos;
|
||||
using Yi.Framework.AiHub.Domain.Entities;
|
||||
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||
|
||||
namespace Yi.Framework.AiHub.Domain.Managers;
|
||||
|
||||
public class AiMessageManager : DomainService
|
||||
{
|
||||
private readonly ISqlSugarRepository<MessageAggregateRoot> _repository;
|
||||
|
||||
public AiMessageManager(ISqlSugarRepository<MessageAggregateRoot> repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建消息
|
||||
/// </summary>
|
||||
/// <param name="sessionId"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task CreateMessageAsync(Guid userId, Guid sessionId, MessageInputDto input)
|
||||
{
|
||||
var message = new MessageAggregateRoot(userId, sessionId, input.Content, input.Role, input.ModelId);
|
||||
await _repository.InsertAsync(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user