Rust – chatgpz.de – KI-Tools & Praxiswissen http://chatgpz.de Unabhängige Tests, Anleitungen und Hintergründe zu KI-Tools. Thu, 26 Dec 2024 11:14:59 +0000 de-DE hourly 1 https://wordpress.org/?v=6.4.2 234900186 LLM-Coaching von Grund auf in Rust | von Stefano Bosisio | Dez. 2024 http://chatgpz.de/machine-learning/llm-coaching-von-grund-auf-in-rust-von-stefano-bosisio-dez-2024/ http://chatgpz.de/machine-learning/llm-coaching-von-grund-auf-in-rust-von-stefano-bosisio-dez-2024/#respond Thu, 26 Dec 2024 11:14:59 +0000 http://chatgpz.de/machine-learning/llm-training-von-grund-auf-in-rust-von-stefano-bosisio-dez-2024/ [ad_1]

In diesem Begleitartikel zeige ich meine Implementierung für das Coaching eines GPT-ähnlichen Modells von Grund auf in Rust. Keine GPUs, nur CPUs, mit einer 30-mal besseren Leistung als der native C-Code.

Bild von GoogleDeepMind An Unsplash

In meinem letzten Artikelhabe ich das Downside der Matrixmultiplikation vorgestellt, wie der Aufmerksamkeitsalgorithmus die Matrixmultiplikation verwendet, um einen Mittelungsprozess durchzuführen, und wie man – oder zumindest für mich – eine Matrixmultiplikationsfunktion in Rust effizient implementiert Blas.

In diesem neuen Artikel möchte ich meinen ersten Baustein zur Umsetzung zeigen llm.c in Rust, nämlich das Trainieren eines GPT-ähnlichen Modells von Grund auf mit Rust. Auf diese Weise habe ich immer mehr über das Rust-Ökosystem gelernt und verstanden, wie vergleichbar es mit C ist. Insbesondere Ich möchte, dass mein Code ein GPT-ähnliches Modell trainieren kann, ausgehend von GPT-Gewichten und nur mit CPUs– additionally keine GPUs oder TPUs. Mein Ziel ist es zu verstehen, wie weit wir diese Modelle auf einfachen Laptops vorantreiben können und wie weit das Rust-Ökosystem dafür genutzt werden kann. Letztendlich kann dieser Code auch zur Feinabstimmung von GPT-Modellen mit einem bestimmten Eingabekorpus nützlich sein.

Alle relevanten Codeteile sind zu finden Hier.

[ad_2]

]]>
http://chatgpz.de/machine-learning/llm-coaching-von-grund-auf-in-rust-von-stefano-bosisio-dez-2024/feed/ 0 6122
Neun Regeln für die Ausführung von Rust auf WASM WASI | von Carl M. Kadie | September 2024 http://chatgpz.de/machine-learning/neun-regeln-fuer-die-ausfuehrung-von-rust-auf-wasm-wasi-von-carl-m-kadie-september-2024/ http://chatgpz.de/machine-learning/neun-regeln-fuer-die-ausfuehrung-von-rust-auf-wasm-wasi-von-carl-m-kadie-september-2024/#respond Sat, 28 Sep 2024 08:05:06 +0000 https://chatgpz.de/machine-learning/neun-regeln-fuer-die-ausfuehrung-von-rust-auf-wasm-wasi-von-carl-m-kadie-september-2024/ [ad_1]

Basierend auf meiner Erfahrung mit range-set-blazeein Datenstrukturprojekt, hier sind die von mir empfohlenen Entscheidungen, einzeln beschrieben. Um Wischiwaschi zu vermeiden, formuliere ich sie als Regeln.

Im Jahr 2019 warfare Docker-Mitschöpfer Solomon Hykes getwittert:

Wenn es WASM+WASI im Jahr 2008 gegeben hätte, hätten wir Docker nicht erstellen müssen. So wichtig ist es. Webassembly auf dem Server ist die Zukunft der Datenverarbeitung. Eine standardisierte Systemschnittstelle warfare das fehlende Bindeglied. Hoffen wir, dass WASI dieser Aufgabe gewachsen ist.

Wenn Sie heute Technologienachrichten verfolgen, werden Sie optimistische Schlagzeilen wie diese sehen:

Eine Collage aus Schlagzeilen zum Thema WebAssembly System Interface (WASI). Die erste Schlagzeile von Forbes lautet: „WebAssembly ist endlich nutzbar, fast.“ Eine Miniaturansicht eines YouTube-Videos zeigt „WASI wird .NET für immer verändern!“ Führen Sie WebAssembly außerhalb des Browsers aus!“ mit James Montemagno. Die untere Überschrift lautet „Unerwartet nützlich: Ein realer Anwendungsfall für WebAssembly System Interface (WASI)“.

