Skip to content

caglareker/chroma-go

 
 

Repository files navigation

Chroma Go

Warning

V1 API Removed: The V1 API has been removed in v0.3.0. If you require V1 API compatibility, please use versions prior to v0.3.0.

go get github.com/amikos-tech/chroma-go@v0.2.4

A simple Chroma Vector Database client written in Go

Works with Chroma Version: v0.6.3 - v1.5.1

We invite users to visit the docs site for the library for more in-depth information: Chroma Go Docs

Feature Parity with ChromaDB API

Operation Support
Create Tenant
Get Tenant
Create Database
Get Database
Delete Database
Reset
Heartbeat
List Collections
Count Collections
Get Version
Create Collection
Delete Collection
Collection Add
Collection Get
Collection Count
Collection Query
Collection Update
Collection Upsert
Collection Delete (delete documents)
Modify Collection
Search API

Additional support features:

  • Authentication (Basic, Token with Authorization header, Token with X-Chroma-Token header)
  • Private PKI and self-signed certificate support
  • ✅ Chroma Cloud support
  • Structured Logging - Injectable logger with Zap bridge for structured logging
  • ✅ Persistent Embedding Function support - automatically load embedding function from Chroma collection configuration
  • ✅ Persistent Client support - Run/embed full-featured Chroma in your Go application without running an external Chroma server process.
  • Search API Support
  • ✅ Array Metadata support with $contains/$not_contains operators (Chroma >= 1.5.0)

Embedding API and Models Support

Sparse & Specialized Embedding Functions:

Reranking Functions

The Chroma Go client supports Reranking functions:

Installation

go get github.com/amikos-tech/chroma-go

Import:

import (
	chroma "github.com/amikos-tech/chroma-go/pkg/api/v2"
)

Usage

Ensure you have a running instance of Chroma running. We recommend one of the two following options:

The Setup (Cloud-native):

minikube start --profile chromago
minikube profile chromago
helm repo add chroma https://amikos-tech.github.io/chromadb-chart/
helm repo update
helm install chroma chroma/chromadb --set chromadb.allowReset=true

Note

To delete the minikube cluster: minikube delete --profile chromago

Getting Started

  • We create a new collection
  • Add documents using the default embedding function
  • Query the collection using the same embedding function
  • Delete documents from the collection
package main

import (
	"context"
	"fmt"
	"log"

	chroma "github.com/amikos-tech/chroma-go/pkg/api/v2"
)

func main() {
	// Create a new Chroma client
	client, err := chroma.NewHTTPClient()
	if err != nil {
		log.Fatalf("Error creating client: %s \n", err)
		return
	}
	// Close the client to release any resources such as local embedding functions
	defer func() {
		err = client.Close()
		if err != nil {
			log.Fatalf("Error closing client: %s \n", err)
		}
	}()

	// Create a new collection with options. We don't provide an embedding function here, so the default embedding function will be used
	col, err := client.GetOrCreateCollection(context.Background(), "col1",
		chroma.WithCollectionMetadataCreate(
			chroma.NewMetadata(
				chroma.NewStringAttribute("str", "hello"),
				chroma.NewIntAttribute("int", 1),
				chroma.NewFloatAttribute("float", 1.1),
			),
		),
	)
	if err != nil {
		log.Fatalf("Error creating collection: %s \n", err)
		return
	}

	err = col.Add(context.Background(),
		chroma.WithIDs("1", "2"),
		chroma.WithTexts("hello world", "goodbye world"),
		chroma.WithMetadatas(
			chroma.NewDocumentMetadata(chroma.NewIntAttribute("int", 1)),
			chroma.NewDocumentMetadata(chroma.NewStringAttribute("str", "hello")),
		))
	if err != nil {
		log.Fatalf("Error adding collection: %s \n", err)
	}

	count, err := col.Count(context.Background())
	if err != nil {
		log.Fatalf("Error counting collection: %s \n", err)
		return
	}
	fmt.Printf("Count collection: %d\n", count)

	qr, err := col.Query(context.Background(),
		chroma.WithQueryTexts("say hello"),
		chroma.WithInclude(chroma.IncludeDocuments),
	)
	if err != nil {
		log.Fatalf("Error querying collection: %s \n", err)
		return
	}
	fmt.Printf("Query result: %v\n", qr.GetDocumentsGroups()[0][0])

	err = col.Delete(context.Background(), chroma.WithIDs("1", "2"))
	if err != nil {
		log.Fatalf("Error deleting collection: %s \n", err)
		return
	}
}

Local Persistent Client (Embedded Runtime)

