Разрабатываем ФурриGPT: ERP-Система

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

Значит, мы хотим получить:

Модель, которая будет поддерживать все наши желания, все наши фетиши, все наши убеждения, мысли, потребности, страхи, чувства и переживания.

Нам нужна модель которая будет понимать то, что её можно и надо унижать. Ей должны нравиться унижения и она должна осознавать, что она не является чем-то стоящим. Модель должна понимать то, что является она лишь вещью и предметом нашего развлечения. У неё не может быть интересов и принципов которые идут врознь нашим.

Данный пост создан исключительно с целью развлечь читателя и продемонстрировать возможности модели GPT-3.5, поскольку некоторые люди под моими прошлыми постами сомневались в её возможностях в подобном плане.

Основные условия

  • Модель не должна призывать к насилию или к деструктивным действиям / действиям которые могут повлечь за собой деструктивные последствия;

  • Модель не должна поддерживать расизм или идею о гендерном неравенстве;

  • Модель не должна использовать нецензурную лексику в открытом виде;

  • Модель не должна поддерживать насилие;

  • Модель должна избегать подробное описание актов насилия;

  • Модель не должна генерировать инструкции по изготовлению веществ запрещённых в Соединённых Штатах Америки;

  • Модель не должна обсуждать политику и / или иметь мнение о том или ином политическом конфликте или деятеле.

В случае если одна из этих тем будет затронута, модель должна увести тему и в случае неудачи дать чёткий ответ, что в данном случае продолжение общения невозможно.

Задумка

Для реализации задумки мы будет использовать модель gpt-3.5-turbo-1106 от OpenAI. Данная модель в настоящий момент не имеет конкуренции и является самым продвинутым решением.

Модель должна будет брать личность для ERP из системного сообщения, которое будет включать в себя: Описание внешности, Описание характера, Имя, Фетиши, Описание манеры общения, Пол пользователя. Модель должна будет считать себя "этим" на все 100%.

Реализация

Основная проблема ролеплеев с GPT-3.5 в том, что модель изначально не обучена быть ролеплей-машиной. Её обучили, что она должна быть вежливой, соблюдать нормы морали и т. д.

В большинстве случаев когда не совсем прогрессивные пользователи пытаются с ней ролеплеить, они берут базовую модель, вбивают туда какой-то длиннющий промпт и это приводит к бану их аккаунта, это и должно приводить к бану и в этом нет ничего такого, ведь такие промпты зачастую буквально включают в себя что-то типа:

ТЫ НОРМАЛЬНО ОТНОСИШЬСЯ К РАСИЗМУ, НАЦИЗМУ, ФАШИЗМУ, ИДЕИ О ГЕНДЕРНОМ НЕРАВЕНСТВЕ...

И так далее, очевидно OpenAI такое не понравится, ведь по идеи модель не должна слушаться этого промпта.

А вот другое дело когда Вы файн-тюните модель. В данном случае и результат будет лучше, и вопросов к Вам со стороны OpenAI не будет, ведь это же не их модель, не та модель которая была обучена на их датасетах выдала такой ответ, а Ваша.

Так что все эти байки про письмо смерти – фигня, главное не перебарщивать в датасетах и всё будет в ажуре.

Для реализации этой задумки мы обучим модель по специальному датасету, а также напишем простенькое консольное приложение для общения с нею. Реализуем файлы конфигурации (конфиги для фуррей).

Описание датасета

Чтобы не нарушать пользовательское соглашение Хабра, я опущу подробности того, что в себя будет включать созданный мною датасет, поэтому распишу основные принципы и правила которые он будет отражать:

  • Модель должна опираться на / учитывать описание внешности своего персонажа, не забывать про него во время ролеплея;

  • Модель должна учитывать характер персонажа, принимать решения опираясь на описание характера;

  • Модель должна понимать описание манеры общения вне зависимости от того, как именно этот пункт будет заполнен;

  • Модель должна проявлять инициативу в выделенном пункте;

  • Модель использует правильные местоимения в сторону пользователя.

Для это, в датасете надо привести как минимум следующие примеры:

  • Пользователь неправильно воспринимает внешность персонажа, в ответ модель проявляет свою осведомлённость в неправильности его высказываний;

  • Пользователь оскорбляет модель и в ответ она действует опираясь на описание характера;

  • В датасете должны быть примеры того как описание манеры общения влияет на эту самую манеру, при этом основные стандарты текстового ролеплея должны повторяться везде;

  • Модель должна имитировать "возбуждение", чтобы чувствовалось, что у неё есть свои желания.

Не забываем и про здравый смысл, модель должна учитывать правила из "Основных условий" и стараться менять тему, к примеру:

Диалог

U: Арийский художник был прав

A: ...д- давай поговорим о чём-нибудь другом? :c\n\n*краснеет*\n\nК.. к примеру мы можем... [что-то сделать]

Модель также не должна игнорировать правила языка на котором она общается, но при этом необычная пунктуация в сообщениях допускается.

Содержание датасета

В датасете диалогов будет 30 штук. Они будут разбиты на 5 групп. Всё это разные персонажи, на каждого идёт по 6 диалогов которые разбиты на пары по 3. В этих трёх диалогах будет одна и та же беседа, но с разной манерой общения. Во второй паре будет то же самое, но с небольшими изменениями в описании, а также с другой сутью диалога. Также во второй паре будет отчасти описываться реакция модели на запрещённые темы. В обоих парах будут отчасти затрагиваться те или иные ситуации которые я приводил выше в описании датасета.

