adapters

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2026 License: Apache-2.0 Imports: 9 Imported by: 1

Documentation

Overview

Package adapters includes multiple adapters to convert one ProviderFoo interface into another one.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenStreamWithToolCallLoop

func GenStreamWithToolCallLoop(ctx context.Context, p genai.Provider, msgs genai.Messages, opts ...genai.GenOption) (iter.Seq[genai.Reply], func() (genai.Messages, genai.Usage, error))

GenStreamWithToolCallLoop runs a conversation loop with an LLM that handles tool calls via streaming until there are no more. It will repeatedly call GenStream(), collect fragments into a complete message, process tool calls with DoToolCalls(), and continue the conversation until the LLM response has no more tool calls.

The function will return early if any error occurs. The returned Messages will include all the messages including the original ones, the LLM's responses, and the tool call result messages.

Warning: If opts.Force == ToolCallRequired, it will be mutated to ToolCallAny after the first tool call.

No need to process the tool calls or accumulate the Reply fragments.

Example
package main

import (
	"context"
	"log"
	"os"
	"time"

	"github.com/maruel/genai"
	"github.com/maruel/genai/adapters"
	"github.com/maruel/genai/providers/gemini"
)

func main() {
	// Supported by Anthropic, Cerebras, Cloudflare, Cohere, DeepSeek, Gemini, Groq, HuggingFace, Mistral,
	// Ollama, OpenAI, TogetherAI.

	// Using a free small model for testing.
	// See https://ai.google.dev/gemini-api/docs/models/gemini?hl=en
	ctx := context.Background()
	c, err := gemini.New(ctx, genai.ProviderOptionModel("gemini-2.5-flash"))
	if err != nil {
		log.Fatal(err)
	}
	msgs := genai.Messages{genai.NewTextMessage("What season are we in?")}
	opts := genai.GenOptionTools{
		// GetTodayClockTime returns the current time and day in a format that the LLM
		// can understand. It includes the weekend.
		Tools: []genai.ToolDef{GetTodayClockTime},
		// Force the LLM to do a tool call first.
		Force: genai.ToolCallRequired,
	}
	fragments, finish := adapters.GenStreamWithToolCallLoop(ctx, c, msgs, &opts)
	for f := range fragments {
		_, _ = os.Stdout.WriteString(f.Text)
	}
	if _, _, err = finish(); err != nil {
		log.Fatal(err)
	}
}

var GetTodayClockTime = genai.ToolDef{
	Name:        "get_today_date_current_clock_time",
	Description: "Get the current clock time and today's date.",
	Callback: func(ctx context.Context, e *empty) (string, error) {
		return time.Now().Format("Monday 2006-01-02 15:04:05"), nil
	},
}

type empty struct{}

func GenSyncWithToolCallLoop

func GenSyncWithToolCallLoop(ctx context.Context, p genai.Provider, msgs genai.Messages, opts ...genai.GenOption) (genai.Messages, genai.Usage, error)

GenSyncWithToolCallLoop runs a conversation with the LLM, handling tool calls in a loop until there are no more tool calls.

It calls the provided Provider.GenSync() method, processes any tool calls using Message.DoToolCalls(), and continues the conversation in a loop until the LLM's response has no more tool calls.

Warning: If opts.Force == ToolCallRequired, it will be mutated to ToolCallAny after the first tool call.

It returns the messages to accumulate to the thread. The last message is the LLM's response.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/maruel/genai"
	"github.com/maruel/genai/adapters"
	"github.com/maruel/genai/providers/gemini"
)

func main() {
	// Supported by Anthropic, Cerebras, Cloudflare, Cohere, DeepSeek, Gemini, Groq, HuggingFace, Mistral,
	// Ollama, OpenAI, TogetherAI.

	// Using a free small model for testing.
	// See https://ai.google.dev/gemini-api/docs/models/gemini?hl=en
	ctx := context.Background()
	c, err := gemini.New(ctx, genai.ProviderOptionModel("gemini-2.5-flash"))
	if err != nil {
		log.Fatal(err)
	}
	msgs := genai.Messages{genai.NewTextMessage("What season are we in?")}
	opts := genai.GenOptionTools{
		// GetTodayClockTime returns the current time and day in a format that the LLM
		// can understand. It includes the weekend.
		Tools: []genai.ToolDef{GetTodayClockTime},
		// Force the LLM to do a tool call first.
		Force: genai.ToolCallRequired,
	}
	newMsgs, _, err := adapters.GenSyncWithToolCallLoop(ctx, c, msgs, &opts)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", newMsgs[len(newMsgs)-1].String())
}

