AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


mem0替代RAG?放NND狗屁
发布日期:2024-08-03 16:03:57 浏览次数: 1790


最近很多AI自媒体又在吹一个叫mem0的项目,可以替代甚至超越RAG。

Mark基于他们提供的知识,分析了半天,得出一个结论:“完全无法替代RAG,又是一个被过度吹捧的项目”。

直到最近,mem0冲上了GitHub热榜Top1,才让我又一次重视起这个项目!

这次我决定自己研究,跑了一下官方给的demo,得出正确的结论:“mem0是个性化记忆层工具,可以让用户实现跨AI应用的长期个性化记忆,和RAG没有半毛钱关系,不可以替代RAG,硬说关联的话,唯一的相同点是都用到了向量存储这种技术”。

真的不能相信自媒体的狗话,差点让我错过了一个好项目。

下面就跟着Mark深入浅出,看一下到底什么是mem0

推荐到我的个人博客获取最佳阅读体验:

https://s.markup.com.cn/4

Mem0 为大型语言模型提供了一个智能、自我改进的记忆层,使得跨应用程序的个性化 AI 体验成为可能。

官网:https://docs.mem0.ai/overview

开源地址:https://github.com/mem0ai/mem0

核心功能

  • 用户、会话与智能体记忆: 跨用户会话、交互及智能体保留信息,确保连贯性与上下文一致性。

  • 自适应个性化: 基于用户互动和反馈持续优化个性化体验。

  • 开发者友好的API: 提供简洁明了的 API,实现与各类应用程序的无缝集成。

  • 平台一致性: 确保不同平台和设备上的行为与数据保持一致。

  • 托管服务: 提供易于部署和维护的托管解决方案。

快速开始

暂时无法在飞书文档外展示此内容

https://nbviewer.org/github/FB208/PromptEngineering/blob/master/4-mem0-quicker%20start.ipynb

原理分析

部分源码

    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.
        """

        if metadata is None:
            metadata = {}
        embeddings = self.embedding_model.embed(data)

        filters = filters or {}
        if user_id:
            filters["user_id"] = metadata["user_id"] = user_id
        if agent_id:
            filters["agent_id"] = metadata["agent_id"] = agent_id
        if run_id:
            filters["run_id"] = metadata["run_id"] = run_id

        if not prompt:
            prompt = MEMORY_DEDUCTION_PROMPT.format(user_input=data, metadata=metadata)
        extracted_memories = self.llm.generate_response(
            messages=[
                {
                    "role""system",
                    "content""You are an expert at deducing facts, preferences and memories from unstructured text.",
                },
                {"role""user""content": prompt},
            ]
        )
        existing_memories = self.vector_store.search(
            name=self.collection_name,
            query=embeddings,
            limit=5,
            filters=filters,
        )
        existing_memories = [
            MemoryItem(
                id=mem.id,
                score=mem.score,
                metadata=mem.payload,
                text=mem.payload["data"],
            )
            for mem in existing_memories
        ]
        serialized_existing_memories = [
            item.model_dump(include={"id""text""score"})
            for item in existing_memories
        ]
        logging.info(f"Total existing memories: {len(existing_memories)}")
        messages = get_update_memory_messages(
            serialized_existing_memories, extracted_memories
        )
        # Add tools for noop, add, update, delete memory.
        tools = [ADD_MEMORY_TOOL, UPDATE_MEMORY_TOOL, DELETE_MEMORY_TOOL]
        response = self.llm.generate_response(messages=messages, tools=tools)
        tool_calls = response["tool_calls"]

        response = []
        if tool_calls:
            # Create a new memory
            available_functions = {
                "add_memory": self._create_memory_tool,
                "update_memory": self._update_memory_tool,
                "delete_memory": self._delete_memory_tool,
            }
            for tool_call in tool_calls:
                function_name = tool_call["name"]
                function_to_call = available_functions[function_name]
                function_args = tool_call["arguments"]
                logging.info(
                    f"[openai_func] func: {function_name}, args: {function_args}"
                )

                # Pass metadata to the function if it requires it
                if function_name in ["add_memory""update_memory"]:
                    function_args["metadata"] = metadata

                function_result = function_to_call(**function_args)
                # Fetch the memory_id from the response
                response.append(
                    {
                        "id": function_result,
                        "event": function_name.replace("_memory"""),
                        "data": function_args.get("data"),
                    }
                )
                capture_event(
                    "mem0.add.function_call",
                    self,
                    {"memory_id": function_result, "function_name": function_name},
                )
        capture_event("mem0.add", self)
        return response

MEMORY_DEDUCTION_PROMPT 如下:

MEMORY_DEDUCTION_PROMPT = """
Deduce the facts, preferences, and memories from the provided text.
Just return the facts, preferences, and memories in bullet points:
Natural language text: {user_input}
User/Agent details: {metadata}

Constraint for deducing facts, preferences, and memories:
- The facts, preferences, and memories should be concise and informative.
- Don't start by "The person likes Pizza". Instead, start with "Likes Pizza".
- Don't remember the user/agent details provided. Only remember the facts, preferences, and memories.

Deduced facts, preferences, and memories:
"""


# 翻译
"""
从提供的文本中推断出事实、偏好和记忆。
只需在要点中返回事实、偏好和记忆:
自然语言文本:{user_input}
用户/代理详细信息:{元数据}

推断事实、偏好和记忆的约束:
-事实、偏好和记忆应该简明扼要。
-不要从“这个人喜欢披萨”开始。相反,从“喜欢披萨”开始。
-不要记住提供的用户/代理详细信息。只记住事实、偏好和记忆。

推断的事实、偏好和记忆:
“”

逻辑

这里的逻辑比较简单

  • 通过 MEMORY_DEDUCTION_PROMPT 结合用户的数据,拼接成提示词

  • 利用大模型提取抽取记忆数据,得到新的记忆项

  • 从历史记忆中提取5条最相关的记忆

  • 然后将新的记忆项、历史记忆 拼接到一起,交予大模型,让大模型调用合适的tool来更新记忆,tools :[ADD_MEMORY_TOOL, UPDATE_MEMORY_TOOL, DELETE_MEMORY_TOOL]

  • 根据function call的结果,调用tool_calls更新记忆

分析

本质上全部委托给大模型,通过prompt做了一定的约束:

  • 通过LLM(大型语言模型)和特定的元数据来抽取记忆信息,类似于进行知识图谱抽取。

  • 相关记忆信息通过向量化存储,因此可以支持记忆信息检索

  • 记忆会根据输入的内容不断更新,但是同所有长期记忆一样,也会逐渐遗忘东西

问题

  • 不支持中文,即使添加了中文记忆,也会自动翻译为英文

    • 经多次测试,并不是每次都会翻译成英文,所以肯定不是刻意为之

    • 阅读源码后发现,记忆提取使用的是llm,system prompt是用英文写的,所以assistant大概率会返回英文也就不奇怪了

    • 解决方法也很简单,因为是开源项目,自己下载源代码,优化system prompt,让他返回中文即可

总结

mem0与RAG无任何关系,更像是之前智能体中常用的“长期记忆”功能的升级,升级了以下几点:

  • 更精准的记忆提取,而非简单摘要

  • 更方便的调用方式(其实就是把功能封装,可以管理Memory一样管理记忆)

  • 支持跨应用记忆



53AI,企业落地应用大模型首选服务商

产品:大模型应用平台+智能体定制开发+落地咨询服务

承诺:先做场景POC验证,看到效果再签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

与创始人交个朋友

回到顶部

 
扫码咨询