service

package
v0.2.3 Latest Latest
Warning

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

Go to latest
Published: May 6, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package service provides memory decision engine for intelligent memory management.

Package service 内的结构化错误,替代独立 pkg/errors,避免多一层 public surface。

Package service provides memory extraction services using LLM.

Package service provides memory extraction services using LLM.

Package service provides the core memory service implementation.

Package service provides namespace policy management.

Package service provides summary generation for memory items and namespaces.

Package service provides Chinese text tokenization using jiebago.

Index

Constants

View Source
const DefaultExtractionJSONSchema = `` /* 658-byte string literal not displayed */

DefaultExtractionJSONSchema 与 DefaultExtractionSystemPrompt 配套。

View Source
const DefaultExtractionSystemPrompt = defaultExtractionSystemBody

DefaultExtractionSystemPrompt 为内建完整 system 提示(含时间/指代段)。

Variables

View Source
var (
	ErrNotFound     = errors.New("item not found")
	ErrConflict     = errors.New("version conflict")
	ErrDuplicate    = errors.New("duplicate item")
	ErrValidation   = errors.New("validation error")
	ErrUnauthorized = errors.New("unauthorized")
	ErrLLM          = errors.New("llm error")
)

标准 sentinels(与 GORM/业务里 errors.Is 配合)

Functions

func BuiltinExtractionPrompt

func BuiltinExtractionPrompt() model.ExtractionPrompt

BuiltinExtractionPrompt 返回代码内建默认;不落库。 dialog_extractions.config_ref 会记录该 ID(prompt-default-v3)作为句柄的一部分。

func DefaultTransientEphemeralSubstrings added in v0.2.3

func DefaultTransientEphemeralSubstrings() []string

DefaultTransientEphemeralSubstrings returns built-in substring cues for noisy transient rows.

func GetLogger

func GetLogger() *slog.Logger

GetLogger returns the package-level logger instance

func SetLogger

func SetLogger(l *slog.Logger)

SetLogger sets the package-level logger (useful for tests)

func TokenizeForSearch

func TokenizeForSearch(text string) string

TokenizeForSearch tokenizes text for search indexing. Uses jiebago's search engine mode for high recall. Long texts are truncated to head+tail to avoid indexing noise from quoted content.

func TokenizeQuery

func TokenizeQuery(query string) string

TokenizeQuery tokenizes user search query. Query is usually short, so no truncation needed.

func WithIsolation added in v0.2.0

func WithIsolation(ctx context.Context, tenantID, userID, sessionID, agentID string) context.Context

WithIsolation sets required isolation identifiers in one call.

Types

type Config

type Config struct {
	// Lifecycle callbacks (all optional)
	OnCreated func(ctx context.Context, item model.MemoryItem)
	OnUpdated func(ctx context.Context, item model.MemoryItem)
	OnDeleted func(ctx context.Context, itemID string)
	OnExpired func(ctx context.Context, itemID string)
}

Config holds configuration and callbacks for MemoryService.

type DecisionEngine

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

DecisionEngine handles intelligent memory decisions

func NewDecisionEngine

func NewDecisionEngine(db *gorm.DB) *DecisionEngine

NewDecisionEngine creates a new decision engine

func (*DecisionEngine) Decide

func (de *DecisionEngine) Decide(ctx context.Context, llmConfig model.LLMConfig, req DecisionRequest) (*DecisionResult, error)

Decide uses LLM to make decisions for each candidate

func (*DecisionEngine) ExecuteDecisions

func (de *DecisionEngine) ExecuteDecisions(ctx context.Context, candidates []ExtractedMemory, decisions []MemoryDecision) (*ExecutionResult, error)

ExecuteDecisions executes the decisions and returns the results

func (*DecisionEngine) FindSimilarMemories

func (de *DecisionEngine) FindSimilarMemories(ctx context.Context, candidate ExtractedMemory, topK int) ([]SimilarMemory, error)

