Реализация кодирования для построения самоорганизующихся графов знаний Zettelkasten и механизмов консолидации сна

В этом руководстве мы погрузимся в передовые технологии агентского ИИ, создав систему памяти «Zettelkasten» — «живую» архитектуру, которая организует информацию подобно человеческому мозгу. Мы выходим за рамки стандартных методов извлечения данных, чтобы построить динамический граф знаний, где агент автономно разлагает входные данные на атомарные факты, связывает их семантически и даже «спит» для консолидации воспоминаний в инсайты более высокого порядка.

Используя Google Gemini, мы реализуем надёжное решение, которое учитывает реальные ограничения API, обеспечивая хранение данных нашим агентом и активное понимание им развивающегося контекста наших проектов.

Импорт библиотек

Мы начинаем с импорта основных библиотек для управления графами и взаимодействия с моделями ИИ, а также для защиты ввода ключа API. Ключевым моментом является определение функции `retrywithbackoff`, которая автоматически обрабатывает ошибки ограничения скорости, обеспечивая плавный переход нашего агента и его восстановление при превышении квоты API во время интенсивной обработки.

«`python
import os
import json
import uuid
import time
import getpass
import random
import networkx as nx
import numpy as np
import google.generativeai as genai
from dataclasses import dataclass, field
from typing import List
from sklearn.metrics.pairwise import cosine_similarity
from IPython.display import display, HTML
from pyvis.network import Network
from google.api_core import exceptions
«`

Определение структуры узла памяти

Мы определяем фундаментальную структуру `MemoryNode` для хранения нашего контента, типов и векторных внедрений в организованном классе данных.

«`python
@dataclass
class MemoryNode:
id: str
content: str
type: str
embedding: List[float] = field(default_factory=list)
timestamp: int = 0
«`

Инициализация класса `RobustZettelkasten`

Затем мы инициализируем основной класс `RobustZettelkasten`, устанавливая сетевой граф и настраивая модель встраивания Gemini, которая служит основой наших возможностей семантического поиска.

«`python
class RobustZettelkasten:
def init(self):
self.graph = nx.Graph()
self.model = genai.GenerativeModel(MODEL_NAME)
self.step_counter = 0
«`

Атомизация ввода

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

«`python
def atomizeinput(self, text):
prompt = f»»»
Break the following text into independent atomic facts.
Output JSON: {{ «facts»: [«fact1», «fact2»] }}
Text: «{text}»
«»»
response = retrywithbackoff(
self.model.generate_content,
prompt,
generationconfig={«responsemime_type»: «application/json»}
)
try:
return json.loads(response.text).get(«facts», []) if response else [text]
except:
return [text]
«`

Добавление памяти

Мы добавляем память, обрабатывая входные данные пользователя и встраивая их в граф.

«`python
def addmemory(self, userinput):
self.step_counter += 1
print(f»\n [Step {self.stepcounter}] Processing: \»{userinput}\»»)
facts = self.atomizeinput(user_input)
for fact in facts:
print(f» -> Atom: {fact}»)
emb = self.getembedding(fact)
candidates = self.findsimilar_nodes(emb)
node_id = str(uuid.uuid4())[:6]
node = MemoryNode(id=nodeid, content=fact, type=’fact’, embedding=emb, timestamp=self.stepcounter)
self.graph.addnode(nodeid, data=node, title=fact, label=fact[:15]+»…»)
if candidates:
context_str = «\n».join([f»ID {c[0]}: {self.graph.nodes[c[0]][‘data’].content}» for c in candidates])
prompt = f»»»
I am adding: «{fact}»
Existing Memory:
{context_str}
Are any of these directly related? If yes, provide the relationship label.
JSON: {{ «links»: [{{ «target_id»: «ID», «rel»: «label» }}] }}
«»»
response = retrywithbackoff(
self.model.generate_content,
prompt,
generationconfig={«responsemime_type»: «application/json»}
)
if response:
try:
links = json.loads(response.text).get(«links», [])
for link in links:
if self.graph.hasnode(link[‘targetid’]):
self.graph.addedge(nodeid, link[‘target_id’], label=link[‘rel’])
print(f» Linked to {link[‘target_id’]} ({link[‘rel’]})»)
except:
pass
time.sleep(1)
«`

Консолидация памяти

Мы реализуем когнитивные функции нашего агента, позволяя ему «спать» и консолидировать плотные кластеры памяти в инсайты более высокого порядка.

