chat

package
v0.61.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package chat composes retrieval with chat models through the rag domain contracts. It owns query transforms, expansion, model-backed ranking, contextual prompts, and retrieval preparation for chat requests. Chat history and prompt policy remain here; queries, candidates, citations, and generation input retain their owners in rag.

Index

Examples

Constants

View Source
const DefaultMultiQueryCount = 3

Variables

View Source
var (
	ErrNilResponse = errors.New("rag: chat model returned a nil response")
	// ErrNoFinalUserMessage rejects requests whose active retrieval query is
	// ambiguous.
	ErrNoFinalUserMessage = errors.New("rag: chat request must end with a user message")
)
View Source
var ErrContextBudgetExceeded = errors.New("rag: context token budget cannot admit evidence")

ErrContextBudgetExceeded means retrieved evidence exists but no complete candidate fits the configured context budget.

View Source
var ErrEmptyModelOutput = errors.New("rag: model returned empty query text")

ErrEmptyModelOutput classifies a model response that rag.Query will not accept as query text, such as text that is empty or blank after trimming. Query owns that admission rule; this sentinel only records that the rejected text came from the model, so a caller can tell it apart from its own invalid query. Missing response text and unsuccessful completion preserve the chatclient errors.

View Source
var ErrInvalidContextBudget = errors.New("rag: invalid context token budget")

ErrInvalidContextBudget identifies an invalid context window or token measurement.

Functions

This section is empty.

Types

type CompressionTransformer

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

func (*CompressionTransformer) Transform

type CompressionTransformerConfig

type CompressionTransformerConfig struct {
	Model corechat.Model

	// PromptTemplate replaces the built-in prompt and must declare
	// {{.History}} and {{.Query}}.
	PromptTemplate *chatclient.Template
}

type ContextualAugmenter

type ContextualAugmenter struct {
	// contains filtered or unexported fields
}
Example
package main

import (
	"context"
	"fmt"

	"github.com/Tangerg/scope/core/document"
	"github.com/Tangerg/scope/rag"

	ragchat "github.com/Tangerg/scope/rag/chat"
)

func main() {
	augmenter, err := ragchat.NewContextualAugmenter(ragchat.ContextualAugmenterConfig{})
	if err != nil {
		panic(err)
	}
	query, err := rag.NewQuery("What does Scope provide?")
	if err != nil {
		panic(err)
	}
	doc, err := document.NewDocument("Scope provides AI infrastructure.", nil)
	if err != nil {
		panic(err)
	}
	doc.ID = "scope"
	doc.Provenance = document.NewProvenance("scope.txt", []byte(doc.Text))
	result, err := augmenter.Augment(context.Background(), query, rag.Candidates{{Document: doc, Score: 1}})
	if err != nil {
		panic(err)
	}
	doc, err = result.Citations().Resolve("[1]")
	if err != nil {
		panic(err)
	}
	fmt.Println(doc.ID, doc.Provenance.Source)
}
Output:
scope scope.txt

func NewContextualAugmenter

func NewContextualAugmenter(config ContextualAugmenterConfig) (*ContextualAugmenter, error)

func (*ContextualAugmenter) Augment

func (c *ContextualAugmenter) Augment(ctx context.Context, query rag.Query, candidates rag.Candidates) (rag.Augmentation, error)

type ContextualAugmenterConfig

type ContextualAugmenterConfig struct {
	// Instructions is the guidance placed before the evidence block. The
	// augmenter always writes the evidence block and the query itself, so a
	// citation can never claim evidence the prompt omits. Empty uses the default.
	Instructions string

	// EmptyContextMessage is the prompt used when no documents are retrieved and
	// AllowEmptyContext is false. Empty uses the default.
	EmptyContextMessage string

	// AllowEmptyContext returns the query unchanged when no documents are
	// retrieved instead of using EmptyContextMessage.
	AllowEmptyContext bool

	// Formatter renders each retrieved document. The default [document.TextFormatter]
	// rejects media with [document.ErrUnsupportedMedia].
	Formatter document.Formatter

	// MaxContextTokens limits the encoded evidence block. Zero leaves context
	// unbounded. A positive value requires TokenCounter. Only complete
	// candidates that fit are included, in retrieval order. Oversized candidates
	// are skipped so later candidates can still fit. If none fits, Augment returns
	// ErrContextBudgetExceeded regardless of AllowEmptyContext.
	MaxContextTokens int
	TokenCounter     tokenizer.TextCounter
}