FindSimilarMemories finds existing memories similar to the candidate using FTS5 BM25

type DecisionExecutionSummary

type DecisionExecutionSummary struct {
	Added   []string `json:"added"`
	Updated []string `json:"updated"`
	Deleted []string `json:"deleted"`
	Ignored []string `json:"ignored"`
	Merged  []string `json:"merged"`
	Errors  []string `json:"errors,omitempty"`
}

DecisionExecutionSummary contains the results of decision-based persistence

type DecisionRequest

type DecisionRequest struct {
	Candidates      []ExtractedMemory `json:"candidates"`
	SimilarMemories []SimilarMemory   `json:"similar_memories"`
	DialogContext   string            `json:"dialog_context"`
}

DecisionRequest contains candidates and similar memories for decision making

type DecisionResult

type DecisionResult struct {
	Decisions      []MemoryDecision `json:"decisions"`
	TotalTokens    int              `json:"total_tokens"`
	ProcessingTime int              `json:"processing_time_ms"`
}

DecisionResult contains all decisions

type DecisionType

type DecisionType string

DecisionType represents the decision for a memory candidate

const (
	DecisionAdd    DecisionType = "ADD"    // Add new memory
	DecisionUpdate DecisionType = "UPDATE" // Update existing memory
	DecisionDelete DecisionType = "DELETE" // Delete outdated memory
	DecisionIgnore DecisionType = "IGNORE" // Ignore this candidate
	DecisionMerge  DecisionType = "MERGE"  // Merge with existing memory
)

type ErrorCode

type ErrorCode string

ErrorCode 用于可编程分支。

const (
	CodeNotFound     ErrorCode = "NOT_FOUND"
	CodeConflict     ErrorCode = "CONFLICT"
	CodeDuplicate    ErrorCode = "DUPLICATE"
	CodeValidation   ErrorCode = "VALIDATION"
	CodeUnauthorized ErrorCode = "UNAUTHORIZED"
	CodeLLM          ErrorCode = "LLM_ERROR"
	CodeInternal     ErrorCode = "INTERNAL"
)

type ExecutionResult

type ExecutionResult struct {
	Added   []string
	Updated []string
	Deleted []string
	Ignored []string
	Merged  []string
	Errors  []string
}

ExecutionResult contains the results of decision execution

type ExtractPolicy added in v0.2.3

type ExtractPolicy struct {
	// DropTransientEphemeral removes NamespaceTransient memories whose normalized text contains
	// ephemeral cues (wall-clock, calendar extrapolation). Useful for hosts that still want
	// transient rows but not “what time is it” noise.
	DropTransientEphemeral bool
	// TransientEphemeralSubstrings overrides substring cues (case-insensitive).
	// Empty/nil with DropTransientEphemeral uses DefaultTransientEphemeralSubstrings().
	TransientEphemeralSubstrings []string
}

ExtractPolicy configures reusable post-LLM filtering applied after the MinConfidence gate and before optional PostExtractHook / persistence.

type ExtractRequest

type ExtractRequest struct {
	DialogText        string
	LLMConfigID       string // deprecated: database lookup is no longer supported
	PromptID          string // deprecated: database lookup is no longer supported
	ContextMemories   []string
	MinConfidence     float64 // default 0.7
	DryRun            bool
	UseDecisionEngine bool // default false, if true uses new extract → similar → decide → persist flow
	SimilarTopK       int  // default 5, number of similar memories to fetch per candidate

	// ReferenceTime is the instant treated as "now" for resolving relative time (e.g. 明天, next week).
	// If nil, Extract uses the wall-clock time when the request runs.
	ReferenceTime *time.Time
	// TimeZone is an IANA name (e.g. "Asia/Shanghai", "America/New_York") for presenting reference
	// instants in the model prompt. Empty = use the location of ReferenceTime (or local wall clock).
	TimeZone string
	// ResolutionContext is optional free text: user display name, who 他/她/经理 refers to, session
	// participants, etc. The model is instructed to replace vague references in stored title/content/summary.
	ResolutionContext string

	// LLMConfig must be provided directly in code.
	LLMConfig *model.LLMConfig

	// ExtractionPrompt allows passing prompt directly in code.
	// If nil, builtin default prompt is used.
	ExtractionPrompt *model.ExtractionPrompt

	// ExtractPolicy applies extra filtering after MinConfidence (e.g. transient ephemeral cues).
	ExtractPolicy *ExtractPolicy

	// PostExtractHook runs after MinConfidence and ExtractPolicy, before persistence.
	PostExtractHook func(ctx context.Context, mem []ExtractedMemory) ([]ExtractedMemory, error)
}

ExtractRequest represents a dialog extraction request

type ExtractResult

type ExtractResult struct {
	ExtractionID   string
	Status         string
	Memories       []ExtractedMemory
	TotalTokens    int
	ProcessingTime int // ms

	// Decision engine results (when UseDecisionEngine is true)
	DecisionResult *DecisionExecutionSummary `json:"decision_result,omitempty"`
}

ExtractResult represents the extraction result

func QuickExtract

func QuickExtract(ctx context.Context, db *gorm.DB, dialogText string, llmCfg *model.LLMConfig) (*ExtractResult, error)

QuickExtract is a convenience function for code-only extraction without DB setup. Useful for simple scripts or when you want to pass config directly each time. Example:

cfg := &model.LLMConfig{
    APIKey:   os.Getenv("OPENAI_API_KEY"),
    Model:    "gpt-4o",
}
result, err := service.QuickExtract(ctx, db, dialogText, cfg)

type ExtractedMemory

type ExtractedMemory struct {
	TempID       string                 `json:"temp_id"`
	Namespace    model.NamespaceType    `json:"namespace"`
	Title        string                 `json:"title"`
	Content      string                 `json:"content"`
	Summary      string                 `json:"summary,omitempty"`
	Tags         []string               `json:"tags,omitempty"`
	Importance   int                    `json:"importance"`
	Confidence   float64                `json:"confidence"`
	Reasoning    string                 `json:"reasoning,omitempty"`
	TaskMetadata map[string]interface{} `json:"task_metadata,omitempty"`
}

ExtractedMemory represents a single extracted memory item

func ApplyExtractPolicy added in v0.2.3

func ApplyExtractPolicy(mem []ExtractedMemory, policy *ExtractPolicy) []ExtractedMemory

ApplyExtractPolicy applies policy filters to an in-memory slice (non-destructive).

type Extractor

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

Extractor handles dialog to memory extraction

func NewExtractor

func NewExtractor(db *gorm.DB) *Extractor

NewExtractor creates a new extractor instance

func (*Extractor) Extract

func (e *Extractor) Extract(ctx context.Context, req ExtractRequest) (*ExtractResult, error)

Extract processes dialog text and extracts memories In production, this would call actual LLM API

type ForgetRequest

type ForgetRequest struct {
	ItemIDs       []string
	Namespace     string
	NamespaceType model.NamespaceType
	Mode          string // "soft" (default), "hard", "expire"
	Reason        string
}

ForgetRequest represents a request to forget memories.

type IsolationMeta added in v0.2.0

type IsolationMeta struct {
	TenantID  string
	UserID    string
	SessionID string
	AgentID   string
}

IsolationMeta carries isolation identifiers extracted from context.

func IsolationFromContext added in v0.2.0

func IsolationFromContext(ctx context.Context) (IsolationMeta, error)

type ListRequest added in v0.1.1

type ListRequest struct {
	Namespaces     []string
	NamespaceTypes []model.NamespaceType
	TagsAny        []string
	TagsAll        []string
	TimeRangeStart *time.Time
	TimeRangeEnd   *time.Time
	IncludeExpired bool
	MinConfidence  float64
	MinImportance  int
	TopK           int
	Offset         int
	ExcludeItemIDs []string
	Order          string // "desc" (default) or "asc", based on created_at
}

