Przejdź do treści głównej

Samouczek Supermemory: Dodaj trwałą pamięć do agentów AI

Zbuduj trenera ćwiczeń w Pythonie, który rejestruje treningi, zapamiętuje historię użytkownika dzięki Supermemory i proponuje spersonalizowane sesje między oddzielnymi uruchomieniami agenta AI.
Zaktualizowano 11 maj 2026  · 15 min Czytać

Większość agentów LLM zaczyna od zera przy każdym uruchomieniu. Zapominają imię użytkownika, ostatnią rozmowę i plik, nad którym pracował. Wszystko, co dotyczy użytkownika, trzeba na nowo ustalać krok po kroku.

Ten samouczek dodaje do agenta trwałą pamięć, aby następne uruchomienie zaczynało się tam, gdzie skończyło poprzednie. Warstwą pamięci jest Supermemory, hostowane API, które przechowuje fakty per użytkownik i zwraca je jednym wywołaniem. Zbudują Państwo osobistego trenera ćwiczeń w Pythonie. Agent zapisuje treningi, sugeruje kolejną sesję i zapamiętuje preferencje oraz ostatnie wyniki między oddzielnymi uruchomieniami skryptu.

Stos jest niewielki. Supermemory przechowuje pamięć. OpenAI Agents SDK obsługuje pętlę agenta. Trener składa się z dwóch plików Pythona oraz pliku pyproject.toml.

Potrzebny będzie Python 3.10 lub nowszy, konto OpenAI, konto Supermemory oraz podstawowa swoboda pracy w wierszu poleceń.

Czym jest Supermemory?

Supermemory najlepiej opisać jako API pamięci dla agentów AI.  Gdy przekażą Państwo Supermemory łańcuchy tekstowe o użytkowniku, później zwróci ono zwięzły obraz tego, kim użytkownik jest i co ostatnio robił. Osadzanie, indeksowanie i wyszukiwanie działają wewnątrz Supermemory, więc kod agenta pozostaje mały.

Benchmark LongMemEval sprawdza, jak dobrze system pamięci odpowiada na pytania w długiej historii rozmowy. Supermemory przywołuje 81,6% właściwych faktów. Zep, następny w kolejności system, uzyskuje 71,2% — 10-punktowa różnica, która przekłada się na mniej więcej 1 dodatkową poprawną odpowiedź na 10 pytań użytkownika. Repozytorium open source ma ponad 22 tys. gwiazdek na GitHubie — kolejny sygnał realnego użycia.

Pamięć vs RAG

Większość czytelników sięgających po narzędzie pamięci agenta wcześniej używała RAG. Istotne jest zestawienie go z Supermemory. RAG i pamięć rozwiązują różne problemy i często współistnieją w tym samym agencie.

System RAG wskazuje na korpus dokumentów przygotowany przez dewelopera raz. Instrukcje produktów, artykuły pomocy, dokumentacja wewnętrzna. Korpus ładuje się w momencie wdrożenia, zapytuje w czasie działania i rzadko się zmienia. Agent używa go do odpowiadania na pytania, na które sam produkt zna odpowiedź.

System pamięci wskazuje na użytkownika. Supermemory zapisuje fakty specyficzne dla użytkownika, gdy agent z nim rozmawia, a zbiór rośnie z każdą konwersacją. Agent używa go do odpowiadania na pytania, na które odpowiedź ma wyłącznie użytkownik, jak preferencje, historia i niedawna aktywność.

Title: Memory vs. RAG: skąd pochodzą dane - Description: Memory vs. RAG: skąd pochodzą dane

W prawdziwym produkcie oba działają obok siebie. RAG nad bazą wiedzy firmy odpowiada na pytanie „jaka jest nasza polityka zwrotów?”. Supermemory nad odpowiedzią użytkownika — „Jaki był mój wycisk na ławce w zeszłym tygodniu?”. Ten sam agent, dwa zbiory danych, dwa zadania.

Profile użytkowników: fakty statyczne i dynamiczne

Główną ideą Supermemory jest profil użytkownika. Każdy zapis trafia do dwóch koszyków: statycznych faktów, które rzadko się zmieniają, oraz dynamicznych faktów o bieżącej aktywności. Powtarzające się wzorce awansują do statycznych. Ostatnia aktywność pozostaje w dynamicznych.

Gdy agent odczytuje profil, jedno wywołanie zwraca oba koszyki plus pasujące fragmenty pamięci.

Podział ma znaczenie, bo fakty statyczne i dynamiczne odpowiadają na różne pytania o tego samego użytkownika:

Fakty statyczne

Fakty dynamiczne