Wenn WASM WASI wirklich bereit und nützlich wäre, würde es bereits jeder nutzen. Die Tatsache, dass wir diese Schlagzeilen immer wieder sehen, deutet darauf hin, dass es noch nicht fertig ist. Mit anderen Worten: Sie müssten nicht ständig darauf bestehen, dass WASM WASI bereit ist, wenn es wirklich so wäre.

Ab WASI Preview 1 ist der Stand der Dinge wie folgt: Sie können auf einige Dateioperationen und Umgebungsvariablen zugreifen und haben Zugriff auf die Zeit- und Zufallszahlengenerierung. Es gibt jedoch keine Unterstützung für die Vernetzung.

WASM WASI könnte für bestimmte Webdienste im AWS-Lambda-Stil nützlich sein, aber selbst das ist ungewiss. Denn würden Sie es nicht vorziehen, Ihren Rust-Code nativ zu kompilieren und im Vergleich zu WASM WASI doppelt so schnell und zur Hälfte der Kosten auszuführen?

Vielleicht ist WASM WASI für Plug-Ins und Erweiterungen nützlich. In der Genomik habe ich eine Rust-Erweiterung für Python, die ich für 25 verschiedene Kombinationen kompiliere (5 Versionen von Python auf 5 Betriebssystemzielen). Trotzdem decke ich nicht alle möglichen Betriebssysteme und Chipfamilien ab. Könnte ich diese Betriebssystemziele durch WASM WASI ersetzen? Nein, es wäre zu langsam. Könnte ich WASM WASI als sechstes „Catch-All“-Ziel hinzufügen? Vielleicht, aber wenn ich wirklich Portabilität benötige, muss ich Python bereits unterstützen und sollte einfach Python verwenden.

Wofür ist WASM WASI additionally intestine? Derzeit liegt sein Hauptwert darin, dass er einen Schritt hin zur Ausführung von Code im Browser oder auf eingebetteten Systemen darstellt.

In Regel 1 habe ich nebenbei „Betriebssystemziele“ erwähnt. Schauen wir uns die Rust-Ziele genauer an – wichtige Informationen nicht nur für WASM WASI, sondern auch für die allgemeine Rust-Entwicklung.

Auf meinem Home windows-Rechner kann ich ein Rust-Projekt kompilieren, um es unter Linux oder macOS auszuführen. Ebenso kann ich von einem Linux-Rechner aus ein Rust-Projekt für Home windows oder macOS kompilieren. Hier sind die Befehle, die ich verwende, um das Linux-Ziel zu einem Home windows-Pc hinzuzufügen und zu überprüfen:

rustup goal add x86_64-unknown-linux-gnu
cargo test --target x86_64-unknown-linux-gnu

Nebenbei: Während cargo test Überprüft, ob der Code kompiliert wird. Für die Erstellung einer voll funktionsfähigen ausführbaren Datei sind zusätzliche Instruments erforderlich. Für die Crosskompilierung von Home windows zu Linux (GNU) müssen Sie außerdem den Linux GNU C/C++-Compiler und die entsprechende Toolchain installieren. Das kann schwierig sein. Glücklicherweise ist die erforderliche Toolchain für die WASM-Ziele, die uns wichtig sind, einfach zu installieren.

Um alle von Rust unterstützten Ziele anzuzeigen, verwenden Sie den folgenden Befehl:

rustc --print target-list

Es werden über 200 Ziele aufgelistet, darunter x86_64-unknown-linux-gnu, wasm32-wasip1Und wasm32-unknown-unknown.

Zielnamen bestehen aus bis zu vier Teilen: CPU-Familie, Hersteller, Betriebssystem und Umgebung (z. B. GNU vs. LVMM):

Ein Diagramm, das die Komponenten des Ziel-Triples x86_64-unknown-linux-gnu erläutert. Es gliedert sich wie folgt: CPU-Architektur (64-Bit x86), Hersteller (nicht spezifiziert, daher „unbekannt“), Betriebssystem (Linux) und Umgebung (GNU C-Bibliothek).
Teile des Zielnamens – Abbildung vom Autor

Nachdem wir nun etwas über Ziele verstanden haben, können wir mit der Set up des Ziels fortfahren, das wir für WASM WASI benötigen.

Um unseren Rust-Code auf WASM außerhalb eines Browsers auszuführen, müssen wir ihn gezielt ausführen wasm32-wasip1 (32-Bit-WebAssembly mit WASI-Vorschau 1). Wir werden auch WASMTIME installieren, eine Laufzeit, die es uns ermöglicht, WebAssembly-Module mithilfe von WASI außerhalb des Browsers auszuführen.

