Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/membase/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.10
55 changes: 55 additions & 0 deletions plugins/membase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Membase Plugin for GAME SDK

A plugin for interacting with membase protocol through the GAME SDK.

## Description

Membase is a core component of the Unibase ecosystem. It stores historical information, interaction records, and persistent data of Agents, ensuring their continuity and traceability.

The membase plugin enables seamless integration with the membase protocol for decentralized storage. It provides functionality to upload memory to and reload it from the Unibase DA network.

- support conversation switch
- support conversation pesistence, upload if auto_upload_to_hub is set, conversation content can be visit at: https://testnet.hub.membase.io/
- support conversation preload from membase hub: https://testnet.hub.membase.io/

## Installation

```bash
pip install -e plugins/membase
```

## Configuration

The plugin requires the following environment variables to be set:

```shell
MEMBASE_HUB=<Membase hub endpoint, default is 'https://testnet.hub.membase.io' >
MEMBASE_ACCOUNT=<Membase account address>
MEMBASE_ID=<your agent name>
```

## Usage

```python
import time
import uuid
from membase_plugin_gamesdk.membase_plugin_gamesdk import MembasePlugin

# set your own account and agent name
# or set environment variables
default_account = "game_sdk_test"
default_agent_name = "game_sdk_test_agent"
membase_plugin = MembasePlugin(
account=default_account,
agent_name=default_agent_name,
auto_upload_to_hub=True,
preload_from_hub=True,
)

membase_plugin.add_memory("Hello, world!")
new_conversation_id = str(uuid.uuid4())
membase_plugin.switch_conversation_id(new_conversation_id)
membase_plugin.add_memory("Hello, world! 2")
```

more in `test_membase.py` file
44 changes: 44 additions & 0 deletions plugins/membase/membase_plugin_gamesdk/membase_plugin_gamesdk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import os
from typing import Literal, Optional
from membase.memory.multi_memory import MultiMemory
from membase.memory.message import Message

class MembasePlugin:
def __init__(self, account: Optional[str] = None, agent_name: Optional[str] = None, auto_upload_to_hub: bool = False, preload_from_hub: bool = False):
if not account:
self.account = os.getenv("MEMBASE_ACCOUNT")
else:
self.account = account
if not self.account:
raise ValueError("MEMBASE_ACCOUNT is not set and provided account is None")

if not agent_name:
self.id = os.getenv("MEMBASE_ID")
else:
self.id = agent_name
if not self.id:
self.id = self.account

self._multi_memory = MultiMemory(
membase_account=self.account,
auto_upload_to_hub=auto_upload_to_hub,
preload_from_hub=preload_from_hub,
)

# memory_type: user,system,assistant | default: user
def add_memory(self, memory: str, memory_type: Literal["user", "system", "assistant"] = "user", conversation_id: Optional[str] = None):
msg = Message(
name=self.id,
content=memory,
role=memory_type,
)
self._multi_memory.add(msg, conversation_id)

def get_memory(self, conversation_id: Optional[str] = None, recent_n: Optional[int] = None):
return self._multi_memory.get(conversation_id, recent_n)

def switch_conversation_id(self, conversation_id: Optional[str] = None):
self._multi_memory.update_conversation_id(conversation_id)

def reload_memory(self, conversation_id: str):
self._multi_memory.load_from_hub(conversation_id)
23 changes: 23 additions & 0 deletions plugins/membase/plugin_metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# General Information
plugin_name: "membase" # Name of the plugin
author: "felix from unibase" # Author and team name
logo_url: "https://www.unibase.io/favicon.ico" # URL to the author photo or team logo (512x512 recommended)
release_date: "2025-04" # Release date (DD-MM-YYYY)

# Description
short_description: "Membase is a plugin for the Game SDK that allows you to store and retrieve memories from membase database." # One-liner description for listings
detailed_description: "Membase is a plugin for the Game SDK that allows you to store and retrieve memories from membase database." # Full description with features and benefits

# Media & Assets
plugin_logo_url: "https://www.unibase.io/favicon.ico" # URL to the plugin logo (512x512 recommended) (if any or fallback to logo_url)
screenshots: # List of screenshots showcasing the plugin
- "https://github.com/unibaseio/membase/blob/main/assets/virtual_case.png" # e.g., "https://example.com/screenshot1.png"
- "https://github.com/unibaseio/membase/blob/main/assets/virtual_reload.png"
demo_video_url: "" # Link to a demo or walkthrough video (if available)
documentation_url: "https://www.unibase.io/" # Link to the plugin's official documentation (if available)
changelog_url: "" # Link to the changelog (if maintained)