Trenuje w domu z hantlami i drążkiem do podciągania

Bieżący cel: siła górnych partii ciała

Kontuzja lewego kolana, bez głębokich przysiadów

Ostatnie wyciskanie: 4 serie po 5 powtórzeń z 185 lb

Chce do końca roku dodać 20 lb do wyciskania

W tym tygodniu pracuje nad metodą „grease-the-groove” w podciąganiu

Trenuje tylko wieczorami, nigdy rano

Wczoraj przebiegł 5 km w 28 minut

Proszę przeczytać pierwszy wiersz. Strona statyczna mówi, jak użytkownik trenuje: w domu, ze swoim sprzętem. To nie zmienia się z tygodnia na tydzień. Strona dynamiczna mówi, nad czym pracuje teraz: górna część ciała, w tym cyklu.

Sugester treningów potrzebuje obu. Strona statyczna wyklucza ćwiczenia wymagające siłowni, a dynamiczna wybiera dzisiejszą sesję.

Za tym profilem Supermemory wykonuje cztery zadania, które inaczej musieliby Państwo zbudować samodzielnie. Przechowuje surowe wspomnienia, osadza każdy fragment, uruchamia wyszukiwanie podobieństwa w czasie odczytu i wyodrębnia fakty profilowe z zapisanych treści. Nic z tego nie pojawia się w Państwa kodzie.

Title: Co Supermemory robi za Ciebie - Description: Co Supermemory robi za Ciebie

Każda pamięć jest tagowana łańcuchem wybranym przez dewelopera. Każdy odczyt przekazuje ten sam łańcuch z powrotem, aby ograniczyć to, co wychodzi. Trener ma na sztywno wpisany jeden tag, bo jeden użytkownik wystarczy, by pokazać działanie profilu. Prawdziwe aplikacje wyliczają tag z uwierzytelnionego użytkownika, np. jego JWT.

Konfigurowanie środowiska Supermemory

Trener potrzebuje dwóch kluczy API (Supermemory i OpenAI) oraz projektu Pythona z trzema zależnościami. Krótki skrypt w tę i z powrotem potwierdzi działanie obu kluczy, zanim jakikolwiek kod agenta ich dotknie.

Pobieranie kluczy API

Klucz API Supermemory znajduje się pod adresem console.supermemory.ai, NIE app.supermemory.ai. Subdomena app to produkt dla konsumentów (do zapisywania notatek, przeglądania swojej przestrzeni). Nie ma strony z kluczem API. Proszę to pominąć i przejść bezpośrednio do konsoli.

W console.supermemory.ai:

  1. Proszę się zalogować.

  2. Kliknąć API Keys w pasku bocznym.

  3. Kliknąć Create API Key.

  4. Nazwa (w demie trenera użyto datacamp-tutorial).

  5. Skopiować powstały klucz. Zaczyna się od sm_.

Title: Konsola deweloperska Supermemory z widokiem strony API Keys - Description: Konsola deweloperska Supermemory z widokiem strony API Keys

Potrzebny będzie także klucz OpenAI do wywołań LLM agenta. Można go pobrać z platform.openai.com/api-keys, jeśli jeszcze Państwo go nie mają.

Proszę utworzyć plik .env w katalogu głównym projektu z oboma kluczami. Nie commitować go.

SUPERMEMORY_API_KEY=sm_your_key_here
OPENAI_API_KEY=sk-your_key_here

Bezpłatny poziom Supermemory obejmuje ten samouczek bez podawania danych płatniczych. Dokładne limity znajdują się na stronie cen.

Instalowanie zależności

Samouczek używa uv do projektowania i uruchamiania. Jeśli uv nie jest zainstalowane, proszę je zainstalować jednorazowo poleceniem z astral.sh/uv.

Inicjalizacja projektu:

uv init supermemory-trainer
cd supermemory-trainer

Proszę usunąć automatycznie wygenerowany README.md dodany przez uv init. Plik hello.py zostanie nadpisany w następnym kroku, więc na razie można go zostawić.

Dodać trzy zależności:

  • supermemory==3.37.0 to klient pamięci, przypięty do wersji zweryfikowanej dla tego samouczka.

  • openai-agents to OpenAI Agents SDK. Nazwa pakietu jest z łącznikiem, ścieżka importu to agents.

  • python-dotenv odczytuje plik .env, który przed chwilą Państwo utworzyli.

uv add supermemory==3.37.0 openai-agents python-dotenv

Powstały plik pyproject.toml:

[project]
name = "supermemory-trainer"
version = "0.1.0"
description = "Personal exercise trainer agent built with Supermemory and the OpenAI Agents SDK."
requires-python = ">=3.10"
dependencies = [
	"openai-agents>=0.10.2",
	"python-dotenv>=1.2.1",
	"supermemory==3.37.0",
]

