ai

package
v0.0.0-...-5dfbc55 Latest Latest
Warning

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

Go to latest
Published: Jul 18, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DeepSeekModel = "deepseek-v4-flash"
)
View Source
const (
	OpenRouterModel = "deepseek/deepseek-v4-flash"
)

Variables

This section is empty.

Functions

func CosineSimilarity

func CosineSimilarity(a, b []float32) float32

CosineSimilarity returns the cosine similarity between two equal-length vectors.

func EmbedText

func EmbedText(ctx context.Context, text string) ([]float32, error)

EmbedText calls Ollama's native embeddings endpoint with nomic-embed-text. Returns error if Ollama is unreachable.

func NewHTTPClient

func NewHTTPClient() *http.Client

NewHTTPClient returns a client suitable for both ordinary provider requests and streaming responses. Transport phases are bounded, but Client.Timeout is intentionally unset because it would terminate healthy long-running streams.

func TopK

func TopK(chunks []db.RulebookChunk, queryEmb []float32, k int) []db.RulebookChunk

TopK returns the k chunks with the highest cosine similarity to queryEmb. Chunks without embeddings are skipped.

func WriteSSE

func WriteSSE(w io.Writer, event SSEEvent) error

WriteSSE writes one JSON event in one data line followed by a blank LF line.

Types

type ChatMessage

type ChatMessage struct {
	Role    string
	Content string
}

ChatMessage is a single turn in a conversation.

type Client

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

Client calls the Anthropic Messages API over plain HTTP.

func NewClient

func NewClient(apiKey string) *Client

NewClient returns a Client using the production Anthropic API URL.

func NewClientWithURL

func NewClientWithURL(apiKey, url string) *Client

NewClientWithURL returns a Client using a custom URL (for tests).

func (*Client) Generate

func (c *Client) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

func (*Client) ProviderName

func (*Client) ProviderName() string

func (*Client) Respond

func (c *Client) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

func (*Client) StreamRespond

func (c *Client) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

StreamRespond sends a streaming request to the Anthropic Messages API and writes each text delta as an SSE data line to w. It returns the full accumulated response text so the caller can persist it.

type Completer

type Completer interface {
	Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
}

Completer generates text from a prompt. Implemented by *Client; nil means AI is disabled. maxTokens caps the output length; pass a tight value to avoid wasted spend.

type DeepSeekClient

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

DeepSeekClient calls the DeepSeek API directly via its OpenAI-compatible endpoint. It implements Completer, Responder, and Streamer.

func NewDeepSeekClient

func NewDeepSeekClient(apiKey string) *DeepSeekClient

NewDeepSeekClient returns a GM client for DeepSeek V4 Flash. DeepSeek defaults to thinking mode (reasoning tokens before output), but this client explicitly disables it via "thinking":{"type":"disabled"} on every request. Reasoning: thinking mode delays streaming start (bad for GM narration) and eats into maxTokens budgets for structured automation tasks. The think-stripping field (think=true) is kept as a safety net for any residual <think> blocks the API might emit despite the disable parameter.

func (*DeepSeekClient) Generate

