- 添加HNSW向量索引提升检索性能 - 实现Hybrid检索模式支持向量和关键词双路召回 - 采用RRF算法融合多路召回结果 - 支持ParentChild分块模式的上下文回填 - 优化向量写入采用批量SQL操作提升性能 - 添加RAG PostgreSQL连接字符串配置 - 更新部署脚本增加PGVector集成测试 - 修正表名引用从document_chunks到b_document_chunks - 重构RagRetrievalService实现完整的检索流程 - 增加重排策略支持关键词和LLM重排 - 修改服务器部署地址配置
93 lines
3.3 KiB
C#
93 lines
3.3 KiB
C#
using System.Runtime.CompilerServices;
|
||
using BuildFlow.Shared.Domain.Common;
|
||
using IM.Domain.Entities.Conversation;
|
||
using IM.Domain.Entities.ConversationParticipant;
|
||
using IM.Domain.Entities.Group;
|
||
using IM.Domain.Entities.GroupMember;
|
||
using IM.Domain.Enums;
|
||
using IM.Infrastructure.Persistence;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
|
||
namespace BuildFlow.IM.Tests;
|
||
|
||
/// <summary>
|
||
/// IM 模块测试数据库工厂:每个用例独立 InMemory 库,并通过 SavingChanges 事件自动补齐
|
||
/// IAuditable / IHasOperatorIP 审计字段(InMemory 无 AuditInterceptor,须手动补值,否则非空审计字段为 null)。
|
||
/// </summary>
|
||
internal static class IMTestDb
|
||
{
|
||
public static ImDbContext Create([CallerMemberName] string testName = "")
|
||
{
|
||
var services = new ServiceCollection();
|
||
services.AddDbContext<ImDbContext>(options =>
|
||
options.UseInMemoryDatabase($"im-{testName}-{Guid.NewGuid()}"));
|
||
var db = services.BuildServiceProvider().GetRequiredService<ImDbContext>();
|
||
db.SavingChanges += FillAuditFields;
|
||
return db;
|
||
}
|
||
|
||
private static void FillAuditFields(object? sender, EventArgs args)
|
||
{
|
||
if (sender is not ImDbContext db) return;
|
||
|
||
foreach (var entry in db.ChangeTracker.Entries())
|
||
{
|
||
if (entry.Entity is IAuditable auditable)
|
||
{
|
||
auditable.CreatedBy ??= "test";
|
||
auditable.UpdatedBy ??= "test";
|
||
if (auditable.CreatedAt == default) auditable.CreatedAt = DateTime.UtcNow;
|
||
if (auditable.UpdatedAt == default) auditable.UpdatedAt = DateTime.UtcNow;
|
||
}
|
||
|
||
if (entry.Entity is IHasOperatorIP operatorEntity)
|
||
operatorEntity.OperatorIP ??= "127.0.0.1";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构造一个群聊会话:群主 + 指成员 + 同步会话参与者。审计字段由 SavingChanges 事件补齐。
|
||
/// 返回 (会话Id, 群组Id)。
|
||
/// </summary>
|
||
public static async Task<(Guid ConversationId, Guid GroupId)> SeedGroupAsync(
|
||
ImDbContext db, string name, Guid ownerId, params Guid[] memberIds)
|
||
{
|
||
var conversation = new ConversationEntity { Type = ConversationTypeEnum.Group };
|
||
db.Conversations.Add(conversation);
|
||
await db.SaveChangesAsync();
|
||
|
||
var group = new GroupEntity
|
||
{
|
||
ConversationId = conversation.Id,
|
||
Name = name,
|
||
OwnerId = ownerId
|
||
};
|
||
db.Groups.Add(group);
|
||
await db.SaveChangesAsync();
|
||
|
||
var allUserIds = new List<Guid> { ownerId };
|
||
allUserIds.AddRange(memberIds.Where(id => id != ownerId));
|
||
|
||
foreach (var userId in allUserIds)
|
||
{
|
||
db.GroupMembers.Add(new GroupMemberEntity
|
||
{
|
||
GroupId = group.Id,
|
||
UserId = userId,
|
||
Role = userId == ownerId ? GroupMemberRoleEnum.Owner : GroupMemberRoleEnum.Member,
|
||
JoinedAt = DateTime.UtcNow
|
||
});
|
||
db.ConversationParticipants.Add(new ConversationParticipantEntity
|
||
{
|
||
ConversationId = conversation.Id,
|
||
UserId = userId,
|
||
JoinedAt = DateTime.UtcNow
|
||
});
|
||
}
|
||
|
||
await db.SaveChangesAsync();
|
||
return (conversation.Id, group.Id);
|
||
}
|
||
}
|