Weryfikacja konfiguracji

Zanim napiszą Państwo jakikolwiek kod agenta, proszę zobaczyć, jak Supermemory działa raz na pojedynczym zdaniu. Poniższy skrypt wysyła jeden fakt do Supermemory, czeka na przetworzenie, a następnie odczytuje z powrotem profil. Jeśli to działa bez błędów, klucze są poprawne, a SDK jest osiągalne. Wyjście da też pierwszy wgląd w to, co Supermemory robi z surowym tekstem.

Proszę otworzyć hello.py w katalogu głównym projektu i zastąpić automatycznie wygenerowane ciało importami oraz wywołaniem zapisu:

import time
 
from dotenv import load_dotenv
from supermemory import Supermemory
 
load_dotenv()
 
client = Supermemory()
USER_ID = "demo_warmup"
 
response = client.add(
	content="The user is learning Supermemory by building a personal trainer agent.",
	container_tag=USER_ID,
)
print(f"client.add() -> id={response.id} status={response.status}")

load_dotenv() wczytuje klucz API z .env do środowiska przed utworzeniem Supermemory(). Klient automatycznie pobiera SUPERMEMORY_API_KEY. Wartość container_tag="demo_warmup" ogranicza ten pojedynczy fakt do tymczasowego użytkownika.

Teraz proszę dodać oczekiwanie i odczyt na dole tego samego pliku:

print("Waiting 20 seconds for processing...")
time.sleep(20)
 
prof = client.profile(container_tag=USER_ID, q="learning")
print(f"profile.static  ({len(prof.profile.static)}): {prof.profile.static}")
print(f"profile.dynamic ({len(prof.profile.dynamic)}): {prof.profile.dynamic}")
print(f"search_results.results ({len(prof.search_results.results)}):")
for r in prof.search_results.results[:3]:
	print(f"  - {r['memory']} (similarity={r['similarity']:.3f})")

20-sekundowa pauza daje czas na przetworzenie nowej pamięci w potoku osadzania i ekstrakcji Supermemory. Bez tego odczyt nic nie zwróci i skrypt będzie wyglądał na zepsuty, choć taki nie jest.

Uruchomienie pliku:

uv run python hello.py

Oczekiwane wyjście:

client.add() -> id=zNLsJBrY1PZupAeZ3Qn6EL status=queued
Waiting 20 seconds for processing...
profile.static  (0): []
profile.dynamic (1): ['Building a personal trainer agent to learn Supermemory.']
search_results.results (1):
  - Building a personal trainer agent to learn Supermemory. (similarity=0.650)

Trzy szczegóły mają tu znaczenie. client.add() zwraca natychmiast ze statusem status="queued", ponieważ Supermemory przetwarza dokumenty asynchronicznie. 20-sekundowe oczekiwanie obejmuje potok osadzania i ekstrakcji. Do czasu odczytu surowe zdanie staje się jednym wyszukiwalnym fragmentem pamięci.

Interesująca linia to profile.dynamic. Wejściem było zdanie „The user is learning Supermemory by building a personal trainer agent.” Wyjściem jest dynamiczny fakt 'Building a personal trainer agent to learn Supermemory.'. Supermemory przepisało zdanie w trzeciej osobie na fakt w pierwszej osobie o użytkowniku. To efekt pracy ekstraktora profilu.

profile.static to pusta lista. Fakty statyczne konsolidują się powoli, po zebraniu kilku powiązanych logów, więc pojedynczy zapis rozgrzewkowy ich nie generuje. Narzędzie sugestii trenera uwzględnia to i traktuje static jako premię, a nie gwarancję.

Budowa agenta Supermemory: osobisty trener ćwiczeń w Pythonie

Trener opakowuje client.add() i client.profile() w dwa narzędzia agenta, więc odczyty i zapisy dzieją się automatycznie w trakcie rozmowy z użytkownikiem. Historia treningów dobrze pasuje do pamięci. Sprzęt, kontuzje i ostatnie wyniki nie znajdują się w danych treningowych LLM, a gromadzą się sesja po sesji.

Title: Gdzie Supermemory włącza się w pętlę agenta - Description: Gdzie Supermemory włącza się w pętlę agenta

Struktura projektu i agent

Trener jest na tyle mały, że cały projekt mieści się w dwóch plikach Pythona plus pyproject.toml, który już istnieje:

supermemory-trainer/
├── .env            	# your real keys (gitignored)
├── .env.example    	# placeholders, committed
├── .gitignore
├── .python-version
├── main.py         	# agent definition, system prompt, REPL loop
├── pyproject.toml
└── tools.py        	# log_workout and suggest_next_session

tools.py zawiera dwa narzędzia oparte na pamięci, które zaraz Państwo napiszą. log_workout zapisuje trening do Supermemory przez client.add(). suggest_next_session odczytuje profil użytkownika przez client.profile(). main.py importuje oba i spina agenta.

Większość main.py to boilerplate OpenAI Agents SDK. Jedno zdanie w promptcie systemowym wykonuje pracę Supermemory: każdy fakt o użytkowniku musi wracać przez wywołania narzędzi. Agentowi mówi się, że nie ma własnej pamięci. Ta jedna zasada sprawia, że trener jest wspierany przez pamięć.

Proszę otworzyć main.py i zacząć od importów oraz promptu systemowego:

import asyncio
 
from agents import Agent, Runner, SQLiteSession
 
from tools import log_workout, suggest_next_session
 
SYSTEM_PROMPT = """You are a personal exercise trainer who logs the user's
workouts and recommends what to do next.
 
You have no memory of the user's history on your own. Every fact about the
user lives in Supermemory and reaches you only through tool calls.
 
Two rules, no exceptions:
 
1. Whenever the user reports completing a workout, call log_workout immediately, before responding. Extract the exercise, sets, reps, weight, and any notes from what they said. If a value is missing, ask one short follow-up question instead of guessing. After logging, confirm in one short sentence and stop. Do NOT recommend the next session unless the user asks for one.
 
2. When the user explicitly asks what to do next (or asks for a recommendation, suggestion, or plan), call suggest_next_session first. Never recommend from your own training data. The tool returns the user's
 recent activity, stable preferences, and matching past sessions. Reference those facts directly in your reply.
 
Keep replies concise (2-4 sentences). Be specific: name the exercise, sets, reps, and weight. Honor any injuries or equipment constraints the tool surfaces.
"""

Obie zasady w promprcie systemowym kierują model przez Supermemory. 

Zasada 1 wymusza wywołanie log_workout za każdym razem, gdy użytkownik zgłasza trening, aby każdy trening trafił do magazynu pamięci. Zasada 2 wymusza wywołanie suggest_next_session przed każdą rekomendacją, aby każda rekomendacja była oparta na tym, co wie Supermemory. 

Bez tych zasad agent odpowiadałby na podstawie swoich danych treningowych, co mija się z celem warstwy pamięci.

Teraz w tym samym pliku proszę zdefiniować agenta i pętlę czatu:

def build_agent() -> Agent:
	return Agent(
    	name="Trainer",
    	instructions=SYSTEM_PROMPT,
    	tools=[log_workout, suggest_next_session],
    	model="gpt-5",
	)
 
 
async def chat() -> None:
	agent = build_agent()
	session = SQLiteSession(session_id="trainer-cli")
 
	print("Trainer ready. Type a message, or 'exit' to quit.\n")
	while True:
    	try:
        	message = input("You: ").strip()
    	except (EOFError, KeyboardInterrupt):
        	print()
        	break
    	if not message:
        	continue
    	if message.lower() in {"exit", "quit"}:
        	break
 
    	result = await Runner.run(agent, message, session=session)
    	print(f"\nTrainer: {result.final_output}\n")
 
 
if __name__ == "__main__":
	asyncio.run(chat())

Warte nazwania są dwie linie w tym bloku. tools=[log_workout, suggest_next_session] rejestruje dwa narzędzia oparte na pamięci. Dekorator @function_tool na każdym z nich (w tools.py) mówi SDK, że są wywoływalne. Bez dekoratora agent nie ma narzędzi w czasie działania, mimo że konstrukcja się udaje.

SQLiteSession(session_id="trainer-cli") utrzymuje krótkoterminową historię tur w działającym procesie Pythona. Supermemory utrzymuje długoterminowe fakty o użytkowniku między procesami. Zabicie procesu Pythona usuwa sesję SQLite, ale dane w Supermemory pozostają.

Ważne: Proszę uruchamiać main.py jako skrypt, nie w komórce Jupytera, ponieważ pętla zdarzeń Jupytera koliduje z asyncio.run(). Synchroniczny klient Supermemory() działa wewnątrz asynchronicznych funkcji narzędzi, ponieważ Agents SDK uruchamia narzędzia w puli wątków. Więcej o samym SDK w samouczku OpenAI Agents SDK.

Pisanie narzędzia do rejestrowania treningów

