Skip to content

之前 RAG 用的是内存向量数据库,实际 AI Agent 产品都用 Milvus 这种专业向量数据库。就像 Web 应用用 MySQL 存数据,AI Agent 应用用 Milvus 存知识和记忆。Milvus 支持向量字段,用余弦相似度做语义检索,这是 MySQL 做不到的。核心流程:Docker 部署 Milvus → 创建 Collection(定义 Schema + 向量索引)→ 插入数据时用嵌入模型向量化 → 检索时 query 向量化做相似度匹配 → 结合 RAG 给大模型当上下文。增删改查都走 SDK,删除不需要向量化。

类比:Web 应用用 MySQL 存数据做增删改查,AI Agent 应用用 Milvus 存知识和记忆做检索增删改。

核心区别:MySQL 只能按 id / 关键词检索,Milvus 支持向量语义检索

Docker 部署 Milvus

bash
docker compose -f ./milvus-standalone-docker-compose.yml up -d
  • 端口:19530(数据库服务)
  • 健康检查:http://localhost:9091/healthz
  • GUI 工具:Attu

安装依赖

bash
pnpm install @zilliz/milvus2-sdk-node @langchain/openai dotenv

创建 Collection(定义 Schema + 索引)

js
import { MilvusClient, DataType, IndexType, MetricType } from '@zilliz/milvus2-sdk-node';

const client = new MilvusClient({ address: 'localhost:19530' });

// 创建集合,定义 Schema
await client.createCollection({
  collection_name: 'ai_diary',
  fields: [
    { name: 'id', data_type: DataType.VarChar, max_length: 50, is_primary_key: true },
    { name: 'vector', data_type: DataType.FloatVector, dim: 1024 },  // 向量字段
    { name: 'content', data_type: DataType.VarChar, max_length: 5000 },
    { name: 'date', data_type: DataType.VarChar, max_length: 50 },
    { name: 'mood', data_type: DataType.VarChar, max_length: 50 },
    { name: 'tags', data_type: DataType.Array, element_type: DataType.VarChar, max_capacity: 10, max_length: 50 },
  ],
});

// 创建向量索引(余弦相似度)
await client.createIndex({
  collection_name: 'ai_diary',
  field_name: 'vector',
  index_type: IndexType.IVF_FLAT,
  metric_type: MetricType.COSINE,  // 用余弦相似度
  params: { nlist: 1024 },
});

// 加载集合到内存
await client.loadCollection({ collection_name: 'ai_diary' });

插入数据(需要向量化)

js
async function getEmbedding(text) {
  return await embeddings.embedQuery(text);
}

const diaryData = await Promise.all(
  diaryContents.map(async (diary) => ({
    ...diary,
    vector: await getEmbedding(diary.content),  // 嵌入模型向量化
  }))
);

await client.insert({
  collection_name: 'ai_diary',
  data: diaryData,
});

检索(query 向量化 + 余弦相似度)

js
const queryVector = await getEmbedding('我想看看关于户外活动的日记');

const searchResult = await client.search({
  collection_name: 'ai_diary',
  vector: queryVector,
  limit: 2,
  output_fields: ['id', 'content', 'date', 'mood', 'tags'],
});

// searchResult.results 包含相似度分数和数据

结合 RAG 完整流程

js
// 1. 检索相关日记
const retrievedDiaries = await retrieveRelevantDiaries(question, k);

// 2. 拼成上下文
const context = retrievedDiaries
  .map((diary, i) => `[日记 ${i + 1}]\n日期: ${diary.date}\n内容: ${diary.content}`)
  .join('\n\n━━━━━\n\n');

// 3. 构建 prompt 调用大模型
const prompt = `基于以下日记内容回答问题:\n${context}\n\n问题: ${question}`;
const response = await model.invoke(prompt);

更新数据(upsert,需要重新向量化)

js
const vector = await getEmbedding(updatedContent.content);

await client.upsert({
  collection_name: 'ai_diary',
  data: [{ ...updatedContent, vector }],  // 带 id 就是更新
});

删除数据(不需要向量化)

js
// 单条删除
await client.delete({
  collection_name: 'ai_diary',
  filter: 'id == "diary_005"',
});

// 批量删除
await client.delete({
  collection_name: 'ai_diary',
  filter: 'id in ["diary_002", "diary_003"]',
});

// 条件删除
await client.delete({
  collection_name: 'ai_diary',
  filter: 'mood == "sad"',
});

流程图

text
AI Agent 应用

Milvus 向量数据库(存知识、记忆)
    ├── 插入:文本 → 嵌入模型 → 向量化 → 存入
    ├── 检索:query → 嵌入模型 → 向量化 → 余弦相似度匹配
    ├── 更新:文本 → 嵌入模型 → 重新向量化 → upsert
    └── 删除:直接按 id / 条件删,不需要向量化

要点

  • Milvus 是 AI Agent 的"数据库" — 就像 MySQL 之于 Web 应用
  • 核心区别是向量语义检索 — MySQL 按关键词,Milvus 按语义相似度
  • 增删改查四件套 — 插入/更新/检索需要嵌入模型向量化,删除不需要
  • Schema 定义 Collection 结构 — 关键是 FloatVector 类型的向量字段
  • 索引用余弦相似度 — MetricType.COSINE,和之前 RAG 的原理一致
  • RAG 流程 — 检索相关文档 → 拼成上下文 → 调用大模型生成回答