cohere

package module
v1.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: MIT Imports: 11 Imported by: 0

README

deps.dev License License Stay with Ukraine

cohere

cohere is a Go client for the Cohere API. It implements the github.com/goloop/ai interface, so it looks and works like every other goloop AI provider, and exposes Cohere's native v2 endpoints on top.

Features

  • Chat: Generate for a single response, Stream for token-by-token output through iter.Seq2.
  • Tool use (function calling), multimodal image input and system prompts.
  • Native ChatCompletion and ChatStream over the v2 chat API.
  • Embeddings, reranking and model listing.
  • Retries on 429 and 5xx with backoff; normalized, typed API errors.
  • Depends only on github.com/goloop/ai and the standard library.
  • Structured output: ai.Format maps onto the provider's response_format (JSON mode or a schema); read the reply with resp.JSON(&v).
  • Hosted capabilities: ai.Request.Hosted is refused with ai.ErrNoHosted, because nothing here runs on the provider's own side.

Installation

go get github.com/goloop/cohere

Quick start

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/goloop/ai"
	"github.com/goloop/cohere"
)

func main() {
	c := cohere.New(os.Getenv("COHERE_API_KEY"))

	resp, err := c.Generate(context.Background(), &ai.Request{
		Model:    cohere.ModelCommandA,
		Messages: []ai.Message{ai.UserText("Say hello in one word.")},
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(resp.Text())
}

Streaming

for chunk, err := range c.Stream(ctx, req) {
	if err != nil {
		break
	}
	fmt.Print(chunk.Text)
}

Embeddings

docs, err := c.Embed(ctx, cohere.ModelEmbedV3, "hello", "world")
// for a search query, pick the input type explicitly:
q, err := c.Embeddings(ctx, &cohere.EmbedRequest{
	Model: cohere.ModelEmbedV3, Texts: []string{"hello"}, InputType: "search_query",
})

Rerank

Rerank scores each document against the query and returns them ordered most relevant first. Each result's Index points back into the request documents.

res, err := c.Rerank(ctx, &cohere.RerankRequest{
	Model:     cohere.ModelRerankV35,
	Query:     "What is the capital of Ukraine?",
	Documents: []string{"Kyiv is the capital.", "Bananas are yellow."},
	TopN:      1,
})
// res[0].Index == 0, res[0].RelevanceScore near 1.0

Documentation

Full reference: DOC.md (Ukrainian: DOC.UK.md).

Contributing

See CONTRIBUTING.md.

License

MIT - see LICENSE.

Documentation

Overview

Package cohere is a client for the Cohere API, built on the goloop/ai interface.

The Client implements ai.Client, so Generate and Stream work the same as with any other goloop AI provider. On top of that it exposes Cohere's native v2 endpoints: chat (with tool use and image input), embeddings, reranking and model listing. Streaming uses Server-Sent Events with typed events; the driver hides that.

c := cohere.New(os.Getenv("COHERE_API_KEY"))
resp, err := c.Generate(ctx, &ai.Request{
    Model:    cohere.ModelCommandA,
    Messages: []ai.Message{ai.UserText("Say hello in one word.")},
})

Structured output

ai.Request.Format maps onto the provider's response_format, so a request for JSON is enforced rather than merely asked for, and ai.Response.JSON decodes the reply. ai.FormatJSONSchema sends the schema inside that same object, which is the shape this provider expects.

Hosted capabilities

This provider's search is orchestration around tools the caller supplies, which ai.Request.Tools already expresses; nothing runs on the provider's own side. ai.Hosted is refused with ai.ErrNoHosted.

The refusal is the documented behavior, not a gap waiting to be filled in silence: an answer produced without the search that was asked for looks exactly like one produced with it. A caller who would rather have the answer anyway asks again without ai.Request.Hosted.

Asking what this driver can do

Capabilities describes this driver for the decision taken before a call: whether to offer a feature at all, and whether it needs one request or two.

if ai.SupportsHosted(c, ai.Hosted{Kind: ai.HostedWebSearch}) { ... }

It is a hint and not a permission - support also depends on the model, the account and the region - so ai.ErrNoHosted and ai.ErrNoFormat remain the source of truth and a caller still handles them. What changes is that a refusal the provider only reports as a 400 now arrives as those same sentinels, wrapped around the original ai.APIError, so one errors.Is covers a limitation this driver knew in advance and one it learned over the wire.

It depends only on goloop/ai and the standard library.

Index

Examples

Constants

View Source
const (
	ModelCommandA     = "command-a-03-2025"
	ModelCommandRPlus = "command-r-plus-08-2024"
	ModelCommandR     = "command-r-08-2024"
	ModelEmbedV3      = "embed-english-v3.0"
	ModelRerankV35    = "rerank-v3.5"
)

Convenience model identifiers. Any model string is accepted; use Models to discover what the account can call.

View Source
const DefaultBaseURL = "https://api.cohere.com"

DefaultBaseURL is the Cohere API base URL.

Variables

This section is empty.

Functions

This section is empty.

Types

type ChatMessage

type ChatMessage struct {
	Role       string     `json:"role"`
	Content    any        `json:"content,omitempty"`
	ToolCalls  []ToolCall `json:"tool_calls,omitempty"`
	ToolCallID string     `json:"tool_call_id,omitempty"`
	ToolPlan   string     `json:"tool_plan,omitempty"`
}

ChatMessage is one message in a chat request. Content is a string or a slice of content blocks (for images).

type ChatRequest

type ChatRequest struct {
	Model          string          `json:"model"`
	Messages       []ChatMessage   `json:"messages"`
	Tools          []Tool          `json:"tools,omitempty"`
	ToolChoice     string          `json:"tool_choice,omitempty"`
	Temperature    *float64        `json:"temperature,omitempty"`
	P              *float64        `json:"p,omitempty"`
	MaxTokens      int             `json:"max_tokens,omitempty"`
	StopSequences  []string        `json:"stop_sequences,omitempty"`
	ResponseFormat json.RawMessage `json:"response_format,omitempty"`
	Stream         bool            `json:"stream,omitempty"`
}

ChatRequest is the native v2 chat request body.

type ChatResponse

type ChatResponse struct {
	ID           string          `json:"id"`
	FinishReason string          `json:"finish_reason"`
	Message      ResponseMessage `json:"message"`
	Usage        Usage           `json:"usage"`
}

ChatResponse is the native v2 chat response.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a Cohere API client. It implements ai.Client and adds the provider's native endpoints (the v2 chat, embed and models APIs).

func New

func New(apiKey string, opts ...Option) *Client

New returns a Client for the given API key. Shared options (WithBaseURL, WithHTTPClient, WithTimeout, WithMaxRetries, WithHeader) configure it.

Example
package main

import (
	"fmt"

	"github.com/goloop/cohere"
)

func main() {
	c := cohere.New("...")
	_ = c // use c.Generate, c.Stream, c.ChatCompletion, ...
	fmt.Println(cohere.ModelCommandA)
}
Output:
command-a-03-2025

func (*Client) Capabilities added in v1.1.0

func (c *Client) Capabilities() ai.Capabilities

Capabilities describes what this driver can be asked for. It is a hint for the decision taken before a call - whether to offer a feature, and whether it needs one request or two - and never a substitute for handling ai.ErrNoHosted, ai.ErrNoFormat or ai.ErrFormatWithHosted, because support also depends on the model, the account and the region.

func (*Client) ChatCompletion

func (c *Client) ChatCompletion(ctx context.Context, req *ChatRequest) (*ChatResponse, error)

ChatCompletion sends a native v2 chat request and returns the whole response. Use it for provider-specific options; use Generate for the shared, provider-agnostic path.

func (*Client) ChatStream

func (c *Client) ChatStream(
	ctx context.Context,
	req *ChatRequest,
) iter.Seq2[StreamEvent, error]

ChatStream sends a native streaming v2 chat request and yields each event as it arrives.

func (*Client) Embed

func (c *Client) Embed(
	ctx context.Context,
	model string,
	texts ...string,
) ([][]float64, error)

Embed embeds one or more texts as documents and returns their vectors in order. For queries, use Embeddings with InputType "search_query".

func (*Client) Embeddings

func (c *Client) Embeddings(
	ctx context.Context,
	req *EmbedRequest,
) ([][]float64, error)

Embeddings sends a native v2 embed request and returns the float vectors.

func (*Client) Generate

func (c *Client) Generate(ctx context.Context, req *ai.Request) (*ai.Response, error)

Generate implements ai.Client over the v2 chat API.

Example

ExampleClient_Generate builds a request. Sending it needs a real API key, so this example only shows the shape.

package main

import (
	"fmt"

	"github.com/goloop/ai"
	"github.com/goloop/cohere"
)

func main() {
	req := &ai.Request{
		Model: cohere.ModelCommandA,
		Messages: []ai.Message{
			ai.UserText("Name the capital of France."),
		},
	}
	fmt.Println(req.Model, len(req.Messages))
}
Output:
command-a-03-2025 1

func (*Client) GetModel

func (c *Client) GetModel(ctx context.Context, name string) (*Model, error)

GetModel retrieves one model by name.

func (*Client) Models

func (c *Client) Models(ctx context.Context) ([]Model, error)

Models lists the models available to the account.

func (*Client) Rerank

func (c *Client) Rerank(
	ctx context.Context,
	req *RerankRequest,
) ([]RerankResult, error)

Rerank scores the request's documents against its query and returns the results ordered most relevant first.

Example

ExampleClient_Rerank shows a rerank request shape. Rerank scores each document against the query and returns them ordered most relevant first.

package main

import (
	"fmt"

	"github.com/goloop/cohere"
)

func main() {
	req := &cohere.RerankRequest{
		Model:     cohere.ModelRerankV35,
		Query:     "What is the capital of Ukraine?",
		Documents: []string{"Kyiv is the capital.", "Bananas are yellow."},
		TopN:      1,
	}
	fmt.Println(req.Model, len(req.Documents))
}
Output:
rerank-v3.5 2

func (*Client) Stream

func (c *Client) Stream(
	ctx context.Context,
	req *ai.Request,
) iter.Seq2[ai.Chunk, error]

Stream implements ai.Client over the streaming v2 chat API.

type ContentBlock

type ContentBlock struct {
	Type     string    `json:"type"`
	Text     string    `json:"text,omitempty"`
	ImageURL *ImageURL `json:"image_url,omitempty"`
}

ContentBlock is one piece of a message's content. For text, Type is "text"; for images, Type is "image_url".

type EmbedRequest

type EmbedRequest struct {
	Model          string   `json:"model"`
	Texts          []string `json:"texts"`
	InputType      string   `json:"input_type"`
	EmbeddingTypes []string `json:"embedding_types,omitempty"`
}

EmbedRequest is the native v2 embed request.

type ImageURL

type ImageURL struct {
	URL string `json:"url"`
}

ImageURL holds an image reference, typically a base64 data URI.

type Model

type Model struct {
	Name             string   `json:"name"`
	Endpoints        []string `json:"endpoints"`
	ContextLength    float64  `json:"context_length,omitempty"`
	TokenizerURL     string   `json:"tokenizer_url,omitempty"`
	Finetuned        bool     `json:"finetuned,omitempty"`
	SupportsVision   bool     `json:"supports_vision,omitempty"`
	DefaultEndpoints []string `json:"default_endpoints,omitempty"`
}

Model describes a model reported by Cohere.

type Option

type Option func(*settings)

Option configures a Client in New.

func WithBaseURL

func WithBaseURL(u string) Option

WithBaseURL overrides the API base URL (proxies, gateways, mock servers).

func WithHTTPClient

func WithHTTPClient(c *http.Client) Option

WithHTTPClient sets the HTTP client used for requests.

func WithHeader

func WithHeader(key, value string) Option

WithHeader adds a header sent with every request.

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets how many times a request is retried on 429 and 5xx.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the per-request timeout when no custom HTTP client is set.

type RerankRequest

type RerankRequest struct {
	Model     string   `json:"model"`
	Query     string   `json:"query"`
	Documents []string `json:"documents"`
	TopN      int      `json:"top_n,omitempty"`
}

RerankRequest is the native v2 rerank request. Rerank scores each document by its relevance to the query and returns them ordered most relevant first.

type RerankResult

type RerankResult struct {
	Index          int     `json:"index"`
	RelevanceScore float64 `json:"relevance_score"`
}

RerankResult is one scored document. Index is the document's position in the request's Documents slice; RelevanceScore is in the range 0..1.

type ResponseMessage

type ResponseMessage struct {
	Role      string         `json:"role"`
	Content   []ContentBlock `json:"content"`
	ToolCalls []ToolCall     `json:"tool_calls"`
	ToolPlan  string         `json:"tool_plan"`
}

ResponseMessage is the assistant message in a chat response.

type StreamEvent

type StreamEvent struct {
	Type  string `json:"type"`
	Index int    `json:"index"`
	Delta struct {
		FinishReason string `json:"finish_reason"`
		Message      struct {
			Content struct {
				Text string `json:"text"`
			} `json:"content"`
			ToolCalls struct {
				ID       string `json:"id"`
				Type     string `json:"type"`
				Function struct {
					Name      string `json:"name"`
					Arguments string `json:"arguments"`
				} `json:"function"`
			} `json:"tool_calls"`
		} `json:"message"`
		Usage Usage `json:"usage"`
	} `json:"delta"`
}

StreamEvent is one streamed v2 chat event. The Type field selects which nested fields are populated ("content-delta", "tool-call-start", "tool-call-delta", "tool-call-end", "message-end", ...).

type Tool

type Tool struct {
	Type     string       `json:"type"`
	Function ToolFunction `json:"function"`
}

Tool declares a callable function.

Example

ExampleTool shows a tool definition passed with a request.

package main

import (
	"encoding/json"
	"fmt"

	"github.com/goloop/ai"
)

func main() {
	tool := ai.Tool{
		Name:        "get_weather",
		Description: "Get the current weather for a city.",
		Schema:      json.RawMessage(`{"type":"object","properties":{"city":{"type":"string"}}}`),
	}
	fmt.Println(tool.Name)
}
Output:
get_weather

type ToolCall

type ToolCall struct {
	ID       string           `json:"id,omitempty"`
	Type     string           `json:"type,omitempty"`
	Function ToolCallFunction `json:"function"`
}

ToolCall is a tool call produced by the model.

type ToolCallFunction

type ToolCallFunction struct {
	Name      string `json:"name,omitempty"`
	Arguments string `json:"arguments,omitempty"`
}

ToolCallFunction is the function name and JSON-encoded arguments of a call.

type ToolFunction

type ToolFunction struct {
	Name        string          `json:"name"`
	Description string          `json:"description,omitempty"`
	Parameters  json.RawMessage `json:"parameters,omitempty"`
}

ToolFunction is a function's name, description and JSON Schema parameters.

type Usage

type Usage struct {
	Tokens struct {
		InputTokens  float64 `json:"input_tokens"`
		OutputTokens float64 `json:"output_tokens"`
	} `json:"tokens"`
}

Usage reports token counts for a chat request.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL