Skip to content

Czj1997-02/MemoryProxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Memory Proxy — 可插拔记忆增强型 LLM 代理服务

基于 FastAPI 的网络请求转发代理,为任意 OpenAI 兼容协议的 LLM 服务注入长期记忆能力。支持多用户记忆隔离、混合检索(向量语义 + 标签匹配 + 图谱扩散)、多级抽象标签体系、元关联图谱、时序对话存储,并附带开箱即用的 Web 对话界面。


目录


功能概览

核心能力

功能 说明
URL 转发代理 请求路径格式 http://本服务/http://目标地址/路径,透明转发请求和响应
记忆自动注入 对话请求自动检索相关历史记忆,注入为 system prompt
记忆后台存储 对话结束后异步分析并存储用户消息和 LLM 回复
多用户隔离 通过 MEMORY_USER 请求头区分用户,记忆互不可见
混合检索 向量语义 + 标签精确匹配 + 元关联图谱扩散,三路融合排序
多级标签 L0 领域 → L1 主题 → L2 实体 → L3 特征,含行为/状态/时间/情感标签
元关联图谱 五维关系(实体共享/主题/时序/宫殿路径/因果行为),支持 BFS 扩散
时序对话存储 SQLite 记录完整对话时间线,支持分页查询和时序语义检索
Web 对话界面 配置缓存、Markdown 渲染、流式输出、历史对话滚动加载
LLM 增强可选 可独立配置 LLM 增强摘要/标签质量,默认使用规则引擎(零延迟)

记忆方法

方法 实现
联想记忆法 关键词 Jaccard 相似度 + 标签匹配加分,建立记忆间关联
宫殿记忆法 层级分类路径(/领域/子域/类型/主关键词)组织记忆空间
聚类分析 基于简化 TF-IDF 的关键词提取(词频 x 词长权重)
元关联图谱 五维关系边 + BFS 扩散检索 + PageRank 风格权重传递
多级抽象标签 8 维度标签体系,倒排索引实现 O(1) 精确匹配

检索与存储机制

机制 说明
混合检索 向量语义 (COSINE) + 标签精确匹配 + 图谱 BFS 扩散,三路加权融合
异步存储 asyncio.create_task() 后台存储,不阻塞 LLM 响应
标签/图谱懒加载 首次调用时从 Milvus 全量重建内存索引,后续增量更新
降级策略 Embedding 服务不可用时返回零向量,退化为纯标签+图谱检索
SSE 兼容 支持标准 OpenAI 流式响应,同时兼容 DeepSeek-R1 的 reasoning_content

技术栈

层次 技术 用途
Web 框架 FastAPI + Uvicorn HTTP 代理服务、REST API
HTTP 客户端 httpx (Async) 连接池复用、流式转发
向量数据库 Milvus (pymilvus ≥ 3.0) 语义向量存储与检索
时序存储 SQLite(默认)/ MySQL(可选) 对话时间线记录
嵌入服务 外部 HTTP 服务 文本 → 向量转换
配置管理 python-dotenv 环境变量加载
前端 原生 HTML/CSS/JS + marked.js Web 对话界面

Python 依赖

fastapi >= 0.110.0
uvicorn >= 0.27.0
httpx >= 0.27.0
python-dotenv >= 1.0.0
pymilvus >= 2.4.0
pymysql >= 1.1.0
  • SQLite 为 Python 标准库内置,无需额外安装
  • PyMySQL 仅在 TIMELINE_DB_TYPE=mysql 时需要

快速开始

1. 前置服务

  • Milvus:向量数据库,需独立部署(≥ 2.4)
  • Embedding 服务:任意兼容 HTTP POST 的文本嵌入服务

2. 安装

cd /pro/memory
pip install -r requirements.txt

3. 配置

cp .env.example .env
# 编辑 .env,填入 Milvus 连接信息和 Embedding 服务地址

4. 启动

python main.py

服务默认监听 0.0.0.0:9917

5. 使用

通过代理调用 LLM