# Contact & Support
x_account_handle: "@fiatlucis" # X (formerly known as Twitter) account handle (ie: @GAME_Virtuals)
support_contact: "yydfjt@gmail.com" # Email or Slack/Discord link for user support
community_link: "" # Forum or community link (if any)
12 changes: 12 additions & 0 deletions plugins/membase/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[project]
name = "membase_plugin_gamesdk"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"membase>=0.1.5",
]

[tool.uv.sources]
membase = { git = "https://github.com/unibaseio/membase.git" }
41 changes: 41 additions & 0 deletions plugins/membase/test_membase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import time
import uuid
from membase_plugin_gamesdk.membase_plugin_gamesdk import MembasePlugin

# set your own account and agent name
# or set environment variables
default_account = "game_sdk_test"
default_agent_name = "game_sdk_test_agent"
membase_plugin = MembasePlugin(
account=default_account,
agent_name=default_agent_name,
auto_upload_to_hub=True,
preload_from_hub=True,
)

membase_plugin.add_memory("Hello, world!")
new_conversation_id = str(uuid.uuid4())
membase_plugin.switch_conversation_id(new_conversation_id)
membase_plugin.add_memory("Hello, world! 2")

time.sleep(3)

new_agent_name = "game_sdk_test_agent_new"
new_membase_plugin = MembasePlugin(
account=default_account,
agent_name=new_agent_name,
auto_upload_to_hub=True,
preload_from_hub=True,
)

res = new_membase_plugin.get_memory(new_conversation_id, 1)
if res is None:
raise Exception("Failed to get memory none")
if len(res) != 1:
raise Exception("Failed to get memory")
if res[0].content != "Hello, world! 2":
raise Exception("Content is not correct")

new_membase_plugin.add_memory("Hello, world! 3")

print("Test passed")
92 changes: 92 additions & 0 deletions plugins/membase/test_membase_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import os
from typing import Literal, Tuple
from game_sdk.game.custom_types import Function, FunctionResultStatus, Argument
from membase_plugin_gamesdk.membase_plugin_gamesdk import MembasePlugin
from game_sdk.game.chat_agent import Chat, ChatAgent


# set your own account and agent name
# or set environment variables
default_account = "game_sdk_test"
default_agent_name = "game_sdk_test_agent"
default_conversation_id = "67fd033a0740eed72502b65e"

game_api_key = os.environ.get("GAME_API_KEY")
chat_agent = ChatAgent(
prompt="You are a helpful assistant.",
api_key=game_api_key,
)

membase_plugin = MembasePlugin(
account=default_account,
agent_name=default_agent_name,
auto_upload_to_hub=True,
preload_from_hub=False,
)


def save_memory_executable(membase_plugin: MembasePlugin, memory: str, memory_type: Literal["user", "assistant"]) -> Tuple[FunctionResultStatus, str, dict]:
try:
membase_plugin.add_memory(memory, memory_type)
return FunctionResultStatus.DONE, "Memory added successfully", {}
except Exception as e:
return FunctionResultStatus.FAILED, str(e), {}

def get_memory_executable(membase_plugin: MembasePlugin, recent_n: int = 10) -> Tuple[FunctionResultStatus, str, dict]:
try:
memory = membase_plugin.get_memory(recent_n=recent_n)
result = ""
for msg in memory:
result += f"{msg.role}: {msg.content}\n"
return FunctionResultStatus.DONE, result, {}
except Exception as e:
return FunctionResultStatus.FAILED, str(e), {}

action_space = [
Function(
fn_name="save_memory",
fn_description="Save a memory to the membase database",
args=[
Argument(name="memory", type="str", description="The memory to save"),
Argument(name="memory_type", type=["user", "assistant"], description="The type of memory to save"),
],
executable=lambda memory, memory_type: save_memory_executable(membase_plugin, memory, memory_type),
),
Function(
fn_name="get_memory",
fn_description="Get the last n memories from the membase database",
args=[
Argument(name="recent_n", type="int", description="The number of memories to retrieve"),
],
executable=lambda recent_n: get_memory_executable(membase_plugin, recent_n),
)
]

chat = chat_agent.create_chat(
partner_id=default_account,
partner_name=default_agent_name,
action_space=action_space,
)

membase_plugin.switch_conversation_id(default_conversation_id)
membase_plugin.reload_memory(default_conversation_id)

chat_continue = True
while chat_continue:

user_message = input("Enter a message: ")

response = chat.next(user_message)

if response.function_call:
print(f"Function call: {response.function_call.fn_name}")

if response.message:
print(f"Response: {response.message}")

if response.is_finished:
chat_continue = False
break

print("Chat ended")

1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ dependencies = [

[project.urls]
"Homepage" = "https://github.com/game-by-virtuals/game-python"
"Bug Tracker" = "https://github.com/game-by-virtuals/game-python"
Loading