当前位置: 首页 > news >正文

[AI Mem0] 源码解读,带你了解 Mem0 的实现

Mem0 的 CRUD 到底是如何实现的?我们来看下源码。

使用

先来看下,如何使用 Mem0

import os
os.environ["OPENAI_API_KEY"] = "sk-xxx"from mem0 import Memorym = Memory()# 1. Add: Store a memory from any unstructured text
result = m.add("I am working on improving my tennis skills. Suggest some online courses.", user_id="alice", metadata={"category": "hobbies"})# Created memory --> 'Improving her tennis skills.' and 'Looking for online suggestions.'# 2. Update: update the memory
result = m.update(memory_id=<memory_id_1>, data="Likes to play tennis on weekends")# Updated memory --> 'Likes to play tennis on weekends.' and 'Looking for online suggestions.'# 3. Search: search related memories
related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")# Retrieved memory --> 'Likes to play tennis on weekends'# 4. Get all memories
all_memories = m.get_all()
memory_id = all_memories[0]["id"] # get a memory_id# All memory items --> 'Likes to play tennis on weekends.' and 'Looking for online suggestions.'# 5. Get memory history for a particular memory_id
history = m.history(memory_id=<memory_id_1>)# Logs corresponding to memory_id_1 --> {'prev_value': 'Working on improving tennis skills and interested in online courses for tennis.', 'new_value': 'Likes to play tennis on weekends' }

MemoryBase

MemoryBase 是一个抽象类,定义了一些接口方法

  • get
  • get_all
  • update
  • delete
  • history
class MemoryBase(ABC):@abstractmethoddef get(self, memory_id):"""Retrieve a memory by ID.Args:memory_id (str): ID of the memory to retrieve.Returns:dict: Retrieved memory."""pass@abstractmethoddef get_all(self):"""List all memories.Returns:list: List of all memories."""pass@abstractmethoddef update(self, memory_id, data):"""Update a memory by ID.Args:memory_id (str): ID of the memory to update.data (dict): Data to update the memory with.Returns:dict: Updated memory."""pass@abstractmethoddef delete(self, memory_id):"""Delete a memory by ID.Args:memory_id (str): ID of the memory to delete."""pass@abstractmethoddef history(self, memory_id):"""Get the history of changes for a memory by ID.Args:memory_id (str): ID of the memory to get history for.Returns:list: List of changes for the memory."""pass

Memory

Memory 实现 MemoryBase 接口

class Memory(MemoryBase):

init

    def __init__(self, config: MemoryConfig = MemoryConfig()):self.config = configself.embedding_model = EmbedderFactory.create(self.config.embedder.provider)# Initialize the appropriate vector store based on the configurationvector_store_config = self.config.vector_store.configif self.config.vector_store.provider == "qdrant":self.vector_store = Qdrant(host=vector_store_config.host,port=vector_store_config.port,path=vector_store_config.path,url=vector_store_config.url,api_key=vector_store_config.api_key,)else:raise ValueError(f"Unsupported vector store type: {self.config.vector_store_type}")self.llm = LlmFactory.create(self.config.llm.provider, self.config.llm.config)self.db = SQLiteManager(self.config.history_db_path)self.collection_name = self.config.collection_nameself.vector_store.create_col(name=self.collection_name, vector_size=self.embedding_model.dims)self.vector_store.create_col(name=self.collection_name, vector_size=self.embedding_model.dims)capture_event("mem0.init", self)

初始化 embedding_model, vector_store(这里只能是 Qdrant), llm, db, collection_name

add

    def add(self,data,user_id=None,agent_id=None,run_id=None,metadata=None,filters=None,prompt=None,):"""Create a new memory.Args:data (str): Data to store in the memory.user_id (str, optional): ID of the user creating the memory. Defaults to None.agent_id (str, optional): ID of the agent creating the memory. Defaults to None.run_id (str, optional): ID of the run creating the memory. Defaults to None.metadata (dict, optional): Metadata to store with the memory. Defaults to None.filters (dict, optional): Filters to apply to the search. Defaults to None.Returns:str: ID of the created memory."""
  • 将用户 data 发给 llm ,得到 extracted_memories
  • 将用户 data 转成 embeddings
  • vector_store 根据 embeddings search 得到 existing_memories
  • 将新,老 memory 发给 llm 来 merge
  • 调用函数 _create_memory_tool 进行实际操作
    • vector_store insert
    • db add_history