# 原始 LLM 地址: http://model-api/v1/chat/completions
# 通过记忆代理调用:
curl -X POST http://localhost:9917/http://model-api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "MEMORY_USER: user_zhangsan" \
  -d '{"model":"gpt-3.5-turbo","messages":[{"role":"user","content":"你好"}]}'

Web 对话界面

浏览器访问 http://localhost:9917/,配置 MEMORY_USER 和 LLM 地址后即可对话。


架构设计

flowchart TB
    Client["客户端请求<br/>POST /http://LLM地址/v1/chat/completions<br/>Header: MEMORY_USER=xxx"]

    subgraph Proxy["main.py (FastAPI) 处理流程"]
        direction LR
        P1["解析目标 URL"] --> P2["提取 MEMORY_USER"] --> P3["Recall 记忆读取"] --> P4["注入 system prompt"] --> P5["转发请求"] --> P6["接收响应"] --> P7["Store 记忆存储"] --> P8["返回响应"]
    end

    subgraph Recall["Recall: 混合检索"]
        R1["向量检索 Milvus"]
        R2["标签匹配 TagIndex"]
        R3["图谱扩散 MemoryGraph"]
    end

    subgraph StoreDetail["Store: 后台存储"]
        S1["写入 SQLite 时序表"]
        S2["分析/嵌入/存入 Milvus"]
    end

    subgraph MemoryCore["memory/ 核心模块"]
        direction LR
        M1["manager.py 协调层"]
        M2["analyzer.py 内容分析"]
        M3["chunker.py 文本分片"]
        M4["embedding.py 嵌入服务"]
        M5["vector_store.py Milvus操作"]
        M6["timeline_store.py SQLite时序"]
        M7["tag_system.py 标签检索"]
        M8["relation_graph.py 元关联图谱"]
        M9["config.py 全局配置"]
        M10["schema.py 数据结构"]
    end

    subgraph Storage["存储层"]
        MILVUS[("Milvus 向量存储")]
        SQLITE[("SQLite 时序存储")]
        EMB["Embedding 外部服务"]
    end

    Client --> Proxy
    P3 -.-> Recall
    P7 -.-> StoreDetail
    Proxy -.-> MemoryCore
    MemoryCore --> MILVUS
    MemoryCore --> SQLITE
    MemoryCore --> EMB
Loading

核心流程

请求阶段(Recall)

flowchart TB
    subgraph Extract["查询提取"]
        direction LR
        E1["提取用户 messages"] --> E2["提取查询文本 最后3条user"] --> E3["向量嵌入 embed_text"]
    end

    subgraph Hybrid["混合检索 HybridRetriever"]
        direction TB
        
        subgraph Vec["向量检索 Milvus COSINE"]
            V1["user_id 隔离过滤"]
            V2["top_k x 3 候选集"]
            V3["threshold >= 0.6"]
            V1 --> V2 --> V3
        end

        subgraph Tag["标签匹配 TagIndex 倒排"]
            T1["8维度标签精确匹配"]
            T2["层级标签扩展 父到子"]
            T3["加权计分"]
            T1 --> T2 --> T3
        end

        subgraph Graph["图谱扩散 MemoryGraph BFS"]
            G1["种子节点 = A 交 B"]
            G2["深度 <= 2 衰减 0.5"]
            G3["PageRank 权重传递"]
            G1 --> G2 --> G3
        end

        Vec --> Graph
        Tag --> Graph
        Graph --> Fusion["三路融合排序: vec x 1.0 + tag x 1.5 + graph x 0.8, 纯向量命中降权 x 0.85"]
    end

    Format["格式化记忆上下文, 注入 system prompt"]

    Extract --> Hybrid --> Format
Loading

响应阶段(Store)

