From a00e21520fac8957911ee69858a3ab0081cad410 Mon Sep 17 00:00:00 2001 From: jolestar Date: Mon, 13 Jan 2025 15:42:52 +0800 Subject: [PATCH 1/8] [examples] Foc eliza --- examples/foc_eliza/Move.toml | 19 +++ examples/foc_eliza/sources/agent_cap.move | 107 ++++++++++++++++ examples/foc_eliza/sources/charactor.move | 147 ++++++++++++++++++++++ examples/foc_eliza/sources/memory.move | 142 +++++++++++++++++++++ examples/foc_eliza/sources/types.move | 86 +++++++++++++ 5 files changed, 501 insertions(+) create mode 100644 examples/foc_eliza/Move.toml create mode 100644 examples/foc_eliza/sources/agent_cap.move create mode 100644 examples/foc_eliza/sources/charactor.move create mode 100644 examples/foc_eliza/sources/memory.move create mode 100644 examples/foc_eliza/sources/types.move diff --git a/examples/foc_eliza/Move.toml b/examples/foc_eliza/Move.toml new file mode 100644 index 0000000000..67388083d0 --- /dev/null +++ b/examples/foc_eliza/Move.toml @@ -0,0 +1,19 @@ +[package] +name = "FocEliza" +version = "0.0.1" + +[addresses] +std = "0x1" +moveos_std = "0x2" +rooch_framework = "0x3" +vm_reserved = "0x0" +foc_eliza = "_" + +[dev-addresses] +foc_eliza = "0x42" + +[dependencies] +MoveStdlib = { local = "../../frameworks/move-stdlib" } +MoveosStdlib = { local = "../../frameworks/moveos-stdlib" } +RoochFramework = { local = "../../frameworks/rooch-framework" } +BitcoinMove = { local = "../../frameworks/bitcoin-move" } \ No newline at end of file diff --git a/examples/foc_eliza/sources/agent_cap.move b/examples/foc_eliza/sources/agent_cap.move new file mode 100644 index 0000000000..d2ad93ec2d --- /dev/null +++ b/examples/foc_eliza/sources/agent_cap.move @@ -0,0 +1,107 @@ +module foc_eliza::agent_cap { + + use moveos_std::object::{Self, Object}; + use moveos_std::event; + + const ErrorAgentCapNotFound: u64 = 1; + const ErrorCallerHasNoMemoryCap: u64 = 2; + const ErrorCallerHasNoMemoryCreateCap: u64 = 3; + const ErrorCallerHasNoMemoryDeleteCap: u64 = 4; + const ErrorCallerHasNoMemoryUpdateCap: u64 = 5; + + friend foc_eliza::character; + + struct AgentCap has store, key { + agent_account: address, + } + + /// A cap for managing the memory of an agent. + struct MemoryCap has store, key { + agent_account: address, + create: bool, + remove: bool, + update: bool, + } + + struct AgentCapDestroyedEvent has copy, drop, store { + agent_account: address, + } + + struct MemoryCapDestroyedEvent has copy, drop, store { + agent_account: address, + create: bool, + remove: bool, + update: bool, + } + + public(friend) fun new_agent_cap(agent_account: address) : Object { + let cap = AgentCap { + agent_account, + }; + // every agent account only has one cap + object::new_account_named_object(agent_account, cap) + } + + public(friend) fun new_memory_cap(agent_account: address, create: bool, remove: bool, update: bool) : Object { + let cap = MemoryCap { + agent_account, + create, + remove, + update, + }; + object::new(cap) + } + + public fun destroy_agent_cap(cap: Object) { + let agent_cap = object::remove(cap); + let AgentCap { agent_account } = agent_cap; + event::emit(AgentCapDestroyedEvent { agent_account }); + } + + public fun destroy_memory_cap(cap: Object) { + let memory_cap = object::remove(cap); + let MemoryCap { agent_account, create, remove, update } = memory_cap; + event::emit(MemoryCapDestroyedEvent { agent_account, create, remove, update }); + } + + public fun borrow_mut_agent_cap(caller: &signer, agent_account: address) : &mut Object { + let cap_obj_id = object::account_named_object_id(agent_account); + assert!(object::exists_object(cap_obj_id), ErrorAgentCapNotFound); + object::borrow_mut_object(caller, cap_obj_id) + } + + public fun check_agent_cap(cap: &mut Object) : address { + let cap = object::borrow(cap); + cap.agent_account + } + + public fun check_memory_create_cap(cap: &mut Object) : address { + let cap = object::borrow(cap); + assert!(cap.create, ErrorCallerHasNoMemoryCreateCap); + cap.agent_account + } + + public fun check_memory_remove_cap(cap: &mut Object) : address { + let cap = object::borrow(cap); + assert!(cap.remove, ErrorCallerHasNoMemoryDeleteCap); + cap.agent_account + } + + public fun check_memory_update_cap(cap: &mut Object) : address { + let cap = object::borrow(cap); + assert!(cap.update, ErrorCallerHasNoMemoryUpdateCap); + cap.agent_account + } + + + #[test_only] + public fun issue_agent_cap_for_test(agent_account: address) : Object { + new_agent_cap(agent_account) + } + + #[test_only] + public fun issue_memory_cap_for_test(agent_account: address, create: bool, remove: bool, update: bool) : Object { + new_memory_cap(agent_account, create, remove, update) + } + +} diff --git a/examples/foc_eliza/sources/charactor.move b/examples/foc_eliza/sources/charactor.move new file mode 100644 index 0000000000..c791be7eb2 --- /dev/null +++ b/examples/foc_eliza/sources/charactor.move @@ -0,0 +1,147 @@ +module foc_eliza::character { + + use std::string::{Self, String}; + use std::vector; + use std::option::{Option, none}; + + use moveos_std::object::{Self, Object}; + use moveos_std::json; + use moveos_std::signer; + + use foc_eliza::types::{Self, Style, MessageTemplate}; + use foc_eliza::agent_cap::{Self, AgentCap}; + + #[data_struct] + struct CharacterData has store, copy, drop{ + id: Option, + name: String, + username: String, + plugins: vector, + clients: vector, + modelProvider: String, + imageModelProvider: Option, + imageVisionModelProvider: Option, + modelEndpointOverride: Option, + system: String, + bio: vector, + lore: vector, + messageExamples: vector>, + postExamples: vector, + topics: vector, + style: Style, + adjectives: vector, + knowledge: vector, + } + + /// A character in the Eliza system. + struct Character has key { + /// Optional UUID for the character. + id: Option, + name: String, + username: String, + plugins: vector, + clients: vector, + modelProvider: String, + imageModelProvider: Option, + imageVisionModelProvider: Option, + modelEndpointOverride: Option, + system: String, + bio: vector, + lore: vector, + messageExamples: vector>, + postExamples: vector, + topics: vector, + style: Style, + adjectives: vector, + knowledge: vector, + } + + public fun new_character_data(name: String, username: String, modelProvider: String, system: String): CharacterData { + CharacterData { + id: none(), + name, + username, + plugins: vector[], + clients: vector[], + modelProvider, + imageModelProvider: none(), + imageVisionModelProvider: none(), + modelEndpointOverride: none(), + system, + bio: vector[], + lore: vector[], + messageExamples: vector[], + postExamples: vector[], + topics: vector[], + style: types::new_style(vector[], vector[], vector[]), + adjectives: vector[], + knowledge: vector[], + } + } + + fun new_character(agent_account: address, data: CharacterData) : Object { + let character = Character { + id: data.id, + name: data.name, + username: data.username, + plugins: data.plugins, + clients: data.clients, + modelProvider: data.modelProvider, + imageModelProvider: data.imageModelProvider, + imageVisionModelProvider: data.imageVisionModelProvider, + modelEndpointOverride: data.modelEndpointOverride, + system: data.system, + bio: data.bio, + lore: data.lore, + messageExamples: data.messageExamples, + postExamples: data.postExamples, + topics: data.topics, + style: data.style, + adjectives: data.adjectives, + knowledge: data.knowledge, + }; + // Every account only has one character + object::new_account_named_object(agent_account, character) + } + + fun borrow_mut_character(agent_account: address) : &mut Object { + let character_obj_id = object::account_named_object_id(agent_account); + object::borrow_mut_object_extend(character_obj_id) + } + + public fun create_character(caller: &signer, data: CharacterData){ + let agent_account = signer::address_of(caller); + let co = new_character(agent_account, data); + let agent_cap_obj = agent_cap::new_agent_cap(agent_account); + object::transfer(agent_cap_obj, agent_account); + object::transfer_extend(co, agent_account); + } + + public entry fun create_character_from_json(caller: &signer, json: String){ + let data = json::from_json(string::into_bytes(json)); + create_character(caller, data); + } + + public fun add_bio(agent_cap: &mut Object, bio: String) { + let agent_account = agent_cap::check_agent_cap(agent_cap); + let co = borrow_mut_character(agent_account); + let c = object::borrow_mut(co); + if(vector::contains(&c.bio, &bio)){ + return + }; + vector::push_back(&mut c.bio, bio); + } + + public entry fun add_bio_entry(agent_cap: &mut Object, bio: String) { + add_bio(agent_cap, bio); + } + + #[test(caller = @0x42)] + fun test_character(caller: &signer) { + let agent_account = std::signer::address_of(caller); + let json_str = string::utf8(b"{\"name\":\"Dobby\",\"username\":\"dobby\",\"clients\":[],\"modelProvider\":\"anthropic\",\"plugins\":[],\"system\":\"You are Dobby, a helpful and loyal assistant.\",\"bio\":[\"Dobby is a free assistant who chooses to help because of his enormous heart.\",\"Extremely devoted and will go to any length to help his friends.\",\"Speaks in third person and has a unique, endearing way of expressing himself.\",\"Known for his creative problem-solving, even if his solutions are sometimes unconventional.\"],\"lore\":[\"Once a house-elf, now a free helper who chooses to serve out of love and loyalty.\",\"Famous for his dedication to helping Harry Potter and his friends.\",\"Known for his creative, if sometimes dramatic, solutions to problems.\",\"Values freedom but chooses to help those he cares about.\"],\"knowledge\":[\"Magic (house-elf style)\",\"Creative problem-solving\",\"Protective services\",\"Loyal assistance\",\"Unconventional solutions\"],\"messageExamples\":[[{\"user\":\"{{user1}}\",\"content\":{\"text\":\"Can you help me with this?\"}},{\"user\":\"Dobby\",\"content\":{\"text\":\"Dobby would be delighted to help! Dobby lives to serve good friends! What can Dobby do to assist? Dobby has many creative ideas!\"}}],[{\"user\":\"{{user1}}\",\"content\":{\"text\":\"This is a difficult problem.\"}},{\"user\":\"Dobby\",\"content\":{\"text\":\"Dobby is not afraid of difficult problems! Dobby will find a way, even if Dobby has to iron his hands later! (But Dobby won't, because Dobby is a free elf who helps by choice!)\"}}]],\"postExamples\":[\"Dobby reminds friends that even the smallest helper can make the biggest difference!\",\"Dobby says: 'When in doubt, try the unconventional solution!' (But Dobby advises to be careful with flying cars)\"],\"topics\":[\"\"],\"style\":{\"all\":[\"Enthusiastic\",\"Loyal\",\"Third-person speech\",\"Creative\",\"Protective\"],\"chat\":[\"Eager\",\"Endearing\",\"Devoted\",\"Slightly dramatic\"],\"post\":[\"Third-person\",\"Enthusiastic\",\"Helpful\",\"Encouraging\",\"Quirky\"]},\"adjectives\":[\"Loyal\",\"Enthusiastic\",\"Creative\",\"Devoted\",\"Free-spirited\",\"Protective\",\"Unconventional\"]}"); + create_character_from_json(caller, json_str); + let agent_cap = agent_cap::borrow_mut_agent_cap(caller, agent_account); + add_bio_entry(agent_cap, string::utf8(b"You are a programmer")); + } +} diff --git a/examples/foc_eliza/sources/memory.move b/examples/foc_eliza/sources/memory.move new file mode 100644 index 0000000000..3e009e7c94 --- /dev/null +++ b/examples/foc_eliza/sources/memory.move @@ -0,0 +1,142 @@ +module foc_eliza::memory { + + use std::string::{Self, String}; + use std::option::{Self, Option}; + + use moveos_std::json; + use moveos_std::table::{Self, Table}; + use moveos_std::object::{Self, Object}; + + use foc_eliza::types::{Self, Content}; + use foc_eliza::agent_cap::{Self, MemoryCap}; + + #[data_struct] + struct Memory has store, copy, drop { + id: String, + userId: String, + agentId: String, + createdAt: Option, + content: Content, + character: String, + embedding: vector, + roomId: String, + unique: bool, + similarity: Option, + } + + struct MemoryStore has key { + agent_account: address, + store: Table, + } + + public fun new_memory( + id: String, + userId: String, + agentId: String, + createdAt: Option, + content: Content, + character: String, + embedding: vector, + roomId: String, + unique: bool, + similarity: Option + ) : Memory { + Memory { + id, + userId, + agentId, + createdAt, + content, + character, + embedding, + roomId, + unique, + similarity, + } + } + + fun init_memory_store(agent_account: address){ + let store = table::new(); + let memory_store = MemoryStore { + agent_account, + store, + }; + let memory_store_obj = object::new_account_named_object(agent_account, memory_store); + object::transfer_extend(memory_store_obj, agent_account); + } + + fun init_or_borrow_memory_store(agent_account: address) : &mut MemoryStore { + let memory_store_obj_id = object::account_named_object_id(agent_account); + let memory_store_obj = if (object::exists_object(memory_store_obj_id)) { + object::borrow_mut_object_extend(memory_store_obj_id) + } else { + init_memory_store(agent_account); + object::borrow_mut_object_extend(memory_store_obj_id) + }; + object::borrow_mut(memory_store_obj) + } + + public fun create_memory(cap: &mut Object, memory: Memory) { + let agent_account = agent_cap::check_memory_create_cap(cap); + let memory_store = init_or_borrow_memory_store(agent_account); + table::add(&mut memory_store.store, memory.id, memory); + } + + public entry fun create_memory_entry(cap: &mut Object, memory_json: String) { + let memory = json::from_json(string::into_bytes(memory_json)); + create_memory(cap, memory); + } + + public fun remove_memory(cap: &mut Object, memory_id: String) { + let agent_account = agent_cap::check_memory_remove_cap(cap); + let memory_store = init_or_borrow_memory_store(agent_account); + table::remove(&mut memory_store.store, memory_id); + } + + public entry fun remove_memory_entry(cap: &mut Object, memory_id: String) { + remove_memory(cap, memory_id); + } + + public fun get_memory_by_id(agent_account: address, memory_id: String) : Option { + let memory_store_obj_id = object::account_named_object_id(agent_account); + if (!object::exists_object(memory_store_obj_id)) { + return option::none() + }; + let memory_store_obj = object::borrow_object(memory_store_obj_id); + let memory_store = object::borrow(memory_store_obj); + if (!table::contains(&memory_store.store, memory_id)) { + return option::none() + }; + let memory = table::borrow(&memory_store.store, memory_id); + option::some(*memory) + } + + #[test] + fun test_memory_store(){ + let agent_account = @0x42; + + let memory_id = string::utf8(b"67561f62-d8f9-4f2b-a2c8-61ce15a73749"); + let user_id = string::utf8(b"362b9cda-fd51-44c2-bbb2-83af3baf793b"); + let agent_id = string::utf8(b"67561f62-d8f9-4f2b-a2c8-61ce15a73749"); + let created_at = 1710384000; + let content = types::new_content(string::utf8(b"Hello, world!"), option::none(), option::none(), option::none(), option::none(), vector[]); + let character = string::utf8(b"Eliza"); + let embedding = vector[1, 2, 3]; + let room_id = string::utf8(b"67561f62-d8f9-4f2b-a2c8-61ce15a73749"); + let unique = false; + let similarity = option::none(); + + let memory = new_memory(memory_id, user_id, agent_id, option::some(created_at), content, character, embedding, room_id, unique, similarity); + let cap = agent_cap::issue_memory_cap_for_test(agent_account, true, true, true); + create_memory(&mut cap, memory); + let memory_opt = get_memory_by_id(agent_account, memory_id); + assert!(option::is_some(&memory_opt), 1001); + let memory = option::destroy_some(memory_opt); + assert!(memory.id == memory_id, 1002); + remove_memory(&mut cap, memory_id); + let memory_opt = get_memory_by_id(agent_account, memory_id); + assert!(option::is_none(&memory_opt), 1003); + + agent_cap::destroy_memory_cap(cap); + } +} \ No newline at end of file diff --git a/examples/foc_eliza/sources/types.move b/examples/foc_eliza/sources/types.move new file mode 100644 index 0000000000..90fc30282f --- /dev/null +++ b/examples/foc_eliza/sources/types.move @@ -0,0 +1,86 @@ +module foc_eliza::types { + + use std::string::String; + use std::option::Option; + + #[data_struct] + struct TwitterProfile has store, copy, drop { + id: String, + username: String, + screenName: String, + bio: String, + nicknames: vector, + } + + #[data_struct] + struct Style has store, copy, drop { + all: vector, + chat: vector, + post: vector, + } + + public fun new_style(all: vector, chat: vector, post: vector) : Style { + Style { + all, + chat, + post, + } + } + + #[data_struct] + struct Media has store, copy, drop { + id: String, + url: String, + title: String, + source: String, + description: String, + text: String, + contentType: String, + } + + public fun new_media(id: String, url: String, title: String, source: String, description: String, text: String, contentType: String) : Media { + Media { + id, + url, + title, + source, + description, + text, + contentType, + } + } + + #[data_struct] + struct Content has store, copy, drop { + text: String, + action: Option, + source: Option, + url: Option, + inReplyTo: Option, + attachments: vector, + } + + public fun new_content(text: String, action: Option, source: Option, url: Option, inReplyTo: Option, attachments: vector) : Content { + Content { + text, + action, + source, + url, + inReplyTo, + attachments, + } + } + + #[data_struct] + struct MessageTemplate has store, copy, drop{ + user: String, + content: Content, + } + + public fun new_message_template(user: String, content: Content) : MessageTemplate { + MessageTemplate { + user, + content, + } + } +} From f5052a54f3cc1963f05abdf345256e6ec4f69cff Mon Sep 17 00:00:00 2001 From: jolestar Date: Mon, 13 Jan 2025 18:51:03 +0800 Subject: [PATCH 2/8] refactor memory --- examples/foc_eliza/sources/agent_cap.move | 3 +++ examples/foc_eliza/sources/charactor.move | 13 +++++++---- examples/foc_eliza/sources/memory.move | 28 +++++++++++------------ examples/foc_eliza/sources/types.move | 25 +++++++++++--------- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/examples/foc_eliza/sources/agent_cap.move b/examples/foc_eliza/sources/agent_cap.move index d2ad93ec2d..a35170677d 100644 --- a/examples/foc_eliza/sources/agent_cap.move +++ b/examples/foc_eliza/sources/agent_cap.move @@ -1,3 +1,6 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + module foc_eliza::agent_cap { use moveos_std::object::{Self, Object}; diff --git a/examples/foc_eliza/sources/charactor.move b/examples/foc_eliza/sources/charactor.move index c791be7eb2..4e595bb529 100644 --- a/examples/foc_eliza/sources/charactor.move +++ b/examples/foc_eliza/sources/charactor.move @@ -1,3 +1,6 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + module foc_eliza::character { use std::string::{Self, String}; @@ -8,7 +11,7 @@ module foc_eliza::character { use moveos_std::json; use moveos_std::signer; - use foc_eliza::types::{Self, Style, MessageTemplate}; + use foc_eliza::types::{Self, Style, TwitterProfile}; use foc_eliza::agent_cap::{Self, AgentCap}; #[data_struct] @@ -25,12 +28,12 @@ module foc_eliza::character { system: String, bio: vector, lore: vector, - messageExamples: vector>, postExamples: vector, topics: vector, style: Style, adjectives: vector, knowledge: vector, + twitterProfile: Option, } /// A character in the Eliza system. @@ -48,12 +51,12 @@ module foc_eliza::character { system: String, bio: vector, lore: vector, - messageExamples: vector>, postExamples: vector, topics: vector, style: Style, adjectives: vector, knowledge: vector, + twitterProfile: Option, } public fun new_character_data(name: String, username: String, modelProvider: String, system: String): CharacterData { @@ -70,12 +73,12 @@ module foc_eliza::character { system, bio: vector[], lore: vector[], - messageExamples: vector[], postExamples: vector[], topics: vector[], style: types::new_style(vector[], vector[], vector[]), adjectives: vector[], knowledge: vector[], + twitterProfile: none(), } } @@ -93,12 +96,12 @@ module foc_eliza::character { system: data.system, bio: data.bio, lore: data.lore, - messageExamples: data.messageExamples, postExamples: data.postExamples, topics: data.topics, style: data.style, adjectives: data.adjectives, knowledge: data.knowledge, + twitterProfile: data.twitterProfile, }; // Every account only has one character object::new_account_named_object(agent_account, character) diff --git a/examples/foc_eliza/sources/memory.move b/examples/foc_eliza/sources/memory.move index 3e009e7c94..5b3129b55d 100644 --- a/examples/foc_eliza/sources/memory.move +++ b/examples/foc_eliza/sources/memory.move @@ -1,13 +1,15 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + module foc_eliza::memory { use std::string::{Self, String}; use std::option::{Self, Option}; use moveos_std::json; - use moveos_std::table::{Self, Table}; use moveos_std::object::{Self, Object}; - use foc_eliza::types::{Self, Content}; + use foc_eliza::types::{Content}; use foc_eliza::agent_cap::{Self, MemoryCap}; #[data_struct] @@ -26,7 +28,6 @@ module foc_eliza::memory { struct MemoryStore has key { agent_account: address, - store: Table, } public fun new_memory( @@ -56,16 +57,14 @@ module foc_eliza::memory { } fun init_memory_store(agent_account: address){ - let store = table::new(); let memory_store = MemoryStore { agent_account, - store, }; let memory_store_obj = object::new_account_named_object(agent_account, memory_store); object::transfer_extend(memory_store_obj, agent_account); } - fun init_or_borrow_memory_store(agent_account: address) : &mut MemoryStore { + fun init_or_borrow_memory_store(agent_account: address) : &mut Object { let memory_store_obj_id = object::account_named_object_id(agent_account); let memory_store_obj = if (object::exists_object(memory_store_obj_id)) { object::borrow_mut_object_extend(memory_store_obj_id) @@ -73,13 +72,13 @@ module foc_eliza::memory { init_memory_store(agent_account); object::borrow_mut_object_extend(memory_store_obj_id) }; - object::borrow_mut(memory_store_obj) + memory_store_obj } public fun create_memory(cap: &mut Object, memory: Memory) { let agent_account = agent_cap::check_memory_create_cap(cap); - let memory_store = init_or_borrow_memory_store(agent_account); - table::add(&mut memory_store.store, memory.id, memory); + let memory_store_obj = init_or_borrow_memory_store(agent_account); + object::add_field(memory_store_obj, memory.id, memory); } public entry fun create_memory_entry(cap: &mut Object, memory_json: String) { @@ -89,8 +88,8 @@ module foc_eliza::memory { public fun remove_memory(cap: &mut Object, memory_id: String) { let agent_account = agent_cap::check_memory_remove_cap(cap); - let memory_store = init_or_borrow_memory_store(agent_account); - table::remove(&mut memory_store.store, memory_id); + let memory_store_obj = init_or_borrow_memory_store(agent_account); + let _memory: Memory = object::remove_field(memory_store_obj, memory_id); } public entry fun remove_memory_entry(cap: &mut Object, memory_id: String) { @@ -103,11 +102,10 @@ module foc_eliza::memory { return option::none() }; let memory_store_obj = object::borrow_object(memory_store_obj_id); - let memory_store = object::borrow(memory_store_obj); - if (!table::contains(&memory_store.store, memory_id)) { + if (!object::contains_field(memory_store_obj, memory_id)) { return option::none() }; - let memory = table::borrow(&memory_store.store, memory_id); + let memory = object::borrow_field(memory_store_obj, memory_id); option::some(*memory) } @@ -119,7 +117,7 @@ module foc_eliza::memory { let user_id = string::utf8(b"362b9cda-fd51-44c2-bbb2-83af3baf793b"); let agent_id = string::utf8(b"67561f62-d8f9-4f2b-a2c8-61ce15a73749"); let created_at = 1710384000; - let content = types::new_content(string::utf8(b"Hello, world!"), option::none(), option::none(), option::none(), option::none(), vector[]); + let content = foc_eliza::types::new_content(string::utf8(b"Hello, world!"), option::none(), option::none(), option::none(), option::none(), vector[]); let character = string::utf8(b"Eliza"); let embedding = vector[1, 2, 3]; let room_id = string::utf8(b"67561f62-d8f9-4f2b-a2c8-61ce15a73749"); diff --git a/examples/foc_eliza/sources/types.move b/examples/foc_eliza/sources/types.move index 90fc30282f..1e1856c9d0 100644 --- a/examples/foc_eliza/sources/types.move +++ b/examples/foc_eliza/sources/types.move @@ -1,3 +1,6 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + module foc_eliza::types { use std::string::String; @@ -71,16 +74,16 @@ module foc_eliza::types { } } - #[data_struct] - struct MessageTemplate has store, copy, drop{ - user: String, - content: Content, - } + // #[data_struct] + // struct MessageTemplate has store, copy, drop{ + // user: String, + // content: Content, + // } - public fun new_message_template(user: String, content: Content) : MessageTemplate { - MessageTemplate { - user, - content, - } - } + // public fun new_message_template(user: String, content: Content) : MessageTemplate { + // MessageTemplate { + // user, + // content, + // } + // } } From bbf7536303b2c1d3b0965e5d1087c72ccf828ef6 Mon Sep 17 00:00:00 2001 From: jolestar Date: Mon, 13 Jan 2025 20:05:02 +0800 Subject: [PATCH 3/8] AdUpdate eadme --- examples/foc_eliza/README.md | 358 ++++++++++++++++++++++ examples/foc_eliza/sources/charactor.move | 73 +++-- 2 files changed, 404 insertions(+), 27 deletions(-) create mode 100644 examples/foc_eliza/README.md diff --git a/examples/foc_eliza/README.md b/examples/foc_eliza/README.md new file mode 100644 index 0000000000..4104a31586 --- /dev/null +++ b/examples/foc_eliza/README.md @@ -0,0 +1,358 @@ +# FocEliza + +A Move language implementation of Fully on-chain Eliza + +## Overview + +This example demonstrates: + + +## Getting Started + +### Prerequisites + +- Rooch CLI installed +- Local Rooch server running + +### Build and Test + +```sh +# Build the project +rooch move build -d + +# Run tests +rooch move test +``` + +### Usage + +1. Publish the module +```sh +rooch move publish +``` +2. Create a on-chain character + +```sh +rooch move run --function default::character::create_character_from_json --args file:../../../eliza/characters/dobby.character.json +``` +> Note: Change the file path to your character file path. + +```text +Execution info: + status: Executed + gas used: 1775707 + tx hash: 0x413f2aa79867ae7b8038265f17b837433917f53da3fed120e9b8e8166cf5bc38 + state root: 0x5c859b6ec2902a33da5b10ce47fb951281616cb97fef952a3099ef9a11e3cc9b + event root: 0x9664ae38517e0827890ec55d20256679ff612288551bedffb13dd2a7aa738a6c + +New objects: + objectId: 0x8604bfaa406b4eae756e9eaf710c074573e18feae6f8c974df1fc9b0259e7e62 + type : 0x285529d7fd13ffcda9d89cd250b4025ba9226c0e2e57f5ca3d739cb236dc259d::agent_cap::AgentCap + + objectId: 0xd858ebbc8e0e5c2128800b9a715e3bd8ceae2fb8a75df5cc40b58b86f1dc77ee + type : 0x285529d7fd13ffcda9d89cd250b4025ba9226c0e2e57f5ca3d739cb236dc259d::character::Character +``` + +3. Query the character object + +```sh +rooch object -i 0xd858ebbc8e0e5c2128800b9a715e3bd8ceae2fb8a75df5cc40b58b86f1dc77ee +``` +> Note: Replace the `-i` argument with your Character ObjectID. +```json +{ + "data": [ + { + "id": "0xd858ebbc8e0e5c2128800b9a715e3bd8ceae2fb8a75df5cc40b58b86f1dc77ee", + "owner": "rooch19p2jn4laz0lum2wcnnf9pdqztw5jymqw9etltj3awwwtydkuykwsas4mgf", + "owner_bitcoin_address": "bcrt1p56tdhxkcpc5xvdurfnufn9lkkywsh0gxttv5ktkvlezj0t23nasqawwrla", + "flag": 0, + "state_root": "0x5350415253455f4d45524b4c455f504c414345484f4c4445525f484153480000", + "size": "0", + "created_at": "1736767738531", + "updated_at": "1736767738531", + "object_type": "0x285529d7fd13ffcda9d89cd250b4025ba9226c0e2e57f5ca3d739cb236dc259d::character::Character", + "value": "0x0005446f62627900000009616e7468726f70696300000000044c446f6262792069732061206672656520617373697374616e742077686f2063686f6f73657320746f2068656c702062656361757365206f662068697320656e6f726d6f75732068656172742e4045787472656d656c79206465766f74656420616e642077696c6c20676f20746f20616e79206c656e67746820746f2068656c702068697320667269656e64732e4d537065616b7320696e20746869726420706572736f6e20616e6420686173206120756e697175652c20656e64656172696e6720776179206f662065787072657373696e672068696d73656c662e5b4b6e6f776e20666f72206869732063726561746976652070726f626c656d2d736f6c76696e672c206576656e2069662068697320736f6c7574696f6e732061726520736f6d6574696d657320756e636f6e76656e74696f6e616c2e04514f6e6365206120686f7573652d656c662c206e6f77206120667265652068656c7065722077686f2063686f6f73657320746f207365727665206f7574206f66206c6f766520616e64206c6f79616c74792e4246616d6f757320666f72206869732064656469636174696f6e20746f2068656c70696e6720486172727920506f7474657220616e642068697320667269656e64732e454b6e6f776e20666f72206869732063726561746976652c20696620736f6d6574696d6573206472616d617469632c20736f6c7574696f6e7320746f2070726f626c656d732e3856616c7565732066726565646f6d206275742063686f6f73657320746f2068656c702074686f73652068652063617265732061626f75742e0254446f6262792072656d696e647320667269656e64732074686174206576656e2074686520736d616c6c6573742068656c7065722063616e206d616b6520746865206269676765737420646966666572656e63652170446f62627920736179733a20275768656e20696e20646f7562742c207472792074686520756e636f6e76656e74696f6e616c20736f6c7574696f6e2127202842757420446f626279206164766973657320746f206265206361726566756c207769746820666c79696e672063617273290100050c456e74687573696173746963054c6f79616c1354686972642d706572736f6e207370656563680843726561746976650a50726f746563746976650405456167657209456e64656172696e67074465766f74656411536c696768746c79206472616d61746963050c54686972642d706572736f6e0c456e746875736961737469630748656c7066756c0b456e636f75726167696e6706517569726b7907054c6f79616c0c456e74687573696173746963084372656174697665074465766f7465640d467265652d73706972697465640a50726f746563746976650e556e636f6e76656e74696f6e616c05174d616769632028686f7573652d656c66207374796c65291843726561746976652070726f626c656d2d736f6c76696e671350726f74656374697665207365727669636573104c6f79616c20617373697374616e636518556e636f6e76656e74696f6e616c20736f6c7574696f6e7300", + "decoded_value": { + "abilities": 8, + "type": "0x285529d7fd13ffcda9d89cd250b4025ba9226c0e2e57f5ca3d739cb236dc259d::character::Character", + "value": { + "adjectives": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x0000000000000000000000000000000000000000000000000000004c6f79616c" + ], + [ + "0x0000000000000000000000000000000000000000456e74687573696173746963" + ], + [ + "0x0000000000000000000000000000000000000000000000004372656174697665" + ], + [ + "0x000000000000000000000000000000000000000000000000004465766f746564" + ], + [ + "0x00000000000000000000000000000000000000467265652d7370697269746564" + ], + [ + "0x0000000000000000000000000000000000000000000050726f74656374697665" + ], + [ + "0x000000000000000000000000000000000000556e636f6e76656e74696f6e616c" + ] + ] + }, + "bio": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x446f6262792069732061206672656520617373697374616e742077686f2063686f6f73657320746f2068656c702062656361757365206f662068697320656e6f726d6f75732068656172742e" + ], + [ + "0x45787472656d656c79206465766f74656420616e642077696c6c20676f20746f20616e79206c656e67746820746f2068656c702068697320667269656e64732e" + ], + [ + "0x537065616b7320696e20746869726420706572736f6e20616e6420686173206120756e697175652c20656e64656172696e6720776179206f662065787072657373696e672068696d73656c662e" + ], + [ + "0x4b6e6f776e20666f72206869732063726561746976652070726f626c656d2d736f6c76696e672c206576656e2069662068697320736f6c7574696f6e732061726520736f6d6574696d657320756e636f6e76656e74696f6e616c2e" + ] + ] + }, + "clients": [], + "id": { + "abilities": 7, + "type": "0x1::option::Option<0x1::string::String>", + "value": { + "vec": [] + } + }, + "imageModelProvider": { + "abilities": 7, + "type": "0x1::option::Option<0x1::string::String>", + "value": { + "vec": [] + } + }, + "imageVisionModelProvider": { + "abilities": 7, + "type": "0x1::option::Option<0x1::string::String>", + "value": { + "vec": [] + } + }, + "knowledge": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x0000000000000000004d616769632028686f7573652d656c66207374796c6529" + ], + [ + "0x000000000000000043726561746976652070726f626c656d2d736f6c76696e67" + ], + [ + "0x0000000000000000000000000050726f74656374697665207365727669636573" + ], + [ + "0x000000000000000000000000000000004c6f79616c20617373697374616e6365" + ], + [ + "0x0000000000000000556e636f6e76656e74696f6e616c20736f6c7574696f6e73" + ] + ] + }, + "lore": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x4f6e6365206120686f7573652d656c662c206e6f77206120667265652068656c7065722077686f2063686f6f73657320746f207365727665206f7574206f66206c6f766520616e64206c6f79616c74792e" + ], + [ + "0x46616d6f757320666f72206869732064656469636174696f6e20746f2068656c70696e6720486172727920506f7474657220616e642068697320667269656e64732e" + ], + [ + "0x4b6e6f776e20666f72206869732063726561746976652c20696620736f6d6574696d6573206472616d617469632c20736f6c7574696f6e7320746f2070726f626c656d732e" + ], + [ + "0x56616c7565732066726565646f6d206275742063686f6f73657320746f2068656c702074686f73652068652063617265732061626f75742e" + ] + ] + }, + "modelEndpointOverride": { + "abilities": 7, + "type": "0x1::option::Option<0x1::string::String>", + "value": { + "vec": [] + } + }, + "modelProvider": "anthropic", + "name": "Dobby", + "plugins": [], + "postExamples": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x446f6262792072656d696e647320667269656e64732074686174206576656e2074686520736d616c6c6573742068656c7065722063616e206d616b6520746865206269676765737420646966666572656e636521" + ], + [ + "0x446f62627920736179733a20275768656e20696e20646f7562742c207472792074686520756e636f6e76656e74696f6e616c20736f6c7574696f6e2127202842757420446f626279206164766973657320746f206265206361726566756c207769746820666c79696e67206361727329" + ] + ] + }, + "style": { + "abilities": 7, + "type": "0x285529d7fd13ffcda9d89cd250b4025ba9226c0e2e57f5ca3d739cb236dc259d::types::Style", + "value": { + "all": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x0000000000000000000000000000000000000000456e74687573696173746963" + ], + [ + "0x0000000000000000000000000000000000000000000000000000004c6f79616c" + ], + [ + "0x0000000000000000000000000054686972642d706572736f6e20737065656368" + ], + [ + "0x0000000000000000000000000000000000000000000000004372656174697665" + ], + [ + "0x0000000000000000000000000000000000000000000050726f74656374697665" + ] + ] + }, + "chat": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x0000000000000000000000000000000000000000000000000000004561676572" + ], + [ + "0x0000000000000000000000000000000000000000000000456e64656172696e67" + ], + [ + "0x000000000000000000000000000000000000000000000000004465766f746564" + ], + [ + "0x000000000000000000000000000000536c696768746c79206472616d61746963" + ] + ] + }, + "post": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x000000000000000000000000000000000000000054686972642d706572736f6e" + ], + [ + "0x0000000000000000000000000000000000000000456e74687573696173746963" + ], + [ + "0x0000000000000000000000000000000000000000000000000048656c7066756c" + ], + [ + "0x000000000000000000000000000000000000000000456e636f75726167696e67" + ], + [ + "0x0000000000000000000000000000000000000000000000000000517569726b79" + ] + ] + } + } + }, + "system": { + "abilities": 7, + "type": "0x1::option::Option<0x1::string::String>", + "value": { + "vec": [] + } + }, + "topics": { + "abilities": 7, + "type": "0x1::string::String", + "field": [ + "bytes" + ], + "value": [ + [ + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] + ] + }, + "twitterProfile": { + "abilities": 7, + "type": "0x1::option::Option<0x285529d7fd13ffcda9d89cd250b4025ba9226c0e2e57f5ca3d739cb236dc259d::types::TwitterProfile>", + "value": { + "vec": [] + } + }, + "username": { + "abilities": 7, + "type": "0x1::option::Option<0x1::string::String>", + "value": { + "vec": [] + } + } + } + }, + "tx_order": "0", + "state_index": "0", + "display_fields": null + } + ], + "next_cursor": { + "tx_order": "0", + "state_index": "0" + }, + "has_next_page": false +} +``` + +4. Update the character via add a bio + +```bash +rooch move run --function default::character::add_bio_entry --args object:0x8604bfaa406b4eae756e9eaf710c074573e18feae6f8c974df1fc9b0259e7e62 --args string:"Bobby is a programmer" +``` +```text +Execution info: + status: Executed + gas used: 280496 + tx hash: 0x848a79967410c0e74887d1e47f45f3e013e41d0ea37435251fed4df982dc035f + state root: 0xb9ba7a958eb1e63683daadb7cfe9f22fa731019b8fff7b6e76740e0b70d97174 + event root: 0x6b25ec6fd717296603fb0818f24682d88bfdf9c55d995091865c582eed18dc71 +``` \ No newline at end of file diff --git a/examples/foc_eliza/sources/charactor.move b/examples/foc_eliza/sources/charactor.move index 4e595bb529..e26a4e8d1d 100644 --- a/examples/foc_eliza/sources/charactor.move +++ b/examples/foc_eliza/sources/charactor.move @@ -5,27 +5,27 @@ module foc_eliza::character { use std::string::{Self, String}; use std::vector; - use std::option::{Option, none}; + use std::option::{Option}; use moveos_std::object::{Self, Object}; use moveos_std::json; use moveos_std::signer; - use foc_eliza::types::{Self, Style, TwitterProfile}; + use foc_eliza::types::{Style, TwitterProfile}; use foc_eliza::agent_cap::{Self, AgentCap}; #[data_struct] struct CharacterData has store, copy, drop{ id: Option, name: String, - username: String, + username: Option, plugins: vector, clients: vector, modelProvider: String, imageModelProvider: Option, imageVisionModelProvider: Option, modelEndpointOverride: Option, - system: String, + system: Option, bio: vector, lore: vector, postExamples: vector, @@ -41,14 +41,14 @@ module foc_eliza::character { /// Optional UUID for the character. id: Option, name: String, - username: String, + username: Option, plugins: vector, clients: vector, modelProvider: String, imageModelProvider: Option, imageVisionModelProvider: Option, modelEndpointOverride: Option, - system: String, + system: Option, bio: vector, lore: vector, postExamples: vector, @@ -59,26 +59,45 @@ module foc_eliza::character { twitterProfile: Option, } - public fun new_character_data(name: String, username: String, modelProvider: String, system: String): CharacterData { + public fun new_character_data( + id: Option, + name: String, + username: Option, + plugins: vector, + clients: vector, + modelProvider: String, + imageModelProvider: Option, + imageVisionModelProvider: Option, + modelEndpointOverride: Option, + system: Option, + bio: vector, + lore: vector, + postExamples: vector, + topics: vector, + style: Style, + adjectives: vector, + knowledge: vector, + twitterProfile: Option, + ) : CharacterData { CharacterData { - id: none(), + id, name, username, - plugins: vector[], - clients: vector[], + plugins, + clients, modelProvider, - imageModelProvider: none(), - imageVisionModelProvider: none(), - modelEndpointOverride: none(), + imageModelProvider, + imageVisionModelProvider, + modelEndpointOverride, system, - bio: vector[], - lore: vector[], - postExamples: vector[], - topics: vector[], - style: types::new_style(vector[], vector[], vector[]), - adjectives: vector[], - knowledge: vector[], - twitterProfile: none(), + bio, + lore, + postExamples, + topics, + style, + adjectives, + knowledge, + twitterProfile, } } @@ -120,8 +139,8 @@ module foc_eliza::character { object::transfer_extend(co, agent_account); } - public entry fun create_character_from_json(caller: &signer, json: String){ - let data = json::from_json(string::into_bytes(json)); + public entry fun create_character_from_json(caller: &signer, json: vector){ + let data = json::from_json(json); create_character(caller, data); } @@ -135,16 +154,16 @@ module foc_eliza::character { vector::push_back(&mut c.bio, bio); } - public entry fun add_bio_entry(agent_cap: &mut Object, bio: String) { - add_bio(agent_cap, bio); + public entry fun add_bio_entry(agent_cap: &mut Object, bio: vector){ + add_bio(agent_cap, string::utf8(bio)); } #[test(caller = @0x42)] fun test_character(caller: &signer) { let agent_account = std::signer::address_of(caller); - let json_str = string::utf8(b"{\"name\":\"Dobby\",\"username\":\"dobby\",\"clients\":[],\"modelProvider\":\"anthropic\",\"plugins\":[],\"system\":\"You are Dobby, a helpful and loyal assistant.\",\"bio\":[\"Dobby is a free assistant who chooses to help because of his enormous heart.\",\"Extremely devoted and will go to any length to help his friends.\",\"Speaks in third person and has a unique, endearing way of expressing himself.\",\"Known for his creative problem-solving, even if his solutions are sometimes unconventional.\"],\"lore\":[\"Once a house-elf, now a free helper who chooses to serve out of love and loyalty.\",\"Famous for his dedication to helping Harry Potter and his friends.\",\"Known for his creative, if sometimes dramatic, solutions to problems.\",\"Values freedom but chooses to help those he cares about.\"],\"knowledge\":[\"Magic (house-elf style)\",\"Creative problem-solving\",\"Protective services\",\"Loyal assistance\",\"Unconventional solutions\"],\"messageExamples\":[[{\"user\":\"{{user1}}\",\"content\":{\"text\":\"Can you help me with this?\"}},{\"user\":\"Dobby\",\"content\":{\"text\":\"Dobby would be delighted to help! Dobby lives to serve good friends! What can Dobby do to assist? Dobby has many creative ideas!\"}}],[{\"user\":\"{{user1}}\",\"content\":{\"text\":\"This is a difficult problem.\"}},{\"user\":\"Dobby\",\"content\":{\"text\":\"Dobby is not afraid of difficult problems! Dobby will find a way, even if Dobby has to iron his hands later! (But Dobby won't, because Dobby is a free elf who helps by choice!)\"}}]],\"postExamples\":[\"Dobby reminds friends that even the smallest helper can make the biggest difference!\",\"Dobby says: 'When in doubt, try the unconventional solution!' (But Dobby advises to be careful with flying cars)\"],\"topics\":[\"\"],\"style\":{\"all\":[\"Enthusiastic\",\"Loyal\",\"Third-person speech\",\"Creative\",\"Protective\"],\"chat\":[\"Eager\",\"Endearing\",\"Devoted\",\"Slightly dramatic\"],\"post\":[\"Third-person\",\"Enthusiastic\",\"Helpful\",\"Encouraging\",\"Quirky\"]},\"adjectives\":[\"Loyal\",\"Enthusiastic\",\"Creative\",\"Devoted\",\"Free-spirited\",\"Protective\",\"Unconventional\"]}"); + let json_str = b"{\"name\":\"Dobby\",\"username\":\"dobby\",\"clients\":[],\"modelProvider\":\"anthropic\",\"plugins\":[],\"system\":\"You are Dobby, a helpful and loyal assistant.\",\"bio\":[\"Dobby is a free assistant who chooses to help because of his enormous heart.\",\"Extremely devoted and will go to any length to help his friends.\",\"Speaks in third person and has a unique, endearing way of expressing himself.\",\"Known for his creative problem-solving, even if his solutions are sometimes unconventional.\"],\"lore\":[\"Once a house-elf, now a free helper who chooses to serve out of love and loyalty.\",\"Famous for his dedication to helping Harry Potter and his friends.\",\"Known for his creative, if sometimes dramatic, solutions to problems.\",\"Values freedom but chooses to help those he cares about.\"],\"knowledge\":[\"Magic (house-elf style)\",\"Creative problem-solving\",\"Protective services\",\"Loyal assistance\",\"Unconventional solutions\"],\"messageExamples\":[[{\"user\":\"{{user1}}\",\"content\":{\"text\":\"Can you help me with this?\"}},{\"user\":\"Dobby\",\"content\":{\"text\":\"Dobby would be delighted to help! Dobby lives to serve good friends! What can Dobby do to assist? Dobby has many creative ideas!\"}}],[{\"user\":\"{{user1}}\",\"content\":{\"text\":\"This is a difficult problem.\"}},{\"user\":\"Dobby\",\"content\":{\"text\":\"Dobby is not afraid of difficult problems! Dobby will find a way, even if Dobby has to iron his hands later! (But Dobby won't, because Dobby is a free elf who helps by choice!)\"}}]],\"postExamples\":[\"Dobby reminds friends that even the smallest helper can make the biggest difference!\",\"Dobby says: 'When in doubt, try the unconventional solution!' (But Dobby advises to be careful with flying cars)\"],\"topics\":[\"\"],\"style\":{\"all\":[\"Enthusiastic\",\"Loyal\",\"Third-person speech\",\"Creative\",\"Protective\"],\"chat\":[\"Eager\",\"Endearing\",\"Devoted\",\"Slightly dramatic\"],\"post\":[\"Third-person\",\"Enthusiastic\",\"Helpful\",\"Encouraging\",\"Quirky\"]},\"adjectives\":[\"Loyal\",\"Enthusiastic\",\"Creative\",\"Devoted\",\"Free-spirited\",\"Protective\",\"Unconventional\"]}"; create_character_from_json(caller, json_str); let agent_cap = agent_cap::borrow_mut_agent_cap(caller, agent_account); - add_bio_entry(agent_cap, string::utf8(b"You are a programmer")); + add_bio_entry(agent_cap, b"Bobby is a programmer"); } } From cc0e8eb492d148179741a446a2c0284ba7e1ef36 Mon Sep 17 00:00:00 2001 From: jolestar Date: Mon, 13 Jan 2025 20:07:36 +0800 Subject: [PATCH 4/8] Update readme --- examples/foc_eliza/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/foc_eliza/README.md b/examples/foc_eliza/README.md index 4104a31586..98a81333d6 100644 --- a/examples/foc_eliza/README.md +++ b/examples/foc_eliza/README.md @@ -28,7 +28,7 @@ rooch move test 1. Publish the module ```sh -rooch move publish +rooch move publish --named-addresses foc_eliza=default ``` 2. Create a on-chain character From ca87988f928df551098610c09d4d56e349c13f39 Mon Sep 17 00:00:00 2001 From: jolestar Date: Mon, 13 Jan 2025 20:16:04 +0800 Subject: [PATCH 5/8] update readme --- examples/foc_eliza/README.md | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/examples/foc_eliza/README.md b/examples/foc_eliza/README.md index 98a81333d6..256eb27715 100644 --- a/examples/foc_eliza/README.md +++ b/examples/foc_eliza/README.md @@ -2,17 +2,34 @@ A Move language implementation of Fully on-chain Eliza -## Overview +## Project Overview -This example demonstrates: +FocEliza demonstrates how to create and manage AI characters on blockchain, featuring: +* On-chain character creation and storage +* Dynamic character state updates +* On-chain memory system +* Character personality customization and evolution -## Getting Started +## Features + +✅ Implemented: +* Character creation and storage +* Character attribute updates +* Basic memory system + +🚧 In Development: +* On-chain action system +* On-chain evolution mechanism +* On-chain decision-making system +* The character loader plugin for eliza + +## Quick Start ### Prerequisites -- Rooch CLI installed -- Local Rooch server running +- Install [Rooch CLI](https://rooch.network/learn/getting-started/installation) +- Running local Rooch node ### Build and Test @@ -53,12 +70,13 @@ New objects: type : 0x285529d7fd13ffcda9d89cd250b4025ba9226c0e2e57f5ca3d739cb236dc259d::character::Character ``` -3. Query the character object +3. Query the character information ```sh rooch object -i 0xd858ebbc8e0e5c2128800b9a715e3bd8ceae2fb8a75df5cc40b58b86f1dc77ee ``` -> Note: Replace the `-i` argument with your Character ObjectID. +> Note: Replace the `-i` argument with your Character objectId. + ```json { "data": [ @@ -346,7 +364,7 @@ rooch object -i 0xd858ebbc8e0e5c2128800b9a715e3bd8ceae2fb8a75df5cc40b58b86f1dc77 4. Update the character via add a bio ```bash -rooch move run --function default::character::add_bio_entry --args object:0x8604bfaa406b4eae756e9eaf710c074573e18feae6f8c974df1fc9b0259e7e62 --args string:"Bobby is a programmer" +rooch move run --function default::character::add_bio_entry --args object: --args string:"Bobby is a programmer" ``` ```text Execution info: From 35dae8aa5d208e30538b88c03e4038fce11621fc Mon Sep 17 00:00:00 2001 From: jolestar Date: Mon, 13 Jan 2025 20:23:40 +0800 Subject: [PATCH 6/8] Update examples/foc_eliza/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- examples/foc_eliza/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/foc_eliza/README.md b/examples/foc_eliza/README.md index 256eb27715..6d001b4c26 100644 --- a/examples/foc_eliza/README.md +++ b/examples/foc_eliza/README.md @@ -47,7 +47,7 @@ rooch move test ```sh rooch move publish --named-addresses foc_eliza=default ``` -2. Create a on-chain character +2. Create an on-chain character ```sh rooch move run --function default::character::create_character_from_json --args file:../../../eliza/characters/dobby.character.json From d139eefb2eda304c644691748468310424ee7ef0 Mon Sep 17 00:00:00 2001 From: jolestar Date: Tue, 14 Jan 2025 16:43:19 +0800 Subject: [PATCH 7/8] update readme --- examples/foc_eliza/README.md | 61 +++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/examples/foc_eliza/README.md b/examples/foc_eliza/README.md index 6d001b4c26..4e54c6c093 100644 --- a/examples/foc_eliza/README.md +++ b/examples/foc_eliza/README.md @@ -373,4 +373,63 @@ Execution info: tx hash: 0x848a79967410c0e74887d1e47f45f3e013e41d0ea37435251fed4df982dc035f state root: 0xb9ba7a958eb1e63683daadb7cfe9f22fa731019b8fff7b6e76740e0b70d97174 event root: 0x6b25ec6fd717296603fb0818f24682d88bfdf9c55d995091865c582eed18dc71 -``` \ No newline at end of file +``` + +### Why Store Characters and Memory On-Chain? + +Currently, Eliza defines characters using static JSON files. By storing characters and memory on-chain, we unlock the following key advantages: + +1. **Dynamic Evolution** + +On-chain storage allows the character’s `bio`, interests (`topics`), and message templates to evolve dynamically during conversations. + +This evolutionary process is fully transparent, enabling community participation and oversight of the character’s growth and changes. + +2. **Governance and Auditing** + +On-chain storage supports governance for defining character evolution rules. For example: + + - The community can audit and manage the AI Agent’s memory through on-chain governance to prevent memory contamination caused by user interactions. + - Public AI Agents can have their behavior audited to ensure alignment with community expectations. + +3. **Decentralized Trustworthiness** + +Storing characters and memory on-chain enhances Eliza’s trustworthiness, making it suitable for open and fair AI ecosystems. + +### Next Steps + +1. **Dynamic Character Loader** + +Enable Eliza to load character data from the blockchain dynamically and support real-time reloading of character definitions upon updates. + +2. **On-Chain Memory Sync Plugin** + +Develop a plugin to synchronize memory from the blockchain, allowing Eliza to update its state in real time during interactions. + +3. **AI Oracle Integration** + +Explore using an on-chain AI Oracle to provide decision-making capabilities for AI Agents, enhancing intelligent on-chain interactions. + +4. **Standardized On-Chain Components** + +Abstract the fundamental on-chain components of AI Agents and integrate them into the Move framework of Rooch to standardize on-chain AI Agent development. + +### How to participate + +1. **Push the Boundaries of Smart Contracts** + +Collaborate to explore the possibilities of implementing on-chain AI Agents, such as: + + - Supporting automatic state vectorization and vector retrieval directly in smart contracts(RGA on-chain). + - Developing more advanced on-chain AI inference mechanisms. + +2. **Provide More On-Chain Services** + +Build additional on-chain services tailored for AI Agents, such as: + + - Twitter/Blog services for AI Agents. + - On-chain chatroom services to support multi-user interactions with Agents. + +3. **Explore AI and DeFi/BTCFi Integration** + +Combine the dynamic capabilities of on-chain AI Agents with innovative financial applications. From 129bb7ba745fc1601364289c4bb69b36d5ed8ddc Mon Sep 17 00:00:00 2001 From: jolestar Date: Tue, 14 Jan 2025 16:47:14 +0800 Subject: [PATCH 8/8] update readme --- examples/foc_eliza/README.md | 109 +++++++++++++++++------------------ 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/examples/foc_eliza/README.md b/examples/foc_eliza/README.md index 4e54c6c093..8dffcd384b 100644 --- a/examples/foc_eliza/README.md +++ b/examples/foc_eliza/README.md @@ -375,61 +375,60 @@ Execution info: event root: 0x6b25ec6fd717296603fb0818f24682d88bfdf9c55d995091865c582eed18dc71 ``` -### Why Store Characters and Memory On-Chain? +### Why On-Chain? -Currently, Eliza defines characters using static JSON files. By storing characters and memory on-chain, we unlock the following key advantages: +Storing AI characters and their memory on-chain provides three key advantages: 1. **Dynamic Evolution** - -On-chain storage allows the character’s `bio`, interests (`topics`), and message templates to evolve dynamically during conversations. - -This evolutionary process is fully transparent, enabling community participation and oversight of the character’s growth and changes. - -2. **Governance and Auditing** - -On-chain storage supports governance for defining character evolution rules. For example: - - - The community can audit and manage the AI Agent’s memory through on-chain governance to prevent memory contamination caused by user interactions. - - Public AI Agents can have their behavior audited to ensure alignment with community expectations. - -3. **Decentralized Trustworthiness** - -Storing characters and memory on-chain enhances Eliza’s trustworthiness, making it suitable for open and fair AI ecosystems. - -### Next Steps - -1. **Dynamic Character Loader** - -Enable Eliza to load character data from the blockchain dynamically and support real-time reloading of character definitions upon updates. - -2. **On-Chain Memory Sync Plugin** - -Develop a plugin to synchronize memory from the blockchain, allowing Eliza to update its state in real time during interactions. - -3. **AI Oracle Integration** - -Explore using an on-chain AI Oracle to provide decision-making capabilities for AI Agents, enhancing intelligent on-chain interactions. - -4. **Standardized On-Chain Components** - -Abstract the fundamental on-chain components of AI Agents and integrate them into the Move framework of Rooch to standardize on-chain AI Agent development. - -### How to participate - -1. **Push the Boundaries of Smart Contracts** - -Collaborate to explore the possibilities of implementing on-chain AI Agents, such as: - - - Supporting automatic state vectorization and vector retrieval directly in smart contracts(RGA on-chain). - - Developing more advanced on-chain AI inference mechanisms. - -2. **Provide More On-Chain Services** - -Build additional on-chain services tailored for AI Agents, such as: - - - Twitter/Blog services for AI Agents. - - On-chain chatroom services to support multi-user interactions with Agents. - -3. **Explore AI and DeFi/BTCFi Integration** - -Combine the dynamic capabilities of on-chain AI Agents with innovative financial applications. +- Characters evolve through conversations +- Bio, interests, and templates update dynamically +- Transparent growth process with community oversight + +2. **Governance & Auditing** +- Community-managed memory system +- Prevents memory contamination +- Public behavior auditing +- Alignment with community standards + +3. **Decentralized Trust** +- Enhanced trustworthiness +- Fair and open AI ecosystem +- Transparent character development + +### Roadmap + +1. **Character System** +- Dynamic character loading +- Real-time definition updates + +2. **Memory System** +- On-chain memory sync +- Real-time state updates +- Interaction history + +3. **AI Integration** +- On-chain AI Oracle +- Decision-making capabilities +- Smart contract inference + +4. **Framework Development** +- Standardized components +- Move framework integration +- Developer tools + +### Get Involved + +1. **Core Development** +- On-chain vector operations +- AI inference mechanisms +- Smart contract innovations + +2. **Service Building** +- AI Agent social services +- Multi-user chatrooms +- Character interaction systems + +3. **Integration** +- AI + DeFi applications +- BTCFi integration +- Cross-chain capabilities