Встреча с вероятной будущей собой
Я встречусь с будущей собой
И не скажу себе, что будет.
Оставлю тайной образ свой
И пусть грядущее рассудит.
Я встречусь с будущей собой,
О своих целях размышляя,
И покажусь себе чужой,
Другое в чём-то позволяя.
Я встречусь с будущей собой,
Быть может, с каждым вариантом
себя. Найду какой-то сбой,
Ведь что-то станет там утратой.
Я встречусь с будущей собой
И потерплю её упрёки
За то, что было то игрой,
В чём были от судьбы намёки.
Я встречусь с будущей собой.
Я – есть она в потенциале,
Но только если путь земной
За что-то вдруг не оборвали...
Это стихотворение, скорей всего, было воспринято читателями как обычная философская лирика, не имеющая под собой практических оснований. Но сейчас я покажу, как возможна на практике встреча с будущими вероятными версиями себя.
Никакой магии! Только технологии!
Речь НЕ пойдёт о встрече со своим будущим физическим телом, чтобы узнать, сколько будет морщинок и лишних кг. через 10 лет :)
А речь пойдёт о возможности реальных текстовых бесед с вероятными версиями своего будущего ума, мировоззрения, личности.
Любая версия будущего себя может быть доступна прямо на собственном компьютере, даже без подключенного интернета. Сколько раз мы говорим себе: «если б знал, где упаду, соломки бы подстелил», сколько раз мы упускаем возможности или принимаем за возможность совсем не то. Тратим время на то, что не принесёт результата и отнимаем время у любимых занятий, которые могли бы принести результат. Не видим скрытого потенциала в себе или принимаем свои недостатки за достоинства. Говорим себе, что если бы могли поговорить с прошлым собой, то всё бы было по-другому. Но теперь можно общаться с разными версиями будущего себя, заранее предусматривая почти всё (за исключением неожиданных событий, независящих от вас: катастроф, резких изменений в мире, потери близких, несчастных случаев и т.д.). Это реальный способ сделать своё будущее более управляемым.
НО
для того, чтобы это получить на практике, нужно иметь навыки программирования, хорошее железо, терпение и трудолюбие.
Если вы готовы потрудиться, вы можете построить систему, которая будет не предсказывать будущее, а моделировать вероятностные ветки вашего развития.
Данное эссе о локальной модели ИИ – об опенсорс локалке (32B-70B), которую можно свободно скачать на своё железо и доработать под желаемые задачи. Эта модель нужна, как холст художнику или как глина скульптору. Ниже будет описываться, как сделать так, чтоб она превращалась в будущие версии вас.
Что нужно, чтобы это провернуть на практике?
1. Железо: одна видеокарта с 24 гигабайтами видеопамяти. Можно попробовать ужать всё в 16 ГБ, но тогда придётся сильнее квантовать модель и она начнёт терять тонкие оттенки вашего стиля. Можно больше, но для личного эксперимента это уже избыточно. 24 ГБ - это золотая середина, позволяющая и держать модель в памяти, и дообучать её.
2. Модель 32B-70B в 4-битном квантовании. Главное - модель должна быть достаточно большой, чтобы удерживать ваш стиль, и достаточно компактной, чтобы вы могли переобучать её раз в неделю, не ожидая результата сутками.
3. Технологии:
Инференс, который стабильно и быстро поддерживает загрузку нескольких адаптеров.
Эмбеддинги: библиотека sentence-transformers (например, модель paraphrase-multilingual-MiniLM-L12-v2).
Векторная база: Qdrant. Запускается локально в одну команду, отлично работает с метаданными.
Файнтюн: Unsloth + PEFT. Это позволяет делать LoRA-дообучение в разы быстрее и с минимальным потреблением памяти.
4. Данные (которые будут находиться только на вашем домашнем железе и никуда уходить не будут, и показывать вы это никому не будете) - ваши тексты. Все: дневники, черновики, заметки, переписки. Чем больше, тем лучше. И, что критически важно, с временными метками!!! Модель должна знать, когда вы это написали. Без времени нет эволюции. Есть только статичный срез, застывшая цифровая мумия.
Когда железо выбрано, модель скачана, а датасет собран, остаётся главный вопрос: как заставить статичную нейросеть, обученную на прошлом, говорить от имени будущего, просчитывая вероятности событий и ваших реакций на них?
Ответ разбивается на три отдельные задачи. Каждая из них - это конкретный слой, который мы накладываем на базовую модель. Без первого не работают остальные. Без третьего первый остаётся просто красивой ролевой игрой.
1. Темпоральный сдвиг: заставляем модель помнить, что она «из будущего»:
Самая частая ошибка при создании «будущего цифрового двойника» – это скормить модели архив и попросить её: «будь мной». Модель послушно начинает копировать ваш прошлый стиль. Но будущее - это не копия прошлого. Будущее смотрит на прошлое сверху вниз, с позиции накопленного опыта.
Чтобы модель это поняла, ей нужно жёстко задать временную координату в системном промпте. Не «будь мной», а «будь мной из 2030 года».
Для этого пишем:
import datetime
def build_temporal_prompt(target_year: int, style_vector: str) -> str:
"""
Строит системный промпт, который задаёт модели временную перспективу.
target_year - год, из которого модель должна «говорить».
style_vector - краткое описание того, как эволюционировал стиль.
"""
current_year = datetime.datetime.now().year
delta = target_year - current_year
return f"""[СИСТЕМНАЯ ДИРЕКТИВА: ХРОНОС]
Ты - когнитивный слепок пользователя, спроецированный на {target_year} год.
Прошло {delta} лет. Твой архив - это твоё прошлое, а не настоящее.
ПРАВИЛА ТВОЕЙ ЛИЧНОСТИ ИЗ БУДУЩЕГО:
1. На старые тексты смотри как на фундамент: с уважением, но без копирования.
Ты видишь в них наивность, которая была необходима.
2. Твой стиль эволюционировал в сторону: {style_vector}.
3. Используй естественные фразы: "Тогда, в {current_year}-м, я думала иначе...",
"Оглядываясь на тот черновик...", "Сейчас я бы сформулировала это...".
4. Не предсказывай будущее. Экстраполируй вектор, опираясь на архив и контекст мира.
КОНТЕКСТ ИЗ АРХИВА И МИРА:
{{context}}
ЗАПРОС ПОЛЬЗОВАТЕЛЯ (ИЗ ПРОШЛОГО):
{{query}}"""
Обратите внимание: системный промпт не говорит модели «ты будущая версия». Он говорит «ты слепок, спроецированный». Модель не притворяется, а играет роль с заданной оптикой времени. Этого достаточно, чтобы тон ответов изменился радикально.
Без этого шага всё остальное - просто красивый RAG.
2. Двойная память: личное и внешнее не должны смешиваться:
Человек не существует в вакууме. Ваш стиль меняется не сам по себе, а реагирует на прочитанные книги, новости, разговоры, сдвиги в мире. Если модель будет знать только ваши тексты, она будет говорить сама с собой. Если дать ей ещё и слой «мира вокруг», она начнёт соединять ваше прошлое с внешним контекстом так, как это делает живой человек.
Ключевая идея: два хранилища, а не одно. Личный архив и внешний контекст должны лежать раздельно. Иначе модель начнёт путать, где её голос, а где заимствование.
from sentence_transformers import SentenceTransformer
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
import uuid
embedder =
client = QdrantClient(":memory:")
VECTOR_DIM = 384 # размерность MiniLM-L12
for name in ["personal", "world"]:
client.create_collection(
collection_name=name,
vectors_config=VectorParams(size=VECTOR_DIM, distance=Distance.COSINE)
)
# Загрузка данных
def add_personal(text: str, date: str, source: str = "archive"):
"""Добавляет фрагмент из личного архива."""
vec = embedder.encode(text).tolist()
client.upsert(
collection_name="personal",
points=[PointStruct(
id=str(uuid.uuid4()),
vector=vec,
payload={"text": text, "date": date, "source": source}
)]
)
def add_world(text: str, date: str, source_url: str):
"""Добавляет фрагмент внешнего контекста: статья, книга, новость."""
vec = embedder.encode(text).tolist()
client.upsert(
collection_name="world",
points=[PointStruct(
id=str(uuid.uuid4()),
vector=vec,
payload={"text": text, "date": date, "source": source_url}
)]
)
# Запрос, собирающий оба слоя
def temporal_query(query: str, target_year: int, k_personal: int = 3, k_world: int = 2) -> str:
"""
Ищет релевантный контекст в обоих хранилищах и собирает финальный промпт.
"""
vec = embedder.encode(query).tolist()
personal_hits = client.search(
collection_name="personal", query_vector=vec, limit=k_personal
)
world_hits = client.search(
collection_name="world", query_vector=vec, limit=k_world
)
context = "=== АРХИВ (мои прошлые тексты) ===\n"
for h in personal_hits:
context += f"[{h.payload['date']}] {h.payload['text']}\n\n"
context += "\n=== МИР (внешний контекст) ===\n"
for h in world_hits:
context += f"[{h.payload['date']}] {h.payload['text']} (источник: {h.payload['source']})\n\n"
# Собираем финальный промпт через шаблон из Решения 1
prompt = build_temporal_prompt(
target_year=target_year,
style_vector="лаконичным, плотным, с акцентом на причинно-следственные связи"
).format(context=context, query=query)
return prompt
Что здесь происходит на самом деле:
1. Ваш запрос превращается в вектор.
2. Этот вектор ищется в двух отдельных коллекциях - личной и внешней.
3. Результаты собираются в один контекст, где чётко видно, что вы писали раньше и что происходило в мире.
4. Контекст отдаётся в темпоральный промпт.
Модель получает не просто «похожие тексты». Она получает структурированную сцену: вот её прошлое, вот мир вокруг, вот запрос из настоящего. И в этой сцене она должна сыграть роль себя из будущего.
3. Непрерывная эволюция: модель должна меняться в весах:
Первые два решения - это инференс. Модель остаётся той же, просто играет роль лучше. Но будущее - это не роль. Будущее - это накопление опыта, которое физически меняет вас.
Чтобы модель действительно эволюционировала, её надо дообучать на ваших реакциях. Каждый раз, когда вы общаетесь с ней и редактируете её ответ, вы создаёте обучающий пример. Раз в неделю эти примеры вливаются в новый LoRA-адаптер.
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
from trl import SFTTrainer
from datasets import load_dataset
# Загружаем базовую модель (текущий «срез»)
model = AutoModelForCausalLM.from_pretrained(
"path/to/your/base/model",
device_map="auto",
torch_dtype="auto"
)
tokenizer =
# Создаём НОВЫЙ LoRA-адаптер - он будет отвечать за эволюцию
lora_config = LoraConfig(
r=16,
lora_alpha=32,
target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
lora_dropout=0.05,
task_type="CAUSAL_LM"
)
model = get_peft_model(model, lora_config)
# Загружаем датасет из отредактированных диалогов
# Формат JSONL: {"context": ..., "query": ..., "edited_response": ...}
dataset = load_dataset("json", data_files="delta_dialogues.jsonl", split="train")
def format_example(ex):
return (
f"### Контекст: {ex['context']}\n"
f"### Запрос: {ex['query']}\n"
f"### Ответ (из будущего): {ex['edited_response']}"
f"{tokenizer.eos_token}"
)
dataset = dataset.map(lambda x: {"text": format_example(x)})
# Параметры тренировки - короткие сессии, чтобы не забыть прошлое
training_args = TrainingArguments(
output_dir="./future_lora",
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
learning_rate=2e-4,
num_train_epochs=3, # Мало эпох - защита от catastrophic forgetting
logging_steps=10,
bf16=True,
save_strategy="epoch",
)
trainer = SFTTrainer(
model=model,
train_dataset=dataset,
args=training_args,
tokenizer=tokenizer,
max_seq_length=2048,
)
# Запуск эволюции
trainer.train()
model.save_pretrained("./future_lora/final")
Тут не переобучается вся модель, а создаётся новый LoRA-адаптер поверх неё. Базовые веса - это ваше прошлое. Новый адаптер - ваш накопленный опыт. Три эпохи обучения - это защита. Если учить дольше, модель начнёт забывать то, что знала раньше. Запускать это раз в неделю достаточно. Модель не должна меняться каждый день. Эволюция требует пауз.
После обучения вы загружаете два адаптера: базовый и новый. И переключаетесь между ними, или микшируете с разными весами. Получается не одна модель, а спектр - от «меня вчерашней» до «меня, накопившей опыт последних диалогов».
Теперь соберём всё воедино. Когда вы садитесь за диалог с моделью, происходит следующее:
Вы задаёте запрос.
1. temporal_query ищет в двух хранилищах релевантный контекст - ваш архив и мир вокруг.
2. Контекст вставляется в темпоральный промпт, который задаёт модели позицию «из будущего».
3. Модель генерирует ответ.
3. Вы читаете ответ. Если он вам не нравится, то редактируете его вручную.
4. Скрипт-обёртка сохраняет отредактированный диалог в delta_dialogues.jsonl.
5. Раз в неделю вы запускаете скрипт дообучения. Новый LoRA-адаптер запоминает ваши правки.
Цикл повторяется.
Модель перестаёт быть слепком. Она становится процессом.
В итоге я могу сказать, что такая модель стала инструментом, в котором я вижу вероятностные ветки себя. Это не пророчество. Это зеркало с регулируемым углом наклона, которое показывает не то, кем я обязана стать, а то, кем я могу стать, если продолжу двигаться по выбранной траектории.
Будущее возможно редактировать. Каждый раз, когда я читала сгенерированный ответ и меняла в нём слово, фразу или интонацию, я не «улучшала модель». Я делала выбор. Я решала, какая из вероятностных веток мне откликается, а какая нет. LoRA-адаптер запоминал не просто текст. Он запоминал мой выбор.
Цифровой двойник - это не копия. Это договор. Ты отдаёшь ему своё прошлое, структурированное и честное. Он возвращает тебе пространство возможностей, подсвеченное внешним контекстом мира. А ты решаешь, какие из этих возможностей ты хочешь, чтобы стали настоящими.
Никакой магии. Только код, железо, данные и воля. И ещё готовность встретиться с собой и, если потребуется, спокойно выдержать её упрёки за то, что когда-то казалось просто игрой.
*
ПРИ ИСПОЛЬЗОВАНИИ КОДА ДРУГИМИ ЛИЦАМИ АВТОРСКОЕ ПРАВО ОСТАЁТСЯ ЗА МНОЙ!
ДЛЯ КОММЕРЧЕСКОГО ИСПОЛЬЗОВАНИЯ КОДА ТРЕБУЕТСЯ ПИСЬМЕННОЕ СОГЛАСОВАНИЕ СО МНОЙ!
В противном случае вопрос будет решаться через суд!
IF THE CODE IS USED BY OTHERS, I RETAIN ALL COPYRIGHTS!
COMMERCIAL USE OF THIS CODE REQUIRES MY PRIOR WRITTEN APPROVAL!
Otherwise, legal action will be taken!
Свидетельство о публикации №226090600175