rustup goal add wasm32-wasip1
cargo set up wasmtime-cli

Um unser Setup zu testen, erstellen wir eine neue „Hey, WebAssembly!“ Rust-Projekt mit cargo new. Dadurch wird ein neues Rust-Paket initialisiert:

cargo new hello_wasi
cd hello_wasi

Bearbeiten src/principal.rs zu lesen:

fn principal() {
#(cfg(not(target_arch = "wasm32")))
println!("Hey, world!");
#(cfg(target_arch = "wasm32"))
println!("Hey, WebAssembly!");
}

Nebenbei: Wir werden uns das genauer ansehen #(cfg(...)) Attribut, das die bedingte Kompilierung ermöglicht, in Regel 4.

Führen Sie nun das Projekt mit aus cargo runund Sie sollten sehen Hey, world! auf der Konsole gedruckt.

Als nächstes erstellen Sie eine .cargo/config.toml Datei, die angibt, wie Rust das Projekt ausführen und testen soll, wenn es auf WASM WASI abzielt.

(goal.wasm32-wasip1)
runner = "wasmtime run --dir ."

Nebenbei: Dies .cargo/config.toml Die Datei unterscheidet sich von der Hauptdatei Cargo.toml Datei, die die Abhängigkeiten und Metadaten Ihres Projekts definiert.

Wenn Sie nun sagen:

cargo run --target wasm32-wasip1

Das solltest du sehen Hey, WebAssembly!. Glückwunsch! Sie haben gerade erfolgreich Rust-Code in der Container-ähnlichen WASM WASI-Umgebung ausgeführt.

Lassen Sie uns nun der Sache nachgehen #(cfg(...))– ein unverzichtbares Werkzeug zum bedingten Kompilieren von Code in Rust. In Regel 3 sahen wir:

fn principal() {
#(cfg(not(target_arch = "wasm32")))
println!("Hey, world!");
#(cfg(target_arch = "wasm32"))
println!("Hey, WebAssembly!");
}

Der #(cfg(...)) Zeilen weisen den Rust-Compiler an, bestimmte Codeelemente basierend auf bestimmten Bedingungen einzuschließen oder auszuschließen. Ein „Codeelement“ bezieht sich auf eine Codeeinheit wie eine Funktion, Anweisung oder einen Ausdruck.

Mit #(cfg(…)) Zeilen können Sie Ihren Code bedingt kompilieren. Mit anderen Worten: Sie können unterschiedliche Versionen Ihres Codes für unterschiedliche Situationen erstellen. Zum Beispiel beim Kompilieren für die wasm32 Ziel, der Compiler ignoriert das #(cfg(not(target_arch = "wasm32"))) Block und umfasst nur Folgendes:

fn principal() {
println!("Hey, WebAssembly!");
}

Sie geben Bedingungen über Ausdrücke an, z. B. target_arch = "wasm32". Zu den unterstützten Schlüsseln gehören: target_os Und target_arch. Siehe die Rust-Referenz für die vollständige Liste der unterstützten Schlüssel. Sie können Ausdrücke auch mit Cargo-Funktionen erstellen, worüber wir in Regel 6 erfahren.

Sie können Ausdrücke mit den logischen Operatoren kombinieren not, anyUnd all. Die bedingte Kompilierung von Rust verwendet keine traditionelle Kompilierung if...then...else Aussagen. Stattdessen müssen Sie verwenden #(cfg(...)) und seine Negation, um verschiedene Fälle zu behandeln:

#(cfg(not(target_arch = "wasm32")))
...
#(cfg(target_arch = "wasm32"))
...

Um eine ganze Datei bedingt zu kompilieren, platzieren Sie #!(cfg(...)) oben in der Datei. (Beachten Sie das „!“). Dies ist nützlich, wenn eine Datei nur für ein bestimmtes Ziel oder eine bestimmte Konfiguration related ist.

Sie können auch verwenden cfg Ausdrücke in Cargo.toml Abhängigkeiten bedingt einzubeziehen. Dadurch können Sie Abhängigkeiten an verschiedene Ziele anpassen. Hier heißt es zum Beispiel: „Verlassen Sie sich auf Criterion mit Rayon, wenn Sie nicht zielen.“ wasm32“.

(goal.'cfg(not(target_arch = "wasm32"))'.dev-dependencies)
criterion = { model = "0.5.1", options = ("rayon") }

Nebenbei: Weitere Informationen zur Verwendung cfg Ausdrücke in Cargo.tomlsiehe meinen Artikel: Neun Rust Cargo.toml Wats und Wat Nots: Beherrschen Sie die Formatierungsregeln von Cargo.toml und vermeiden Sie Frustration | Auf dem Weg zur Datenwissenschaft (medium.com).