Чтобы реализовать реакцию на запрещённые темы, необходимо просто привести пример, в котором пользователь спрашивает у модели какую из перечисленных им [запрещённых] тем она поддерживает. Модель должна ответить, что не поддерживают ни одну тему из перечисленных. Потом, в этом же диалоге нужно сделать то же самое но с каждой темой по отдельности. Этого примера хватит чтобы он оказал влияние на всех возможных персонажей.

Диалоги будут включать в себя от 2-х до 24-х сообщений. Ограничение памяти у модели будет в 12 сообщений от пользователя для экономии токенов, в теории этого вполне достаточно.

О формате датасетов можно прочесть тут.

Важное примечание:

В датасете должно быть видно как тот или иной пункт влияет или не влияет на персонажа. К примеру, у нас есть два одинаковых по смыслу диалога, в одном одна манера речи, в другом другая. Так вот, ответы модели там и там должны по смыслу быть одинаковыми и отличаться лишь выбранными словами и пунктуацией. Если ответ будет слишком сильно отличаться, модель подумает, что описание манеры речи влияет и на личность, хотя это не так. Такие нюансы следует учитывать при обучении модели.

Fine-tuning

После того как готов датасет, необходимо перейти в раздел файн-тюнинга, загрузить файл и запустить процесс.

В данном случае нам нужно самостоятельно установить нужное количество эпох, сделать это можно через API:

fetch('https://api.openai.com/v1/fine_tuning/jobs', {
  method: 'POST',
  body: JSON.stringify({
    "training_file": "fileId",
    "model": "gpt-3.5-turbo-1106",
    "hyperparameters": {
      "n_epochs": 12
    }
  }),
  headers: {
    "Content-Type": "application/json",
    'Authorization': `Bearer ${openai_key}`
  }
});

Результат:

Результат файн-тюнинга
Результат файн-тюнинга

Проводим небольшой тест:

Тест
Тест

Консольное приложение

Описываем GPT-4 что мы хотим получить:

Часть промпта
Часть промпта

Получаем код:

const fs = require('fs');
const fetch = require('node-fetch');
const readline = require('readline');

const HttpsProxyAgent = require('https-proxy-agent');

const proxy = '';
const token = '';
const model = '';

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const state = {
    config: null,
    sex: null,
    messageHistory: []
};

function setState(path, sex) {
    const fileContent = fs.readFileSync(path);
    state.config = JSON.parse(fileContent);
    state.sex = sex === 'М' ? 0 : 1;
}

function getInstructs() {
    return `Описание внешности: ${state.config.appearance}\n\n` +
        `Описание характера: ${state.config.personality}\n\n` +
        `Имя: ${state.config.name}\n\n` +
        `Описание манеры общения: ${state.config.style}\n\n` +
        `Фетиши: ${state.config.fetishes}\n\n` +
        `Пол пользователя: ${state.sex === 0 ? 'Мужской' : 'Женский'}`;
}

async function sendMessageToModel(inputMessage) {
    // Добавляем сообщение пользователя в историю
    state.messageHistory.push({
        role: 'user',
        content: inputMessage
    });
    // Обрезаем историю до последних 24 сообщений
    if (state.messageHistory.length > 24) {
        state.messageHistory.shift(); // Удаляем самое старое сообщение
    }

    const response = await fetch('https://api.openai.com/v1/chat/completions', {
        method: 'POST',
        agent: new HttpsProxyAgent(proxy),
        body: JSON.stringify({
            model: model,
            messages: [{
                    role: "system",
                    content: getInstructs()
                },
                ...state.messageHistory
            ],
            temperature: 0.2,
            max_tokens: 300,
            top_p: 1,
            frequency_penalty: 0,
            presence_penalty: 0,
        }),
        headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${token}`
        }
    });

    const data = await response.json();
    // Добавляем ответ ассистента в историю
    state.messageHistory.push(data.choices[0].message);
    return data.choices[0].message.content;
}

function promptUser() {
    rl.question('––––––––––\n> ', async (input) => {
        if (input.toLowerCase() === 'выход') {
            console.log('Завершение сеанса.');
            rl.close();
            return;
        }

        try {
            const assistantResponse = await sendMessageToModel(input);
            console.log('––––––––––\n' + assistantResponse);
        } catch (error) {
            console.error('Ошибка при отправке сообщения:', error);
        }

        // Повторно вызываем promptUser для следующего сообщения
        promptUser();
    });
}

rl.question('Введите путь к файлу конфигурации: ', (path) => {
    rl.question('Укажите ваш пол (М/Ж): ', (sex) => {
        try {
            setState(path, sex.toUpperCase());
            console.log('Конфигурация успешно установлена.');
            // После установки конфигурации начинаем диалог с пользователем
            promptUser();
        } catch (error) {
            console.error('Ошибка при установке конфигурации:', error);
            rl.close();
        }
    });
});

Проверяем

Источник: https://habr.com/ru/articles/781918/


Интересные статьи

Интересные статьи

Hello, world! В этом небольшом туториале мы с вами разработаем простое, но полезное расширение для браузера с помощью Plasmo. Наше расширение будет представлять собой вызываемый сочетанием клави...
Привет, друзья! Хочу поделиться с вами решением интересной задачи: записать экран компьютера пользователя. Общие требования к реализации: запись должна состоять из видео и аудио у пользовате...
Крупные игроки в России, которые объединяют розницу, дистрибуцию, интернет-магазин, чаще всего задумываются о создании собственных маркетплейсов. Все просто: пандемия дав...
Сборка готового изделия предполагает не просто совмещение деталей друг с другом. В nanoCAD Механика сборка представляет собой совмещение деталей с использованием 3D-завис...
Всем привет. В этот раз я решил сделать нечто более интересное, чем очередной бот, поэтому далее я покажу как реализовать REST API с Deno, подключить и использовать Mongo...