«`python
def consolidate_memory(self):
print(f»\n [Consolidation Phase] Reflecting…»)
highdegreenodes = [n for n, d in self.graph.degree() if d >= 2]
processed_clusters = set()

for mainnode in highdegree_nodes:
neighbors = list(self.graph.neighbors(main_node))
clusterids = tuple(sorted([mainnode] + neighbors))

if clusterids in processedclusters: continue
processedclusters.add(clusterids)

clustercontent = [self.graph.nodes[n][‘data’].content for n in clusterids]

prompt = f»»»
Generate a single high-level insight summary from these facts.
Facts: {json.dumps(cluster_content)}
JSON: {{ «insight»: «Your insight here» }}
«»»
response = retrywithbackoff(
self.model.generate_content,
prompt,
generationconfig={«responsemime_type»: «application/json»}
)

if response:
try:
insight_text = json.loads(response.text).get(«insight»)
if insight_text:
insight_id = f»INSIGHT-{uuid.uuid4().hex[:4]}»
print(f» Insight: {insight_text}»)
emb = self.getembedding(insight_text)

insightnode = MemoryNode(id=insightid, content=insight_text, type=’insight’, embedding=emb)
self.graph.addnode(insightid, data=insightnode, title=f»INSIGHT: {insighttext}», label=»INSIGHT», color=»#ff7f7f»)
self.graph.addedge(insightid, mainnode, label=»abstractedfrom»)
except:
continue
time.sleep(1)
«`

Ответ на запрос

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

«`python
def answer_query(self, query):
print(f»\n Querying: \»{query}\»»)
emb = self.getembedding(query)
candidates = self.findsimilarnodes(emb, topk=2)

if not candidates:
print(«No relevant memory found.»)
return

relevant_context = set()
for node_id, score in candidates:
nodecontent = self.graph.nodes[nodeid][‘data’].content
relevantcontext.add(f»- {nodecontent} (Direct Match)»)
for n1 in self.graph.neighbors(node_id):
rel = self.graph[node_id][n1].get(‘label’, ‘related’)
content = self.graph.nodes[n1][‘data’].content
relevant_context.add(f» — linked via ‘{rel}’ to: {content}»)

contexttext = «\n».join(relevantcontext)
prompt = f»»»
Answer based ONLY on context.
Question: {query}
Context:
{context_text}
«»»
response = retrywithbackoff(self.model.generate_content, prompt)
if response:
print(f» Agent Answer:\n{response.text}»)
«`

Визуализация графа

Мы добавляем метод визуализации, который генерирует интерактивный HTML-граф памяти нашего агента, позволяя нам проверять узлы и рёбра.

«`python
def show_graph(self):
try:
net = Network(notebook=True, cdnresources=’remote’, height=»500px», width=»100%», bgcolor=’#222222′, fontcolor=’white’)
for n, data in self.graph.nodes(data=True):
color = «#97c2fc» if data[‘data’].type == ‘fact’ else «#ff7f7f»
net.add_node(n, label=data.get(‘label’, »), title=data[‘data’].content, color=color)
for u, v, data in self.graph.edges(data=True):
net.add_edge(u, v, label=data.get(‘label’, »))
net.show(«memory_graph.html»)
display(HTML(«memory_graph.html»))
except Exception as e:
print(f»Graph visualization error: {e}»)
«`

В заключение мы имеем полностью функциональный прототип «Живой памяти», который выходит за рамки простого хранения данных в базе. Наш агент активно связывает связанные концепции и размышляет о своём опыте во время фазы «консолидации», решая критическую проблему фрагментированного контекста в длительных взаимодействиях с ИИ. Эта система демонстрирует, что истинный интеллект требует обработки данных и структурированной, развивающейся памяти, открывая путь к созданию более способных, персонализированных автономных агентов.

1. Какие технологии и инструменты используются для реализации системы памяти Zettelkasten в статье?

В статье используется передовой агентский ИИ, а также Google Gemini для реализации надёжного решения. Для управления графами и взаимодействия с моделями ИИ используются такие библиотеки, как networkx, numpy, google.generativeai и другие.

2. Какие основные этапы включает в себя процесс добавления памяти в систему Zettelkasten?

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

3. Какие функции выполняет агент в системе Zettelkasten и как он помогает консолидировать память?

Агент в системе Zettelkasten выполняет функции атомизации ввода, идентификации и создания семантических связей, а также консолидации памяти. Он «спит» для консолидации плотных кластеров памяти в инсайты более высокого порядка, позволяя системе формировать более глубокие и сложные понимания на основе накопленных данных.

4. Какие методы используются для визуализации графа памяти в системе Zettelkasten?

Для визуализации графа памяти используется метод, который генерирует интерактивный HTML-граф памяти агента. Это позволяет проверять узлы и рёбра графа и обеспечивает наглядное представление структуры памяти.

5. Какие преимущества предоставляет система Zettelkasten по сравнению с традиционными методами хранения данных?

Система Zettelkasten предоставляет ряд преимуществ по сравнению с традиционными методами хранения данных, включая активное связывание связанных концепций, размышление агента о своём опыте и консолидацию памяти. Это позволяет преодолеть проблему фрагментированного контекста в длительных взаимодействиях с ИИ и создаёт более способные, персонализированные автономные агенты.

Источник