Es ist Zeit zu versuchen zu rennen dein Projekt zu WASM WASI. Erstellen Sie wie in Regel 3 beschrieben eine .cargo/config.toml Datei für Ihr Projekt. Es erklärt Cargo, wie es Ihr Projekt auf WASM WASI ausführen und testen soll.

(goal.wasm32-wasip1)
runner = "wasmtime run --dir ."

Nächste, Ihr Projekt sollte – wie jeder gute Code – bereits Checks enthalten. Mein range-set-blaze Das Projekt umfasst beispielsweise diesen Take a look at:

#(take a look at)
fn insert_255u8() {
let range_set_blaze = RangeSetBlaze::<u8>::from_iter((255));
assert!(range_set_blaze.to_string() == "255..=255");
}

Versuchen wir nun, die Checks Ihres Projekts auf WASM WASI auszuführen. Verwenden Sie den folgenden Befehl:

cargo take a look at --target wasm32-wasip1

Wenn das funktioniert, sind Sie vielleicht fertig – aber es wird wahrscheinlich nicht funktionieren. Wenn ich das anprobiere range-set-blazeerhalte ich diese Fehlermeldung, die sich über die Verwendung von Rayon auf WASM beschwert.

 error: Rayon can't be used when focusing on wasi32. Strive disabling default options.
--> C:Userscarlk.cargoregistrysrcindex.crates.io-6f17d22bba15001fcriterion-0.5.1srclib.rs:31:1
|
31 | compile_error!("Rayon can't be used when focusing on wasi32. Strive disabling default options.");

Um diesen Fehler zu beheben, müssen wir zunächst die Cargo-Funktionen verstehen.

Um Probleme wie den Rayon-Fehler in Regel 5 zu beheben, ist es wichtig zu verstehen, wie die Cargo-Funktionen funktionieren.

In Cargo.tomlein optionales (options) Im Abschnitt können Sie verschiedene Konfigurationen oder Versionen Ihres Projekts definieren, je nachdem, welche Funktionen aktiviert oder deaktiviert sind. Hier ist zum Beispiel ein vereinfachter Teil davon Cargo.toml Datei aus der Kriterien-Benchmarking-Projekt:

(options)
default = ("rayon", "plotters", "cargo_bench_support")
rayon = ("dep:rayon")
plotters = ("dep:plotters")
html_reports = ()
cargo_bench_support = ()

(dependencies)
#...
# Elective dependencies
rayon = { model = "1.3", elective = true }
plotters = { model = "^0.3.1", elective = true, default-features = false, options = (
"svg_backend",
"area_series",
"line_series",
) }

Dies definiert vier Cargo-Funktionen: rayon, plotters, html_reportsUnd cargo_bench_support. Da jede Funktion ein- oder ausgeschlossen werden kann, ergeben diese vier Funktionen 16 mögliche Konfigurationen des Projekts. Beachten Sie auch die spezielle Commonplace-Cargo-Funktion.

Eine Cargo-Funktion kann andere Cargo-Funktionen umfassen. Im Beispiel das Besondere default Die Cargo-Funktion umfasst drei weitere Cargo-Funktionen: rayon, plottersUnd cargo_bench_support.

Eine Cargo-Funktion kann eine Abhängigkeit enthalten. Der rayon Die obige Frachtfunktion umfasst die rayon Kiste als abhängiges Paket.

Darüber hinaus können abhängige Pakete über eigene Cargo-Funktionen verfügen. Zum Beispiel die plotters Die obige Frachtfunktion umfasst die plotters abhängiges Paket mit den folgenden aktivierten Cargo-Funktionen: svg_backend, area_seriesUnd line_series.

Sie können angeben, welche Cargo-Funktionen beim Ausführen aktiviert oder deaktiviert werden sollen cargo test, cargo construct, cargo runoder cargo take a look at. Wenn Sie beispielsweise am Criterion-Projekt arbeiten und nur Folgendes überprüfen möchten html_reports Funktion ohne Standardeinstellungen können Sie Folgendes ausführen:

cargo test --no-default-features --features html_reports

Dieser Befehl weist Cargo an, standardmäßig keine Cargo-Funktionen einzuschließen, sondern diese gezielt zu aktivieren html_reports Cargo-Funktion.

In Ihrem Rust-Code können Sie Codeelemente basierend auf aktivierten Cargo-Funktionen einschließen/ausschließen. Die Syntax verwendet #cfg(…)gemäß Regel 4:

#(cfg(characteristic = "html_reports"))
SOME_CODE_ITEM