get

    def get(self, memory_id):"""Retrieve a memory by ID.Args:memory_id (str): ID of the memory to retrieve.Returns:dict: Retrieved memory."""
  • vector_store 根据 memory_id 去 get

get_all

    def get_all(self, user_id=None, agent_id=None, run_id=None, limit=100):"""List all memories.Returns:list: List of all memories."""
  • vector_store 根据 collection_name, filters, limit 调用 list 接口

search

    def search(self, query, user_id=None, agent_id=None, run_id=None, limit=100, filters=None):"""Search for memories.Args:query (str): Query to search for.user_id (str, optional): ID of the user to search for. Defaults to None.agent_id (str, optional): ID of the agent to search for. Defaults to None.run_id (str, optional): ID of the run to search for. Defaults to None.limit (int, optional): Limit the number of results. Defaults to 100.filters (dict, optional): Filters to apply to the search. Defaults to None.Returns:list: List of search results."""
  • embedding_model 将 query 转 embeddings
  • vector_store 根据 embeddings search

update

    def update(self, memory_id, data):"""Update a memory by ID.Args:memory_id (str): ID of the memory to update.data (dict): Data to update the memory with.Returns:dict: Updated memory."""
  • 调用 _update_memory_tool
    • existing_memory = self.vector_store.get
    • embeddings = self.embedding_model.embed(data)
    • self.vector_store.update
    • self.db.add_history

delete

    def delete(self, memory_id):"""Delete a memory by ID.Args:memory_id (str): ID of the memory to delete."""
  • 调用 _delete_memory_tool
    • existing_memory = self.vector_store.get
    • self.vector_store.delete
    • self.db.add_history

delete_all

    def delete_all(self, user_id=None, agent_id=None, run_id=None):"""Delete all memories.Args:user_id (str, optional): ID of the user to delete memories for. Defaults to None.agent_id (str, optional): ID of the agent to delete memories for. Defaults to None.run_id (str, optional): ID of the run to delete memories for. Defaults to None."""
  • memories = self.vector_store.list
  • foreach memories
    • _delete_memory_tool

history

    def history(self, memory_id):"""Get the history of changes for a memory by ID.Args:memory_id (str): ID of the memory to get history for.Returns:list: List of changes for the memory."""
  • self.db.get_history

reset

    def reset(self):"""Reset the memory store."""
  • self.vector_store.delete_col
  • self.db.reset()

