Skip to content

Commit 10f0442

Browse files
committed
Updated how initial prompt is handled (Release v0.2.0)
1 parent 08bd3d1 commit 10f0442

5 files changed

Lines changed: 66 additions & 22 deletions

File tree

cmd/tinymem/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ func setupServices(a *app.App) (*evidence.Service, recall.Recaller, *inject.Memo
163163
} else {
164164
recallEngine = recall.NewEngine(a.Memory, evidenceService, a.Core.Config, a.Core.Logger, a.Core.DB.GetConnection())
165165
}
166-
injector := inject.NewMemoryInjector(recallEngine)
166+
injector := inject.NewMemoryInjector(recallEngine, a.Core.Logger, a.Core.Config.AlwaysIncludeUserPrompt)
167167
return evidenceService, recallEngine, injector
168168
}
169169

internal/config/config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Config struct {
4747
ExtractionBufferBytes int
4848
RecallMaxItems int
4949
RecallMaxTokens int
50+
AlwaysIncludeUserPrompt bool
5051
// Metrics configuration
5152
MetricsEnabled bool
5253
// CoVe (Chain-of-Verification) configuration
@@ -91,6 +92,9 @@ type fileConfig struct {
9192
BaseURL string `toml:"base_url"`
9293
Model string `toml:"model"`
9394
} `toml:"embedding"`
95+
Prompt struct {
96+
AlwaysIncludeUserPrompt *bool `toml:"always_include_user_prompt"`
97+
} `toml:"prompt"`
9498
Metrics struct {
9599
Enabled bool `toml:"enabled"`
96100
} `toml:"metrics"`
@@ -141,6 +145,7 @@ func LoadConfig() (*Config, error) {
141145
ExtractionBufferBytes: DefaultExtractionBufferBytes,
142146
RecallMaxItems: 10,
143147
RecallMaxTokens: 2000,
148+
AlwaysIncludeUserPrompt: true,
144149
MetricsEnabled: false,
145150
// CoVe defaults (enabled by default)
146151
CoVeEnabled: true,
@@ -214,6 +219,9 @@ func LoadConfig() (*Config, error) {
214219
if parsed.Embedding.Model != "" {
215220
cfg.EmbeddingModel = parsed.Embedding.Model
216221
}
222+
if parsed.Prompt.AlwaysIncludeUserPrompt != nil {
223+
cfg.AlwaysIncludeUserPrompt = *parsed.Prompt.AlwaysIncludeUserPrompt
224+
}
217225
// Metrics configuration
218226
cfg.MetricsEnabled = parsed.Metrics.Enabled
219227
// CoVe configuration (only override defaults if [cove] is present)

internal/inject/injector.go

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,28 @@ import (
66
"github.com/daverage/tinymem/internal/cove"
77
"github.com/daverage/tinymem/internal/memory"
88
"github.com/daverage/tinymem/internal/recall"
9+
"go.uber.org/zap"
910
"strconv"
1011
"strings"
1112
)
1213

14+
const noMemorySentinel = "[no memory found; continue with user request]"
15+
1316
// MemoryInjector handles injecting memories into prompts
1417
type MemoryInjector struct {
15-
recallEngine recall.Recaller
16-
coveVerifier *cove.Verifier
18+
recallEngine recall.Recaller
19+
coveVerifier *cove.Verifier
20+
logger *zap.Logger
21+
alwaysIncludeUserPrompt bool
1722
}
1823

1924
// NewMemoryInjector creates a new memory injector
20-
func NewMemoryInjector(recallEngine recall.Recaller) *MemoryInjector {
25+
func NewMemoryInjector(recallEngine recall.Recaller, logger *zap.Logger, alwaysIncludeUserPrompt bool) *MemoryInjector {
2126
return &MemoryInjector{
22-
recallEngine: recallEngine,
23-
coveVerifier: nil, // Can be set later via SetCoVeVerifier
27+
recallEngine: recallEngine,
28+
coveVerifier: nil, // Can be set later via SetCoVeVerifier
29+
logger: logger,
30+
alwaysIncludeUserPrompt: alwaysIncludeUserPrompt,
2431
}
2532
}
2633

@@ -45,32 +52,57 @@ func (mi *MemoryInjector) FilterRecallResults(ctx context.Context, results []rec
4552

4653
// InjectMemoriesIntoPrompt injects relevant memories into a prompt
4754
func (mi *MemoryInjector) InjectMemoriesIntoPrompt(prompt string, projectID string, maxItems int, maxTokens int) (string, error) {
55+
basePrompt := prompt
56+
4857
// Perform recall to find relevant memories
4958
results, err := mi.recallEngine.Recall(recall.RecallOptions{
5059
ProjectID: projectID,
51-
Query: prompt,
60+
Query: basePrompt,
5261
MaxItems: maxItems,
5362
MaxTokens: maxTokens,
5463
})
5564
if err != nil {
5665
return "", err
5766
}
5867

59-
if len(results) == 0 {
60-
// No relevant memories found, return original prompt
61-
return prompt, nil
62-
}
68+
if !mi.alwaysIncludeUserPrompt {
69+
if len(results) == 0 {
70+
return prompt, nil
71+
}
72+
73+
results = mi.FilterRecallResults(context.Background(), results, basePrompt)
74+
if len(results) == 0 {
75+
return prompt, nil
76+
}
6377

64-
// COVE INTEGRATION POINT 2: Optional recall filtering (advisory only)
65-
// This can only remove memories, never add new ones.
66-
results = mi.FilterRecallResults(context.Background(), results, prompt)
78+
memorySection := buildMemorySection(results)
79+
return memorySection + prompt, nil
80+
}
6781

82+
results = mi.FilterRecallResults(context.Background(), results, basePrompt)
6883
if len(results) == 0 {
69-
// All memories filtered out, return original prompt
70-
return prompt, nil
84+
mi.logZeroMemoryPath()
85+
finalBuilder := strings.Builder{}
86+
finalBuilder.WriteString(basePrompt)
87+
finalBuilder.WriteString("\n\n")
88+
finalBuilder.WriteString(noMemorySentinel)
89+
finalBuilder.WriteString("\n")
90+
return finalBuilder.String(), nil
7191
}
7292

73-
// Build memory section
93+
memorySection := buildMemorySection(results)
94+
95+
var finalBuilder strings.Builder
96+
finalBuilder.WriteString(basePrompt)
97+
finalBuilder.WriteString("\n\n")
98+
finalBuilder.WriteString(noMemorySentinel)
99+
finalBuilder.WriteString("\n")
100+
finalBuilder.WriteString(memorySection)
101+
102+
return finalBuilder.String(), nil
103+
}
104+
105+
func buildMemorySection(results []recall.RecallResult) string {
74106
var memorySection strings.Builder
75107
memorySection.WriteString("\n\n=== RELEVANT MEMORY ===\n")
76108

@@ -96,10 +128,14 @@ func (mi *MemoryInjector) InjectMemoriesIntoPrompt(prompt string, projectID stri
96128

97129
memorySection.WriteString("=== END MEMORY ===\n")
98130

99-
// Prepend memories to the original prompt
100-
injectedPrompt := memorySection.String() + prompt
131+
return memorySection.String()
132+
}
101133

102-
return injectedPrompt, nil
134+
func (mi *MemoryInjector) logZeroMemoryPath() {
135+
if mi.logger == nil {
136+
return
137+
}
138+
mi.logger.Info("zero-memory prompt path", zap.String("layer", "memory_injector"))
103139
}
104140

105141
// FormatMemoriesForSystemMessage formats memories in a structured way for system messages

internal/server/proxy/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func NewServer(a *app.App) *Server {
7474
} else {
7575
recallEngine = recall.NewEngine(a.Memory, evidenceService, a.Core.Config, a.Core.Logger, a.Core.DB.GetConnection())
7676
}
77-
injector := inject.NewMemoryInjector(recallEngine)
77+
injector := inject.NewMemoryInjector(recallEngine, a.Core.Logger, a.Core.Config.AlwaysIncludeUserPrompt)
7878
llmClient := llm.NewClient(a.Core.Config)
7979
extractor := extract.NewExtractor(evidenceService)
8080
taskService := tasks.NewService(a.Core.DB, a.Memory, a.Project.ID)

internal/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ package version
22

33
// Version is the current version of tinyMem
44
// This can be overridden at build time using -ldflags "-X github.com/daverage/tinymem/internal/version.Version=vX.Y.Z"
5-
var Version = "v0.1.23"
5+
var Version = "v0.2.0"

0 commit comments

Comments
 (0)