log_workout to strona zapisu pamięci agenta. Funkcja przyjmuje ustrukturyzowane argumenty z agenta: nazwę ćwiczenia, serie, powtórzenia, ciężar i opcjonalne uwagi. Zamienia je na jedno krótkie zdanie po angielsku i przekazuje je do Supermemory przez client.add(). Potok osadzania i ekstrakcji działa następnie wewnątrz Supermemory i nie wymaga niczego od trenera.

Proszę otworzyć tools.py i zacząć od importów oraz jednego współdzielonego klienta:

from agents import function_tool
from dotenv import load_dotenv
from supermemory import Supermemory
 
load_dotenv()
 
USER_ID = "demo_user"
 
client = Supermemory()

load_dotenv() uruchamia się przy imporcie, więc SUPERMEMORY_API_KEY jest w środowisku przed utworzeniem Supermemory(). Jeśli utworzą Państwo klienta przed wczytaniem env, powstanie klient nieuwierzytelniony. Pierwsze wywołanie zwróci wówczas mylący błąd 401. Obie funkcje narzędziowe w tym pliku współdzielą tego jednego klienta i stałą USER_ID.

Poniżej klienta proszę dodać narzędzie logujące:

@function_tool
def log_workout(
	exercise: str,
	sets: int,
	reps: int,
	weight: float,
	notes: str = "",
) -> str:
	"""Log a completed workout to the user's memory.
 
	Args:
    	exercise: Name of the exercise.
    	sets: Number of sets performed.
    	reps: Number of reps per set.
    	weight: Weight in pounds. Pass 0 for bodyweight or cardio.
    	notes: Optional notes about the session.
	"""
	print(f"[log_workout] {exercise=} {sets=} {reps=} {weight=} {notes=}")
 
	content = f"Performed {exercise}: {sets} sets of {reps} reps at {weight} lbs."
	if notes:
    	content += f" Notes: {notes}"
 
	response = client.add(content=content, container_tag=USER_ID)
	print(f"[log_workout] -> id={response.id} status={response.status}")
	return f"Logged {exercise} ({sets}x{reps} @ {weight} lb)."

Docstring dekoratora @function_tool to to, co widzi LLM, gdy decyduje, czy wywołać narzędzie. Blok Args: mapuje się na opisy parametrów. Oba elementy są częścią kontraktu agenta z funkcją.

Narzędzie wysyła do client.add() zwykłe zdanie, nie JSON. Ekstraktor profilu Supermemory czyta język naturalny i wnioskuje z niego fakty. JSON technicznie zadziała, ale jakość ekstrakcji spada, bo model nie ma narracji do streszczenia. „Performed bench press: 4 sets of 5 reps at 185.0 lbs” daje ekstraktorowi czyste zdanie do pracy.

Dwa wywołania print() zapisują każde użycie narzędzia w terminalu: najpierw sparsowane argumenty, potem odpowiedź.

[log_workout] exercise='bench press' sets=4 reps=5 weight=185.0 notes=''
[log_workout] -> id=xY7AK3qLzBPx5Vd2HnRf1M status=queued

Wartość status="queued" odpowiada temu, co wcześniej zwrócił skrypt rozgrzewkowy. Surowy log jest zapisany, ale client.profile() nie zwróci go jako wyniku wyszukiwania, dopóki potok się nie zakończy. Później dodadzą Państwo krok weryfikacji, który na to poczeka.

Pisanie narzędzia do sugestii treningów

suggest_next_session to strona odczytu i tu procentuje podział na statyczne i dynamiczne. Jedno wywołanie client.profile(container_tag=USER_ID, q=focus) zwraca trzy widoki użytkownika w jednym obiegu. 

Stabilne preferencje wracają jako profile.static, bieżąca aktywność jako profile.dynamic, a najbliższe pasujące przeszłe wspomnienia jako search_results.results. Zadaniem narzędzia jest spłaszczenie tych trzech widoków do jednego bloku kontekstu, który agent może cytować.

Po kilku treningach narzędzie generuje taki wynik:

Recent activity:
- Trains at home instead of a gym
- Performed deadlift: 3 sets of 5 reps at 225.0 lbs
- Performed 5k run in 26 minutes
- Reports no knee pain during bench press
- Performed bench press: 4 sets of 5 reps at 185.0 lbs
Closest matching past entries:
- Trains at home instead of a gym
- Performed deadlift: 3 sets of 5 reps at 225.0 lbs
- Performed bench press: 4 sets of 5 reps at 185.0 lbs
- Performed 5k run in 26 minutes
- Reports no knee pain during bench press

Agent czyta ten blok i pisze rekomendację opartą na faktycznej historii użytkownika. Bez profilu Supermemory trzeba byłoby zbudować ten sam kontekst samodzielnie. Oznacza to osobne wyszukiwanie semantyczne, własny magazyn profilu i scalenie wyników. Pojedyncze wywołanie client.profile() zastępuje wszystkie trzy.

Proszę dodać to do tools.py poniżej log_workout:

@function_tool
def suggest_next_session(focus: str) -> str:
	"""Fetch the user's training history and preferences for a given focus.
 
	Returns a context string the agent can use to recommend the next session.
	The agent is responsible for the actual recommendation. This tool only
	surfaces what Supermemory knows about the user.
 
	Args:
    	focus: What the user wants to train next (e.g. "upper body", "legs",
        	"cardio", "today"). Drives semantic search against past logs.
	"""
	print(f"[suggest_next_session] focus={focus!r}")
	profile = client.profile(container_tag=USER_ID, q=focus)
 
	static_facts = profile.profile.static
	dynamic_facts = profile.profile.dynamic
	matches = profile.search_results.results
 
	print(
    	f"[suggest_next_session] static={len(static_facts)} "
    	f"dynamic={len(dynamic_facts)} matches={len(matches)}"
	)
 
	sections = []
	if static_facts:
    	sections.append("Stable preferences and constraints:")
    	sections.extend(f"- {fact}" for fact in static_facts)
	if dynamic_facts:
    	sections.append("Recent activity:")
    	sections.extend(f"- {fact}" for fact in dynamic_facts)
	if matches:
    	sections.append("Closest matching past entries:")
    	for r in matches[:5]:
        	sections.append(f"- {r['memory']}")
 
	if not sections:
    	return (
        	"No prior training history found for this user. "
        	"Ask the user about their goals, equipment, and recent training."
    	)
	return "\n".join(sections)

client.profile(container_tag=USER_ID, q=focus) zwraca obiekt ProfileResponse. Po 5 krótkich logach trzy pola odczytywane przez narzędzie wyglądają tak:

profile.profile.static        	# [] (list[str])
profile.profile.dynamic       	# ["Performed bench press: 4 sets of 5 reps at 185.0 lbs", ...]
profile.search_results.results	# [{"memory": "...", "similarity": 0.631, ...}, ...] (list[dict])

Każdy wynik wyszukiwania to słownik Pythona, a nie obiekt Pydantic. Proszę używać r["memory"] do tekstu i r["similarity"] do wyniku. Pełny słownik zawiera następujące klucze:

  • id

  • memory

  • rootMemoryId

  • metadata

  • updatedAt

  • version

  • similarity

  • filepath

  • documents

Fragment r.memory or r.chunk ze strony integracji Supermemory z OpenAI Agents SDK powoduje AttributeError przy supermemory==3.37.0. Proszę używać dostępu przez nawiasy kwadratowe.

static jest tutaj puste, dlatego narzędzie rozgałęzia się warunkiem if static_facts:. Gałęzie dynamic i search_results wykonują realną pracę dla pierwszego tuzina logów.

Supermemory stosuje też domyślny próg podobieństwa. Fakt wspomniany raz może nie wrócić przy każdym zapytaniu. Powyższe 5 logów wszystkie wróciły dla q="today", ale bardziej szczegółowy ciąg zapytania może zwrócić mniej. Zabezpieczenie if matches: obsługuje to bez błędów.

Sesja 1: rejestrowanie treningów

Proszę rozpocząć sesję 1 i zapisać kilka treningów, aby wypełnić Supermemory danymi do późniejszego odczytu. Uruchomienie skryptu:

uv run python main.py

Proszę zarejestrować wyciskanie na ławce, potem bieg na 5 km, potem martwy ciąg oraz jedno stwierdzenie preferencji: „Trenuję tylko w domu, bez siłowni.” Agent wywołuje log_workout raz na trening, a linie print() narzędzia pokazują każde wywołanie w terminalu.

Title: Terminal sesji 1 pokazujący trzy wywołania log_workout - Description: Terminal sesji 1 pokazujący trzy wywołania log_workout

Przykładowe wyjście. Dokładne sformułowania Państwa agenta będą się różnić, ponieważ model jest niedeterministyczny.

Trzy linie status=queued to moment, w którym Supermemory przejmuje działanie. Każda odpowiada dokumentowi przechodzącemu przez potok osadzania i ekstrakcji po stronie Supermemory. Dla krótkich logów takich jak te dokument staje się wyszukiwalny przez client.profile() w ciągu ~12 sekund.

Kod trenera na to nie czeka. Agent idzie dalej, a Supermemory kończy pracę w tle.

