Cohere Provider
Cohere specializes in enterprise-grade language models optimized for production use cases including RAG, search, classification, and embeddings. Known for reliable performance and strong multilingual support.
Setup
Installation
import (
"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/providers/cohere"
)
Configuration
provider := cohere.New(cohere.Config{
APIKey: os.Getenv("COHERE_API_KEY"),
})
model, err := provider.LanguageModel("command-r-plus")
if err != nil {
log.Fatal(err)
}
Get API Key
- Sign up at cohere.com
- Get API key from dashboard
- Set environment variable:
export COHERE_API_KEY=...
Available Models
Language Models
| Model ID | Context | Input Price | Output Price | Best For |
|---|---|---|---|---|
| command-r-plus | 128K | $3.00/1M | $15.00/1M | RAG, search, agents |
| command-r | 128K | $0.50/1M | $1.50/1M | Cost-effective tasks |
| command | 4K | $1.00/1M | $2.00/1M | Legacy |
| command-light | 4K | $0.30/1M | $0.60/1M | Fast responses |
Embedding Models
| Model ID | Dimensions | Price | Best For |
|---|---|---|---|
| embed-english-v3.0 | 1024 | $0.10/1M | English semantic search |
| embed-multilingual-v3.0 | 1024 | $0.10/1M | Multilingual search |
| embed-english-light-v3.0 | 384 | $0.10/1M | Fast embeddings |
Provider-Specific Features
Vision Input (Image Parts)
Cohere chat models support image input in user messages.
prompt := types.Prompt{
Messages: []types.Message{
{
Role: types.RoleUser,
Content: []types.ContentPart{
types.TextContent{Text: "Describe this image"},
types.FileContent{
FileData: types.FileData{
Type: types.FileDataTypeURL,
URL: "https://example.com/cat.png",
MediaType: "image/png",
},
},
},
},
},
}
result, err := model.DoGenerate(ctx, &provider.GenerateOptions{Prompt: prompt})
RAG Optimization
Cohere models are optimized for retrieval-augmented generation:
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Messages: []types.Message{
{
Role: types.RoleUser,
Content: []types.ContentPart{
types.FileContent{
Data: []byte("Go was created at Google in 2007"),
MediaType: "text/plain",
},
types.TextContent{Text: "Who created Go?"},
},
},
},
})
Tool Use
Tool calling, TopP/TopK/penalties/Seed/StopSequences, and JSON
response_format are all forwarded to Cohere's v2 chat API:
searchTool := types.Tool{
Name: "search_products",
Description: "Search product database",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"query": map[string]string{"type": "string"},
},
"required": []string{"query"},
},
}
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: "Find laptop under $1000",
Tools: []types.Tool{searchTool},
StopWhen: []ai.StopCondition{ai.IsStepCount(5)},
})
for _, call := range result.ToolCalls {
fmt.Printf("Tool: %s Args: %v\n", call.ToolName, call.Arguments)
}
providerOptions.cohere.thinking takes precedence over the standardized
Reasoning call option when both are set. Unsupported provider-defined
tools produce warnings instead of being silently dropped.
Structured Output
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{
Model: model,
Prompt: "Extract the person's name and age from: John is 30.",
ResponseFormat: &provider.ResponseFormat{
Type: "json",
Schema: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"name": map[string]string{"type": "string"},
"age": map[string]string{"type": "integer"},
},
"required": []string{"name", "age"},
},
},
})
Citations
DoGenerate (non-streaming) surfaces Cohere's inline citations as ordered
types.SourceContent parts in result.Content (SourceType: "document"),
with citation span, text, and source detail under
ProviderMetadata["cohere"]. Streaming does not accumulate citations —
Cohere's citation-start / citation-end stream events carry no payload to
reconstruct them from.
for _, part := range result.Content {
if source, ok := part.(types.SourceContent); ok {
fmt.Printf("Cited: %s\n", source.Title)
}
}
STOP_SEQUENCE maps to types.FinishReasonStop.
Reranking
Improve search results with reranking:
reranker, err := provider.RerankingModel("rerank-english-v3.0")
if err != nil {
log.Fatal(err)
}
topN := 2
result, err := reranker.DoRerank(ctx, &provider.RerankOptions{
Query: "machine learning",
Documents: []string{
"ML is a subset of AI",
"Weather forecast for today",
"Neural networks learn patterns",
},
TopN: &topN,
})
if err != nil {
log.Fatal(err)
}
for i, doc := range result.Ranking {
fmt.Printf("%d. Score: %.2f - Index: %d\n", i+1, doc.RelevanceScore, doc.Index)
}
Examples
Basic Text Generation
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/digitallysavvy/go-ai/pkg/ai"
"github.com/digitallysavvy/go-ai/pkg/providers/cohere"
)
func main() {
ctx := context.Background()
provider := cohere.New(cohere.Config{
APIKey: os.Getenv("COHERE_API_KEY"),
})
model, err := provider.LanguageModel("command-r-plus")
if err != nil {
log.Fatal(err)
}
result, err := ai.GenerateText(ctx, ai.GenerateTextOptions{Model: model, Prompt: "Explain vector databases"})
if err != nil {
log.Fatal(err)
}
fmt.Println(result.Text)
}
Embeddings for Semantic Search
embeddingModel, err := provider.EmbeddingModel("embed-english-v3.0")
if err != nil {
log.Fatal(err)
}
// Embed documents
docs := []string{
"Go is a statically typed language",
"Python is dynamically typed",
"JavaScript runs in browsers",
}
docResult, err := ai.EmbedMany(ctx, ai.EmbedManyOptions{
Model: embeddingModel,
Inputs: docs,
})
// Embed query
queryResult, err := ai.Embed(ctx, ai.EmbedOptions{
Model: embeddingModel,
Input: "Tell me about Go programming",
})
// Find most similar
bestMatch := findMostSimilar(queryResult.Embedding, docResult.Embeddings)
Best Practices
-
Model Selection
- Use Command R+ for RAG and multi-step reasoning
- Use Command R for cost-effective production workloads
- Use embed-v3.0 for semantic search
-
RAG Implementation
- Provide relevant documents in context
- Use citations for transparency
- Implement reranking for better results
-
Embeddings
- Use input_type parameter (search_document, search_query, classification)
- Batch embed operations
- Cache embeddings for repeated documents
Rate Limits & Pricing
Rate Limits
| Tier | RPM | Tokens/Min |
|---|---|---|
| Trial | 100 | 40K |
| Production | 10K | 10M |
Workflow Serialization
Cohere embedding models can cross a workflow boundary with
providerutils.SerializeModel / DeserializeModel (language models could
already be serialized). See
Provider Serialization
for the mechanism; reranking models are not yet serializable.
See Also
May 2026 parity updates
Image input
Cohere chat models support image input. Use types.FileContent for new code, or types.ImageContent for compatibility. Provider option imageDetail is forwarded when present under the cohere key.
messages := []types.Message{{
Role: types.RoleUser,
Content: []types.ContentPart{
types.TextContent{Text: "What is in this image?"},
types.FileContent{
FileData: types.FileData{
Type: types.FileDataTypeURL,
URL: "https://example.com/image.png",
MediaType: "image/png",
},
ProviderOptions: map[string]interface{}{
"cohere": map[string]interface{}{"imageDetail": "auto"},
},
},
},
}}