给 AI 装上记忆:基于 Milvus 向量数据库与 RAG 的智能日记系统实战

本文基于 ai/agent_in_action/milvus-demo 目录下的项目代码与文档编写,深入讲解向量数据库的核心概念、Milvus 的技术原理,并通过一个完整的「AI 日记本」项目,手把手带你从零搭建一套基于语义检索的 RAG(Retrieval-Augmented Generation)智能问答系统。


目录

  1. [向量数据库:AI 时代的新型存储引擎](#向量数据库:AI 时代的新型存储引擎 "#1-%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93ai-%E6%97%B6%E4%BB%A3%E7%9A%84%E6%96%B0%E5%9E%8B%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E")
  2. Milvus:海量高维向量数据的专属数据库
  3. [Zilliz Cloud:基于 Milvus 的全托管向量数据库服务](#Zilliz Cloud:基于 Milvus 的全托管向量数据库服务 "#3-zilliz-cloud%E5%9F%BA%E4%BA%8E-milvus-%E7%9A%84%E5%85%A8%E6%89%98%E7%AE%A1%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E6%9C%8D%E5%8A%A1")
  4. [AI 日记本:项目全景](#AI 日记本:项目全景 "#4-ai-%E6%97%A5%E8%AE%B0%E6%9C%AC%E9%A1%B9%E7%9B%AE%E5%85%A8%E6%99%AF")
  5. 环境准备与项目初始化
  6. [数据建模:从结构化到向量化的 Schema 设计](#数据建模:从结构化到向量化的 Schema 设计 "#6-%E6%95%B0%E6%8D%AE%E5%BB%BA%E6%A8%A1%E4%BB%8E%E7%BB%93%E6%9E%84%E5%8C%96%E5%88%B0%E5%90%91%E9%87%8F%E5%8C%96%E7%9A%84-schema-%E8%AE%BE%E8%AE%A1")
  7. 向量嵌入(Embedding):将语义转化为数字
  8. 数据插入:把日记写入向量数据库
  9. 语义检索:用自然语言查找记忆
  10. [RAG 完整流程:让大模型读懂你的日记](#RAG 完整流程:让大模型读懂你的日记 "#10-rag-%E5%AE%8C%E6%95%B4%E6%B5%81%E7%A8%8B%E8%AE%A9%E5%A4%A7%E6%A8%A1%E5%9E%8B%E8%AF%BB%E6%87%82%E4%BD%A0%E7%9A%84%E6%97%A5%E8%AE%B0")
  11. [传统数据库 vs 向量数据库:根本性差异](#传统数据库 vs 向量数据库:根本性差异 "#11-%E4%BC%A0%E7%BB%9F%E6%95%B0%E6%8D%AE%E5%BA%93-vs-%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E6%A0%B9%E6%9C%AC%E6%80%A7%E5%B7%AE%E5%BC%82")
  12. [架构思考:Workflow 与 Agent ------ 确定性执行与不确定探索](#架构思考:Workflow 与 Agent —— 确定性执行与不确定探索 "#12-%E6%9E%B6%E6%9E%84%E6%80%9D%E8%80%83workflow-%E4%B8%8E-agent--%E7%A1%AE%E5%AE%9A%E6%80%A7%E6%89%A7%E8%A1%8C%E4%B8%8E%E4%B8%8D%E7%A1%AE%E5%AE%9A%E6%8E%A2%E7%B4%A2")
  13. 总结与展望

1. 向量数据库:AI 时代的新型存储引擎

1.1 为什么需要向量数据库?

在 AI 应用蓬勃发展的今天,我们处理的不仅是结构化的数字和字符串,更多的是非结构化的语义信息 ------一段文本的含义、一张图片的内容、一段音频的情绪。传统的数据库(如 MySQL、PostgreSQL)擅长根据精确的 ID 或关键词(LIKE)进行查询,但无法理解"语义相似"。

举个例子:用户想查找"最近心情比较好的日记"。在传统数据库中,你只能写 SELECT * FROM diaries WHERE mood = 'happy',但"心情好"可能是 happyjoyfulcontentexcitedrelaxed......不同的表达方式无法被简单的字符串匹配覆盖。

向量数据库的出现解决了这个难题。它的核心思想是:

把任何实体(文本、图片、音频)转化为一串高维向量,然后通过计算向量之间的相似度来找到语义上最接近的内容。

1.2 工作原理:Loader → Splitter → 向量数据库

在工程的实践中,一个典型的向量数据库工作流水线如下:

css 复制代码
原始文档 → [Loader 加载] → [Splitter 切分] → [Embedding 向量化] → [Vector Store 存储]
  • Loader(加载器):从各种来源读取数据------PDF 文件、网页、数据库记录、API 响应。
  • Splitter(切分器):将长文档切分成适当大小的"块"(chunk)。太长的文本会稀释语义密度,太短则丢失上下文。
  • Embedding(向量化) :调用大模型的 Embedding API,将每个文本块转化为固定维度的浮点数向量(如 [0.12, -0.34, 0.56, ...] --- 共 1024 个维度)。
  • Vector Store(向量数据库):存储这些向量以及对应的原始数据,并提供高效的相似度检索能力。

1.3 从内存向量数据库到专业引擎

开发初期,我们可以在内存中维护一个简单的向量存储(如 NumPy 数组 + 暴力搜索),适用于几百条数据的原型验证。但当数据量增长到上万、上百万级别时,暴力逐条比对变得不可接受。此时就需要专业的向量数据库引擎------Milvus 正是为此而生。


2. Milvus:海量高维向量数据的专属数据库

2.1 Milvus 是什么?

Milvus 是一款开源向量数据库,专门为处理海量高维向量数据而设计。它支持:

  • 多种索引类型:IVF_FLAT(聚簇索引)、HNSW(图索引)、AUTOINDEX(自动选择最优索引)等,让查询从毫秒级到亚毫秒级。
  • 多种相似度度量:余弦相似度(COSINE)、欧几里得距离(L2)、内积(IP)。
  • 水平扩展:分布式架构,支持十亿级别向量的存储与检索。
  • 丰富的 SDK:Python、Node.js、Java、Go 等多语言支持。

几乎所有的 AI Agent 产品都会使用像 Milvus 这样的向量数据库来存储知识记忆,并对这些非结构化数据进行语义级别的增删改查。

2.2 索引的核心价值:为什么不能没有索引?

main.mjs 的注释中,有一个非常形象的解释:

Milvus 存储的是高维向量。没有索引时,每次查询都要把库里的向量和查询的向量逐一算相似度------数据量大了就慢得没法用。

就像图书馆里找一本《三体》:如果没有索引,你就得把每一本书都翻一遍。有了索引(比如按"小说/科幻"分类),就能迅速缩小搜索范围。

IVF_FLAT 聚簇索引:将向量空间中的向量预先聚类,查询时只在最近的几个聚类中搜索,实现毫秒级返回。

2.3 从代码看 Milvus 客户端的使用

javascript 复制代码
// 来自 main.mjs ------ 建立连接并进行健康检查
import { MilvusClient, IndexType, MetricType } from '@zilliz/milvus2-sdk-node';

const client = new MilvusClient({
  address: process.env.MILVUS_ADDRESS,  // 云端地址
  token: process.env.MILVUS_TOKEN       // API Key 鉴权
});

const checkHealth = await client.checkHealth();
if (!checkHealth.isHealthy) {
  console.error('连接失败', checkHealth.reasons);
  return;
}
console.log('连接成功,集群状态正常。');

这段代码展示了三个关键步骤:

  1. 建立客户端:传入云端地址和认证 Token。
  2. 健康检查:确认 Milvus 集群状态可用,这是生产环境的必备操作。
  3. 前置验证:在后续任何数据操作之前确保连接通畅。

3. Zilliz Cloud:基于 Milvus 的全托管向量数据库服务

Zilliz 是基于 Milvus 的全托管向量数据库云服务。对于不想自行运维 Milvus 集群的开发者,Zilliz 提供了开箱即用的 SaaS 解决方案:

  • 无需运维:自动扩缩容、备份、监控。
  • Serverless 模式:按使用量计费,适合中小型项目或初期探索。
  • 全球部署:阿里云、AWS、GCP 等多区域可选。

本项目正是通过 Zilliz Cloud(杭州区)来连接 Milvus 的:

ini 复制代码
MILVUS_ADDRESS=https://in03-0deed7b89de0e9e.serverless.ali-cn-hangzhou.cloud.zilliz.com.cn

4. AI 日记本:项目全景

4.1 项目定位

这个项目构建了一个"AI 日记本"------将用户的日记内容向量化存储到 Milvus 中,然后通过语义搜索和 RAG 技术,让用户可以用自然语言提问(如"我最近做了什么快乐的事?"),由 AI 基于日记内容给出温暖、有同理心的回答。

4.2 项目文件结构

bash 复制代码
milvus-demo/
├── readme.md                 # 向量数据库与 Milvus 概念文档
└── demo/
    ├── .env                  # 环境变量(模型、API Key、Milvus 地址)
    ├── package.json          # 项目依赖
    ├── pnpm-lock.yaml        # 依赖锁定文件
    └── src/
        ├── main.mjs          # 入门:连接、建集合、插入、搜索
        ├── index.mjs         # AI 日记本:Schema 设计、向量化、批量插入
        ├── query.mjs         # 语义查询:基于向量的日记检索
        └── rag.mjs           # RAG 流程:检索 + LLM 生成回答

4.3 四个文件的递进关系

文件 定位 核心能力
main.mjs 入门实验 连接 Milvus → 建简单集合 → 插入低维向量 → 相似度搜索
index.mjs 数据生产 定义日记 Schema → 调用 Embedding API → 批量插入日记数据
query.mjs 语义查询 将问题向量化 → 在日记库中做相似度匹配 → 按分数排序输出
rag.mjs 智能问答 检索(Retrieve)→ 构造 Prompt → LLM 生成(Generate)→ 完整 RAG

5. 环境准备与项目初始化

5.1 依赖包

项目依赖三个核心包(见 package.json):

json 复制代码
{
  "dependencies": {
    "@zilliz/milvus2-sdk-node": "^3.0.3",   // Milvus Node.js SDK
    "@langchain/openai": "^1.5.5",           // LangChain 的 OpenAI 集成
    "dotenv": "^17.4.2"                      // 加载 .env 环境变量
  }
}
  • @zilliz/milvus2-sdk-node:官方 Node.js SDK,提供 Milvus 客户端、索引管理、数据增删改查、向量搜索等全部 API。
  • @langchain/openai :统一封装了 OpenAI 兼容接口的 Chat 模型(ChatOpenAI)和 Embedding 模型(OpenAIEmbeddings)。尽管项目实际使用的是阿里云 DashScope 的 API(兼容 OpenAI 格式),但通过 baseURL 配置可以无缝切换。
  • dotenv :从 .env 文件加载配置,避免将密钥硬编码在代码中。

5.2 环境变量配置

.env 文件包含了项目运行所需的所有配置:

bash 复制代码
MODEL_NAME=qwen-plus                              # 大语言模型(通义千问)
EMBEDDINGS_MODEL_NAME=text-embedding-v4             # 向量嵌入模型
OPENAI_API_KEY=sk-xxx                               # API Key
OPENAI_BASE_URL=https://dashscope.aliyuncs.com/...  # 阿里云 DashScope 端点
MILVUS_ADDRESS=https://...zilliz.com.cn              # Milvus 云端地址
MILVUS_TOKEN=9aac37...                              # Milvus 鉴权 Token

关键设计点:

  • Embedding 模型 选用了 text-embedding-v4,输出维度为 1024 维。维度越高,语义表达能力越强,但存储和计算成本也越大。1024 是业界常用的平衡点。
  • Chat 模型 使用 qwen-plus,在 langchain/openai 中通过 baseURL 指向阿里云 DashScope,体现了 OpenAI 兼容接口的灵活性。
  • Milvus 使用 Zilliz Cloud 的 Serverless 实例,免去了自建集群的运维负担。

6. 数据建模:从结构化到向量化的 Schema 设计

6.1 Collection 的概念

在 Milvus 中,Collection(集合)相当于 MySQL 中的 Table(表)。但与 MySQL 的固定列定义不同,Milvus Collection 的 Schema 更加灵活------它可以将结构化字段 (如日期、心情标签)与非结构化向量(日记内容的语义表示)放在同一个实体中,实现"结构化过滤 + 语义搜索"的混合查询能力。

6.2 AI 日记的 Schema 设计

index.mjs 中,我们为 ai_dairy 集合定义了详细的字段结构:

javascript 复制代码
// 创建 AI 日记的 Collection Schema
await client.createCollection({
  collection_name: 'ai_dairy',
  fields: [
    {
      name: 'id',
      data_type: DataType.VarChar,
      max_length: 50,
      is_primary_key: true        // 主键,唯一标识一篇日记
    },
    {
      name: 'vector',
      data_type: DataType.FloatVector,
      dim: 1024                    // 1024 维浮点向量
    },
    {
      name: 'content',
      data_type: DataType.VarChar,
      max_length: 5000             // 日记正文,最多 5000 字符
    },
    {
      name: 'date',
      data_type: DataType.VarChar,
      max_length: 50               // 日期字符串 "2026-01-10"
    },
    {
      name: 'mood',
      data_type: DataType.VarChar,
      max_length: 50               // 心情标签:happy/excited/relaxed...
    },
    {
      name: 'tags',
      data_type: DataType.Array,   // 数组类型
      element_type: DataType.VarChar,
      max_capacity: 10,            // 最多 10 个标签
      max_length: 50               // 每个标签最长 50 字符
    }
  ]
});

6.3 Schema 设计分析

字段 类型 用途 设计考量
id VarChar (PK) 日记唯一标识 使用 diary_001 这样可读的 ID,而非自增数字
vector FloatVector(1024) 日记内容的语义向量 核心字段,所有语义搜索都基于此字段的相似度计算
content VarChar(5000) 日记原文 检索后需要返回给用户或填入 LLM Prompt
date VarChar(50) 日记日期 便于按时间筛选,也用于 Prompt 中的上下文
mood VarChar(50) 心情标签 结构化情感元数据,支持过滤查询
tags Array(VarChar) 多标签分类 Milvus 支持数组类型,一篇日记可以有多个标签

设计哲学 :向量数据库的设计不是"把传统数据库的字段搬过来再加一个向量列"这么简单。你需要同时考虑两类查询路径------精确查询 ("找出所有 mood=happy 的日记")和语义查询("找出和'快乐的户外活动'最相关的日记")。优秀的 Schema 设计应该让这两类查询路径都能高效执行。

6.4 索引的创建

数据模型定义好后,还需要为向量字段创建索引:

javascript 复制代码
// 为 vector 字段创建 IVF_FLAT 索引,使用余弦相似度
await client.createIndex({
  collection_name: 'ai_dairy',
  field_name: 'vector',
  index_type: IndexType.IVF_FLAT,
  metric_type: MetricType.COSINE
});
  • IVF_FLAT(Inverted File with Flat compression):先对向量空间做 K-Means 聚类,查询时只在与查询向量最近的几个聚类中心范围内做精确匹配。适合百万级数据量。
  • COSINE (余弦相似度):衡量两个向量方向的相似程度,值域 [-1, 1],越接近 1 表示语义越相似。特别适合文本语义匹配场景,因为它更关注"方向"而非"长度"。

7. 向量嵌入(Embedding):将语义转化为数字

7.1 Embedding 是什么?

Embedding(嵌入)是将非结构化的自然语言转化为固定维度浮点数向量的过程。这个向量的神奇之处在于------语义相近的文本,其向量在高维空间中的距离也很近

例如,"今天天气很好,去公园散步了" 和 "周末和朋友去爬山,享受大自然" 这两句话虽然文字完全不同,但都表达了户外活动和愉悦心情,它们的向量在 1024 维空间中会非常接近。而"今天学习了 Milvus 向量数据库"的向量则会和它们有明显距离。

7.2 代码实现

index.mjs 中,我们通过 @langchain/openai 来调用 Embedding 服务:

javascript 复制代码
import { OpenAIEmbeddings } from '@langchain/openai';

const embeddings = new OpenAIEmbeddings({
  apiKey: process.env.OPENAI_API_KEY,
  model: process.env.EMBEDDINGS_MODEL_NAME,   // text-embedding-v4
  configuration: {
    baseURL: process.env.OPENAI_BASE_URL       // 阿里云 DashScope
  },
  dimensions: 1024                              // 指定输出维度
});

const getEmbedding = async (text) => {
  const result = await embeddings.embedQuery(text);
  return result;  // 返回 number[],长度为 1024
};

7.3 批量向量化

实际业务中,我们通常需要批量处理多条数据:

javascript 复制代码
const diaryContents = [
  {
    id: 'diary_001',
    content: '今天天气很好,去公园散步了,心情愉快。看到了很多花开了,春天真美好。',
    date: '2026-01-10',
    mood: 'happy',
    tags: ['生活', '散步']
  },
  // ... 更多日记
];

// 并行调用 Embedding API,对每篇日记内容进行向量化
const diaryData = await Promise.all(
  diaryContents.map(async (diary) => ({
    ...diary,
    vector: await getEmbedding(diary.content)  // 将 content 转为 1024 维向量
  }))
);

这里使用 Promise.all 并行处理所有日记的 Embedding 请求,大幅提升了吞吐量------5 条数据几乎同时完成向量化。


8. 数据插入:把日记写入向量数据库

8.1 插入操作

与 MySQL 需要手写 INSERT SQL 不同,Milvus 的 Node.js SDK 提供了面向对象的插入方式------直接传入 JSON 数据即可:

javascript 复制代码
const insertResult = await client.insert({
  collection_name: 'ai_dairy',
  data: diaryData    // 包含 id、vector、content、date、mood、tags
});

console.log(insertResult.insert_cnt, "条记录成功插入。");
// 输出:5 条记录成功插入。

Milvus SDK 自动处理了数据类型校验、向量维度验证等底层细节。比传统 SQL 更简洁、更不容易出错。

8.2 数据的加载

插入数据后,还需要将 Collection 加载到内存中才能进行搜索:

javascript 复制代码
await client.loadCollection({
  collection_name: 'ai_dairy'
});
console.log('collection loaded');

这一步将数据和索引从磁盘加载到内存,是实现毫秒级搜索的前提。在 Zilliz Cloud 的 Serverless 模式下,loadCollection 会触发计算资源的分配。


9. 语义检索:用自然语言查找记忆

9.1 语义搜索的原理

传统数据库搜索:SELECT * FROM diary WHERE content LIKE '%户外%' ------ 只能匹配字面字符串。

向量数据库搜索:将查询语句向量化,然后计算查询向量与库中所有日记向量的相似度,返回最接近的 Top-K 结果。

9.2 代码实现

query.mjs 中,我们实现了完整的语义检索流程:

javascript 复制代码
async function main() {
  console.log('Connection to Milvus...');
  await client.connectPromise;  // 先建立连接,再操作
  console.log('Connected');

  const query = '我想看看关于户外活动的日记';
  console.log(`QUERY: ${query}`);

  // 第一步:将查询语句向量化
  const queryVector = await getEmbedding(query);

  // 第二步:在 Milvus 中执行向量搜索
  const searchResult = await client.search({
    collection_name: 'ai_dairy',
    vector: queryVector,          // 查询向量
    limit: 2,                     // 返回 Top-2 最相似结果
    metric_type: MetricType.COSINE,  // 使用余弦相似度
    output_fields: ['id', 'content', 'date', 'mood', 'tags']  // 需要返回的字段
  });

  // 第三步:格式化输出结果
  console.log(`Found ${searchResult.results.length} results.`);
  searchResult.results.forEach((item, index) => {
    console.log(`${index + 1}. [Score: ${item.score.toFixed(4)}]`);
    console.log(`
      ID: ${item.id};
      Date: ${item.date};
      Mood: ${item.mood};
      Tags: ${item.tags?.join(",")}
      Content: ${item.content}
    `);
  });
}

9.3 搜索结果解读

查询"我想看看关于户外活动的日记"时,系统会返回:

yaml 复制代码
1. [Score: 0.9234]
   ID: diary_003; Date: 2026-01-12; Mood: relaxed;
   Tags: 户外,朋友
   Content: 周末和朋友去爬山,天气很好,心情也很放松。享受大自然的感觉真好。

2. [Score: 0.8741]
   ID: diary_001; Date: 2026-01-10; Mood: happy;
   Tags: 生活,散步
   Content: 今天天气很好,去公园散步了,心情愉快。看到了很多花开了,春天真美好。
  • diary_003(爬山)得分最高,因为它直接包含了"户外"和"大自然"的语义。
  • diary_001(公园散步)排名第二,"散步"和"户外活动"在语义空间中天然相近。

值得注意的是,两篇日记的正文中都没有出现"户外活动"这四个字------这正是向量搜索超越关键词匹配的核心价值。


10. RAG 完整流程:让大模型读懂你的日记

10.1 什么是 RAG?

RAG(Retrieval-Augmented Generation,检索增强生成) 是当前 AI Agent 领域最核心的技术范式之一。它的工作流程分为三步:

css 复制代码
用户提问 → [R] 检索相关文档 → [A] 将文档拼入 Prompt → [G] LLM 生成回答

传统 LLM 只能根据训练数据回答,无法访问用户的私有数据。RAG 技术让 LLM 能够"查阅"外部知识库------在本项目中,就是用户的日记。

10.2 完整的 RAG 实现

rag.mjs 将前面的所有环节串联成一个完整的 RAG 管线:

第一步:检索(Retrieve)

javascript 复制代码
async function retrieveRelevantDiaries(question, k = 2) {
  const queryVector = await getEmbedding(question);  // 问题向量化
  const searchResult = await client.search({
    collection_name: 'ai_dairy',
    vector: queryVector,
    limit: k,                      // 检索 Top-k 篇最相关日记
    metric_type: MetricType.COSINE,
    output_fields: ['id', 'content', 'mood', 'tags']
  });
  return searchResult.results;
}

第二步:增强(Augment)------ 构造 Prompt

javascript 复制代码
const context = retrievedDiaries
  .map((diary, i) => `
    [日记 ${i + 1}]
    日期:${diary.date}
    心情:${diary.mood}
    标签:${diary.tags?.join(',')}
    内容:${diary.content}
  `).join('\n\n----\n\n');

const prompt = `
你是一个专业的日记分析助手,你的任务是基于用户的日记内容回答问题,
用亲切自然的语言。请根据以下日记内容回答问题:

${context}

用户问题:${question}

回答要求:
1. 如果日记中有相关信息,请结合日记内容给出详细、温暖的回答。
2. 可以总结多篇日记的内容,找出共同点或趋势。
3. 如果日记中没有相关信息,请温和告知用户。
4. 用第一人称"你"来称呼日记的作者。
5. 回答要有同理心,让用户感到理解和关心。

AI助手的回答:
`;

这里的关键设计是 Prompt 工程

  • 角色设定:"专业的日记分析助手",限定了 LLM 的行为边界。
  • 上下文注入:将检索到的日记以结构化格式嵌入(日期、心情、标签、内容),帮助 LLM 理解每条日记的语境。
  • 约束条件:5 条回答要求确保输出质量------温暖、有同理心、第一人称、不编造信息。

第三步:生成(Generate)

javascript 复制代码
const model = new ChatOpenAI({
  temperature: 0.1,    // 低温度 = 更稳定、更忠实于上下文
  model: 'qwen-plus',
  apiKey: process.env.OPENAI_API_KEY,
  configuration: {
    baseURL: process.env.OPENAI_BASE_URL
  }
});

const response = await model.invoke(prompt);
console.log(response.content);

temperature: 0.1 是一个精心选择的参数:

  • 在 RAG 场景中,我们希望 LLM 忠实于检索到的文档,而非自由发挥。低温度减少了随机性,让输出更加可控。
  • 如果是创意写作场景,temperature 通常设在 0.7-1.0;但问答场景需要 0-0.3。

10.3 RAG 问答效果示例

当用户问 "我最近做了什么让我感到快乐的事情?" 时,整个链路如下:

csharp 复制代码
用户提问: "我最近做了什么让我感到快乐的事情?"
    │
    ▼
[Embedding] → 1024维查询向量
    │
    ▼
[Milvus Search] → Top-2 相关日记:
    1. diary_001 (0.89) "去公园散步了,心情愉快。看到了很多花开了"
    2. diary_003 (0.82) "周末和朋友去爬山,心情也很放松"
    │
    ▼
[Prompt 构造] → 日记内容 + 角色设定 + 约束条件 → 完整的 Prompt
    │
    ▼
[LLM 生成] → 
    "根据你的日记,最近让你感到快乐的事情主要有两件:
     1. 在1月10日,你去公园散步,看到春天盛开的花朵,心情非常愉快。
     2. 在1月12日,你和朋友一起去爬山,享受大自然,心情很放松。
     这两件事都体现了你对户外活动的热爱,也说明与自然相处和朋友的陪伴
     都是你快乐的重要来源。继续保持这样的生活节奏吧!🌿"

11. 传统数据库 vs 向量数据库:根本性差异

11.1 类比理解

就像 Web 应用把业务数据存储在 MySQL、SQLite、PostgreSQL 中,基于对数据的增删改查(CRUD)实现各种功能。传统的查询模式是:

  • 根据 ID 精确查找:WHERE id = 'diary_001'
  • 根据关键词模糊匹配:WHERE content LIKE '%户外%'
  • 关联查询:JOIN 多张表获取完整数据

而 AI Agent 则把知识记忆放在 Milvus 这样的向量数据库中,实现的是:

  • 语义检索:search(vector, top_k=5) → "找出和'户外活动'最语义相关的日记"
  • 混合查询:mood='happy' AND vector_similarity('户外') > 0.8
  • 记忆管理:存储和检索对话历史、用户偏好、知识片段

11.2 核心差异对比

维度 传统数据库(MySQL/SQLite) 向量数据库(Milvus)
查询方式 精确匹配、模糊匹配 语义相似度检索
数据形式 结构化(数字、字符串、日期) 非结构化(文本、图片、音频 → 向量)
典型操作 SELECT WHERE id=? search(vector, limit=K)
应用场景 订单管理、用户信息、审批流程 知识库、长时记忆、RAG、推荐系统
索引技术 B-Tree、Hash IVF、HNSW、DiskANN
返回结果 精确行集合 带相似度分数的 Top-K 排序结果

11.3 本文项目中的双重数据管理

AI 日记本实际上是一个混合架构的雏形:

  • 结构化数据(日期、心情标签):存储在 Milvus 的标量字段中,支持传统过滤。
  • 语义数据(日记内容的向量表示):存储在 Milvus 的向量字段中,支持语义搜索。
  • AI 增强(LLM 的回答生成):通过 RAG 管线,将检索到的日记上下文注入 LLM,生成自然语言回答。

这正是 readme.md 中提到的核心理念的代码级实现:

Agent 会把知识、记忆放在 Milvus 数据库中,对知识、记忆进行语义级别的增删改查等各种功能。


12. 架构思考:Workflow 与 Agent ------ 确定性执行与不确定探索

前面我们用代码跑通了 AI 日记本的完整 RAG 流程。但如果把视角拉高,从架构层面审视这个系统,你会发现它同时具备两种截然不同的 AI 工作模式------**Workflow(工作流)**和 Agent(智能体)。理解二者的区别与协作,是 AI 工程化的关键命题。

12.1 Workflow:AI 世界的生产流水线

Workflow 本质上是一套预定义的流程,可以把它想象成一条工业流水线------每一步都有明确的输入和输出,每个节点的逻辑是固定的,当条件满足,就自动进入下一环节。

从技术上看,Workflow 通常表现为一个由 LLM 调用、条件判断、循环逻辑 组成的编排图谱。以 LangChain 为例,它的核心理念就是 pipe(管道)------像传送带一样把各个工作节点串联起来:

typescript 复制代码
// LangChain 的 LCEL (LangChain Expression Language) 管道式编排
const creativeChain = storyPrompt
  .pipe(creativeModel)   // 节点1: 传入大模型
  .pipe(outputParser);   // 节点2: 解析输出

creativeChain.invoke("恭喜拿下offer");  // 触发整条链路

这就是 Pipe 管道模式 :数据像水流一样,从一个节点流向另一个,每个节点各司其职,最终产出结果。Coze 等平台将这种编排能力做成了可视化拖拽------选择节点(输入、逻辑判断、LLM 调用、图片生成、输出),连成一条确定性的执行链路(如"AI 照相馆"工作流)。

一个典型 Workflow 案例:AI 简历筛选

招聘工作天然具备固定流程,非常适合用 Workflow 编排:

css 复制代码
[简历 PDF 输入]
    │
    ▼
[节点1: PDF 解析]        → 提取原始文本
    │
    ▼
[节点2: 信息抽取]        → 技能描述、工作经历、教育经历
    │
    ▼
[节点3: RAG 岗位匹配]    → 与 JD 做语义比对
    │
    ▼
[节点4: 打分排序]        → 综合评分 → 优质简历列表

每一步的输出都是下一步的输入,流程确定、结果可预期、执行可复现 。这正是 Workflow 的核心优势------确定性执行。对于审批流程、数据清洗、客服 AI 等需要稳定、可审计执行的场景,Workflow 是 FDE(前端+后端+数据)工程师的提效神器。

12.2 Agent:站在开放空间中的自主探索者

与 Workflow 完全不同,Agent 不走在一条预设的轨道上,而是站在一个开放的空间里,自己去探索怎么做。

从技术角度,一个 Agent 具备三大核心能力:

第一,感知环境。通过输入文本、图像、数据来理解任务------当前有哪些工具可以调用?情况如何?需要分几步?如何规划?

第二,规划路径 。不是预先定义好的,而是动态生成任务链。Agent 会根据当前反馈实时调整下一步动作,而非死板地遵循既定顺序。

第三,执行行动。调用工具、完成子任务,并根据执行结果不断修正策略------这是一个"感知 → 规划 → 行动 → 再感知"的闭环。

一个典型 Agent 场景:AI 旅行规划

你让 Agent 去规划一次旅行,它的行为路径可能是:

  • 先搜索机票和酒店价格 → 发现某目的地太贵
  • 转而查询天气和签证需求 → 排除雨季国家
  • 结合你的偏好和预算 → 动态权衡,给出三个备选方案
  • 你选了方案 A → Agent 接着细化每日行程、推荐餐厅

整个过程,它走的路径可能和你预期的完全不同。这就是 Agent 的关键特质------自主性和适应性。它不会被固定流程限制,而像一个思考中的个体,能够随时改道、尝试新路线,甚至在目的地发生变化时自行调整。

12.3 核心区别:高速公路 vs 司机

用两个比喻来理解:

Workflow Agent
比喻 🛣️ 高速公路 --- 路径清晰固定,效率极高 🚗 司机 --- 知道要去哪里,但随时改道
执行模式 确定性执行,输入→输出可复现 不确定探索,同一问题可能走不同路径
核心依赖 规则引擎、图形化编排(Coze)、流程引擎 大模型推理能力、记忆能力、工具调用(Function Call)
适合场景 审批流程、数据清洗、客服 AI 复杂搜索、策略规划、自主决策
创造力 几乎没有,按照既定剧本走 有,但不可控、不可预测

12.4 回头看 AI 日记本:Workflow + Agent 的混合体

现在用这个视角重新审视我们搭建的 AI 日记本系统,你会发现它恰好同时体现了两种模式:

Workflow 部分------RAG 管线就是一个确定性流水线:

css 复制代码
用户问题输入 → [节点1: Embedding 向量化] → [节点2: Milvus 向量检索]
→ [节点3: Prompt 模板填入] → [节点4: LLM 调用] → 输出回答

每一步都是预先编排好的,输入输出明确,逻辑固定------这是典型的 Workflow。

Agent 部分------LLM 在回答时体现的自主性:

当 LLM 拿到日记上下文和用户问题后,它需要自主判断:哪些日记片段是相关的?如何组织语言?以什么语气回应?如果检索到的日记不够好,它需要温和告知用户而非胡编乱造。这些决策无法被硬编码------这是 Agent 的智能体现。

所以,即便是一个看似简单的 RAG 应用,其内部也已经是 Workflow + Agent 的共生体

12.5 未来 AI 工程的架构蓝图

从产业趋势看,未来的 AI 工程将集合 Workflow 和 Agent 的双重能力:

复制代码
┌─────────────────────────────────────┐
│           Agent(上层)              │
│   灵活决策 · 自主规划 · 动态适应     │
│         智能 · 创造力                │
├─────────────────────────────────────┤
│         Workflow(底层)             │
│   稳定执行 · 流程可控 · 结果可审计    │
│         效率 · 确定性                │
└─────────────────────────────────────┘
  • 底层是 Workflow:提供稳定性和可控性------数据入库、向量检索、Prompt 组装等步骤必须走确定性流程。
  • 上层是 Agent:提供灵活性和智能性------理解用户意图、动态调整回答策略、根据上下文自主决策。

Workflow 是骨架,Agent 是 Workflow 的大脑。 Workflow 没什么创造力,Agent 有,但不可控、不可预测。二者结合,才能构建出既高效又有智慧的 AI 系统。这正是我们这个 AI 日记本项目所展现的核心理念------也是一个合格的 AI 工程师必须理解的架构思维。


13. 总结与展望

13.1 项目回顾

本文通过 milvus-demo 项目,完整地展示了一个基于向量数据库的 AI Agent 记忆系统的搭建过程:

  1. 基础设施层:通过 Zilliz Cloud 连接 Milvus,免去自建集群的复杂度。
  2. 数据建模层:设计同时包含结构化字段和向量字段的 Collection Schema。
  3. 向量化层 :使用 text-embedding-v4 模型,将日记文本转为 1024 维语义向量。
  4. 存储层:将向量化后的日记批量插入 Milvus,创建索引并加载到内存。
  5. 检索层:将用户问题向量化,在日记库中执行余弦相似度搜索。
  6. 生成层:将检索结果注入精心设计的 Prompt,由 LLM 生成温暖的回答。

13.2 核心概念映射

flowchart LR A[日记文本] -->|Embedding| B[1024维向量] B -->|Insert| C[(Milvus 向量库)] D[用户问题] -->|Embedding| E[查询向量] E -->|Cosine Search| C C -->|Top-K 结果| F[日记上下文] F -->|填入 Prompt| G[LLM 大模型] G -->|生成| H[自然语言回答]

13.3 延伸方向

在此基础上,你可以进一步探索:

  • 多模态扩展:不仅存储日记文本,还可以将图片(如旅行照片)通过 CLIP 模型向量化,实现"找出和这张照片场景相似的日记"。
  • 混合查询(Hybrid Search):结合标量过滤和向量搜索------例如"找出过去一个月内、心情为 happy 的日记中、和'成就感'最相关的 3 篇"。
  • 动态记忆管理:让 Agent 自动决定哪些记忆需要长期保留、哪些可以遗忘------模仿人脑的长期记忆和短期记忆机制。
  • 多租户隔离:通过 Milvus 的 Partition Key 特性,在同一个 Collection 中隔离不同用户的数据。
  • 流式索引更新:当日记不断增多时,如何在不停服的情况下增量更新索引。

写在最后 :向量数据库不是要替代传统数据库,而是在 AI 时代提供了一种新的数据组织范式。就像 readme.md 中所说的:"AI Agent 产品都会使用 Milvus 这样的 Vector Store"。理解并掌握向量数据库,是每一个 AI 工程师的必修课。希望本文能帮助你在向量数据库和 RAG 的道路上迈出坚实的第一步。

相关推荐
九皇叔叔1 小时前
RHEL 9.8 安装 Redis 8.8.1
数据库·redis·bootstrap
Python私教1 小时前
如意 Django CRM 容器化实战:后端、前端、数据库、Redis 的协同启动逻辑
前端·数据库·django
海兰2 小时前
【数据库】tdsql(MySQL )的事务隔离级别
android·数据库·mysql
灵析表格2 小时前
Excel连接MySQL的函数化革命:灵析表格MySQL函数族业务应用分析
数据库·mysql·adb·excel·wps·灵析表格·excel公式盒子
todoitbo2 小时前
把发票台账接进 Codex:KingbaseES MCP 的一次只读风险排查实践
数据库·oracle·codex·kingbasees·mcp
Navicat中国2 小时前
使用 Navicat 轻松生成数据库测试数据
数据库·数据
zyplayer-doc3 小时前
核心制度不该被随手修改:用zyplayer-doc锁定文档和全部子文档
大数据·数据库·人工智能·笔记·pdf·ocr
一路向北North3 小时前
Spring AI(11) :ChatPDF-向量数据库、PDF处理、向量写入和向量搜索
数据库·人工智能·spring
暗暗别做白日梦3 小时前
CompletableFuture 并发统计
网络·数据库·oracle