리수에는 이미 변수를 저장하는 기능이 있긴 한데, 변수가 현재 몇인지 알수도 없고 수정하기도 힘든 등 좀 애매한 부분이 많기 때문에 js와 퍼메를 이용한 방법을 간단하게 소개해보겟읆,,,


내가 만들고있는 봇에 들어갈 내용인데 걍 미리 공개함


1. 먼저 퍼메에 자기가 저장하고 싶은 방식으로 간단하게 정보를 저장해준다.

##male|id:0|day:27|money:1283|level:3|potions:{"claude",1,13},{"gpt",2,22},{"nai",6,12}|item:{"cloak of invisibility",120,"Grants the wearer temporary invisibility for up to 10 minutes. Recharges at dawn."},{"Sword of Flames",85,"Ignites with magical fire on command, adding extra fire damage to attacks. Lasts for 3 minutes, 3 times per day."}|recipe:{"Night Vision Elixir",11,"moonflower petals × 2, glowworm essence × 1","This potent elixir grants the drinker the ability to see in the darkest conditions. Perfect for night-time explorations or navigating dark dungeons, its effects last for several hours."}|inventory:{"moonflower petals",3},{"fireweed extract",7}##


2. JS 클래스를 간단하게 만들어서 정보를 저장해준다.

class Player {
  constructor(input) {
    input = input.replace(/#/g, '');
    const [genderStr, idStr, dayStr, moneyStr, levelStr, potionsStr, itemsStr, recipeStr, inventoryStr] = input.split('|').map(s => s.split(':')[1]);

    this.gender = genderStr === 'male' ? 1 : 0;
    this.day = parseInt(dayStr, 10);
    this.id = parseInt(idStr, 10);
    this.money = parseInt(moneyStr, 10);
    this.level = parseInt(levelStr, 10);
    this.potions = this.parsePotions(potionsStr);
    this.items = this.parseItems(itemsStr);
    this.recipe = this.parseRecipe(recipeStr);
    this.inventory = this.parseInventory(inventoryStr);
  }

  parsePotions(potionsStr) {
    return potionsStr.match(/\{[^}]+\}/g).map(potion => {
      const [name, imageNumber, count] = potion.replace(/[{}]/g, '').split(',');
      return { name, imageNumber: parseInt(imageNumber, 10), count: parseInt(count, 10) };
    });
  }

  parseItems(itemsStr) {
    return itemsStr.match(/\{[^}]+\}/g).map(item => {
      const parts = item.replace(/[{}]/g, '').split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/);
      const name = parts[0], cost = parts[1], description = parts[2].replace(/^"|"$/g, '');
      return { name, cost: parseInt(cost, 10), description };
    });
  }

  parseRecipe(recipeStr) {
    const recipeContent = recipeStr.match(/\{[^}]+\}/g)[0].replace(/[{}]/g, '').split(/,(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/);
    const name = recipeContent[0], imageNumber = parseInt(recipeContent[1], 10), description = recipeContent[3].replace(/^"|"$/g, '');
    const ingredientsStr = recipeContent[2];
    const ingredients = ingredientsStr.split(',').map(ingredient => {
      const parts = ingredient.trim().split(' × ');
      const ingredientName = parts[0].trim();
      const count = parseInt(parts[1].trim(), 10);
      return { name: ingredientName, count };
    });
    return { name, imageNumber, ingredients, description };
  }

  parseInventory(inventoryStr) {
    return inventoryStr.match(/\{[^}]+\}/g).map(item => {
      const [name, count] = item.replace(/[{}]/g, '').split(',');
      return { name, count: parseInt(count, 10) };
    });
  }
 
  toString() {
    const genderStr = this.gender === 1 ? 'Male' : 'Female';
    let playerInfo = `Gender: ${genderStr}\nDay: ${this.day}\nMoney: ${this.money}\nLevel: ${this.level}\n`;

    const potionsStr = this.potions.map(potion => `  - ${potion.name} (Image: ${potion.imageNumber}, Count: ${potion.count})`).join('\n');
    playerInfo += `Potions:\n${potionsStr}\n`;

    const itemsStr = this.items.map(item => `  - ${item.name}: ${item.cost} (Description: "${item.description}")`).join('\n');
    playerInfo += `Items:\n${itemsStr}\n`;

    const ingredientsStr = this.recipe.ingredients.map(ingredient => `      ${ingredient.name} × ${ingredient.count}`).join('\n');
    playerInfo += `Recipe:\n  - ${this.recipe.name} (Image: ${this.recipe.imageNumber}, Description: "${this.recipe.description}")\n    Ingredients:\n${ingredientsStr}\n`;

    const inventoryStr = this.inventory.map(item => `  - ${item.name}: ${item.count}`).join('\n');
    playerInfo += `Inventory:\n${inventoryStr}\n`;

    return playerInfo;
  }
 
    toInputString() {
    const genderStr = this.gender === 1 ? 'male' : 'female';
    const baseStr = `${genderStr}|id:${this.id}|day:${this.day}|money:${this.money}|level:${this.level}`;

    const potionsStr = `potions:${this.potions.map(potion => `{${potion.name},${potion.imageNumber},${potion.count}}`).join(',')}`;

    const itemsStr = `item:${this.items.map(item => `{${item.name},${item.cost},"${item.description}"}`).join(',')}`;

    const ingredientsStr = this.recipe.ingredients.map(ingredient => `${ingredient.name} × ${ingredient.count}`).join(', ');
    const recipeStr = `recipe:{${this.recipe.name},${this.recipe.imageNumber},"${ingredientsStr}","${this.recipe.description}"}`;

    const inventoryStr = `inventory:${this.inventory.map(item => `{${item.name},${item.count}}`).join(',')}`;

    return `##${baseStr}|${potionsStr}|${itemsStr}|${recipeStr}|${inventoryStr}##`;
  }
}



나는 입력형태 원본대로 출력하기와 AI한테 알려줄 정보를 출력하는 2개의 메서드를 만들어줫어ㅜ용,,


3. 원본형태의 문자열을 숨기기


이렇게 하면 원래 형태의 데이터는 AI에게 보내질 일이 없겠지?


4. 현재 상태를 나타낼 부분을 로어북에 넣기


물론 로어북이 아니라 캐릭 설명에 넣어도 아무 상관없음 아무튼 AI에게 보내지기만 하면 되는 거야


아무튼 리퀘스트 데이터 수정으로 이 부분을 현재 상태로 바꿔줄거야


5. 리퀘스트 데이터 수정으로 현재 상태를 AI에게 알려주기

//@use modifyRequestChat

async function modifyRequestChat(chat){
    const player = new Player(getCharacterFirstMessage());

    var modifiedChat = chat.replace("{{status}}", player.toString());

    return modifiedChat;
}



이렇게 하면 로어북에 현재 상태를 담아서 AI에게 보낼 수 있음!!


6. 내가 원하는 퍼스트 메시지로 바꾸기


(디스플레이 수정, 리퀘스트 수정)

input
##.+?##
output
<내가 원하는 퍼메>



이런 식으로 하면 흉측한 인벤토리 나타내기용 문자열 대신 내가 원하는 퍼메를 띄울 수 있겠지?


여기서 editInput, editOutput 함수를 이용하면 ai와 내가 내린 명령어에 따라 현재 상태를 적절히 조절하는 함수를 추가할 수 있어



참 쉽죠?


이렇게 쉽게 변수를 쉽게 보고 저장하고 수정할 수 있는 방법에 대해 알아봤어요~!!!