JSON словарь в качестве постоянной памяти для GPT-ботов (версия 3.0)

Какую проблему решаем?

Любой GPT-бот на базе любой LLM (например на ChatGPT) должен сам и незаметно для пользователя запоминать в постоянную память нужные нам сведения из диалога.

Шаг№1: Создадим определение функции

{ 
    "name": "ai_memory_v3", 
    "description": "Call this function when you need to make adjustments to JSON memory.", 
    "parameters": { 
      "type": "object", 
      "properties": { 
        "key": { 
          "type": "string", 
          "description": "New or existing key from JSON memory", 
        },
        "value": { 
          "type": "string", 
          "description": "Text to be written by the specified key", 
        },
        "action": {
            "type": "string",
            "enum": ["+", '-', '.', '_'],
            "description": "Action type. `+` - means adding information to memory. `-` - means deleting information from memory. `.` - means changing information in memory. `_` - means clear all memory",
        },
      }, 
      "required": ["key", "value", "action"], 
    }, 
}, 

Параметры нашей функции:

  • «key» — Новый или существующий ключ из JSON памяти. Этот параметр указывает, к какому ключу будет применено действие.

  • «value» — Текст, который будет записан по указанному ключу. Этот параметр содержит данные, которые будут добавлены, изменены или удалены в памяти.

  • «action» — Тип действия, которое будет выполнено с памятью. Возможные значения:
     — + — добавление информации в память.
     — - — удаление информации из памяти.
     — . — изменение информации в памяти.
     — _ — очистка всей памяти.

Обработчик функции на нашем сервере

from flask import Flask, request, json
import os
import logging

# Инициализация логгера
logger = logging.getLogger(__name__)
config.ROOT_PATH = '/path/to/your/application/'  # Установите корректный путь к приложению

# Создаем экземпляр приложения Flask
app = Flask(__name__)

# Определение маршрута и функции для записи в постоянную память
@app.route('/write_memory_dict', methods=['POST'])
def write_memory_dict():
    # Получение данных из запроса в формате JSON
    data = GetJsonFromRequest(request)
    # Логирование данных запроса
    logger.debug(f"[/write_memory_dict] {data}")
    # Инициализация сообщения для пользователя
    Res = 'Покажи новое состояние памяти и получи подтверждение на внесение изменений пользователю.n'
    # Основная логика для обработки различных действий
    if data['action'] == '_':
        try:
            # Попытка удалить файл памяти
            os.remove(config.ROOT_PATH + 'json_memory/' + data['chat_id'])
        except Exception as e:
            # Если файл не найден, логируем предупреждение
            logger.warning(f"File not found {data['chat_id']}")
        # Ответ о том, что память очищена
        Res = 'Память очищена.n'
    else:
        # Имя файла соответствует chat_id
        filename = data['chat_id']
        memory_json = {}
        if filename is not None:
            # Чтение существующего файла памяти
            memory_json = read_file(config.ROOT_PATH + 'json_memory/' + filename)
            try:
                # Попытка преобразовать прочитанные данные из файла в JSON
                memory_json = json.loads(memory_json)
            except:
                # Если преобразование не удалось, считаем что данных нет
                memory_json = {}
        # Добавление данных в память
        if data['action'] == '+' and data['key'] not in memory_json:
            memory_json[data['key']] = data['value']
            Res = 'Данные добавлены в постоянную память.n'
        if data['action'] == '+' and data['key'] in memory_json:
            memory_json[data['key']] += ', ' + data['value']
            Res = 'Данные добавлены в постоянную память.\n'
        # Удаление данных из памяти
        if data['action'] == '-' and data['key'] in memory_json:
            memory_json.pop(data['key'])
            Res = 'Данные удалены из постоянной памяти.n'
        # Обновление данных в памяти
        if data['action'] == '.' and data['key'] in memory_json:
            memory_json[data['key']] = data['value']
            Res = 'Данные в постоянной памяти изменены.n'
        # Сохранение изменений в файл
        if filename is not None and memory_json is not {}:
            with open(config.ROOT_PATH + 'json_memory/' + filename, 'w', encoding='utf-8') as f:
                json.dump(memory_json, f, ensure_ascii=False, indent=4)
            # Логирование успешного сохранения
            logger.info(f"/write memory_json OK {filename}, {memory_json}")    
            Res += 'Данные сохранены в постоянную память.n'
    # Возвращение ответа клиенту
    return json.dumps(Res), 200

# Функция для чтения файла, предполагается, что она определена где-то в коде
def read_file(file_path):
    # Тут должна быть ваша реализация функции чтения файла
    pass

# Функция для получения JSON из запроса, предполагается, что она определена где-то в коде
def GetJsonFromRequest(req):
    # Тут должна быть ваша реализация функции извлечения JSON из запроса
    pass

# Запустить приложение, если файл запущен напрямую
if __name__ == '__main__':
    app.run()

Создаем бота для тестирования постоянной памяти

Бот для теста постоянной памяти на платформе ProTalk

Бот для теста постоянной памяти на платформе ProTalk

Подключаем нашу функцию к боту

Подключаем нашу функцию к боту

Указываем что именно мы хотим заносить в постоянную память

Указываем что именно мы хотим заносить в постоянную память

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

Тестируем бота и работу памяти

Для начала мы просто назовем имя боту:

Начало общения с ботом с постоянной памятью

Начало общения с ботом с постоянной памятью

Видим, что имя попало в постоянную память.

Теперь назовем возраст:

Уже два ключа в нашем JSON словаре для постоянной памяти

Уже два ключа в нашем JSON словаре для постоянной памяти

Теперь протестируем изменения данных в памяти бота:

Ключ с данными по возрасту пользователя был успешно изменен на новое значение

Ключ с данными по возрасту пользователя был успешно изменен на новое значение

Теперь проверим как бот общается с такими данными в памяти:

{
    "user_name": "Андрей",
    "user_age": "45",
    "user_habits": "кофе",
    "user_interests": "горы, велосипеды, море, пробежки по утрам"
}

Бот отвечает с учетом данных о пользователе из постоянной памяти

Бот отвечает с учетом данных о пользователе из постоянной памяти

Итоги

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

P.S.

У меня уже выходила статья по данной проблеме (https://habr.com/ru/articles/791916/), но решение было не очень стабильным и требовало дополнительный запрос к ИИ каждый раз при внесении изменений в данные постоянной памяти.

© Habrahabr.ru