├── __init__.py ├── tools ├── __init__.py ├── query_memory.py ├── add_memory.py ├── query_memory.yaml └── add_memory.yaml ├── _assets └── logo.png ├── mem0ai.py ├── mem0ai.yaml └── .gitignore /__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chisaki-takahashi/dify-plugin-mem0ai/HEAD/_assets/logo.png -------------------------------------------------------------------------------- /mem0ai.py: -------------------------------------------------------------------------------- 1 | from core.tools.entities.tool_entities import ToolInvokeMessage, ToolProviderType 2 | from core.tools.tool.tool import Tool 3 | from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController 4 | from core.tools.errors import ToolProviderCredentialValidationError 5 | 6 | from core.tools.provider.builtin.google.tools.google_search import GoogleSearchTool 7 | 8 | import httpx 9 | 10 | from typing import Any, Dict 11 | 12 | 13 | class GoogleProvider(BuiltinToolProviderController): 14 | def _validate_credentials(self, credentials: Dict[str, Any]) -> None: 15 | http_client = httpx.Client( 16 | base_url=credentials["api_url"], 17 | headers={"Authorization": f"Bearer {credentials['api_key']}"} 18 | ) 19 | 20 | response = http_client.get("/authorized").json() 21 | 22 | if response["code"] != 0: 23 | raise ToolProviderCredentialValidationError("Authorization failed") 24 | -------------------------------------------------------------------------------- /mem0ai.yaml: -------------------------------------------------------------------------------- 1 | identity: # 工具供应商的基本信息 2 | author: tonori # 作者 3 | name: mem0ai # 名称,唯一,不允许和其他供应商重名 4 | label: # 标签,用于前端展示 5 | en_US: mem0ai # 英文标签 6 | zh_Hans: mem0ai # 中文标签 7 | description: # 描述,用于前端展示 8 | en_US: "Unofficial mem0ai provider for use in conjunction with https://github.com/tonori/mem0ai-api." # 英文描述 9 | zh_Hans: "与 https://github.com/tonori/mem0ai-api 配合使用的非官方的 mem0ai provider. " # 中文描述 10 | icon: logo.png # 图标,需要放置在当前模块的_assets文件夹下 11 | credentials_for_provider: 12 | api_url: 13 | type: text-input 14 | required: true 15 | label: 16 | en_US: API URL 17 | zh_Hans: API URL 18 | placeholder: 19 | en_US: "Please input your mem0ai API URL." 20 | zh_Hans: "请输入你的 mem0ai API URL" 21 | url: "https://github.com/tonori/mem0ai-api" 22 | 23 | api_key: 24 | type: secret-input 25 | required: false 26 | label: 27 | en_US: API Key 28 | zh_Hans: API Key 29 | placeholder: 30 | en_US: "Please input your mem0ai API Key." 31 | zh_Hans: "请输入你的 mem0ai API Key" 32 | url: "https://github.com/tonori/mem0ai-api" 33 | -------------------------------------------------------------------------------- /tools/query_memory.py: -------------------------------------------------------------------------------- 1 | import httpx 2 | import json 3 | 4 | from core.tools.tool.builtin_tool import BuiltinTool 5 | from core.tools.entities.tool_entities import ToolInvokeMessage 6 | 7 | from typing import Any, Dict, List, Union 8 | 9 | 10 | class QueryMem0AIMemory(BuiltinTool): 11 | def _invoke(self, 12 | user_id: str, 13 | tool_parameters: Dict[str, Any], 14 | ) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]: 15 | """ 16 | invoke tools 17 | """ 18 | http_client = httpx.Client( 19 | base_url=self.runtime.credentials["api_url"], 20 | headers={"Authorization": f'Bearer {self.runtime.credentials["api_key"]}'}, 21 | timeout=60 22 | ) 23 | 24 | _filters = None 25 | 26 | if tool_parameters.get("filters", None) is not None: 27 | _filters = json.loads(tool_parameters.get("filters")) 28 | 29 | response = http_client.post("/search", json={ 30 | "query": tool_parameters.get("query"), 31 | "user_id": tool_parameters.get("user_id", user_id), 32 | "agent_id": tool_parameters.get("agent_id"), 33 | "run_id": tool_parameters.get("run_id"), 34 | "limit": tool_parameters.get("limit"), 35 | "filters": _filters 36 | }) 37 | 38 | return self.create_text_message(response.text) 39 | -------------------------------------------------------------------------------- /tools/add_memory.py: -------------------------------------------------------------------------------- 1 | import httpx 2 | import json 3 | 4 | from core.tools.tool.builtin_tool import BuiltinTool 5 | from core.tools.entities.tool_entities import ToolInvokeMessage 6 | 7 | from typing import Any, Dict, List, Union 8 | 9 | 10 | class AddMem0AIMemory(BuiltinTool): 11 | def _invoke(self, 12 | user_id: str, 13 | tool_parameters: Dict[str, Any], 14 | ) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]: 15 | """ 16 | invoke tools 17 | """ 18 | http_client = httpx.Client( 19 | base_url=self.runtime.credentials["api_url"], 20 | headers={"Authorization": f'Bearer {self.runtime.credentials["api_key"]}'}, 21 | timeout=60 22 | ) 23 | 24 | _metadata = {} 25 | 26 | if tool_parameters.get("data") == "": 27 | raise ValueError("No data provided") 28 | 29 | if tool_parameters.get("metadata", None): 30 | _metadata = json.loads(tool_parameters.get("metadata")) 31 | 32 | response = http_client.post("/store", json={ 33 | "data": tool_parameters.get("data"), 34 | "user_id": tool_parameters.get("user_id", user_id), 35 | "agent_id": tool_parameters.get("agent_id"), 36 | "run_id": tool_parameters.get("run_id"), 37 | "metadata": _metadata, 38 | "filters": tool_parameters.get("filters") or {}, 39 | "prompt": tool_parameters.get("prompt") 40 | }) 41 | 42 | return self.create_text_message(response.text) 43 | -------------------------------------------------------------------------------- /tools/query_memory.yaml: -------------------------------------------------------------------------------- 1 | identity: # 工具的基本信息 2 | name: query_mem0ai_memory # 工具名称,唯一,不允许和其他工具重名 3 | author: tonori # 作者 4 | label: # 标签,用于前端展示 5 | en_US: Query mem0ai memory # 英文标签 6 | zh_Hans: 查找记忆 # 中文标签 7 | description: # 描述,用于前端展示 8 | human: # 用于前端展示的介绍,支持多语言 9 | en_US: Query mem0ai memory 10 | zh_Hans: 查找记忆 11 | llm: Query mem0ai memory. # 传递给 LLM 的介绍,为了使得LLM更好理解这个工具,我们建议在这里写上关于这个工具尽可能详细的信息,让 LLM 能够理解并使用这个工具 12 | parameters: # 参数列表 13 | - name: query # 参数名称 14 | required: true # 参数是否必须 15 | type: string # 参数类型 16 | label: # 参数标签 17 | en_US: Query content # 英文标签 18 | zh_Hans: 查询内容 # 中文标签 19 | human_description: # 用于前端展示的介绍,支持多语言 20 | en_US: Query content 21 | zh_Hans: 查询内容 22 | llm_description: query content # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 23 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 24 | - name: user_id 25 | type: string # 参数类型 26 | label: # 参数标签 27 | en_US: User ID # 英文标签 28 | zh_Hans: 用户 ID # 中文标签 29 | human_description: # 用于前端展示的介绍,支持多语言 30 | en_US: User ID 31 | zh_Hans: 用户 ID 32 | llm_description: User ID # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 33 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 34 | - name: agent_id 35 | type: string # 参数类型 36 | required: false 37 | label: # 参数标签 38 | en_US: Agent ID # 英文标签 39 | zh_Hans: Agent ID # 中文标签 40 | human_description: # 用于前端展示的介绍,支持多语言 41 | en_US: Agent ID 42 | zh_Hans: Agent ID 43 | llm_description: Agent ID # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 44 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 45 | - name: run_id 46 | type: string # 参数类型 47 | required: false 48 | label: # 参数标签 49 | en_US: Run ID # 英文标签 50 | zh_Hans: Run ID # 中文标签 51 | human_description: # 用于前端展示的介绍,支持多语言 52 | en_US: Run ID 53 | zh_Hans: Run ID 54 | llm_description: Run ID # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 55 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 56 | - name: filters 57 | type: string # 参数类型 58 | required: false 59 | label: # 参数标签 60 | en_US: Filters # 英文标签 61 | zh_Hans: 过滤条件 # 中文标签 62 | human_description: # 用于前端展示的介绍,支持多语言 63 | en_US: filter condition 64 | zh_Hans: 过滤条件 65 | llm_description: The filter condition of returned query results # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 66 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 67 | - name: limit 68 | type: number # 参数类型 69 | required: false 70 | default: 100 71 | label: # 参数标签 72 | en_US: limit # 英文标签 73 | zh_Hans: 查询结果数量限制 # 中文标签 74 | human_description: # 用于前端展示的介绍,支持多语言 75 | en_US: The limit on the number of returned query results 76 | zh_Hans: 查询结果的返回数量限制 77 | llm_description: The limit on the number of returned query results # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 78 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 -------------------------------------------------------------------------------- /tools/add_memory.yaml: -------------------------------------------------------------------------------- 1 | identity: # 工具的基本信息 2 | name: add_mem0ai_memory # 工具名称,唯一,不允许和其他工具重名 3 | author: tonori # 作者 4 | label: # 标签,用于前端展示 5 | en_US: Add mem0ai memory # 英文标签 6 | zh_Hans: 写入记忆 # 中文标签 7 | description: # 描述,用于前端展示 8 | human: # 用于前端展示的介绍,支持多语言 9 | en_US: Add mem0ai memory 10 | zh_Hans: 在 mem0ai 中写入记忆 11 | llm: Add mem0ai memory. # 传递给 LLM 的介绍,为了使得LLM更好理解这个工具,我们建议在这里写上关于这个工具尽可能详细的信息,让 LLM 能够理解并使用这个工具 12 | parameters: # 参数列表 13 | - name: data # 参数名称 14 | required: true # 参数是否必须 15 | type: string # 参数类型 16 | label: # 参数标签 17 | en_US: Memory content # 英文标签 18 | zh_Hans: 记忆内容 # 中文标签 19 | human_description: # 用于前端展示的介绍,支持多语言 20 | en_US: Memory content 21 | zh_Hans: 记忆内容 22 | llm_description: memory content # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 23 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 24 | - name: user_id 25 | type: string # 参数类型 26 | label: # 参数标签 27 | en_US: User ID # 英文标签 28 | zh_Hans: 用户 ID # 中文标签 29 | human_description: # 用于前端展示的介绍,支持多语言 30 | en_US: User ID 31 | zh_Hans: 用户 ID 32 | llm_description: User ID # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 33 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 34 | - name: agent_id 35 | type: string # 参数类型 36 | required: false 37 | label: # 参数标签 38 | en_US: Agent ID # 英文标签 39 | zh_Hans: Agent ID # 中文标签 40 | human_description: # 用于前端展示的介绍,支持多语言 41 | en_US: Agent ID 42 | zh_Hans: Agent ID 43 | llm_description: Agent ID # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 44 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 45 | - name: run_id 46 | type: string # 参数类型 47 | required: false 48 | label: # 参数标签 49 | en_US: Run ID # 英文标签 50 | zh_Hans: Run ID # 中文标签 51 | human_description: # 用于前端展示的介绍,支持多语言 52 | en_US: Run ID 53 | zh_Hans: Run ID 54 | llm_description: Run ID # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 55 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 56 | - name: metadata 57 | type: string # 参数类型 58 | required: false 59 | label: # 参数标签 60 | en_US: metadata # 英文标签 61 | zh_Hans: 元数据 # 中文标签 62 | human_description: # 用于前端展示的介绍,支持多语言 63 | en_US: metadata 64 | zh_Hans: 元数据 65 | llm_description: metadata # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 66 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 67 | - name: filters 68 | type: string # 参数类型 69 | required: false 70 | label: # 参数标签 71 | en_US: Filters # 英文标签 72 | zh_Hans: 过滤条件 # 中文标签 73 | human_description: # 用于前端展示的介绍,支持多语言 74 | en_US: Filters 75 | zh_Hans: 过滤条件 76 | llm_description: Filters # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 77 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 78 | - name: prompt 79 | type: string # 参数类型 80 | required: false 81 | label: # 参数标签 82 | en_US: Prompt # 英文标签 83 | zh_Hans: 提示词 # 中文标签 84 | human_description: # 用于前端展示的介绍,支持多语言 85 | en_US: Prompt 86 | zh_Hans: 提示词 87 | llm_description: Prompt # 传递给LLM的介绍,同上,为了使得LLM更好理解这个参数,我们建议在这里写上关于这个参数尽可能详细的信息,让LLM能够理解这个参数 88 | form: llm # 表单类型,llm表示这个参数需要由Agent自行推理出来,前端将不会展示这个参数 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 110 | .pdm.toml 111 | .pdm-python 112 | .pdm-build/ 113 | 114 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 115 | __pypackages__/ 116 | 117 | # Celery stuff 118 | celerybeat-schedule 119 | celerybeat.pid 120 | 121 | # SageMath parsed files 122 | *.sage.py 123 | 124 | # Environments 125 | .env 126 | .venv 127 | env/ 128 | venv/ 129 | ENV/ 130 | env.bak/ 131 | venv.bak/ 132 | 133 | # Spyder project settings 134 | .spyderproject 135 | .spyproject 136 | 137 | # Rope project settings 138 | .ropeproject 139 | 140 | # mkdocs documentation 141 | /site 142 | 143 | # mypy 144 | .mypy_cache/ 145 | .dmypy.json 146 | dmypy.json 147 | 148 | # Pyre type checker 149 | .pyre/ 150 | 151 | # pytype static type analyzer 152 | .pytype/ 153 | 154 | # Cython debug symbols 155 | cython_debug/ 156 | 157 | # PyCharm 158 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 159 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 160 | # and can be added to the global gitignore or merged into this file. For a more nuclear 161 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 162 | #.idea/ 163 | --------------------------------------------------------------------------------