flowchart TB
    subgraph Collect["响应收集"]
        direction LR
        C1["LLM 响应 流式收集"] --> C2["提取 assistant content"] --> C3["写入 SQLite 时序表"]
    end

    subgraph Async["后台异步存储流程"]
        direction TB
        
        subgraph Analyze["analyze_content 每条记忆单元"]
            direction LR
            A2a["关键词提取"]
            A2b["摘要生成"]
            A2c["情感分析"]
            A2d["重要性评估"]
            A2e["记忆类型判断"]
            A2f["多级标签提取"]
            A2g["宫殿路径生成"]
            A2h["联想关系构建"]
        end
        
        A1["1. 消息分组 按role交替拆分"]
        A3["2. 过滤低重要性记忆"]
        A4["3. 文本分片 chunk=512 overlap=50"]
        A5["4. 向量嵌入 Embedding服务"]
        A6["5. 合并分片向量 取平均"]
        A7["6. 写入 Milvus insert"]
        A8["7. 更新标签索引 TagIndex"]
        A9["8. 更新图谱 build_edges+add_edges"]

        A1 --> Analyze --> A3 --> A4 --> A5 --> A6 --> A7 --> A8 --> A9
    end

    Collect --> Async
Loading

记忆体系

多级标签层级

L0 领域 (Domain)    技术 / 工作 / 学习 / 生活 / 创作
    │
L1 主题 (Topic)    后端 / 前端 / AI / 数据库 / ...
    │
L2 实体 (Entity)    人名、组织、技术栈、项目名、数字、URL
    │
L3 特征 (Feature)   高频词、专有名词、动词短语

扩展维度:
  - 行为标签 (Action): 创建/修改/查询/分析/部署/...
  - 状态标签 (Status): 完成/进行中/待办/已废弃/...
  - 时间标签 (Temporal): 近期/中期/远期
  - 情感标签 (Sentiment): positive/negative/neutral

元关联图谱关系类型

关系类型 权重 触发条件
entity_share 0.8 共享同一实体(人/组织/技术/项目)
topic 0.6 关键词 Jaccard ≥ 0.3 或同类型
temporal 0.4 7 天内记忆,指数衰减
palace_path 0.5 记忆宫殿路径前缀匹配
causal / action 0.7 因果触发词对 / 行为词重叠

重要性评分因子

因子 权重 说明
信息密度 +0.15 关键词数 / 文本长度
情感强度 +0.10 偏离中性程度
是否提问 +0.15 ?
文本长度适中 ±0.10 50~500 字符最优
数字/专有名词 +0.05 含数字或大写英文词
标签丰富度 +0.02×N 标签维度越多越重要

数据表设计

1. Milvus — 向量记忆表

Collection: memory_entries
度量: COSINE
索引: IVF_FLAT (nlist=128)

字段 类型 长度 说明
id INT64 自增主键
memory_id VARCHAR 64 记忆唯一 ID (UUID)
user_id VARCHAR 512 用户标识 (MEMORY_USER)
content VARCHAR 65535 原始文本内容
summary VARCHAR 2048 内容摘要
keywords VARCHAR 2048 关键词 JSON 数组
memory_type VARCHAR 32 记忆类型
importance FLOAT 重要性评分 [0,1]
related_ids VARCHAR 4096 关联记忆 ID JSON
memory_palace_path VARCHAR 1024 宫殿路径
tags VARCHAR 8192 多级标签 JSON
sentiment VARCHAR 16 情感标签
created_at FLOAT 创建时间戳
access_count INT64 访问次数
last_accessed_at FLOAT 最后访问时间
metadata VARCHAR 8192 元数据 JSON
embedding FLOAT_VECTOR dim=512 语义向量

用户隔离:搜索时自动追加过滤条件 user_id == "{user_id}" or user_id == "SYSTEM"

2. 时序对话表(SQLite / MySQL 双后端)

通过 TIMELINE_DB_TYPE 环境变量切换后端(默认 sqlite)。

表名: chat_timeline

字段 SQLite 类型 MySQL 类型 说明
id INTEGER AUTOINCREMENT BIGINT AUTO_INCREMENT 自增主键
memory_user TEXT VARCHAR(512) 用户标识
role TEXT VARCHAR(32) 角色 (user/assistant/system)
content TEXT MEDIUMTEXT 消息内容
memory_ids TEXT VARCHAR(4096) 关联向量记忆 ID,逗号分隔(自动回填)
created_at REAL DOUBLE Unix 时间戳(秒)

索引: (memory_user, created_at DESC) — 支持按用户时间线高效分页查询。

MySQL 模式:设置 TIMELINE_DB_TYPE=mysql 并配置连接信息,代码自动完成数据库和表的创建。


API 文档

管理接口

GET /health

健康检查。

响应:

{
  "status": "ok",
  "memory_module": "active"
}

GET /memory/stats?user_id=xxx

获取指定用户的记忆统计信息。

响应:

{
  "user_id": "user_zhangsan",
  "total_memories": 42,
  "memory_types": {"semantic": 20, "episodic": 12, "procedural": 10}
}

DELETE /memory/clear?user_id=xxx&confirm=yes

清除指定用户的所有记忆(向量 + 时序 + 内存索引)。

响应:

{
  "status": "ok",
  "user_id": "user_zhangsan",
  "deleted_vector_memories": 42,
  "deleted_timeline_records": 86
}

GET /api/timeline

分页查询对话时间线。

参数 类型 默认值 说明
memory_user string SYSTEM 用户标识
before_id int 上一页最后一条 ID
before_time float 上一页最后一条时间戳
role string 过滤角色
page_size int 20 每页数量 (1-100)

响应:

{
  "memory_user": "user_zhangsan",
  "total": 86,
  "page_size": 20,
  "records": [
    {
      "id": 86,
      "memory_user": "user_zhangsan",
      "role": "assistant",
      "content": "你好!有什么可以帮助你的吗?",
      "memory_ids": ["abc-123"],
      "created_at": 1717257600.0
    }
  ],
  "has_more": true,
  "next_cursor": {
    "before_id": 67,
    "before_time": 1717257500.0
  }
}

代理接口

ALL /{path:path}

核心代理路由。路径格式为 /http://目标地址/剩余路径

请求头:

头名称 说明
MEMORY_USER 用户标识(≤512字符),不设置则默认 SYSTEM
其他头 原样转发(hop-by-hop 头除外)

行为:

  • 如果是 /chat/completions 接口:自动 Recall → 注入记忆 → 转发 → Store
  • 其他接口:直接转发

调试技巧

  • 查看控制台日志:所有 [MEMORY] [VECTOR_STORE] [EMBEDDING] 前缀的日志会打印到 stdout
  • 验证记忆存储:GET /memory/stats?user_id=xxx 查看记忆数量和类型分布
  • 查看时序对话:GET /api/timeline?memory_user=xxx 获取完整对话时间线
  • 清除测试数据:DELETE /memory/clear?user_id=xxx&confirm=yes

配置说明

完整配置见 .env.example,关键配置项:

# 服务监听
SERVER_HOST=0.0.0.0
SERVER_PORT=9917

# Milvus 向量数据库
MILVUS_HOST=127.0.0.1
MILVUS_PORT=19530
MILVUS_USER=root
MILVUS_PASSWORD=your_password
MILVUS_DB_NAME=memory

# Embedding 服务
EMBEDDING_SERVICE_URL=http://embed-model-api/embed
EMBEDDING_VECTOR_DIMENSION=512
EMBEDDING_BATCH_SIZE=1024

# 内容分片
EMBEDDING_CHUNK_SIZE=512
EMBEDDING_CHUNK_OVERLAP=50

# 记忆检索
MEMORY_TOP_K=5
MEMORY_SIMILARITY_THRESHOLD=0.6

# 混合检索权重
HYBRID_VECTOR_WEIGHT=1.0
HYBRID_TAG_WEIGHT=1.5
HYBRID_GRAPH_WEIGHT=0.8

# 图谱扩散
GRAPH_SPREAD_MAX_DEPTH=2
GRAPH_SPREAD_DECAY=0.5

# 存储策略
MEMORY_ASYNC_STORE=true
MEMORY_MIN_IMPORTANCE=0.3

