flutter_gemma_rag_qdrant 1.3.0 copy "flutter_gemma_rag_qdrant: ^1.3.0" to clipboard
flutter_gemma_rag_qdrant: ^1.3.0 copied to clipboard

qdrant-edge on-device RAG vector store for flutter_gemma, via the official qdrant_edge UniFFI SDK. Opt-in VectorStoreRepository with payload filtering. Native platforms only (no web).

flutter_gemma_rag_qdrant #

qdrant-edge on-device RAG vector store for flutter_gemma. Opt-in package implementing VectorStoreRepository on top of the official qdrant_edge UniFFI Dart SDK (a binding over the qdrant-edge Rust crate). qdrant's HNSW index makes it the fastest native RAG store — roughly 5–11× faster search than the in-SQLite sqlite-vec/vec0 store at 1k–10k docs, and further ahead as the corpus grows (see benchmark). (The earlier "~75×" figure was against the now-deleted Dart brute-force store.) For web, or when exact KNN with identical results across platforms matters more than peak speed, use flutter_gemma_rag_sqlite.

Native only (Android, iOS, macOS, Linux, Windows). For web, use flutter_gemma_rag_sqlite (WebSqliteVectorStore).

Usage #

import 'package:flutter_gemma/flutter_gemma.dart';
import 'package:flutter_gemma_rag_qdrant/flutter_gemma_rag_qdrant.dart';

await FlutterGemma.initialize(
  vectorStore: QdrantVectorStore(),
);

Then use the unchanged RAG API:

await FlutterGemmaPlugin.instance.initializeVectorStore('rag_store'); // a directory
await FlutterGemmaPlugin.instance.addDocument(/* ... */);
final hits = await FlutterGemmaPlugin.instance.searchSimilar(query: query, topK: 5);

QdrantVectorStore also honors the payload-aware Filter DSL on searchSimilar(..., filter: Filter(must: [FieldEquals(key: 'lang', value: 'en')], mustNot: [...])).

Field names here are almost unrestricted — payload keys are free-form UTF-8 — with one exception: a name containing . is rejected, because qdrant reads it as a nested payload path, so doc.type would mean "type inside doc" here and a flat column on sqlite. Note this store accepts names SqliteVectorStore refuses; if a schema must work on both, keep it inside sqlite's narrower set.

The storage path passed to initializeVectorStore is treated as a shard directory (qdrant creates files under it), not a single .db file. Use a distinct path from any sqlite store so they don't collide on disk.

Behavior notes #

  • Cross-platform web is not supportedQdrantVectorStore is native-only.
  • enableHnsw is accepted but a no-op: qdrant decides indexing internally (brute-forces below ~20k points, which is already faster than the Dart HNSW for typical RAG corpora).
  • addDocument's metadata is forwarded as a raw JSON string into the payload; filtering by metadata fields requires valid JSON.
  • Distance defaults to cosine.

Upgrading from 1.x #

1.3 cannot read a store written by 1.2 or earlier. The shard format changed with the move to crate 0.8.0, and this release keeps its data in an owned qdrant_edge_v1/ subdirectory rather than directly at the path you pass to initialize().

initialize() throws a QdrantLegacyStoreException naming the situation — not the first write, so a read-only session hits it too. It names the three entries a 1.x shard owns (edge_config.json, wal/, segments/); remove those from the directory yourself, then re-index.

import 'package:flutter_gemma_rag_qdrant/flutter_gemma_rag_qdrant.dart';

final store = QdrantVectorStore();
try {
  await store.initialize(path);
} on QdrantLegacyStoreException catch (e) {
  // e.message names exactly what to remove. Do it with the file APIs you
  // already use for `path`, then initialize() again and re-index.
  rethrow;
}

This release never deletes a file it cannot read. clear() empties the shard in place — the SDK's own EdgeShard.clear() — so it does not remove the directory, and it refuses outright when a 1.x layout is present. The previous design deleted directories to erase an index, and twice removed files that belonged to the caller rather than to the store; the deletion is gone, and with it that whole class of mistake.

Catch QdrantLegacyStoreException, never the base VectorStoreException: initialize() also throws the base type when a 2.0 shard is present but will not open right now — a WAL held by another store, a permission problem — and that is not a store you want to act destructively on.

Platforms #

Platform Support
Android (arm64, x64)
iOS (arm64, simulator)
macOS (arm64)
Linux
Windows (x64)
Web ❌ — use flutter_gemma_rag_sqlite (WebSqliteVectorStore)

An unsupported native target (e.g. Intel macOS, Windows arm64, 32-bit Android) has no prebuilt archive for the SDK's hook to fetch. The hook prints a warning naming the slice and skips it, so the build still produces the supported ABIs — armeabi-v7a is in flutter build apk/appbundle's default set, and failing there would break the standard Android release build of every consuming app. Code that reaches the engine on a skipped ABI fails to load the library at runtime; restrict the ABI set if you want that to be impossible:

flutter build apk --target-platform android-arm64,android-x64

The native binary is provisioned by the qdrant_edge SDK's own Native Assets build hook (SHA256-verified per-platform archive) — this package has no native code, build script, or download logic of its own.

0
likes
80
points
4.47k
downloads

Documentation

API reference

Publisher

verified publishersashadenisov.dev

Weekly Downloads

qdrant-edge on-device RAG vector store for flutter_gemma, via the official qdrant_edge UniFFI SDK. Opt-in VectorStoreRepository with payload filtering. Native platforms only (no web).

Homepage
Repository (GitHub)
View/report issues

Topics

#rag #qdrant #vector-search #embeddings #on-device

License

MIT (license)

Dependencies

flutter, flutter_gemma, path, qdrant_edge, uuid

More

Packages that depend on flutter_gemma_rag_qdrant