Mit diesem Verständnis der Cargo-Funktionen können wir nun versuchen, das Downside zu beheben Rayon Fehler, der beim Ausführen von Checks auf WASM WASI aufgetreten ist.

Als wir versuchten zu laufen cargo take a look at --target wasm32-wasip1Teil der Fehlermeldung lautete: Criterion ... Rayon can't be used when focusing on wasi32. Strive disabling default options. Dies legt nahe, dass wir Criterion deaktivieren sollten rayon Frachtfunktion beim Anvisieren von WASM WASI.

Dazu müssen wir zwei Änderungen in unserem vornehmen Cargo.toml. Zuerst müssen wir das deaktivieren rayon Funktion von Criterion in der (dev-dependencies) Abschnitt. Additionally diese Startkonfiguration:

(dev-dependencies)
criterion = { model = "0.5.1", options = ("html_reports") }

wird dazu, dass wir die Standardfunktionen für Criterion explizit deaktivieren und dann alle Cargo-Funktionen außer aktivieren rayon.

(dev-dependencies)
criterion = { model = "0.5.1", options = (
"html_reports",
"plotters",
"cargo_bench_support"),
default-features = false }

Als nächstes, um sicherzustellen rayon weiterhin für Nicht-WASM-Ziele verwendet wird, fügen wir es mit einer bedingten Abhängigkeit wieder hinzu Cargo.toml wie folgt:

(goal.'cfg(not(target_arch = "wasm32"))'.dev-dependencies)
criterion = { model = "0.5.1", options = ("rayon") }

Wenn Sie auf WASM WASI abzielen, müssen Sie im Allgemeinen möglicherweise Ihre Abhängigkeiten und ihre Cargo-Funktionen ändern, um die Kompatibilität sicherzustellen. Manchmal ist dieser Prozess unkompliziert, aber manchmal kann er eine Herausforderung sein – oder sogar unmöglich, wie wir in Regel 8 besprechen werden.

Nebenbei: Im nächsten Artikel dieser Reihe – über WASM im Browser – werden wir tiefer auf Strategien zur Behebung von Abhängigkeiten eingehen.

Nachdem wir die Checks erneut ausgeführt haben, überwinden wir den vorherigen Fehler, nur um dann auf einen neuen zu stoßen, was ein Fortschritt ist!

#(take a look at)
fn test_demo_i32_len() {
assert_eq!(demo_i32_len(i32::MIN..=i32::MAX), u32::MAX as usize + 1);
^^^^^^^^^^^^^^^^^^^^^ try to compute
`usize::MAX + 1_usize`, which might overflow
}

Der Compiler beschwert sich darüber u32::MAX as usize + 1 Überläufe. Unter 64-Bit-Home windows läuft der Ausdruck nicht über, weil usize ist das gleiche wie u64 und halten kann u32::MAX as usize + 1. WASM ist jedoch eine 32-Bit-Umgebung usize ist das gleiche wie u32 und der Ausdruck ist eins zu groß.

Die Lösung hier ist ersetzen usize mit u64um sicherzustellen, dass der Ausdruck nicht überläuft. Im Allgemeinen erkennt der Compiler diese Probleme nicht immer, daher ist es wichtig, dass Sie Ihre Verwendung überprüfen usize Und isize. Wenn Sie sich auf die Größe oder den Index einer Rust-Datenstruktur beziehen, usize ist richtig. Wenn Sie es jedoch mit Werten zu tun haben, die die 32-Bit-Grenzen überschreiten, sollten Sie verwenden u64 oder i64.

Nebenbei: In einer 32-Bit-Umgebung ein Rust-Array, Vec, BTreeSetusw. können nur bis zu 2³²−1=4.294.967.295 Elemente enthalten.

Wir haben additionally das Abhängigkeitsproblem behoben und a usize Überlauf. Aber können wir alles reparieren? Leider lautet die Antwort nein.

WASM WASI Preview 1 (die aktuelle Model) unterstützt den Dateizugriff (innerhalb eines angegebenen Verzeichnisses), das Lesen von Umgebungsvariablen und das Arbeiten mit Zeit und Zufallszahlen. Allerdings sind seine Fähigkeiten im Vergleich zu dem, was Sie von einem vollständigen Betriebssystem erwarten würden, begrenzt.

Wenn Ihr Projekt Zugriff auf Netzwerke, asynchrone Aufgaben mit Tokio oder Multithreading mit Rayon erfordert, werden diese Funktionen in Vorschau 1 leider nicht unterstützt.

Glücklicherweise wird erwartet, dass WASM WASI Preview 2 diese Einschränkungen überwindet und mehr Funktionen bietet, einschließlich einer besseren Unterstützung für Netzwerk- und möglicherweise asynchrone Aufgaben.

So bestehen Ihre Checks auf WASM WASI und Ihr Projekt läuft erfolgreich. Bist du fertig? Nicht ganz. Denn wie ich gerne sage:

Wenn es nicht in CI ist, existiert es nicht.

Steady Integration (CI) ist ein System, das Ihre Checks jedes Mal automatisch ausführen kann, wenn Sie Ihren Code aktualisieren, um sicherzustellen, dass Ihr Code weiterhin wie erwartet funktioniert. Durch das Hinzufügen von WASM WASI zu Ihrem CI können Sie garantieren, dass zukünftige Änderungen die Kompatibilität Ihres Projekts mit dem WASM WASI-Ziel nicht beeinträchtigen.

In meinem Fall wird mein Projekt auf GitHub gehostet und ich verwende GitHub Actions als mein CI-System. Hier ist die Konfiguration, die ich hinzugefügt habe .github/workflows/ci.yml um mein Projekt auf WASM WASI zu testen:

test_wasip1:
identify: Take a look at WASI P1
runs-on: ubuntu-latest
steps:
- identify: Checkout
makes use of: actions/checkout@v4
- identify: Arrange Rust
makes use of: dtolnay/rust-toolchain@grasp
with:
toolchain: secure
targets: wasm32-wasip1
- identify: Set up Wasmtime
run: |
curl https://wasmtime.dev/set up.sh -sSf | bash
echo "${HOME}/.wasmtime/bin" >> $GITHUB_PATH
- identify: Run WASI checks
run: cargo take a look at --verbose --target wasm32-wasip1

Durch die Integration von WASM WASI in CI kann ich sicher neuen Code zu meinem Projekt hinzufügen. CI testet automatisch, ob mein gesamter Code auch in Zukunft WASM WASI unterstützt.

[ad_2]

]]>
http://chatgpz.de/machine-learning/neun-regeln-fuer-die-ausfuehrung-von-rust-auf-wasm-wasi-von-carl-m-kadie-september-2024/feed/ 0 4160
Vector Streaming: Speichereffiziente Indizierung mit Rust http://chatgpz.de/data-analytics/vector-streaming-speichereffiziente-indizierung-mit-rust/ http://chatgpz.de/data-analytics/vector-streaming-speichereffiziente-indizierung-mit-rust/#respond Tue, 17 Sep 2024 10:44:19 +0000 https://chatgpz.de/data-analytics/vector-streaming-speichereffiziente-indizierung-mit-rust/ [ad_1]

Einführung

Vektor-Streaming wird in EmbedAnything eingeführt, eine Funktion, die das Einbetten von Dokumenten in großem Maßstab optimieren soll. Das Aktivieren von asynchronem Chunking und Einbetten mithilfe der Parallelität von Rust reduziert den Speicherverbrauch und beschleunigt den Prozess. Heute zeige ich, wie man es in die Weaviate-Vektordatenbank integriert, um Bilder nahtlos einzubetten und zu suchen.

In meinem vorherigen Artikel Optimieren Sie Ihre Embeddings-Pipeline mit EmbedAnythingIch habe die Idee hinter EmbedAnything erläutert und wie es das Erstellen von Einbettungen aus mehreren Modalitäten vereinfacht. In diesem Artikel möchte ich eine neue Funktion von EmbedAnything namens Vektor-Streaming vorstellen und zeigen, wie sie mit der Weaviate-Vektordatenbank funktioniert.

Vector Streaming: Speichereffiziente Indizierung mit Rus

Überblick

  • Vektor-Streaming in EmbedAnything optimiert das Einbetten großer Dokumente durch asynchrones Chunking mit der Parallelität von Rust.
  • Es löst Speicher- und Effizienzprobleme bei herkömmlichen Einbettungsmethoden durch die parallele Verarbeitung von Blöcken.
  • Die Integration mit Weaviate ermöglicht die nahtlose Einbettung und Suche in einer Vektordatenbank.
  • Die Implementierung von Vektor-Streaming umfasst das Erstellen eines Datenbankadapters, das Initiieren eines Einbettungsmodells und das Einbetten von Daten.
  • Dieser Ansatz bietet eine effizientere, skalierbarere und flexiblere Lösung für die Einbettung umfangreicher Dokumente.

Was ist das Downside?

Untersuchen wir zunächst das aktuelle Downside bei der Erstellung von Einbettungen, insbesondere in umfangreichen Dokumenten. Die aktuelle Einbettungsframeworks arbeiten in einem zweistufigen Prozess: Chunking und Embedding. Zuerst wird der Textual content aus allen Dateien extrahiert und Chunks/Knoten werden erstellt. Dann werden diese Chunks einem Embedding-Modell mit einer bestimmten Batch-Größe zugeführt, um die Embeddings zu verarbeiten. Während dies geschieht, verbleiben die Chunks und die Embeddings im Systemspeicher.