You can run Chroma locally in-process (no external server process) with NewLocalClient. The runtime uses chroma-go-local. By default, NewLocalClient auto-downloads the correct shim library from the matching chroma-go-local GitHub release and caches it under ~/.cache/chroma/local_shim. You can still override this with CHROMA_LIB_PATH or WithLocalLibraryPath(...). NewLocalClient defaults to embedded mode; use WithLocalRuntimeMode(chroma.LocalRuntimeModeServer) (or WithLocalPort(...)) when you want a local HTTP server. For persistence, WithLocalPersistPath(...) is typically all you need. In server mode, the default port is 8000 unless overridden.

client, err := chroma.NewLocalClient(
	chroma.WithLocalPersistPath("./chroma_data"),
	chroma.WithLocalAllowReset(true),
	chroma.WithLocalClientOption(chroma.WithDatabaseAndTenant("default_database", "default_tenant")),
)
if err != nil {
	log.Fatalf("Error creating local client: %s", err)
}
defer client.Close()

Strict Metadata Map Validation

When metadata comes from map[string]interface{}:

  • NewMetadataFromMap is best-effort and silently skips invalid []interface{} values.
  • NewMetadataFromMapStrict returns an error for invalid or unsupported values.
  • WithCollectionMetadataMapCreateStrict applies strict conversion in create/get-or-create flows and returns a deferred option error before any HTTP request is sent.
// Strict create/get-or-create metadata map conversion
col, err := client.GetOrCreateCollection(context.Background(), "col1",
	chroma.WithCollectionMetadataMapCreateStrict(map[string]interface{}{
		"description": "validated metadata",
		"tags":        []interface{}{"a", "b"},
	}),
)
if err != nil {
	log.Fatalf("Error creating collection: %s", err)
}

// Strict metadata map conversion before collection metadata update
newMetadata, err := chroma.NewMetadataFromMapStrict(map[string]interface{}{
	"description": "updated description",
	"tags":        []interface{}{"x", "y"},
})
if err != nil {
	log.Fatalf("Invalid metadata map: %s", err)
}
if err := col.ModifyMetadata(context.Background(), newMetadata); err != nil {
	log.Fatalf("Error modifying metadata: %s", err)
}

Unified Options API

The V2 API provides a unified options pattern where common options work across multiple operations:

Option Get Query Delete Add Update Search
WithIDs
WithWhere
WithWhereDocument
WithInclude
WithTexts
WithMetadatas
WithEmbeddings
// Get documents by ID or filter
results, _ := col.Get(ctx,
chroma.WithIDs("id1", "id2"),
chroma.WithWhere(chroma.EqString("status", "active")),
chroma.WithInclude(chroma.IncludeDocuments, chroma.IncludeMetadatas),
)

// Query with semantic search
results, _ := col.Query(ctx,
chroma.WithQueryTexts("machine learning"),
chroma.WithWhere(chroma.GtInt("year", 2020)),
chroma.WithNResults(10),
)

// Delete by filter
_ = col.Delete(ctx, chroma.WithWhere(chroma.EqString("status", "archived")))

// Search API with ranking and pagination
results, _ := col.Search(ctx,
chroma.NewSearchRequest(
chroma.WithKnnRank(chroma.KnnQueryText("query")),
chroma.WithFilter(chroma.EqString(chroma.K("category"), "tech")),
chroma.NewPage(chroma.Limit(20)),
chroma.WithSelect(chroma.KDocument, chroma.KScore),
),
)

Structured Logging

The client supports injectable loggers for structured logging. Here's a quick example using Zap:

package main

import (
	"context"
	"log"

	"go.uber.org/zap"
	chromalogger "github.com/amikos-tech/chroma-go/pkg/logger"
	chroma "github.com/amikos-tech/chroma-go/pkg/api/v2"
)

func main() {
	// Create a zap logger
	zapLogger, _ := zap.NewDevelopment()
	defer zapLogger.Sync()

	// Wrap it in the Chroma logger
	logger := chromalogger.NewZapLogger(zapLogger)

	// Create client with the logger
	client, err := chroma.NewHTTPClient(
		chroma.WithBaseURL("http://localhost:8000"),
		chroma.WithLogger(logger),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// All client operations will now be logged with structured logging
	ctx := context.Background()
	collections, _ := client.ListCollections(ctx)

	// You can also log directly
	logger.Info("Retrieved collections",
		chromalogger.Int("count", len(collections)),
	)

	// For debug logging, use WithLogger with a debug-level logger
	devLogger, _ := chromalogger.NewDevelopmentZapLogger()
	debugClient, _ := chroma.NewHTTPClient(
		chroma.WithBaseURL("http://localhost:8000"),
		chroma.WithLogger(devLogger),
	)
	defer debugClient.Close()
}

See the logging documentation for more details.

Development

Build

make build

Test

make test

Lint

make lint-fix

Local Server

Note: Docker must be installed

make server

References

About

The Go client for Chroma vector database

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Go 99.2%
  • Other 0.8%