ai agent --- 文件存储

文章来源声明: 原文作者:snow来了; 来源站点:掘金; 原文链接:https://juejin.cn/post/7692274273326579748; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

适合正在搭建RAG或AI Agent的开发者阅读。MinIO适合本地低成本起步,阿里云OSS省运维,掌握S3统一API可显著降低迁移与维护成本。

![image.png](https://p6-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/9be2f6e37ba14190afa02d679434d68a~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAgc25vd-adpeS6hg==:q75.awebp?rk3s=f64ab15b&x-expires=1791721950&x-signature=BsRZraoStT62%2FLk8K%2BqNfVcGC6Y%3D)

在和ai会话的时候我们总会给他一堆文件要他处理,有图片,word,excel,pdf等等。会话结束后,在历史会话里面,如何拿到这个文件,就成了问题。文件必须要存储在一个地方,这个地方就是对象数据库。

一.对象数据库

对象数据库 = 让数据库"懂对象" ,也就是用来存储对象的数据库。对象和类直接存进去,免了 ORM 那层转换,适合数据结构复杂、对象关系盘根错节的场景;平时最常见的CRUD业务它并不占优。

上面的概念太笼统,我们不想听,那就想下mysql,mysql是关系型数据库,就是一行一行的保存数据,但是mysql对文件图片的存储是有限制的,你可以把图片转成base64存进去,但是大文档呢?

一般的对象数据库有:MinIO、RustFS、和 阿里云 OSS,MinIO和RustFS是你可以安装到本地的对象数据库,阿里云 OSS是阿里云上的对象存储方案。

image.png

二.在ai agent 里面 minIO 使用场景

在一般的企业会将文件都存到对象数据库里面,然后将文件的元数据(文件名字,大小,存储位置,时间等信息)存储到关系型数据库上。

在 ai agent 项目里面,会话文件会存储,RAG检索也会有文件存储,一般我们都将文件放到minIO里面,然后将文件的元数据存放在mysql里面。使用的时候,我们会根据mysql的id拿到元数据,再通过元数据去阿里云minIO里面去获取原文件。

具体操作流程如下:

image.png

强调:minIO里面存储的是文档原件,向量数据库milvus存储的是文件块的向量值,文件块和元数据是放在mysql里面的。

image.png

对于RAG这个场景,我们做一下系统的梳理:

1.存数据

用户通过前端上传文件,后端代码将上传的原文件存到minIO数据库,然后从这个原文件提取文件元数据(文件名,类型,大小,上传时候等等信息),然后把原文件切成块,将文件块和元数据存到mysql里面,,然后用嵌入模型将切好的文档块转化成向量值,存到向量数据库milvus里面。当然你可以选择postgreSQl数据库,将元数据、文件块、向量都存到postgreSQl数据库里面。

image.png

2.取数据

用户提问,先用嵌入模型将问题处理成向量,去milvus里面做余弦相似度比较,找到相似文件块,根据id去mysql里面找到原文件的元信息(文件名,存储位置等等),根据文件位置去minIO里面拿对应的原文件。

image.png

三.如何选择阿里云 OSS、MinIO、RustFS

  • 如果业务跑在公有云上、想省去运维压力,直接选阿里云 OSS。
  • 如果只是小型本地自建知识库、低成本快速落地,优先 MinIO。
  • 如果是海量音视频存储、大型集团国产化项目,推荐 RustFS。

image.png

四.使用阿里云oss

1.在线使用阿里云oss

官网地址:www.aliyun.com/product/os 五块钱可以用很久。

image.png

支付成功进入控制台

image.png

进入bucket列表创建一个bucket

image.png

上传文件

image.png

点击可以查看或者下载

image.png

点击详情可以看到上传图片的详细信息,还能拿到url在浏览器上下载

image.png

2.在nodejs里面使用oss

进入:oss.console.aliyun.com/vector-buck…

2.1 安装包

pnpm install dotenv ali-oss

2.2 配置信息

OSS_REGION=oss-cn-beijing
OSS_ACCESS_KEY_ID=你的id
OSS_ACCESS_KEY_SECRET=你的秘钥
OSS_BUCKET=agent-bucket999

OSS\_BUCKET这里取image.png

OSS\_REGION这里取image.png

OSS\_ACCESS\_KEY\_ID 和 OSS\_ACCESS\_KEY\_SECRET 这里取image.png

image.png

创建个子账号,获取OSS\_ACCESS\_KEY\_ID 和 OSS\_ACCESS\_KEY\_SECRET

image.png

2.3nodejs代码

import 'dotenv/config';
import OSS from 'ali-oss';
import fs from 'fs';
import { fileURLToPath } from 'url';

import path from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const client = new OSS({
  region: process.env.OSS_REGION,
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  bucket: process.env.OSS_BUCKET,
});

async function putStream () {
  try {
    const stream = fs.createReadStream(path.join(__dirname, 'zao.png'));
    let result = await client.putStream('aaa/bbb/first.png', stream);    
    console.log(result); 
  } catch (e) {
    console.log(e)
  }
}

putStream();

执行后查看结果:oss.console.aliyun.com/bucket/oss-…

image.png

五.使用@aws-sdk/client-s3

在使用 阿里云oss、minIO、rustFS上他们的api使用方式都差不多,是因为他们三类存储底层全部遵循 S3 标准协议,核心能力基本一致。

所以安装 @aws-sdk/client-s3 这一个aws的包就能对接所有OSS服务,也可以分别用ali-oss、minio来对接。

S3 = Simple Storage Service,AWS 的对象存储服务。

我们用 @aws-sdk/client-s3对接ali-oss试试。

@aws-sdk/client-s3是 AWS 官方 Node.js SDK v3,专门用来操作 S3 对象存储。

import 'dotenv/config';
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import fs from 'fs';
import { fileURLToPath } from 'url';
import path from 'path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 对接阿里云OSS(S3兼容模式)
const s3Client = new S3Client({
  // ✅ endpoint必须完整https地址
  endpoint: `https://${process.env.OSS_REGION}.aliyuncs.com`,
  credentials: {
    accessKeyId: process.env.OSS_ACCESS_KEY_ID,
    secretAccessKey: process.env.OSS_ACCESS_KEY_SECRET
  },
 // forcePathStyle: true, // 阿里云S3兼容模式必须开启
  region: process.env.OSS_REGION
});

async function putStream() {
  try {
    const stream = fs.readFileSync(path.join(__dirname, 'shanf.png'));

    const command = new PutObjectCommand({
      Bucket: process.env.OSS_BUCKET,
      Key: 'bbb/ccc/second.png',
      Body: stream,
      ContentType: 'image/png'
    });

    const result = await s3Client.send(command);
    console.log('上传成功:', result);
  } catch (e) {
    console.error('上传异常:', e);
  }
}

putStream();


image.png

六.在aiagent里面使用过oss

如果在和ai聊天的时候使用图片,那么对应的大模型一定是多模态大模型,也就是他自己得会读图片和视频里面的内容才行。

比如这个就是多模态的,他支持文本,图片,视频

image.png

比如这个就是单模态的,他只能输入文本

image.png

所以说,所谓的多模态模型就是那些认识图片和视频,并且能给你解释其中内容的大模型。

在agent里面,ali-oss的使用场景:

image.png

用户输入图片或视频,先存储到oss里面,oss会返回一个url,然后都给大模型调用url访问oss里面的文件,大模型处理后的结果 (新生成的图片) 先存储到oss里面,然后再返回给用户。

值得注意的是,大模型拿到的是url,不是图片文件本身。

实现nodejs代码

import 'dotenv/config';
import { ChatOpenAI } from '@langchain/openai';
import { HumanMessage } from '@langchain/core/messages';

const model = new ChatOpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  model: 'qwen-vl-plus',
  configuration: {
    baseURL: process.env.OPENAI_BASE_URL,
  },
});

const response = await model.invoke([
  new HumanMessage({
    content: [
      { type: 'text', text: '详细描述这张图片的内容' },
      {
        type: 'image_url',
        image_url: {
          url: 'https://agent-bucket999.oss-cn-beijing.aliyuncs.com/%E8%8A%B1%E8%8A%B1.png',
        },
      },
    ],
  }),
]);

console.log('model: qwen-vl-plus');
console.log(response.content);

我们在代码里面要大模型读取一下这个地址的图片看看

image.png

查看结果如下

image.png