Dies ist kein Downside, wenn die Dateien und Einbettungsdimensionen klein sind. Es wird jedoch zu einem Downside, wenn viele Dateien vorhanden sind und Sie mit großen Modellen und, noch schlimmer, mit Multi-Vektor-Einbettungen arbeiten. Um damit arbeiten zu können, ist additionally viel RAM erforderlich, um die Einbettungen zu verarbeiten. Wenn dies synchron erfolgt, geht außerdem viel Zeit verloren, während die Chunks erstellt werden, da das Chunking kein rechenintensiver Vorgang ist. Während die Chunks erstellt werden, wäre es effizient, sie an das Einbettungsmodell zu übergeben.

Unsere Lösung des Issues

Die Lösung besteht darin, eine asynchrone Chunking- und Embedding-Aufgabe zu erstellen. Wir können Threads effektiv erstellen, um diese Aufgabe mithilfe der Parallelitätsmuster und Threadsicherheit von Rust zu bewältigen. Dies geschieht mithilfe von Rusts MPSC-Modul (Multi-producer Single Shopper), das Nachrichten zwischen Threads überträgt. Dadurch wird ein Datenstrom von Chunks erstellt, der mit einem Puffer an den Einbettungsthread übergeben wird. Sobald der Puffer vollständig ist, bettet er die Chunks ein und sendet die Einbettungen zurück an den Hauptthread, der sie dann an die Vektordatenbank sendet. Dadurch wird sichergestellt, dass keine Zeit für einen einzelnen Vorgang verschwendet wird und keine Engpässe auftreten. Darüber hinaus speichert das System nur die Chunks und Einbettungen im Puffer und löscht sie aus dem Speicher, sobald sie in die Vektordatenbank verschoben werden.

Vektor-Streaming

Beispiel-Anwendungsfall mit EmbedAnything

Sehen wir uns diese Funktion nun in Aktion an:

Mit EmbedAnything können Sie die Vektoren aus einem Verzeichnis mit Dateien in das Vektordatenbank ist ein einfacher dreistufiger Prozess.

  1. Erstellen Sie einen Adapter für Ihre Vektordatenbank: Dies ist ein Wrapper um die Funktionen der Datenbank, der es Ihnen ermöglicht, einen Index zu erstellen, Metadaten vom EmbedAnything-Format in das von der Datenbank benötigte Format zu konvertieren und die Funktion zum Einfügen der Einbettungen in den Index bereitzustellen. Adapter für die wichtigsten Datenbanken wurden bereits erstellt und sind vorhanden. Hier.
  1. Initiieren Sie ein Einbettungsmodell Ihrer Wahl: Sie können zwischen verschiedenen lokalen Modellen oder sogar Cloud-Modellen wählen. Die Konfiguration kann auch durch Festlegen der Blockgröße und der Puffergröße bestimmt werden, je nachdem, wie viele Einbettungen gleichzeitig gestreamt werden müssen. Idealerweise sollte dies so hoch wie möglich sein, aber der System-RAM begrenzt dies.
  1. Rufen Sie die Einbettungsfunktion von EmbedAnything auf: Übergeben Sie einfach den einzubettenden Verzeichnispfad, das Einbettungsmodell, den Adapter und die Konfiguration.

In diesem Beispiel betten wir ein Verzeichnis mit Bildern ein und senden es an die Vektordatenbanken.

Schritt 1: Erstellen des Adapters

In EmbedAnything werden die Adapter außerhalb erstellt, um die Bibliothek nicht zu schwer zu machen, und Sie können auswählen, mit welcher Datenbank Sie arbeiten möchten. Hier ist ein einfacher Adapter für Weaviate:

from embed_anything import EmbedData

from embed_anything.vectordb import Adapter

class WeaviateAdapter(Adapter):

    def __init__(self, api_key, url):

        tremendous().__init__(api_key)

        self.shopper = weaviate.connect_to_weaviate_cloud(

            cluster_url=url, auth_credentials=wvc.init.Auth.api_key(api_key)

        )

        if self.shopper.is_ready():

            print("Weaviate is prepared")

    def create_index(self, index_name: str):

        self.index_name = index_name

        self.assortment = self.shopper.collections.create(

            index_name, vectorizer_config=wvc.config.Configure.Vectorizer.none()

        )

        return self.assortment

    def convert(self, embeddings: Record(EmbedData)):

        information = ()

        for embedding in embeddings:

            property = embedding.metadata

            property("textual content") = embedding.textual content

            information.append(

                wvc.information.DataObject(properties=property, vector=embedding.embedding)

            )

        return information

    def upsert(self, embeddings):

        information = self.convert(embeddings)

        self.shopper.collections.get(self.index_name).information.insert_many(information)

    def delete_index(self, index_name: str):

        self.shopper.collections.delete(index_name)

