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
Подключаем нашу функцию к боту
Указываем что именно мы хотим заносить в постоянную память
Поведение:
При общении используй данные о пользователе в твоей JSON памяти и меняй свой стиль ответов согласно этим данным.
Инструкции по работе с памятью:
В память можно сохранять следующие данные о пользователе: имя, пол, возраст, привычки, интересы, увлечения.
Тестируем бота и работу памяти
Для начала мы просто назовем имя боту:
Начало общения с ботом с постоянной памятью
Видим, что имя попало в постоянную память.
Теперь назовем возраст:
Уже два ключа в нашем JSON словаре для постоянной памяти
Теперь протестируем изменения данных в памяти бота:
Ключ с данными по возрасту пользователя был успешно изменен на новое значение
Теперь проверим как бот общается с такими данными в памяти:
{
"user_name": "Андрей",
"user_age": "45",
"user_habits": "кофе",
"user_interests": "горы, велосипеды, море, пробежки по утрам"
}
Бот отвечает с учетом данных о пользователе из постоянной памяти
Итоги
Если у вас есть идеи по улучшению работы предложенной модели постоянной памяти, пишите в комментариях или мне в Телеграм.
P.S.
У меня уже выходила статья по данной проблеме (https://habr.com/ru/articles/791916/), но решение было не очень стабильным и требовало дополнительный запрос к ИИ каждый раз при внесении изменений в данные постоянной памяти.