25-Day 6 长期记忆 —— 接触向量数据库

📅 Day 6:长期记忆 —— 向量数据库入门

让 Agent 记住“用户偏好”,而不仅是对话历史


🎯 教学目标

  1. 理解长期记忆 vs 短期记忆的区别
  2. 掌握向量数据库(FAISS)的基本用法
  3. 学会用文本嵌入(Embedding)实现语义检索
  4. 完成一个可运行的“偏好记忆”小系统
  5. 为 Day 7(Agent + 长期记忆)打下基础

🔍 核心概念讲解

向量数据库的概念

[🎥 打开向量数据库视频](file:///D:/24-python-AI%20Agent/%E5%90%91%E9%87%8F%E6%95%B0%E6%8D%AE%E5%BA%93%E6%8A%80%E6%9C%AF.mp4)

图片

❓ 为什么需要“长期记忆”?

  • 对话历史(SQLite)只能记住说过什么,但无法回答:
    • “我上次说喜欢什么?”
    • “我对开会的态度是什么?”
  • 长期记忆 = 用户偏好的知识库,需支持语义模糊匹配

💡 向量数据库如何工作?

原始文本 → [嵌入模型] → 高维向量 → 存入 FAISS
查询文本 → [嵌入模型] → 向量 → 在 FAISS 中找最近邻 → 返回原文

✅ 为什么选 FAISS?

FAISS(Facebook AI Similarity Search)是由 Facebook AI 团队开发的一个高效、开源的向量相似性搜索库,主要用于在大规模高维向量数据集中快速查找最相似的向量。它广泛应用于推荐系统、图像检索、自然语言处理(如语义搜索)、聚类等需要进行近似最近邻(Approximate Nearest Neighbor, ANN)搜索的场景。

  • Facebook 开源,纯 Python 支持(langchain-community
  • 内存存储,无需部署数据库
  • 适合小规模、本地实验

⚠️ 注意:FAISS 不持久化!程序退出后数据丢失(下一篇 会解决)


💻 实验:构建你的第一个向量记忆系统

步骤 1:准备环境

# 进入项目目录
mkdir -p day06 && cd day06

python3 -m venv vector_memory

# 激活虚拟环境(延续 Day5)
source vector_memory/bin/activate

# 安装依赖
pip install \
    langchain \
    langchain-community \
    langchain-openai \
    python-dotenv \
    -i https://mirrors.aliyun.com/pypi/simple/
    
pip install    \
    faiss-cpu  \
    dashscope  \
    -i https://mirrors.aliyun.com/pypi/simple/

# 创建 .env 文件
echo "DASHSCOPE_API_KEY=(替换为您的实际API Key)" > .env

步骤 2:编写 vector_memory.py

当然可以!以下是在不改变原有逻辑的基础上,将你的 vector_memory.py 升级为 交互式 CLI 程序的版本。用户可以:

  • 动态添加记忆(如“我喜欢看电影”)
  • 随时查询语义相关记忆(如“我讨厌什么?”)
  • 输入 quit 退出

这样实验过程更有“Agent 记忆”的感觉,也便于课堂演示。


tee vector_memory.py <<'EOF'
# day06/vector_memory.py
# 使用 DashScope 原生 API + 适配新版 LangChain 的向量记忆系统

import os
from dotenv import load_dotenv
import dashscope
from dashscope import TextEmbedding
from langchain_community.vectorstores import FAISS
from langchain_core.embeddings import Embeddings
from typing import List

# 加载环境变量
load_dotenv()
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")

class DashScopeEmbeddings(Embeddings):
    def __init__(self, model: str = "text-embedding-v2"):
        self.model = model

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        texts = [t for t in texts if t.strip()]
        if not texts:
            return []
        response = TextEmbedding.call(
            model=self.model,
            input=texts
        )
        if response.status_code != 200:
            raise RuntimeError(f"Embedding failed: {response}")
        return [item["embedding"] for item in response.output["embeddings"]]

    def embed_query(self, text: str) -> List[float]:
        return self.embed_documents([text])[0]

# 初始化
embeddings = DashScopeEmbeddings(model="text-embedding-v2")
initial_memories = [
    "用户喜欢喝美式咖啡",
    "用户住在杭州"
]

print("🧠 向量记忆系统启动中...")
vectorstore = FAISS.from_texts(initial_memories, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

print("✅ 系统就绪!")
print("\n💡 使用说明:")
print("  - 输入陈述句(如“我讨厌开会”)→ 保存为记忆")
print("  - 输入问句(如“我喜欢什么?”)→ 检索相关记忆")
print("  - 输入 'quit' 退出\n")

while True:
    try:
        user_input = input("🗨️  请输入: ").strip()
    except (KeyboardInterrupt, EOFError):
        print("\n👋 再见!")
        break

    if not user_input:
        continue

    if user_input.lower() == "quit":
        print("👋 再见!")
        break

    # 判断是否为查询(问句)
    if user_input.endswith('?') or any(w in user_input for w in ["什么", "怎么", "是否", "吗", "呢", "为什么", "谁"]):
        print(f"\n🔍 检索: 「{user_input}」")
        docs = retriever.invoke(user_input)  # ✅ 关键修复:用 .invoke() 替代 .get_relevant_documents()
        if docs:
            print("✅ 找到记忆:")
            for i, doc in enumerate(docs, 1):
                print(f"  {i}. {doc.page_content}")
        else:
            print("❌ 无相关记忆")
        print()
    else:
        # 规范化记忆文本
        if user_input.startswith("我"):
            memory_text = "用户" + user_input[1:]
        elif not user_input.startswith("用户"):
            memory_text = "用户" + user_input
        else:
            memory_text = user_input

        vectorstore.add_texts([memory_text])
        print(f"💾 已保存: 「{memory_text}」\n")
EOF

✨ 功能亮点

功能 说明
智能判断输入类型 ? 或疑问词(什么/吗/呢)结尾 → 查询;否则 → 添加记忆
自动规范化记忆文本 将“我喜欢吃苹果”转为“用户喜欢吃苹果”,保持格式统一
返回 Top-3 结果 避免只看第一条,提升语义覆盖
友好提示 清晰区分“存”和“查”操作

🧪 测试

💡先输入几条偏好,再用不同问法测试召回能力,感受“语义匹配” vs “关键词匹配”的区别。

架构正确,只是数据质量和检索策略需要优化

posted @ 2026-01-31 11:56  船山薪火  阅读(0)  评论(0)    收藏  举报
![image](https://img2024.cnblogs.com/blog/3174785/202601/3174785-20260125205854513-941832118.jpg)