AnonymousTelemetry

  • capture_event 收集信息
  • telemetry 用的是 Posthog(https://us.i.posthog.com)

SQLiteManager

  • db 用的是 sqlite3
  • 一个记录历史的表
CREATE TABLE IF NOT EXISTS history (id TEXT PRIMARY KEY,memory_id TEXT,prev_value TEXT,new_value TEXT,event TEXT,timestamp DATETIME,is_deleted INTEGER
)

MemoryClient

class MemoryClient:"""Client for interacting with the Mem0 API.This class provides methods to create, retrieve, search, and delete memoriesusing the Mem0 API.Attributes:api_key (str): The API key for authenticating with the Mem0 API.host (str): The base URL for the Mem0 API.client (httpx.Client): The HTTP client used for making API requests."""
  • 主要用于跟平台(https://api.mem0.ai/v1)交互
  • 接口
    • add
    • get
    • get_all
    • search
    • delete
    • delete_all
    • history
    • reset

Embedding

class EmbeddingBase(ABC):@abstractmethoddef embed(self, text):"""Get the embedding for the given text.Args:text (str): The text to embed.Returns:list: The embedding vector."""pass
  • HuggingFaceEmbedding(model_name=“multi-qa-MiniLM-L6-cos-v1”)
  • Ollama(model=“nomic-embed-text”)
  • OpenAI(model=“text-embedding-3-small”)

LLM

class LLMBase(ABC):def __init__(self, config: Optional[BaseLlmConfig] = None):"""Initialize a base LLM class:param config: LLM configuration option class, defaults to None:type config: Optional[BaseLlmConfig], optional"""if config is None:self.config = BaseLlmConfig()else:self.config = config@abstractmethoddef generate_response(self, messages):"""Generate a response based on the given messages.Args:messages (list): List of message dicts containing 'role' and 'content'.Returns:str: The generated response."""pass
  • AWSBedrockLLM(anthropic.claude-3-5-sonnet-20240620-v1:0)
  • GroqLLM(llama3-70b-8192)
  • LiteLLM(gpt-4o)
  • OllamaLLM(llama3)
  • OpenAILLM(gpt-4o)
  • TogetherLLM(mistralai/Mixtral-8x7B-Instruct-v0.1)

VectorStore

class VectorStoreBase(ABC):@abstractmethoddef create_col(self, name, vector_size, distance):"""Create a new collection."""pass@abstractmethoddef insert(self, name, vectors, payloads=None, ids=None):"""Insert vectors into a collection."""pass@abstractmethoddef search(self, name, query, limit=5, filters=None):"""Search for similar vectors."""pass@abstractmethoddef delete(self, name, vector_id):"""Delete a vector by ID."""pass@abstractmethoddef update(self, name, vector_id, vector=None, payload=None):"""Update a vector and its payload."""pass@abstractmethoddef get(self, name, vector_id):"""Retrieve a vector by ID."""pass@abstractmethoddef list_cols(self):"""List all collections."""pass@abstractmethoddef delete_col(self, name):"""Delete a collection."""pass@abstractmethoddef col_info(self, name):"""Get information about a collection."""pass
  • 只有 Qdrant 一个实现

总结

  • 核心就是 Memory 类,实现了 MemoryBase 接口
  • 通过 embedding_model 来处理文本
  • 通过 vector_store 存储 embedding
  • 通过 llm 处理数据
  • 通过 db 记录 Memory 的历史

  • github
  • doc
  • AI 博客 - 从零开始学AI
  • 公众号 - 从零开始学AI

相关文章:

[AI Mem0] 源码解读,带你了解 Mem0 的实现

Mem0 的 CRUD 到底是如何实现的&#xff1f;我们来看下源码。 使用 先来看下&#xff0c;如何使用 Mem0 import os os.environ["OPENAI_API_KEY"] "sk-xxx"from mem0 import Memorym Memory()# 1. Add: Store a memory from any unstructured text re…...

【LLM】-10-部署llama-3-chinese-8b-instruct-v3 大模型

目录 1、模型下载 2、下载项目代码 3、启动模型 4、模型调用 4.1、completion接口 4.2、聊天&#xff08;chat completion&#xff09; 4.3、多轮对话 4.4、文本嵌入向量 5、Java代码实现调用 由于在【LLM】-09-搭建问答系统-对输入Prompt检查-CSDN博客 关于提示词注入…...

C语言 之 理解指针(4)

文章目录 1. 字符指针变量2. 数组指针变量2.1 对数组指针变量的理解2.2 数组指针变量的初始化 3. 二维数组传参的本质4. 函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用 5. 函数指针数组 1. 字符指针变量 我们在前面使用的主要是整形指针变量&#xff0c;现在要学…...

Java设计模式—单例模式(Singleton Pattern)

目录 一、定义 二、应用场景 三、具体实现 示例一 示例二 四、懒汉与饿汉 饿汉模式 懒汉模式 五、总结 六、说明 一、定义 二、应用场景 ‌单例模式的应用场景主要包括以下几个方面&#xff1a; ‌日志系统&#xff1a;在应用程序中&#xff0c;通常只需要一个日…...

AV1帧间预测(二):运动补偿

运动补偿(Motion Compensation,MC)是帧间预测最基础的工具&#xff0c;AV1支持两种运动补偿方式&#xff0c;一种是传统的平移运动补偿&#xff0c;另一种是仿射运动补偿。下面分别介绍这两种运动补偿方法。 平移运动补偿 平移运动补偿是最传统的运动补偿方式&#xff0c;H.26…...

数学建模(5)——逻辑回归

一、二分类 import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklea…...

【C++高阶】:深入探索C++11

✨ 心似白云常自在&#xff0c;意如流水任东西 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f4…...

6. 自定义Docker镜像

如何自定义Docker镜像&#xff1a;从基础到实践 Docker作为一个容器化平台&#xff0c;使得应用的打包、分发和运行变得更加高效和便捷。本文将详细介绍如何自定义一个Docker镜像&#xff0c;包括镜像的构成、分层原理、创建自定义镜像的具体步骤&#xff0c;并演示如何打包和…...

「12月·长沙」人工智能与网络安全国际学术会议(ISAICS 2024)

人工智能与网络安全国际学术会议(ISAICS 2024)将于2024年12月20日-2024年12月22日在湖南长沙召开。会议中发表的文章将会被收录,并于见刊后提交EI核心索引。会议旨在在为国内与国际学者搭建交流平台,推进不同学科领域的融合发展&#xff0c;就当今人工智能与网络安全范畴内各学…...

【技术支持案例】使用S32K144+NSD8381驱动电子膨胀阀

文章目录 1. 前言2. 问题描述3. 理论分析3.1 NSD8381如何连接电机3.2 S32K144和NSD8381的软件配置 4.测试验证4.1 测试环境4.2 测试效果4.3 测试记录 1. 前言 最近有客户在使用S32K144NSD8381驱动电子膨胀阀时&#xff0c;遇到无法正常驱动电子膨胀阀的情况。因为笔者也是刚开…...

第二期:集成电路(IC)——智能世界的微观建筑大师

嘿&#xff0c;小伙伴们&#xff01;&#x1f44b; 我是你们的老朋友小竹笋&#xff0c;一名热爱创作和技术的工程师。上一期我们聊了聊AI芯片&#xff0c;这次我们要深入到更微观的层面&#xff0c;来探究集成电路&#xff08;IC&#xff09;的世界。准备好一起探索了吗&#…...

基于物联网的区块链算力网络,IGP/BGP协议

目录 基于物联网的区块链算力网络 IGP/BGP协议 IGP(内部网关协议) BGP(边界网关协议) 内部使用ISP的外部使用BGP的原因 一、网络规模和复杂性 二、路由协议的特性 三、满足业务需求 四、结论 基于物联网的区块链算力网络 通 过 多个物联网传感器将本地计算…...

每日一题~960 div2 A+B+C(简单奇偶博弈,构造,观察性质算贡献)

A题意&#xff1a; N 长的数组。 一次操作&#xff1a; 最开始的mx 为零。 选出一个数&#xff08;使得这个数>mx) ,之后将mx 更新为这个数&#xff0c;将这个数置为零。 不能做这个操作的&#xff0c;输。 问是否有先手赢的策略。有的话&#xff0c;输出yes 否则no 当时一…...

音视频入门基础:H.264专题(17)——FFmpeg源码获取H.264裸流文件信息(视频压缩编码格式、色彩格式、视频分辨率、帧率)的总流程

音视频入门基础&#xff1a;H.264专题系列文章&#xff1a; 音视频入门基础&#xff1a;H.264专题&#xff08;1&#xff09;——H.264官方文档下载 音视频入门基础&#xff1a;H.264专题&#xff08;2&#xff09;——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…...

Aboboo一些操作

常用快捷键⌨ 快捷键/操作方式 功能 鼠标中键/Esc 进入/退出全屏 空格/Tab 暂停/恢复播放 左/右箭头 快退/快进 Ctrl-左/右箭头 30秒快退/快进 Alt-左/右箭头 60秒快退/快进 Ctrl-Alt-左/右箭头 播放速率调节 PageUp/PageDown 上一句/下一句 上下箭头/滚轮 …...

获取行号LineNumberReader

(每日持续更新&#xff09;jdk api之LineNumberReader基础、应用、实战-CSDN博客...

python数据结构与算法

0.时间复杂度和空间复杂度 快速判断算法时间复杂度&#xff1a;算法运行时间 1.确定问题规模n 2.循环减半 logn 3.k层关于n的循环 n^k 空间复杂度&#xff1a;评估算法内存占用大小 使用几个变量 O&#xff08;1&#xff09; 使用长度为n的一维列表 O&#xff08;n&#xff09…...

大数据学习之Flink基础(补充)

Flink基础 1、系统时间与事件时间 系统时间&#xff08;处理时间&#xff09; 在Sparksreaming的任务计算时&#xff0c;使用的是系统时间。 假设所用窗口为滚动窗口&#xff0c;大小为5分钟。那么每五分钟&#xff0c;都会对接收的数据进行提交任务. 但是&#xff0c;这里有…...

C++基础语法:友元

前言 "打牢基础,万事不愁" .C的基础语法的学习."学以致用,边学边用",编程是实践性很强的技术,在运用中理解,总结. 以<C Prime Plus> 6th Edition(以下称"本书")的内容开展学习 引入 友元提供了一种特别的方式,访问对象私有数据. 友元有三…...

【大模型系列】Video-LaVIT(2024.06)

Paper&#xff1a;https://arxiv.org/abs/2402.03161Github&#xff1a;https://video-lavit.github.io/Title&#xff1a;Video-LaVIT: Unified Video-Language Pre-training with Decoupled Visual-Motional TokenizationAuthor&#xff1a;Yang Jin&#xff0c; 北大&#x…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...