当前位置: 首页 > backend >正文

【MRAG】使用RAG技术增强AI回复的实时性和准确性

概要

我们用2周时间,使用Rust+Python开发了这个名为MRAG的知识库系统。

体验地址:https://mrag.coderbox.cn/

支持私有化部署。
在这里插入图片描述

技术栈

  • 知识库:使用向量数据库milvus,Python的API。目前我们主要维护了一个高考知识库,其中收集整理了近5年的高考相关内容,包含录取分数线、学校信息、专业信息、各专业在各个省份的录取线等,仍在完善中。我们通过对这些非结构化的数据归一化为统一的特征向量,来增强模型的知识能力。其他知识库正在补充中。
  • 服务端:使用Rust(Rocket+Rbatis)。首次尝试使用Rust进行完整的服务端开发,也遇到了不小的阻力。我们使用默认的配置,在x86_64-unknown-linux-musl编译后,可执行文件仅有29M,运行内存稳定在70M左右,相比于Java小了很多。
  • 前端:仍然使用Vue + Element UI。
  • 模型:使用第三方模型,如Deepseek、Qwen等

遇到的问题

ORM框架的抉择

我们最初尝试了diesel,diesel性能确实很不错,但是鉴于不能很好的支持复杂和动态SQL,于是我们选择了Rbatis,一是因为它和MyBatis比较像,可以很快的切换过来,二是因为支持动态SQL,可以很方便的写复杂SQL,虽然性能比diesel差一点点(大概慢5~10ms左右),但是利于开发。

Rbatis事务问题

使用Rbatis时,目前需要手动提交事务,有时候会忘记提交,所以我们简单封装了一个事务函数,当业务逻辑执行成功后自动提交事务,否则回滚。

pub async fn tx<'a, F, R, RV>(exec: F) -> AppResult<RV>
whereF: Fn(RBatisTxExecutor) -> R,R: Future<Output = AppResult<RV>>,
{let tx = match Pool::get()?.acquire_begin().await {Ok(tx) => tx,Err(e) => {log::error!("事务异常: {}", e);return Err(db_error!(e));}};let result = exec(tx.clone()).await;match result {Ok(result) => {match tx.commit().await {Ok(_) => log::debug!("事务提交成功,事务ID:{}", tx.tx_id),Err(e) => {log::error!("事务提交失败,事务ID:{}, 原因: {}", tx.tx_id, e);return Err(db_error!(e));}};Ok(result)}Err(e) => {log::debug!("事务闭包执行失败,即将回滚,错误原因: {}", e);match tx.rollback().await {Ok(_) => {log::debug!("事务回滚成功,事务ID:{}", tx.tx_id);Err(e)}Err(e) => {log::error!("事务回滚失败,事务ID:{}, 原因: {}", tx.tx_id, e);Err(db_error!(e))}}}}
}

Rocket的SSE连接及恢复

Web框架我们使用的是Rocket,Rocket对SSE的支持比较简单,不能向SpringBoot那样直接拿到连接对象,所以我们自己封装了一个SSE的连接池,并支持了连接恢复,使得页面刷新后仍然能接收流式输出。这个问题,在这里也有提到。

让人烦躁的错误处理

在Rust中,无法抛出一个异常,也无法捕获一个异常,需要我们手动处理每一个异常,因此不得不让人思考应该返回什么错误,如何处理这个错误。我们可以使用anyhow传递大部分错误,但是有些错误我们不希望传递到前端展示,比如数据库错误等,以防泄露一些信息,因为我们需要对错误进行分类。
我们对Error分为了以下几种类型:

#[derive(Debug, thiserror::Error)]
pub enum AppError {/// 初始化错误#[error("init error: {0}")]InitError(String),/// 数据库错误#[error("db error: {0}")]DbError(rbatis::Error),/// 系统错误#[error("system error: {0}")]SystemError(anyhow::Error),/// 业务错误。改错误不会传递到前端,仅内部科可见。所有的业务逻辑处理均使用该错误。#[error("business error: {0}")]BusinessError(anyhow::Error),/// 提示类错误。该错误会传递到前端,前端显示给用户,且不会输出到日志。#[error("{0}")]MessageError(String),/// 提示类错误。该错误会传递到前端,并指定一个错误编码,前端显示给用户,且不会输出到日志。#[error("{1}")]MessageCodeError(i32, String),
}

其中只有MessageError错误需要传递到前端展示。

为此我们也提供了一些宏来简化错误处理,例如:

#[macro_export]
macro_rules! message_error {($e:expr) => {AppError::MessageError($e.to_string())};($fmt:expr, $($arg:tt)*) => {AppError::MessageError(format!($fmt, $($arg)*))};
}#[macro_export]
macro_rules! message_code_error {($code:expr, $e:expr) => {AppError::MessageCodeError($code, $e.to_string())};($fmt:expr, $($arg:tt)*) => {AppError::MessageCodeError($code, format!($fmt, $($arg)*))};
}#[macro_export]
macro_rules! business_error {($e:expr) => {AppError::BusinessError(anyhow!($e))};($fmt:expr, $($arg:tt)*) => {AppError::BusinessError(anyhow!(format!($fmt, $($arg)*)))};
}#[macro_export]
macro_rules! db_error {($e:expr) => {AppError::DbError($e)};
}

于是对于大部分错误,我们可以将原始的错误类型包装为AppError,例如:map_err(|e| db_error!(e))?

移动端UI适配

移动端做的比较少,在UI适配时花了不少时间,但效果仍然不理想。可能是因为移动端也使用的时ElementUI,而ElementUI对移动端的支持不是很好的缘故吧。

Rust服务端项目架构问题

前些年使用Java开发后端服务均使用微服务架构,而现在使用Rust开发时时常回想需不需要微服务架构,目前来看是不需要的,一是因为数据量不大,二是因为Rust的性能较好,且比较稳定,可能不需要拆分服务,三是因为Cargo的强大的包管理能力,也很利于分模块或分团队开发,能够在不拆分服务的情况下降低系统耦合度。所以目前来看不需要微服务的,如果向提高并行处理能力,多节点部署即可。

最后

我们后续将开发更简单易用的RAG产品,让所有人都能够建立自己的个性化知识库。

http://www.xdnf.cn/news/655.html

相关文章:

  • Android Kotlin AIDL 完整实现与优化指南
  • Leetcode 3524. Find X Value of Array I
  • 9、Hooks:现代魔法咒语集——React 19 核心Hooks
  • 山东大学软件学院项目实训-基于大模型的模拟面试系统-Token过期重定向问题
  • 代码随想录算法训练营第三十五天|416. 分割等和子集、698.划分为k个相等的子集、473.火柴拼正方形
  • IDEA连接达梦数据库
  • Android学习之实战登录注册能力
  • Django 使用教程
  • 4月19日记(补)算了和周日一块写了 4月20日日记
  • 无法右键下载文档?网页PDF下载方法大全
  • Python赋能去中心化电子商务平台:重构交易生态的新未来
  • 2000-2017年各省天然气消费量数据
  • uni-app中map的使用
  • 52单片机LED实验
  • leetcode205.同构字符串
  • ​opencv图像库编程
  • 股票分析技术指标【MACD】
  • 基于Redis实现RAG架构的技术解析与实践指南
  • [Windows] Adobe Camera Raw 17.2 win/Mac版本
  • Java Streams 使用教程
  • 【Qt】QMainWindow类
  • go环境安装mac
  • QML中的JSON 处理
  • 字节跳动发布视频生成基础大模型 Seaweed-7B
  • 力扣刷题Day 21:两数之和(1)
  • 精打细算 - GPU 监控
  • 解决SQLserver中使用命令bcp,因权限问题无法将文件写入C盘
  • 今天分享一个网店客服回复数据集-用于网点客服AI助手自动回复智能体训练
  • 华硕原厂系统枪神9/9p超竟版-WIN11原装开箱出厂系统安装
  • 山东科技大学人工智能原理考试回忆复习资料