type ConversationQuery added in v0.60.0

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

ConversationQuery makes the history dependency of a chat query transform explicit. History is a private snapshot preceding the active user turn; generic retrieval stages receive only the resulting rag.Query.

func NewConversationQuery added in v0.60.0

func NewConversationQuery(query rag.Query, history []corechat.Message) (ConversationQuery, error)

func (ConversationQuery) History added in v0.60.0

func (c ConversationQuery) History() []corechat.Message

func (ConversationQuery) Query added in v0.60.0

func (c ConversationQuery) Query() rag.Query

func (ConversationQuery) Validate added in v0.60.0

func (c ConversationQuery) Validate() error

type ConversationTransformer added in v0.60.0

type ConversationTransformer interface {
	Transform(context.Context, ConversationQuery) (rag.Query, error)
}

type ConversationTransformerFunc added in v0.60.0

type ConversationTransformerFunc func(context.Context, ConversationQuery) (rag.Query, error)

func (ConversationTransformerFunc) Transform added in v0.60.0

type MultiQueryExpander

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

func NewMultiQueryExpander

func NewMultiQueryExpander(config MultiQueryExpanderConfig) (*MultiQueryExpander, error)

func (*MultiQueryExpander) Expand

func (m *MultiQueryExpander) Expand(ctx context.Context, query rag.Query) ([]rag.Query, error)

Expand requires exactly NumberOfQueries distinct variants; empty, duplicate, and original-query entries do not count toward it. No usable variant returns rag.ErrEmptyExpansion.

type MultiQueryExpanderConfig

type MultiQueryExpanderConfig struct {
	Model corechat.Model

	// IncludeOriginal prepends the original query to the variant list.
	IncludeOriginal bool

	// NumberOfQueries is the variant count requested from the model. Zero
	// uses [DefaultMultiQueryCount]; negative values are invalid.
	NumberOfQueries int

	// PromptTemplate replaces the built-in prompt and must declare
	// {{.Number}} and {{.Query}}.
	PromptTemplate *chatclient.Template
}

type PreparedRequest added in v0.19.0

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

PreparedRequest owns an immutable augmented request and its retrieval evidence. Its zero value is invalid. Prepare once, then pass the complete model or tool orchestration to Call or Stream; downstream continuations never retrieve again.

func (PreparedRequest) Call added in v0.19.0

Call runs the prepared request through next. Retrieval remains on the prepared request; this call never retrieves again, including on a model failure.

func (PreparedRequest) Retrieval added in v0.60.0

func (p PreparedRequest) Retrieval() Retrieval

Retrieval returns an owned candidate snapshot and the immutable prompt citations. Complete documents are never added to model response metadata implicitly.

func (PreparedRequest) Stream added in v0.19.0

Stream starts model work lazily and never retrieves again; stopping iteration releases the downstream stream.

type Preparer added in v0.19.0

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

Preparer owns retrieval and augmentation at the start of a user turn. It is immutable after construction and safe for concurrent use when its Retriever, Augmenter and QueryTransformer are safe for concurrent use. Preservation keeps every user Part. Text replacements require exactly one text Part and preserve all other Parts and their relative positions; ambiguous rewrites fail with rag.ErrInvalidAugmentation before calling the model.

Example
preparer, err := ragchat.NewPreparer(ragchat.PreparerConfig{
	Retriever: rag.RetrieverFunc(func(context.Context, rag.Query) (rag.Candidates, error) {
		return rag.Candidates{{Document: &document.Document{Text: "Scope provides AI infrastructure."}}}, nil
	}),
	Augmenter: rag.IdentityAugmenter(),
})
if err != nil {
	panic(err)
}
ctx := context.Background()
request, err := chat.NewRequest(chat.NewUserMessage(chat.NewTextPart("What is Scope?")))
if err != nil {
	panic(err)
}
prepared, err := preparer.Prepare(ctx, request)
if err != nil {
	panic(err)
}
model := chat.ModelFunc(func(context.Context, *chat.Request) (*chat.Response, error) {
	return textResponse("AI infrastructure"), nil
})
response, err := prepared.Call(ctx, model)
if err != nil {
	panic(err)
}
candidates := prepared.Retrieval().Candidates
fmt.Println(response.Text(), len(candidates))
Output:
AI infrastructure 1