Każdy log wywołuje dokładnie jedno log_workout, a agent się zatrzymuje. Bez proaktywnych rekomendacji, bez dodatkowych wywołań narzędzi, bez dalszych sugestii. Pierwsza zasada promptu systemowego to wymusza. Bez niej agent sugerowałby kolejną sesję po każdym logu, podwajając liczbę wywołań narzędzi.

Proszę wpisać exit, aby zamknąć sesję 1. Proces Pythona kończy się i SQLiteSession znika wraz z nim. Logi treningów i stwierdzenie preferencji teraz żyją w Supermemory pod container_tag="demo_user", oddzielone od skryptu, który je zapisał.

Weryfikacja odtworzenia i sesja 2

Przed sesją 2 proszę potwierdzić, że fakty z sesji 1 są wyszukiwalne. Proszę otworzyć świeży REPL Pythona albo zapisać to jako krótki skrypt:

from dotenv import load_dotenv
from supermemory import Supermemory
 
load_dotenv()
client = Supermemory()
 
prof = client.profile(container_tag="demo_user", q="training")
print(f"static  ({len(prof.profile.static)}): {prof.profile.static}")
print(f"dynamic ({len(prof.profile.dynamic)}):")
for fact in prof.profile.dynamic:
	print(f"  - {fact}")
print(f"matches ({len(prof.search_results.results)}):")
for r in prof.search_results.results[:5]:
	print(f"  - {r['memory']} (similarity={r['similarity']:.3f})")

Rzeczywiste wyjście przechwycone między dwiema sesjami:

static  (0): []
dynamic (5):
  - Trains at home instead of a gym
  - Performed deadlift: 3 sets of 5 reps at 225.0 lbs
  - Performed 5k run in 26 minutes
  - Reports no knee pain during bench press
  - Performed bench press: 4 sets of 5 reps at 185.0 lbs
matches (5):
  - Trains at home instead of a gym (similarity=0.682)
  - Performed deadlift: 3 sets of 5 reps at 225.0 lbs (similarity=0.643)
  - Performed bench press: 4 sets of 5 reps at 185.0 lbs (similarity=0.631)
  - Performed 5k run in 26 minutes (similarity=0.585)
  - Reports no knee pain during bench press (similarity=0.585)

Proszę spojrzeć, co wyprodukował ekstraktor Supermemory. Użytkownik raz powiedział: „Trenuję tylko w domu, bez siłowni”. Ekstraktor zamienił to w dynamiczny fakt „Trains at home instead of a gym”.

Log wyciskania zawierał w polu uwag informację o braku bólu kolana. Ekstraktor podzielił ten pojedynczy log na dwa dynamiczne fakty: jeden o treningu, drugi o braku bólu.

Cztery logi stały się pięcioma znormalizowanymi faktami dynamicznymi plus pięć pasujących fragmentów pamięci z wynikami podobieństwa między 0,585 a 0,682. Żadne z tego dzielenia, normalizacji ani dopasowywania nie działało w kodzie trenera. Jeśli u Państwa dynamic jest puste, proszę poczekać kolejne 10 sekund i ponownie uruchomić fragment. Kolejka przetwarzania czasem rośnie.

Teraz proszę rozpocząć sesję 2 w zupełnie nowym procesie:

uv run python main.py

To świeży interpreter Pythona. Bez współdzielonej pamięci z sesją 1. Bez ciepłej pamięci podręcznej. Wszystko, co agent odtworzy, pochodzi z Supermemory.

Proszę wysłać jedną wiadomość: „Co powinienem dziś zrobić na treningu?”

Title: Terminal sesji 2 w świeżym procesie odtwarzający wcześniejsze treningi - Description: Terminal sesji 2 w świeżym procesie odtwarzający wcześniejsze treningi

Przykładowe wyjście. Ten sam magazyn pamięci, świeży proces Pythona.

Agent wywołuje suggest_next_session("today"). Narzędzie wypisuje static=0 dynamic=5 matches=5. Zarejestrowane uruchomienie odpowiedziało sesją na dolne partie ciała w domu (przysiady, wykroki, step-upy).

Rekomendacja zgrała się z poprzednimi logami, bo profil Supermemory powiedział agentowi, jakie one były. Wyciskanie, martwy ciąg i 5 km to górne partie lub cardio, a użytkownik trenował tylko w domu. Oba fakty wróciły z tego samego wywołania client.profile(). Państwa uruchomienie sformułuje to inaczej, bo model jest niedeterministyczny, ale ścieżka odtworzenia jest taka sama.

Dalsze kroki dla Państwa agenta Supermemory

Demo obejmuje jednego użytkownika, dwa narzędzia i CLI. Prawdziwa wersja trenera rozszerza się w trzech kierunkach „na kształt Supermemory” zanim dotknie pętli agenta.

