# 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

```go
import (
    "github.com/digitallysavvy/go-ai/pkg/ai"
    "github.com/digitallysavvy/go-ai/pkg/providers/cohere"
)
```

### Configuration

```go
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

1. Sign up at [cohere.com](https://cohere.com)
2. Get API key from dashboard
3. Set environment variable:

```bash
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.

```go
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:

```go
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:

```go
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

```go
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.

```go
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:

```go
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

```go
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

```go
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

1. **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

2. **RAG Implementation**
   - Provide relevant documents in context
   - Use citations for transparency
   - Implement reranking for better results

3. **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](https://goaisdk.com/docs/agents/workflow-agent.md#provider-serialization)
for the mechanism; reranking models are not yet serializable.

## See Also

- [API Reference: GenerateText](https://goaisdk.com/docs/reference/ai/generate-text.md)
- [Cohere API Documentation](https://docs.cohere.com)

## 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.

```go
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"},
            },
        },
    },
}}
```
