本项目包含以下主要组件:
- DBGen: 向量数据库生成服务,用于处理用户上传的文档并生成向量数据库
- RagCore: RAG核心服务,用于基于向量数据库进行检索增强生成
- AIServer: Web API服务器,集成DBGen和RagCore,提供REST API
- RagTest: 示例程序,演示如何使用RagCore连接到独立的向量数据库和历史对话数据库
本项目中涉及两种完全独立的数据库:
-
向量数据库:由DBGen生成,存储文档的向量表示和原始内容
- 主要用途:存储文档向量和内容,用于语义搜索
- 包含表:
documents、document_records、ActiveIDMapping - 技术特点:需要vec0 SQLite扩展支持
-
会话历史数据库:由RagCore维护,独立存储用户对话历史
- 用途:记录用户的对话历史,提供上下文连续性
- 包含表:
ActiveIDHistoryMapping - 技术特点:使用标准SQLite,不需要特殊扩展
-
用户上传文档时:
- 通过
FileController调用DBGen服务 DBGen将文档进行拆分、向量化,并存储到特定的向量数据库中
- 通过
-
用户对话时:
- 通过
QuestController调用RagCore服务 RagCore动态切换到指定的向量数据库和历史对话数据库- 在向量数据库中搜索相关内容,并与LLM结合生成回答
- 对话历史保存在独立的历史对话数据库中
- 通过
最新版本实现了以下重要改进:
-
数据库完全分离:向量数据库和历史对话数据库现在完全独立
// RagOptions现在包含两个数据库连接字符串 public required string DbConnectionString { get; set; } public required string HistoryDbConnectionString { get; set; }
-
新增接口方法:
IRagService增加了切换历史数据库和同时切换两个数据库的方法Task SwitchVectorDatabaseAsync(string dbPath); Task SwitchHistoryDatabaseAsync(string dbPath); Task SwitchDatabasesAsync(string vectorDbPath, string historyDbPath);
-
服务注册扩展:新增
AddRagCoreWithSeparateDb方法,支持分别指定两个数据库services.AddRagCoreWithSeparateDb(options => { ... }, vectorDbPath, historyDbPath);
-
简化路径设置:移除了路径构建的复杂逻辑,允许用户直接指定完整路径
主要有两种使用方式:
-
服务注册时指定:适用于固定使用特定数据库的场景
// 同时指定两个数据库路径 services.AddRagCoreWithSeparateDb(options => { ... }, vectorDbPath, historyDbPath); // 只指定向量数据库,历史数据库使用默认路径 services.AddRagCoreWithExistingVectorDb(options => { ... }, vectorDbPath);
-
动态切换:适用于需要在运行时切换数据库的场景
// 同时切换两个数据库 await ragService.SwitchDatabasesAsync(vectorDbPath, historyDbPath); // 只切换向量数据库 await ragService.SwitchVectorDatabaseAsync(vectorDbPath); // 只切换历史对话数据库 await ragService.SwitchHistoryDatabaseAsync(historyDbPath);
RagTest是一个控制台应用程序,演示了如何使用RagCore连接到独立的数据库:
- 允许用户分别指定向量数据库和历史对话数据库路径
- 支持命令行参数(--vectordb=PATH, --historydb=PATH)
- 支持标签筛选和流式响应
详细使用说明请参考 RagTest/README.md。
- 向量数据库使用SQLite + vec0扩展实现
- 历史对话数据库使用标准SQLite,无需特殊扩展
- 两个数据库可以存储在不同位置,方便管理
- 支持内存数据库模式(":memory:")用于测试
// 构建数据库路径
var company = User.FindFirst("Company")?.Value ?? "Default";
var vectorDbPath = Path.Combine(Directory.GetCurrentDirectory(), $"Vector/{company}.db");
var historyDbPath = Path.Combine(Directory.GetCurrentDirectory(), $"History/{company}.db");
// 切换到指定的数据库
await _ragService.SwitchDatabasesAsync(vectorDbPath, historyDbPath);
// 设置活动ID并使用RAG服务
_ragService.SetActiveId(request.ActiveID);
await foreach (var chunk in _ragService.GetChatResponseAsync(request.Question, request.Tag))
{
// 处理响应
}// 注册服务,同时指定两个数据库
services.AddRagCoreWithSeparateDb(options => {
options.OpenAIApiKey = configuration["AppSettings:OpenAIApiKey"];
options.OpenAIModelId = configuration["AppSettings:OpenAIModelId"];
options.ChatServiceApiKey = configuration["AppSettings:ChatServiceApiKey"];
options.ChatServiceModelId = configuration["AppSettings:ChatServiceModelId"];
}, vectorDbPath, historyDbPath);
// 获取服务并使用
var ragService = serviceProvider.GetRequiredService<IRagService>();
await ragService.CreateTablesIfNotExistsAsync();
ragService.SetActiveId(1);
// 获取回答
await foreach (var chunk in ragService.GetChatResponseAsync("你的问题", "可选标签"))
{
Console.Write(chunk);
}如果您之前使用的是单一数据库版本,需要迁移到分离数据库版本,请按以下步骤操作:
- 保留原数据库作为向量数据库
- 创建新的空数据库作为历史对话数据库
- 使用新的API同时连接两个数据库
- 历史对话会自动在新数据库中重新创建