func (c *DeepSeekClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

func (*DeepSeekClient) ProviderName

func (*DeepSeekClient) ProviderName() string

func (*DeepSeekClient) Respond

func (c *DeepSeekClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

func (*DeepSeekClient) StreamRespond

func (c *DeepSeekClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

type DualDeepSeekClient

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

DualDeepSeekClient routes GM narrative calls (Respond, StreamRespond) to one DeepSeek model and all automation calls (Generate) to a smaller/faster model.

func NewDualDeepSeekClient

func NewDualDeepSeekClient(deepseekKey, autoModel string) *DualDeepSeekClient

NewDualDeepSeekClient creates a client that sends GM calls to the default DeepSeek V4 Flash model and automation calls to a faster model.

func (*DualDeepSeekClient) Generate

func (d *DualDeepSeekClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

func (*DualDeepSeekClient) ProviderName

func (*DualDeepSeekClient) ProviderName() string

func (*DualDeepSeekClient) Respond

func (d *DualDeepSeekClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

func (*DualDeepSeekClient) StreamRespond

func (d *DualDeepSeekClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

type DualOllamaClient

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

DualOllamaClient routes GM streaming/response calls to one model and all automation Generate calls to another. This lets you use a RP-tuned model (e.g. hermes3:8b) for narrative prose and a stronger instruction-following model (e.g. phi4:14b) for structured JSON tasks.

func NewDualOllamaClient

func NewDualOllamaClient(gmModel, autoModel string) *DualOllamaClient

NewDualOllamaClient creates a split-model Ollama client.

func (*DualOllamaClient) Generate

func (d *DualOllamaClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

func (*DualOllamaClient) ProviderName

func (*DualOllamaClient) ProviderName() string

func (*DualOllamaClient) Respond

func (d *DualOllamaClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

func (*DualOllamaClient) StreamRespond

func (d *DualOllamaClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

type DualOpenRouterClient

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

DualOpenRouterClient routes GM narrative calls (Respond, StreamRespond) to the NVIDIA model and all automation calls (Generate) to a fast small model.

func NewDualOpenRouterClient

func NewDualOpenRouterClient(openrouterKey, autoModel string) *DualOpenRouterClient

NewDualOpenRouterClient creates a client that sends GM calls to OpenRouter (NVIDIA) and automation calls to a fast OpenRouter model specified by autoModel.

func (*DualOpenRouterClient) Generate

func (d *DualOpenRouterClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

func (*DualOpenRouterClient) ProviderName

func (*DualOpenRouterClient) ProviderName() string

func (*DualOpenRouterClient) Respond

func (d *DualOpenRouterClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

func (*DualOpenRouterClient) StreamRespond

func (d *DualOpenRouterClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

type HybridClient

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

HybridClient routes GM streaming/response calls to a local Ollama model and all automation Generate calls to the Anthropic API (Claude Haiku). Use this when you want an uncensored local model for roleplay but Claude for structured JSON tasks (objective detection, NPC extraction, recaps, etc.).

func NewHybridClient

func NewHybridClient(gmModel, anthropicKey string) *HybridClient

NewHybridClient creates a client that sends GM calls to Ollama and automation calls to Anthropic. The GM client is tuned for roleplay quality (see NewOllamaGMClient).

func (*HybridClient) Generate

func (h *HybridClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

func (*HybridClient) ProviderName

func (*HybridClient) ProviderName() string

func (*HybridClient) Respond

func (h *HybridClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

func (*HybridClient) StreamRespond

func (h *HybridClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

type OllamaClient

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

OllamaClient calls a local Ollama instance via its OpenAI-compatible API. It implements Completer, Responder, and Streamer.

func NewOllamaClient

func NewOllamaClient(model string) *OllamaClient

NewOllamaClient creates an OllamaClient for the given model using the default localhost:11434 base URL. Override with OLLAMA_HOST env var via NewOllamaClientWithURL.

func NewOllamaClientWithURL

func NewOllamaClientWithURL(model, baseURL string) *OllamaClient

NewOllamaClientWithURL is like NewOllamaClient but uses the given base URL (for tests).

func NewOllamaGMClient

func NewOllamaGMClient(model string) *OllamaClient

NewOllamaGMClient creates an OllamaClient tuned for GM roleplay:

  • num_ctx 8192: enough for full session history
  • temperature 0.72: focused but not mechanical
  • repeat_penalty 1.05: prevents looping prose
  • think: prepends /think to system prompt so Qwen3 reasons before responding

func (*OllamaClient) Generate

func (c *OllamaClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

Generate implements Completer. Sends a single-turn prompt and returns the response.

func (*OllamaClient) ProviderName

func (*OllamaClient) ProviderName() string

func (*OllamaClient) Respond

func (c *OllamaClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

Respond implements Responder. Sends a multi-turn conversation with a system prompt.

func (*OllamaClient) StreamRespond

func (c *OllamaClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

StreamRespond implements Streamer. Streams the response as SSE data lines to w.

type OpenRouterClient

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

OpenRouterClient calls the OpenRouter API using the OpenAI-compatible endpoint. It implements Completer, Responder, and Streamer.

func NewOpenRouterClient

func NewOpenRouterClient(apiKey string) *OpenRouterClient

NewOpenRouterClient returns a GM client for DeepSeek V4 Flash: reasoning suppressed server-side and tuned for prose quality.

func (*OpenRouterClient) Generate

func (c *OpenRouterClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)

func (*OpenRouterClient) ProviderName

func (*OpenRouterClient) ProviderName() string

func (*OpenRouterClient) Respond

func (c *OpenRouterClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)

func (*OpenRouterClient) StreamRespond

func (c *OpenRouterClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)

type ProviderNamer

type ProviderNamer interface {
	ProviderName() string
}

ProviderNamer identifies the provider that handles automation Generate calls. Circuit-breaker keys use this stable name rather than concrete Go type names.

type Responder

type Responder interface {
	Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
}

Responder generates a reply from a system prompt and conversation history.

type SSEEvent

type SSEEvent struct {
	Type      string `json:"type"`
	Delta     string `json:"delta,omitempty"`
	Code      string `json:"code,omitempty"`
	RequestID string `json:"request_id,omitempty"`
}

SSEEvent is the only server-to-browser GM streaming frame shape.

type Streamer

type Streamer interface {
	StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, w http.ResponseWriter) (string, error)
}

Streamer streams a reply from the Anthropic API as SSE chunks, writing each text delta directly to the ResponseWriter. Returns the full accumulated text.

Jump to

Keyboard shortcuts

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