ListRequest represents a request to list memories by time.

type MemoryDecision

type MemoryDecision struct {
	Decision      DecisionType `json:"decision"`
	TargetID      string       `json:"target_id,omitempty"` // Existing memory ID for UPDATE/DELETE/MERGE
	Reason        string       `json:"reason"`
	Confidence    float64      `json:"confidence"`
	MergedContent string       `json:"merged_content,omitempty"` // For MERGE: merged content
	MergedTitle   string       `json:"merged_title,omitempty"`   // For MERGE: merged title
	NewImportance int          `json:"new_importance,omitempty"` // Suggested importance after action
}

MemoryDecision represents the decision for a single memory candidate

type MemoryError

type MemoryError struct {
	Code    ErrorCode
	Message string
	Cause   error
	Retry   bool
}

MemoryError 带 code / 链式 unwrap。

func ErrorAs

func ErrorAs(err error) (*MemoryError, bool)

ErrorAs 从错误链取出 *MemoryError(兼容 errors.As)。

func ErrorNew

func ErrorNew(code ErrorCode, message string) *MemoryError

ErrorNew 与 ErrorWrap、ErrorAs 供根包重导出,或需直接 import service 的调用方使用。

func ErrorWrap

func ErrorWrap(code ErrorCode, message string, cause error) *MemoryError

func (*MemoryError) Error

func (e *MemoryError) Error() string

func (*MemoryError) Unwrap

func (e *MemoryError) Unwrap() error

type MemoryHit

type MemoryHit struct {
	model.MemoryItem
	Score           float64
	FTSScore        float64
	RecencyScore    float64
	ImportanceScore float64
	ConfidenceScore float64
	MatchReasons    []string
}

MemoryHit represents a recalled memory with relevance info.

type MemoryService

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

MemoryService provides core memory operations.

func NewMemoryService

func NewMemoryService(db *gorm.DB) *MemoryService

NewMemoryService creates a new memory service instance.

func (*MemoryService) CleanupExpired

func (s *MemoryService) CleanupExpired(ctx context.Context) (int64, error)

CleanupExpired marks expired items as expired status (soft cleanup).

func (*MemoryService) Forget

func (s *MemoryService) Forget(ctx context.Context, req ForgetRequest) (int, error)

Forget removes or marks memories as deleted/expired.

func (*MemoryService) List added in v0.1.1

List returns memories ordered by created_at.

func (*MemoryService) PurgeDeleted

func (s *MemoryService) PurgeDeleted(ctx context.Context, before time.Time) (int64, error)

PurgeDeleted physically deletes soft-deleted items and moves them to deleted_items.

func (*MemoryService) RebuildFTS

func (s *MemoryService) RebuildFTS(ctx context.Context) error

RebuildFTS rebuilds the FTS5 virtual table from scratch (emergency use).

func (*MemoryService) Recall

func (s *MemoryService) Recall(ctx context.Context, req RecallRequest) ([]MemoryHit, error)

Recall searches for memories using FTS and filtering.

func (*MemoryService) Remember

func (s *MemoryService) Remember(ctx context.Context, req RememberRequest) (string, error)

Remember stores a memory item with idempotency support.

func (*MemoryService) RenewExpiration

func (s *MemoryService) RenewExpiration(ctx context.Context, itemID string, ttlSeconds int) error

RenewExpiration manually renews the expiration time for an item.

func (*MemoryService) Touch

func (s *MemoryService) Touch(ctx context.Context, itemID string) error

Touch updates access statistics for an item (used for sliding TTL).

func (*MemoryService) TouchWithRenew

func (s *MemoryService) TouchWithRenew(ctx context.Context, itemID string, threshold int, ttlSeconds int) (renewed bool, err error)

TouchWithRenew updates access stats and renews expiration for sliding TTL items. threshold: access count threshold to trigger renewal (e.g., every 3rd access) ttlSeconds: new TTL duration to set when renewing