Zakres pamięci per prawdziwy użytkownik. Stała USER_ID = "demo_user" działa dla jednej osoby. Aplikacje produkcyjne wyliczają tag z ID uwierzytelnionego użytkownika, np. container_tag="user_sarah" albo container_tag=customer_id. Pamięć między użytkownikami pozostaje rozdzielona, bo każdy odczyt przekazuje tag z powrotem. Jedna zmiana w tools.py, reszta kodu bez zmian.

Dodanie kolejnych narzędzi wspieranych pamięcią. Tydzień rozładowania, śledzenie rekordów (PR) i cotygodniowe wskazówki mobilności. Każde to kolejna funkcja @function_tool, która wywołuje client.add() do zapisów i client.profile() do odczytów przeciwko temu samemu container_tag. Kształt narzędzia pozostaje taki sam. Zmienia się tylko to, co agent zapisuje i o co pyta.

Obsługa awarii Supermemory. Proszę opakować client.add() i client.profile() w try/except supermemory.APIError, aby przejściowe awarie Supermemory nie wyłączały agenta. Proszę ustawić limity czasu na żądanie, jeśli agent działa w środowisku o ograniczonych zasobach.

Część pętli agenta jest niezależna od Supermemory i może się zmienić później. Proszę podstawić pod CLI Telegram, Discord lub Slack, aby użytkownik wysłał trening SMS-em, a bot wywołał Runner.run(). Albo podmienić framework. Supermemory ma integrację z LangChain, jeśli Państwa stos już korzysta z agentów LangChain, a kod pamięci się nie zmienia.

Podział na statyczne i dynamiczne pasuje też do innych domen. 

  • Agent wsparcia klienta: statyczne = znane problemy i preferencje konta, dynamiczne = otwarte zgłoszenia i ostatnie kontakty. 
  • Agent kodujący: statyczne = preferowane języki i frameworki, dynamiczne = bieżące zadanie i ostatnio dotykane pliki. 

Podział działa zawsze, gdy źródłem prawdy jest użytkownik.

Zakończenie

Właśnie zbudowali Państwo trenera w Pythonie z dwoma narzędziami i trwałą pamięcią między procesami. client.add() zapisuje treningi. client.profile() odczytuje użytkownika jako fakty statyczne, dynamiczne i dopasowania semantyczne w jednym wywołaniu, wszystko w zakresie określonym przez container_tag. Supermemory wykonuje podział na fragmenty, osadzanie, wyszukiwanie i ekstrakcję profilu, których demo nie musiało pisać.

W parze z RAG ten sam agent odpowiada na pytania o użytkownika i produkt. Wyjaśnienie agentów LLM obejmuje szersze wzorce agentów, a ścieżka Associate AI Engineer for Developers sięga dalej w agentów wspieranych pamięcią.

Supermemory — najczęstsze pytania

Czym jest Supermemory?

Supermemory to hostowane API pamięci, które przechowuje, indeksuje i wyszukuje kontekst długoterminowy dla agentów AI, aby mogli pamiętać użytkowników między sesjami.

Czym Supermemory różni się od zwykłych baz wektorowych?

Supermemory dodaje do przechowywania osadzenia, indeksowanie, wyszukiwanie semantyczne i ekstrakcję faktów w stylu profilu, dzięki czemu jednym wywołaniem API otrzymują Państwo użyteczne wspomnienia.

Czy Supermemory obsługuje zarówno RAG, jak i pamięć użytkownika?

Tak, obsługuje dokumentowy RAG dla plików i adresów URL oraz pamięć zorientowaną na użytkownika, dzięki czemu to samo API może zasilać wiedzę o produkcie i historię osobistą.

Czy muszę zarządzać własnymi modelami osadzania w Supermemory?

Nie, Supermemory uruchamia za Państwa potok osadzania i wyszukiwania; wysyłają Państwo surowy tekst lub treść i zapytują później bez samodzielnej obsługi modeli czy indeksów.

Czy jest darmowy poziom do wypróbowania Supermemory?

Tak, dostępny jest darmowy plan przeznaczony do testów i małych projektów, z miesięcznymi limitami tokenów i zapytań, aby można było integrować i eksperymentować przed upgradem.

Tematy

Ucz się AI Engineering z DataCamp!

Track

Associate AI Engineer for Developers

26 godz.
Learn how to integrate AI into software applications using APIs and open-source libraries. Start your journey to becoming an AI Engineer today!
Zobacz szczegółyRight Arrow
Rozpocznij kurs
Zobacz więcejRight Arrow