# 时序数据库(默认 SQLite,可选 MySQL)
TIMELINE_DB_TYPE=sqlite
# TIMELINE_MYSQL_HOST=127.0.0.1
# TIMELINE_MYSQL_PORT=3306
# TIMELINE_MYSQL_USER=root
# TIMELINE_MYSQL_PASSWORD=your_password
# TIMELINE_MYSQL_DATABASE=memorys

# 可选 LLM 增强(独立于主转发模型)
# MEMORY_LLM_API_URL=http://model-api/v1/chat/completions
# MEMORY_LLM_API_KEY=sk-xxx
# MEMORY_LLM_MODEL=gpt-3.5-turbo
# MEMORY_LLM_ENHANCE_SUMMARY=false
# MEMORY_LLM_ENHANCE_TAGS=false

项目结构

/pro/memory/
│
├── main.py                       # FastAPI 入口 (533行)
│   ├── 路由: /health, /memory/stats, /memory/clear
│   ├── 路由: /api/timeline (分页查询)
│   ├── 路由: / (前端页面)
│   └── 路由: /{path:path} (核心代理)
│
├── memory/                       # 记忆模块核心包
│   ├── __init__.py               # 包导出
│   ├── config.py                 # 全局配置 (MemoryConfig)
│   ├── schema.py                 # 数据结构 (MemoryEntry, MemoryQueryResult)
│   │
│   ├── manager.py                # 记忆管理器 (MemoryManager)
│   │   ├── recall()              # 混合检索记忆
│   │   ├── store()               # 分析并存储记忆
│   │   ├── store_background()    # 后台异步存储
│   │   └── format_memory_context() # 格式化记忆上下文
│   │
│   ├── analyzer.py               # 记忆分析器 (407行)
│   │   ├── extract_keywords()    # TF-IDF 关键词提取
│   │   ├── generate_summary()    # 摘要生成
│   │   ├── analyze_sentiment()   # 情感分析
│   │   ├── evaluate_importance() # 重要性评估
│   │   ├── classify_memory_type()# 记忆类型判断
│   │   ├── generate_palace_path()# 宫殿路径生成
│   │   ├── find_related_memories()# 联想关系构建
│   │   ├── analyze_content()     # 主分析入口
│   │   └── extract_query_tags()  # 查询标签提取
│   │
│   ├── chunker.py                # 文本分片器 (96行)
│   │   └── TextChunker.chunk()   # 语义边界智能切分
│   │
│   ├── embedding.py              # 嵌入服务客户端 (113行)
│   │   └── EmbeddingService      # 批量嵌入 + 降级零向量
│   │
│   ├── vector_store.py           # Milvus 操作层 (487行)
│   │   └── VectorStore           # CRUD + 用户隔离 + 自动建库
│   │
│   ├── timeline_store.py         # SQLite 时序存储 (281行)
│   │   └── TimelineStore         # 追加/分页查询/统计/清除
│   │
│   ├── tag_system.py             # 标签体系 (566行)
│   │   ├── TagExtractor          # 8维度标签提取
│   │   ├── TagIndex              # 倒排索引
│   │   └── HybridRetriever       # 三路融合检索
│   │
│   └── relation_graph.py         # 元关联图谱 (552行)
│       ├── RelationBuilder       # 五维关系构建
│       └── MemoryGraph           # BFS扩散 + PageRank
│
├── static/
│   └── index.html                # Web 对话界面 (480行)
│       ├── 配置面板 (localStorage 持久化)
│       ├── 对话区 (Markdown 渲染 + SSE 流式)
│       └── 历史加载 (向上滚动分页)
│
├── utils/
│   ├── __init__.py
│   └── treat.py                  # 请求体调试打印
│
├── data/
│   └── timeline.db               # SQLite 数据库 (运行时自动创建)
│
├── requirements.txt              # Python 依赖
├── .env.example                  # 环境变量模板
├── .gitignore                    # Git 忽略规则
└── README.md                     # 本文件

代码统计:约 3,700 行 Python + 480 行 HTML/JS/CSS。


前端界面

访问 http://localhost:9917/ 使用 Web 对话界面。