func (*MemoryService) Update

func (s *MemoryService) Update(ctx context.Context, req UpdateRequest) error

Update modifies a memory item with optimistic locking.

func (*MemoryService) ValidateFTS added in v0.2.2

func (s *MemoryService) ValidateFTS(ctx context.Context) (bool, error)

ValidateFTS validates that active memory rows and FTS rows are in sync.

func (*MemoryService) WithConfig

func (s *MemoryService) WithConfig(config Config) *MemoryService

WithConfig sets the configuration for the memory service. Returns the service for method chaining.

type PolicyManager

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

PolicyManager handles namespace policy resolution.

func NewPolicyManager

func NewPolicyManager(db *gorm.DB) *PolicyManager

NewPolicyManager creates a new policy manager.

func (*PolicyManager) GetPolicy

func (pm *PolicyManager) GetPolicy(ctx context.Context, namespace string) (model.NamespacePolicy, error)

GetPolicy retrieves the policy for a namespace (exact match first, then type default).

func (*PolicyManager) GetRankWeights

func (pm *PolicyManager) GetRankWeights(policy model.NamespacePolicy) (fts, recency, importance, confidence float64)

GetRankWeights parses the rank weights JSON from a policy.

func (*PolicyManager) SetPolicy

func (pm *PolicyManager) SetPolicy(ctx context.Context, policy model.NamespacePolicy) error

SetPolicy sets a custom policy for a namespace (exact match only).

type RecallRequest

type RecallRequest struct {
	Query          string
	Namespaces     []string
	NamespaceTypes []model.NamespaceType
	TagsAny        []string
	TagsAll        []string
	TimeRangeStart *time.Time
	TimeRangeEnd   *time.Time
	IncludeExpired bool
	MinConfidence  float64
	MinImportance  int
	TopK           int
	ExcludeItemIDs []string
}

RecallRequest represents a request to recall memories.

type RememberRequest

type RememberRequest struct {
	NamespaceType model.NamespaceType
	Title         string
	Content       string
	Summary       string
	Tags          []string
	SourceType    model.SourceType
	SourceRef     string
	Importance    int
	Confidence    float64
	TTLSeconds    *int
	DedupeKey     *string
}

RememberRequest represents a request to store a memory.

type SimilarMemory

type SimilarMemory struct {
	ID         string   `json:"id"`
	Namespace  string   `json:"namespace"`
	Title      string   `json:"title"`
	Content    string   `json:"content"`
	Summary    string   `json:"summary"`
	Tags       []string `json:"tags"`
	Importance int      `json:"importance"`
	Confidence float64  `json:"confidence"`
	CreatedAt  string   `json:"created_at"`
	Similarity float64  `json:"similarity"` // 0-1 similarity score
}

SimilarMemory represents a potentially related existing memory

type SummaryGenerator

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

SummaryGenerator handles summary generation for items and namespaces.

func NewSummaryGenerator

func NewSummaryGenerator(db *gorm.DB) *SummaryGenerator

NewSummaryGenerator creates a new summary generator.

func (*SummaryGenerator) GenerateItemSummary

func (g *SummaryGenerator) GenerateItemSummary(ctx context.Context, itemID string) error

GenerateItemSummary generates a summary for a single memory item. In production, this would call an LLM to summarize. For now, it truncates content.

func (*SummaryGenerator) GenerateNamespaceSummary

func (g *SummaryGenerator) GenerateNamespaceSummary(ctx context.Context, namespace string) (string, error)

GenerateNamespaceSummary generates a summary for a namespace.

type UpdateRequest

type UpdateRequest struct {
	ItemID          string
	Title           *string
	Content         *string
	Summary         *string
	Tags            []string
	Importance      *int
	Confidence      *float64
	ExpectedVersion int // For optimistic locking
}

UpdateRequest represents a request to update a memory.

Jump to

Keyboard shortcuts

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