Strona główna / Artykuły

Prywatny „drugi mózg” AI: lokalny system RAG z wykorzystaniem AnythingLLM, Ollamy i Obsidian.

Prywatny drugi mózg: AnythingLLM oraz model embeddingowy na maszynie wirtualnej Proxmox umożliwiają lokalnemu modelowi Mistral 7B wyszukiwanie notatek w Obsidian za pomocą Ollama RAG, przy rzeczywistym zużyciu zasobów.

Wydawca: REACTAPP.TOP8 min czytania1758 słów

Źródła: Giving My Local AI a Memory: Turning It Into a Private AI Second Brain with RAG and AnythingLLM

Błyskotliwy amnezik

Lokalny model językowy potrafi prowadzić rozmowy, wyjaśniać koncepcje i pomagać w przemyśleniu pomysłów, przy czym ani jeden bajt nie opuszcza budynku. Nie potrafi jednak automatycznie przywołać niczego, co zostało zapisane.

Wyobraź sobie rok zgromadzonych notatek w Obsidianie: linki zaznaczone o północy, nieukończone myśli, długi artykuł o silnikach wyszukiwania, ogłoszenia o pracę oraz notatki z warsztatów. Wszystko to znajduje się w folderze na laptopie, niewidoczne dla sztucznej inteligencji, która potrzebowała całego weekendu, by działać offline.

Pamięć przechowywania nigdy nie była problemem. Problemem jest dostęp do danych. Wybór właściwej notatki we właściwym momencie to to, co zamienia folder pełen linków w wiedzę, a nie w dobrze zorganizowaną skrzynkę na śmieci. Dlatego naturalnym następnym krokiem w prywatnym setupie sztucznej inteligencji jest umożliwienie jej dostępu do tych notatek.

Czym jest RAG i dlaczego jest ważne

Większość przewodników dotyczących „uruchamiania AI lokalnie” pomija tę część, prawdopodobnie dlatego, że embeddingi wydają się nudne. Rzeczywiście są nieco nudne, ale warto je zrozumieć.

RAG to skrót od Retrieval-Augmented Generation. Umożliwia modelowi językowemu korzystanie z twoich własnych dokumentów bez konieczności ponownego szkolenia ani przesyłania ich na serwer third party.

Pomyśl o zatrudnieniu bardzo szybkiego bibliotekarza zamiast prośeniu AI o zapamiętanie każdej książki. Bibliotekarz nie zna twoich notatek na pamięć, wie tylko, którą wybrać, gdy zadasz pytanie.

Oto co dzieje się w tle:

  1. Dokumenty są dzielone na fragmenty i przekształcane w embeddingi, czyli liczbowe reprezentacje znaczenia, które są przechowywane w bazie danych wektorowej.
  2. Pytanie również jest przekształcane w embedding.
  3. Baza danych znajduje fragmenty o znaczeniu najbliższym pytaniu.
  4. Te fragmenty trafiają do modelu językowego jako kontekst.
  • Model odpowiada na podstawie twoich rzeczywistych dokumentów, a nie tylko na podstawie tego, co przyswoił podczas szkolenia.
  • Narzędzie: AnythingLLM

    AnythingLLM nadaje się do tego zastosowania z kilku powodów:

    • Przestrzenie robocze przechowują oddzielne bazy wiedzy dla różnych kontekstów, takich jak notatki, badania czy szkice blogów.
    • Czyta pliki w formacie Markdown natywnie, więc notatki w Obsidianie nie wymagają konwersji.
    • Łączy się bezpośrednio z Ollamą.
    • Jest uruchamiany lokalnie jako kontener Docker, bez konieczności posiadania konta ani korzystania z chmury.
    • Posiada również aplikację na komputer stacjonarny, która pomaga osobom, które nie mają homelabu.

    To nie jest jedyna opcja. Open WebUI również ma wbudowany mechanizm RAG. Jednak model przestrzeni roboczej AnythingLLM lepiej odpowiada koncepcji „drugiego mózgu”, a jego interfejs jest na tyle przyjazny, że można go polecić osobom niebędącym specjalistami technicznymi.

    Budowanie środowiska

    Punkt wyjścia

    Ustawienie zakłada następującą bazę:

    • host Proxmox VE działający bez systemu operacyjnego;
    • jedna maszyna wirtualna Ubuntu 24.04 z Ollamą i modelami Mistral 7B;
    • Open WebUI jako interfejs do rozmów.

    W procesie konfiguracji dodaje się drugą maszynę wirtualną obok niej.

    Nowa maszyna wirtualna w Proxmox

    Stwórz nową maszynę wirtualną Ubuntu 24.04 LTS przeznaczoną dla AnythingLLM. Utrzymywanie jej oddzielnie od maszyny z Ollamą umożliwia tworzenie zrzutów stanu, celowe uszkadzanie konfiguracji oraz jej przywracanie bez wpływu na rzeczywiste ustawienia inferencji. Celowe uszkadzanie jest lepsze niż przypadkowe awarie później.

    Zalecane specyfikacje:

    • 4 vCPUs
    • 8 GB RAM
    • 40 GB dysku, ponieważ bazy wektorowe zajmują dużo miejsca

    Nic tutaj nie jest trudne. Dokumentacja to omawia, a dodatkowo trochę prób i błędów wystarczy, szczególnie dla tych, którzy już uruchomili maszynę wirtualną Ollama. Prawdziwym ograniczeniem jest dostępny sprzęt, a praca w ramach tych ograniczeń stanowi sedno tego ćwiczenia.

    Instalowanie modelu embedding

    Większość przewodników pomija ten krok, co powoduje najwięcej problemów.

    RAG wymaga dwóch modeli. Jeden to model inferencji, który już dostarcza Mistral 7B. Drugi to model embedding, który przekształca tekst na wektory. Są to różne rzeczy, a niewiele przewodników informuje o tym od razu.

    Na istniejącej maszynie wirtualnej Ollama pobierz model embedding:

    ollama pull nomic-embed-text
    

    nomic-embed-text ma niewielką objętość, około 270 MB, szybko działa na procesorze i dobrze radzi sobie z tekstem w języku angielskim – jest więc rozsądnym wyborem dla sprzętu bez karty graficznej.

    Kolejny problem: Ollama domyślnie słucha tylko na localhost. Aby AnythingLLM działający na innej maszynie wirtualnej mógł do niego uzyskać dostęp, Ollama musi być dostępny na wszystkich interfejsach. Zacznij od edycji usługi:

    sudo systemctl edit ollama
    

    Następnie dodaj tę modyfikację:

    [Service]
    Environment="OLLAMA_HOST=0.0.0.0"
    

    Przeładowaj systemd i uruchom ponownie usługę:

    sudo systemctl daemon-reload
    sudo systemctl restart ollama
    

    Następnie otwórz port 11434 w firewallu Proxmox pomiędzy dwoma maszynami wirtualnymi. Lekcja się powtarza: usługa była w porządku, model również. Problemem była założenie, że wszystko może komunikować się ze sobą domyślnie.

    Zasady sieciowe mogłyby być bardziej restrykcyjne i prawdopodobnie tak powinno być w końcu. To typowe podejście amatorów: sprawić, by coś działało, zrozumieć, co zostało zbudowane, a potem to zdemontować i zrobić to poprawnie od nowa.

    AnythingLLM przez Docker

    Na nowej maszynie wirtualnej najpierw zainstaluj Docker:

    # Install Docker
    curl -fsSL <https://get.docker.com> | sh
    sudo usermod -aG docker $USER
    newgrp docker
    

    Następnie uruchom AnythingLLM:

    # Run AnythingLLM
    docker run -d \
      -p 3001:3001 \
      --name anythingllm \
      -v ~/.anythingllm:/app/server/storage \
      mintplexlabs/anythingllm
    

    Otwórz w przeglądarce http://<new-vm-ip>:3001. Konfiguracja przy pierwszym uruchomieniu jest następująca:

    • Dostawca LLM: Ollama, pod adresem http://<ollama-vm-ip>:11434
    • Model do czatowania: Mistral 7B
    • Dostawca embeddingów: Ollama, z użyciem nomic-embed-text
    • Baza wektorowa: LanceDB, wbudowana w system i nie wymagająca dodatkowej konfiguracji

    Dostarczanie mu notatek

    Stwórz przestrzeń roboczą o nazwie „Second Brain” i skieruj AnythingLLM na schowek Obsidian. Jego menedżer dokumentów przyjmuje pliki z folderów, więc podaj mu katalog z notatkami i pozwól mu je przetworzyć.

    Przetwarza pliki typu .md, .txt, .pdf, .docx oraz .csv. Pliki Obsidian Canvas są w rzeczywistości plikami JSON, więc nie spowodują błędu, ale też nie dostarczą żadnych użytecznych informacji.

    Po przyjęciu tekstu przestrzeń robocza pokazuje liczbę fragmentów oraz status ich embedowania. Każda notatka jest dzielona na nakładające się fragmenty po około 500 tokenów, co oznacza, że długi artykuł o silnikach wyszukiwania staje się dziesiątkami oddzielnie dostępnych fragmentów.

    Moment kliknięcia

    Prawdziwą próbą jest zwykła prośba, na przykład poproszenie asystenta o sprawdzenie konkretnej notatki o nazwie „ulepszenia w homelabie”.

    Asystent znajduje właściwy plik, podaje jego nazwę i przytacza dokładny fragment wraz z datą i godziną. Odniesienie zawiera nazwę dokumentu źródłowego oraz datę publikacji. Funkcja wyszukiwania działa zgodnie z obietnicami: plik jest nazwany i odnaleziony, bez wymyślonego treści ani niejasnej parafrazy – tylko właściwe informacje wraz z odniesieniem.

    Zabawne jest to, gdy model próbuje wyjaśnić tę notatkę. Opisuje Claude Code jako swego rodzaju asystenta osobistego lub usługę. Mistral 7B, działający offline na urządzeniu domowym z samym procesorem, nie ma pojęcia, czym jest Claude Code ani serwer MCP. Potrafi pobrać słowa, ale nie potrafi ich w pełni zrozumieć.

    To jest ważniejsza lekcja. Pobieranie informacji i ich rozumienie to odrębne problemy. RAG umieszcza odpowiedni kontekst przed modelem, ale zrozumienie tego kontekstu nadal zależy od samego modelu. Przy małym modelu 7B i braku dostępu do Internetu te ograniczenia pojawiają się szybko.

    Co poszło nie tak i co to nauczyło

    Kilka założeń nie przetrwało procesu budowy.

    • RAG to nie magia. Jest tak użyteczny, jak to, co mu dostarczono, a nieuporządkowane notatki dają nieuporządkowane wyniki. Co włożysz, to i dostaniesz.
    • Tworzenie sieci staje się częścią projektu już na wczesnym etapie. Gdy usługi są rozproszone na kilku maszynach, kluczowe jest zapewnienie ich niezawodnej komunikacji, co ma takie samo znaczenie jak konfiguracja każdej z nich.
    • Nie winić zbyt szybko modelu. Czasami problem leży w dostarczonym kontekście. Dobre mechanizmy wyszukiwania mogą sprawić, że mały model okaże się zaskakująco przydatny, ale nie mogą dostarczyć wiedzy, której model nigdy nie posiadał.

    Co ostatecznie otrzymujemy i jaki jest to koszt

    Rok zapisanych linków, pomysłów i nieukończonych myśli staje się dostępny do wyszukiwania, i to nie tylko za pomocą słów kluczowych, ale także semantycznie. Zadaj pytanie dotyczące jakiegoś pojęcia, a pojawią się powiązane notatki, o których zapomniałeś, że są powiązane, każda z nich z odniesieniem do pliku źródłowego.

    Maszyna testowa to EliteDesk z procesorem i5, 32 GB pamięci RAM i bez karty graficznej, a wszystko działało offline. Wyniki z tego jednego testu:

    Pozycja Wynik
    Czas przetwarzania zapytania od początku do końca 1 min 35,9 s, przy czym AnythingLLM podaje 41,9 s na generowanie
    Pamięć AnythingLLM w stanie spoczynku około 440 MB z przydzielonych 7,76 GB
    Pamięć używana przez wirtualną maszynę Ollama 7,8 GB z 19 GB
    Pamięć potrzebna do działania Mistral około 6,5 GB
    nomic-embed-text około 360 MB
    Open WebUI około 1 GB

    Około 54-sekundowa różnica pomiędzy tymi dwoma czasami nie ma wyjaśnienia. Prawdopodobną przyczyną może być ponowne ładowanie modelu przez Ollamę z dysku twardego.

    Żadna z tych wartości nie jest szybka i tak też nie powinno być. To dopiero pierwszy dzień pracy konfiguracji RAG w domowym laboratorium, która wciąż szuka swojej formy, a nie jest to benchmark do porównywania z poważnymi rozwiązaniami. Będzie ciekawie spojrzeć w przyszłości na te liczby, gdy lokalny sprzęt będzie mógł przetwarzać znacznie więcej tokenów na sekundę.

    Gdzie to was prowadzi

    Projekt zaczyna się od prostego celu – umożliwienia lokalnej sztucznej inteligencji przeglądania waszych notatek – ale uczy również wielu innych rzeczy. W trakcie nauki poznajecie, jak działa RAG, czym są bazy danych wektorowych, co sprawia, że wyszukiwanie jest skuteczne, oraz dlaczego odpowiedni kontekst może być ważniejszy niż większy model.

    Co ważniejsze, rezultatem jest coś, czego rzeczywiście będziecie używać. Dwanaście miesięcy zgromadzonej wiedzy przestaje być rozproszona w folderach i staje się czymś, o co można po prostu zapytać. Wszystko to działa na używanym laptopie stojącym w kącie pokoju, co nie jest złe jak na maszynę przeznaczoną do odstawienia.

    RAG faktycznie działa. Zrozumienie to już inna historia.

    Dalsza lektura

    Dokumentacja dotycząca AnythingLLM, Ollamy, LanceDB i Obsidian zawiera szczegółowe informacje. Oryginalny artykuł na temat RAG, „Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks”, wyjaśnia ideę leżącą u podstaw tego rozwiązania. Wszystko to działa na przekształconym sprzęcie, bez użycia chmury, bez subskrypcji i bez wychodzenia danych poza sieć.