Base de données vectorielle intégrée pour GO avec une interface de type chroma et zéro dépendances tierces. En mémoire avec persistance facultative.
Parce que chromem-go est intégré, il vous permet d'ajouter des fonctionnalités de génération augmentée (RAG) et similaires basées sur des intégres dans votre application GO sans avoir à exécuter une base de données distincte . Comme lors de l'utilisation de SQLite au lieu de PostgreSQL / MySQL / etc.
Ce n'est pas une bibliothèque pour se connecter au chroma et non pas non plus une réimplémentation en Go. C'est une base de données à elle seule.
L'accent n'est pas une échelle (des millions de documents) ou un nombre de fonctionnalités, mais de simplicité et de performances pour les cas d'utilisation les plus courants. Sur un processeur d'ordinateur portable Intel de milieu de gamme 2020, vous pouvez interroger 1 000 documents dans 0,3 ms et 100 000 documents en 40 ms, avec très peu et petites allocations de mémoire. Voir Benchmarks pour plus de détails.
️ Le projet est en version bêta, en construction lourde, et peut introduire des changements de rupture dans les versions avantv1.0.0. Tous les modifications sont documentées dans leCHANGELOG.
Avec une base de données vectorielle, vous pouvez faire diverses choses:
Examinons le cas d'utilisation du chiffon plus en détail:
La connaissance des modèles de grande langue (LLMS) - même ceux avec 30 milliards, 70 milliards de paramètres et plus - est limité. Ils ne savent rien de ce qui s'est passé après la fin de leur formation, ils ne savent rien des données avec lesquelles ils n'ont pas été formés (comme l'intranet de votre entreprise, Jira / Bug Tracker, Wiki ou d'autres types de bases de connaissances), et même les données qu'ils savent qu'ils ne peuvent souvent pas les reproduire exactement , mais commencer à halluminer à la place.
Fonctionner un LLM peut aider un peu, mais il est plus censé améliorer le raisonnement LLMS sur des sujets spécifiques, ou reproduire le style de texte ou de code écrit. Le réglage fin n'ajoute pas de connaissances 1: 1 dans le modèle. Les détails sont perdus ou mélangés. Et la coupure des connaissances (à propos de tout ce qui s'est passé après le réglage fin) n'est pas non plus résolue.
=> Une base de données vectorielle peut agir comme la connaissance précise et précise des LLM:
text-embedding-3-small d'Openai.chromem-go peut le faire pour vous et prend en charge plusieurs fournisseurs d'intégration et modèles prêts à l'emploi.Consultez l'exemple de code pour le voir en action!
Notre inspiration originale était l'interface chroma, dont l'API de base est la suivante (tirée de leur lecture):
import chromadb
# setup Chroma in-memory, for easy prototyping. Can add persistence easily!
client = chromadb . Client ()
# Create collection. get_collection, get_or_create_collection, delete_collection also available!
collection = client . create_collection ( "all-my-documents" )
# Add docs to the collection. Can also update and delete. Row-based API coming soon!
collection . add (
documents = [ "This is document1" , "This is document2" ], # we handle tokenization, embedding, and indexing automatically. You can skip that and add your own embeddings as well
metadatas = [{ "source" : "notion" }, { "source" : "google-docs" }], # filter on these!
ids = [ "doc1" , "doc2" ], # unique for each doc
)
# Query/search 2 most similar results. You can also .get by id
results = collection . query (
query_texts = [ "This is a query document" ],
n_results = 2 ,
# where={"metadata_field": "is_equal_to_this"}, # optional filter
# where_document={"$contains":"search_string"} # optional filter
)Notre bibliothèque Go expose la même interface:
package main
import "github.com/philippgille/chromem-go"
func main () {
// Set up chromem-go in-memory, for easy prototyping. Can add persistence easily!
// We call it DB instead of client because there's no client-server separation. The DB is embedded.
db := chromem . NewDB ()
// Create collection. GetCollection, GetOrCreateCollection, DeleteCollection also available!
collection , _ := db . CreateCollection ( "all-my-documents" , nil , nil )
// Add docs to the collection. Update and delete will be added in the future.
// Can be multi-threaded with AddConcurrently()!
// We're showing the Chroma-like method here, but more Go-idiomatic methods are also available!
_ = collection . Add ( ctx ,
[] string { "doc1" , "doc2" }, // unique ID for each doc
nil , // We handle embedding automatically. You can skip that and add your own embeddings as well.
[] map [ string ] string {{ "source" : "notion" }, { "source" : "google-docs" }}, // Filter on these!
[] string { "This is document1" , "This is document2" },
)
// Query/search 2 most similar results. You can also get by ID.
results , _ := collection . Query ( ctx ,
"This is a query document" ,
2 ,
map [ string ] string { "metadata_field" : "is_equal_to_this" }, // optional filter
map [ string ] string { "$contains" : "search_string" }, // optional filter
)
} Initialement, chromem-go a commencé avec les quatre méthodes de base, mais nous avons ajouté plus au fil du temps. Nous ne voulons pas intentionnellement couvrir 100% de la surface de l'API de Chroma.
Nous fournissons plutôt des méthodes alternatives plus idiomatiques.
Pour l'interface complète, voir le godoc: https://pkg.go.dev/github.com/philippgille/chromem-go
chromem.EmbeddingFunc )chromem-go les créer$contains , $not_contains io.Writer / io.Reader afin que vous puissiez brancher des seaux S3 et d'autres stockages Blob, voir des exemples / S3-Export-Import par exemple le codeEmbeddingFunc qui télécharge et coche à Llafile$and , $or etc.) go get github.com/philippgille/chromem-go@latest
Voir le godoc pour une référence: https://pkg.go.dev/github.com/philippgille/chromem-go
Pour les exemples complets et de travail, en utilisant la base de données vectorielle pour la récupération de la génération augmentée (RAG) et la recherche sémantique et en utilisant OpenAI ou en exécutant localement le modèle Embeddings et LLM (dans Olllama), voir l'exemple de code.
Ceci est tiré de l'exemple "minimal":
package main
import (
"context"
"fmt"
"runtime"
"github.com/philippgille/chromem-go"
)
func main () {
ctx := context . Background ()
db := chromem . NewDB ()
c , err := db . CreateCollection ( "knowledge-base" , nil , nil )
if err != nil {
panic ( err )
}
err = c . AddDocuments ( ctx , []chromem. Document {
{
ID : "1" ,
Content : "The sky is blue because of Rayleigh scattering." ,
},
{
ID : "2" ,
Content : "Leaves are green because chlorophyll absorbs red and blue light." ,
},
}, runtime . NumCPU ())
if err != nil {
panic ( err )
}
res , err := c . Query ( ctx , "Why is the sky blue?" , 1 , nil , nil )
if err != nil {
panic ( err )
}
fmt . Printf ( "ID: %v n Similarity: %v n Content: %v n " , res [ 0 ]. ID , res [ 0 ]. Similarity , res [ 0 ]. Content )
}Sortir:
ID: 1
Similarity: 0.6833369
Content: The sky is blue because of Rayleigh scattering.
Benchmarked le 2024-03-17 avec:
$ go test -benchmem -run=^$ -bench .
goos: linux
goarch: amd64
pkg: github.com/philippgille/chromem-go
cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
BenchmarkCollection_Query_NoContent_100-8 13164 90276 ns/op 5176 B/op 95 allocs/op
BenchmarkCollection_Query_NoContent_1000-8 2142 520261 ns/op 13558 B/op 141 allocs/op
BenchmarkCollection_Query_NoContent_5000-8 561 2150354 ns/op 47096 B/op 173 allocs/op
BenchmarkCollection_Query_NoContent_25000-8 120 9890177 ns/op 211783 B/op 208 allocs/op
BenchmarkCollection_Query_NoContent_100000-8 30 39574238 ns/op 810370 B/op 232 allocs/op
BenchmarkCollection_Query_100-8 13225 91058 ns/op 5177 B/op 95 allocs/op
BenchmarkCollection_Query_1000-8 2226 519693 ns/op 13552 B/op 140 allocs/op
BenchmarkCollection_Query_5000-8 550 2128121 ns/op 47108 B/op 173 allocs/op
BenchmarkCollection_Query_25000-8 100 10063260 ns/op 211705 B/op 205 allocs/op
BenchmarkCollection_Query_100000-8 30 39404005 ns/op 810295 B/op 229 allocs/op
PASS
ok github.com/philippgille/chromem-go 28.402s go build ./...go test -v -race -count 1 ./...go test -benchmem -run=^$ -bench . (ajouter > bench.out ou similaire à écrire dans un fichier)go test -benchmem -run ^$ -cpuprofile cpu.out -bench .-cpuprofile , -memprofile , -blockprofile , -mutexprofile )benchstat : go install golang.org/x/perf/cmd/benchstat@latestbenchstat before.out after.out En décembre 2023, lorsque je voulais jouer avec la génération augmentée (RAG) de récupération dans un programme Go, j'ai cherché une base de données vectorielle qui pourrait être intégrée dans le programme Go, tout comme vous intégriez SQLite afin de ne pas nécessiter de configuration et de maintenance DB distinctes. J'ai été surpris quand je n'en ai pas trouvé, étant donné l'abondance de magasins de valeurs clés intégrés dans l'écosystème Go.
À l'époque, la plupart des bases de données vectorielles populaires comme Pinecone, Qdrant, Milvus, Chrom, Weavate et d'autres n'étaient pas du tout intégrées ou seulement dans Python ou JavaScript / TypeScript.
Ensuite, j'ai trouvé le blog de @ Eliben et l'exemple de code qui montraient qu'avec un code GO très peu, vous pouviez créer un POC très basique d'une base de données vectorielle.
C'est à ce moment-là que j'ai décidé de construire ma propre base de données vectorielle, intégrée dans GO, inspirée par l'interface ChromAdb. Chromadb s'est démarqué d'être intégré (dans Python), et en montrant son API principale dans 4 commandes sur leur Readme et sur la page de destination de leur site Web.