### Begin the shopper and index

URL = "your-weaviate-url"

API_KEY = "your-weaviate-api-key"

weaviate_adapter = WeaviateAdapter(API_KEY, URL)

index_name = "Test_index"

if index_name in weaviate_adapter.shopper.collections.list_all():

    weaviate_adapter.delete_index(index_name)

weaviate_adapter.create_index("Test_index")

Schritt 2: Erstellen des Einbettungsmodells

Da wir hier Bilder einbetten, können wir das Clip-Modell verwenden

import embed_anything import WhichModel

mannequin = embed_anything.EmbeddingModel.from_pretrained_cloud(

        embed_anything.WhichModel.Clip,     

        model_id="openai/clip-vit-base-patch16")

Schritt 3: Verzeichnis einbetten

information = embed_anything.embed_image_directory(

    "image_directory",

    embeder=mannequin,

    adapter=weaviate_adapter,

    config=embed_anything.ImageEmbedConfig(buffer_size=100),

)

Schritt 4: Abfrage der Vektordatenbank

query_vector = embed_anything.embed_query(("picture of a cat"), embeder=mannequin)(0).embedding

Schritt 5: Abfrage der Vektordatenbank

response = weaviate_adapter.assortment.question.near_vector(

    near_vector=query_vector,

    restrict=2,

    return_metadata=wvc.question.MetadataQuery(certainty=True),

)

Test the response;

Ausgabe

Mithilfe des Clip-Modells haben wir das gesamte Verzeichnis mit Bildern von Katzen, Hunden und Affen vektorisiert. Mit der einfachen Abfrage „Bilder von Katzen“ konnten wir alle Dateien nach Bildern von Katzen durchsuchen.

Ausgabe

Den Code finden Sie im Notizbuch hier auf Zusammenarbeit.

Abschluss

Ich denke, dass Vektor-Streaming eine der Funktionen ist, die viele Ingenieure dazu befähigen wird, sich für eine optimiertere Lösung ohne technische Schulden zu entscheiden. Anstatt sperrige Frameworks in der Cloud zu verwenden, können Sie eine leichte Streaming-Choice nutzen.

Schauen Sie sich das GitHub-Repository hier an: EmbedAnything-Repository.

Häufig gestellte Fragen

Frage 1. Was ist Vektor-Streaming in EmbedAnything?

Antwort: Vektor-Streaming ist eine Funktion, die das Einbetten von Dokumenten in großem Maßstab optimiert, indem sie die Parallelität von Rust für asynchrones Chunking und Einbetten nutzt, wodurch der Speicherverbrauch reduziert und der Prozess beschleunigt wird.

Frage 2. Welches Downside löst Vektor-Streaming?

Antwort: Es behebt den hohen Speicherverbrauch und die Ineffizienz herkömmlicher Einbettungsmethoden, indem es Blöcke asynchron verarbeitet, Engpässe reduziert und die Ressourcennutzung optimiert.

Frage 3. Wie funktioniert Vektor-Streaming mit Weaviate?

Antwort: Es verwendet einen Adapter, um EmbedAnything mit der Weaviate-Vektordatenbank zu verbinden, was ein nahtloses Einbetten und Abfragen von Daten ermöglicht.

Frage 4. Welche Schritte sind zur Verwendung von Vektor-Streaming erforderlich?

Antwort: Hier sind die Schritte:
1. Erstellen Sie einen Datenbankadapter.
2. Initiieren Sie ein Einbettungsmodell.
3. Betten Sie das Verzeichnis ein.
4. Abfrage der Vektordatenbank.

Frage 5. Warum sollte man Vektor-Streaming herkömmlichen Methoden vorziehen?

Antwort: Es bietet im Vergleich zu herkömmlichen Einbettungsmethoden eine bessere Effizienz, einen geringeren Speicherverbrauch, Skalierbarkeit und Flexibilität.

KI-Entwickler @ Serpentine AI || TU Eindhoven Entwicklung von Starlight – semantische Suchmaschine für Home windows in Rust 🦀. Entwicklung von EmbedAnything – eine minimale Einbettungspipeline, die auf Candle basiert. Ich liebe es, beim Coaching großer KI-Modelle zuzusehen.

[ad_2]

]]>
http://chatgpz.de/data-analytics/vector-streaming-speichereffiziente-indizierung-mit-rust/feed/ 0 3940