Documentation
¶
Index ¶
- Constants
- func CosineSimilarity(a, b []float32) float32
- func EmbedText(ctx context.Context, text string) ([]float32, error)
- func NewHTTPClient() *http.Client
- func TopK(chunks []db.RulebookChunk, queryEmb []float32, k int) []db.RulebookChunk
- func WriteSSE(w io.Writer, event SSEEvent) error
- type ChatMessage
- type Client
- func (c *Client) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*Client) ProviderName() string
- func (c *Client) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (c *Client) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type Completer
- type DeepSeekClient
- func (c *DeepSeekClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*DeepSeekClient) ProviderName() string
- func (c *DeepSeekClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (c *DeepSeekClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type DualDeepSeekClient
- func (d *DualDeepSeekClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*DualDeepSeekClient) ProviderName() string
- func (d *DualDeepSeekClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (d *DualDeepSeekClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type DualOllamaClient
- func (d *DualOllamaClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*DualOllamaClient) ProviderName() string
- func (d *DualOllamaClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (d *DualOllamaClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type DualOpenRouterClient
- func (d *DualOpenRouterClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*DualOpenRouterClient) ProviderName() string
- func (d *DualOpenRouterClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (d *DualOpenRouterClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type HybridClient
- func (h *HybridClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*HybridClient) ProviderName() string
- func (h *HybridClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (h *HybridClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type OllamaClient
- func (c *OllamaClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*OllamaClient) ProviderName() string
- func (c *OllamaClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (c *OllamaClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type OpenRouterClient
- func (c *OpenRouterClient) Generate(ctx context.Context, prompt string, maxTokens int) (string, error)
- func (*OpenRouterClient) ProviderName() string
- func (c *OpenRouterClient) Respond(ctx context.Context, system string, history []ChatMessage, maxTokens int) (string, error)
- func (c *OpenRouterClient) StreamRespond(ctx context.Context, system string, history []ChatMessage, maxTokens int, ...) (string, error)
- type ProviderNamer
- type Responder
- type SSEEvent
- type Streamer
Constants ¶
const (
DeepSeekModel = "deepseek-v4-flash"
)
const (
OpenRouterModel = "deepseek/deepseek-v4-flash"
)
Variables ¶
This section is empty.
Functions ¶
func CosineSimilarity ¶
CosineSimilarity returns the cosine similarity between two equal-length vectors.
func EmbedText ¶
EmbedText calls Ollama's native embeddings endpoint with nomic-embed-text. Returns error if Ollama is unreachable.
func NewHTTPClient ¶
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.
Types ¶
type ChatMessage ¶
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 NewClientWithURL ¶
NewClientWithURL returns a Client using a custom URL (for tests).
func (*Client) ProviderName ¶
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) 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) 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) 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) 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) 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 ¶
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) 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.