var GetTodayClockTime = genai.ToolDef{
	Name:        "get_today_date_current_clock_time",
	Description: "Get the current clock time and today's date.",
	Callback: func(ctx context.Context, e *empty) (string, error) {
		return time.Now().Format("Monday 2006-01-02 15:04:05"), nil
	},
}

type empty struct{}

func WrapReasoning

func WrapReasoning(c genai.Provider) genai.Provider

WrapReasoning wraps a Provider and processes its output to extract reasoning blocks ONLY if needed.

Types

type ProviderAppend

type ProviderAppend struct {
	genai.Provider

	Append genai.Request
}

ProviderAppend wraps a Provider and appends a Request before processing when the messages end with a user message.

Useful to inject a "/think" for Qwen3 models.

func (*ProviderAppend) GenStream

func (c *ProviderAppend) GenStream(ctx context.Context, msgs genai.Messages, opts ...genai.GenOption) (iter.Seq[genai.Reply], func() (genai.Result, error))

GenStream implements genai.Provider.

func (*ProviderAppend) GenSync

func (c *ProviderAppend) GenSync(ctx context.Context, msgs genai.Messages, opts ...genai.GenOption) (genai.Result, error)

GenSync implements genai.Provider.

func (*ProviderAppend) Unwrap

func (c *ProviderAppend) Unwrap() genai.Provider

type ProviderReasoning

type ProviderReasoning struct {
	genai.Provider

	// ReasoningTokenStart is the start reasoning token. It is often "<think>\n" but there are cases when it can
	// be never output, like "qwen-3-235b-a22b-thinking-2507".
	ReasoningTokenStart string
	// ReasoningTokenEnd is the end reasoning token, where the explicit answer lies after. It is often
	// "\n</think>\n".
	ReasoningTokenEnd string
	// contains filtered or unexported fields
}

ProviderReasoning wraps a Provider and processes its output to extract reasoning blocks.

It looks for content within tags ReasoningTokenStart and ReasoningTokenEnd and places it in Reasoning Content blocks instead of Text.

It requires the starting reasoning tag. Otherwise, the content is assumed to be text. This is necessary for JSON formatted responses.

func (*ProviderReasoning) GenStream

func (c *ProviderReasoning) GenStream(ctx context.Context, msgs genai.Messages, opts ...genai.GenOption) (iter.Seq[genai.Reply], func() (genai.Result, error))

GenStream implements the Provider interface for streaming by delegating to the wrapped provider and processing each fragment to extract reasoning blocks. If no reasoning tags are present, the first part of the message is assumed to be reasoning.

func (*ProviderReasoning) GenSync

func (c *ProviderReasoning) GenSync(ctx context.Context, msgs genai.Messages, opts ...genai.GenOption) (genai.Result, error)

GenSync implements the Provider interface by delegating to the wrapped provider and processing the result to extract reasoning blocks.

func (*ProviderReasoning) Unwrap

func (c *ProviderReasoning) Unwrap() genai.Provider

type ProviderUsage

type ProviderUsage struct {
	genai.Provider
	// contains filtered or unexported fields
}

ProviderUsage wraps a Provider and accumulates Usage values across multiple requests to track total token consumption.

func (*ProviderUsage) GenStream

func (c *ProviderUsage) GenStream(ctx context.Context, msgs genai.Messages, opts ...genai.GenOption) (iter.Seq[genai.Reply], func() (genai.Result, error))

GenStream implements the Provider interface and accumulates usage statistics.

func (*ProviderUsage) GenSync

func (c *ProviderUsage) GenSync(ctx context.Context, msgs genai.Messages, opts ...genai.GenOption) (genai.Result, error)

GenSync implements the Provider interface and accumulates usage statistics.

func (*ProviderUsage) GetAccumulatedUsage

func (c *ProviderUsage) GetAccumulatedUsage() genai.Usage

GetAccumulatedUsage returns the current accumulated usage values.

func (*ProviderUsage) Unwrap

func (c *ProviderUsage) Unwrap() genai.Provider

Jump to

Keyboard shortcuts

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