func NewPreparer added in v0.19.0

func NewPreparer(config PreparerConfig) (*Preparer, error)

func (*Preparer) Prepare added in v0.19.0

func (p *Preparer) Prepare(ctx context.Context, request *corechat.Request) (PreparedRequest, error)

Prepare snapshots request and retrieves evidence for its final user message. Retrieval and augmentation finish before any model or tool execution begins.

type PreparerConfig added in v0.19.0

type PreparerConfig struct {
	Retriever rag.Retriever
	// QueryTransformer resolves conversational context for retrieval only;
	// augmentation still receives the active user question. Nil preserves it.
	QueryTransformer ConversationTransformer

	// Augmenter folds retrieved documents into the outgoing user message.
	// Required; use [rag.IdentityAugmenter] for retrieval without prompt changes.
	Augmenter rag.Augmenter
}

type RerankModel added in v0.60.0

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

RerankModel uses the canonical rerank contract, so candidate formatting and document ownership remain with rag/rerank.Refiner. It ranks every input before applying TopK; a shortened answer cannot hide a missing or repeated index.

Example
ctx := context.Background()
model, err := ragchat.NewRerankModel(ctx, ragchat.RerankModelConfig{
	Model: chat.ModelFunc(func(context.Context, *chat.Request) (*chat.Response, error) {
		return textResponse(`{"scores":[{"index":0,"score":0.2},{"index":1,"score":0.9}]}`), nil
	}),
})
if err != nil {
	panic(err)
}
refiner, err := ragrerank.NewRefiner(ragrerank.RefinerConfig{Model: model, TopK: 1})
if err != nil {
	panic(err)
}
query, err := rag.NewQuery("What is Scope?")
if err != nil {
	panic(err)
}
ranked, err := refiner.Refine(ctx, query, rag.Candidates{
	{Document: &document.Document{ID: "unrelated", Text: "A different topic."}},
	{Document: &document.Document{ID: "scope", Text: "Scope provides AI infrastructure."}},
})
if err != nil {
	panic(err)
}
fmt.Println(ranked[0].Document.ID, ranked[0].Score)
Output:
scope 0.9

func NewRerankModel added in v0.60.0

func NewRerankModel(_ context.Context, config RerankModelConfig) (*RerankModel, error)

func (*RerankModel) Call added in v0.60.0

type RerankModelConfig added in v0.60.0

type RerankModelConfig struct {
	Model corechat.Model
	// Templates must use Query and Documents so the original index remains the
	// only identity a generated ranking can return.
	PromptTemplate *chatclient.Template
}

type Retrieval added in v0.60.0

type Retrieval struct {
	Candidates rag.Candidates
	Citations  rag.Citations
}

Retrieval is what one prepared request retrieved and cited. It belongs to RAG and remains available independently of model success or stream consumption.

type RewriteTransformer

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

func NewRewriteTransformer

func NewRewriteTransformer(config RewriteTransformerConfig) (*RewriteTransformer, error)

func (*RewriteTransformer) Transform

func (r *RewriteTransformer) Transform(ctx context.Context, query rag.Query) (rag.Query, error)

type RewriteTransformerConfig

type RewriteTransformerConfig struct {
	Model corechat.Model

	// TargetSearchSystem names the downstream search engine — "vector
	// store", "web search engine", "database", etc. Required.
	TargetSearchSystem string

	// PromptTemplate replaces the built-in prompt and must declare
	// {{.Target}} and {{.Query}}.
	PromptTemplate *chatclient.Template
}

type TranslationTransformer

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

func (*TranslationTransformer) Transform

func (t *TranslationTransformer) Transform(ctx context.Context, query rag.Query) (rag.Query, error)

type TranslationTransformerConfig

type TranslationTransformerConfig struct {
	Model corechat.Model

	// TargetLanguage is the language the embedding model expects —
	// "English", "Chinese", "Spanish", etc. Required.
	TargetLanguage string

	// PromptTemplate replaces the built-in prompt and must declare
	// {{.Target}} and {{.Query}}.
	PromptTemplate *chatclient.Template
}

Jump to

Keyboard shortcuts

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