功能

  • 配置面板:MEMORY_USER、API Base URL、Key、模型名、System Prompt
  • 配置持久化到浏览器 localStorage
  • 流式 SSE 对话,Markdown 渲染(代码高亮、表格、引用)
  • 历史对话自动加载(向上滚动分页,保持滚动位置)
  • 深色主题,响应式布局
  • 自动代理拼接:用户只需配置 LLM 地址到 /v1 层级(如 http://localhost:3000/v1),前端自动拼接为 当前页面地址 + / + LLM地址 + /chat/completions 通过 Memory Proxy 转发
  • 自动补全协议:若输入地址不含 http:// 前缀,自动补全

数据流

sequenceDiagram
    participant User as 👤 用户
    participant Frontend as 🌐 前端页面
    participant Proxy as 🔄 Memory Proxy
    participant LLM as 🤖 LLM API
    participant DB as 💾 存储层

    User->>Frontend: 输入消息
    Frontend->>Proxy: fetch(SSE stream)<br/>自动拼接代理地址 + MEMORY_USER
    Proxy->>DB: Recall(混合检索记忆)
    DB-->>Proxy: 相关记忆
    Proxy->>LLM: 转发请求(含注入的记忆上下文)
    LLM-->>Proxy: 流式响应
    Proxy-->>Frontend: SSE 流式返回
    Frontend->>User: Markdown 渲染显示
    Proxy->>DB: Store(后台异步写入 SQLite + Milvus)
Loading

部署建议

生产环境

# 使用 gunicorn + uvicorn workers
pip install gunicorn
gunicorn main:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:9917

Docker

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
RUN mkdir -p data
EXPOSE 9917
CMD ["python", "main.py"]

注意事项

  1. Milvus 需独立部署,确保网络可达
  2. Embedding 服务 需提前部署并配置 URL;若不可用,记忆模块将降级为零向量模式(仅标签+图谱匹配,向量检索不可用)
  3. 时序存储:默认 SQLite(data/timeline.db),建议挂载到持久卷;生产环境可切换 MySQL(设置 TIMELINE_DB_TYPE=mysql 并配置连接信息)
  4. MEMORY_USER 建议使用业务系统中的用户 ID 或 UUID
  5. LLM 增强 默认关闭,开启后会额外调用 LLM 增加延迟
  6. 兼容性:支持标准 OpenAI 流式/非流式响应,以及 DeepSeek-R1 的 reasoning_content 字段

变更与优化指南

添加新的记忆方法

  1. memory/analyzer.py 中添加新的分析函数
  2. analyze_content() 中调用并写入 MemoryEntry 相应字段
  3. 如需新的检索方式,在 tag_system.pyHybridRetriever 中添加新路

扩展标签体系

  1. 编辑 memory/tag_system.py 中的 DOMAIN_HIERARCHY 字典
  2. 修改 TagExtractor.extract() 添加新的标签类别
  3. 同步更新 TagIndex 的索引结构

替换嵌入模型

修改 .env 中的 EMBEDDING_SERVICE_URLEMBEDDING_VECTOR_DIMENSION 即可。注意维度变更后需重建 Milvus Collection。

添加新的关系类型

  1. memory/relation_graph.pyRelationBuilder.build_edges() 中添加新的关系检测逻辑
  2. 返回对应的 GraphEdge(指定新的 relation_type 和权重)

调整混合检索策略

修改 .env 中的权重参数:

  • HYBRID_VECTOR_WEIGHT:向量语义权重
  • HYBRID_TAG_WEIGHT:标签匹配权重
  • HYBRID_GRAPH_WEIGHT:图谱扩散权重
  • GRAPH_SPREAD_MAX_DEPTH:BFS 扩散深度
  • GRAPH_SPREAD_DECAY:扩散衰减系数

接入新 LLM

只要目标 API 兼容 OpenAI 的 /v1/chat/completions 协议(支持 messages + stream),无需任何代码修改,直接通过代理地址调用即可。

About

可插拔记忆增强型 LLM 代理服务

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors