compaction de contexte, filtre/pagination/suppression des conversations
- compaction automatique du contexte LLM quand la taille atteint le seuil (contexte max - taille de réponse max), par résumé de l'historique ancien - filtre textuel (?q=) et pagination (20/page) de l'historique des conversations - correctif ORM : offset de pagination en base 0 - suppression d'une conversation : messages associés supprimés, session en cours annulée, popup de confirmation (ConfirmDialog) - titres de conversation nettoyés du markdown - styles des listes markdown, variante danger du bouton - go.mod/go.sum : dépendances go-rod et stealth manquantes du commit précédent
This commit is contained in:
1 parent
a970bfa991
commit
51bbb45b32
86 files changed
+770
-113
No files matched your search
@@ -0,0 +1,97 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"trankilou.fr/lassistanoque/backend/internal/domain"
|
||||
)
|
||||
|
||||
type fakeEngine struct{ summary string }
|
||||
|
||||
func (f *fakeEngine) ListProviderTypes() []domain.Item { return nil }
|
||||
func (f *fakeEngine) ListModelsFromProvider(ctx context.Context, p *domain.Provider) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (f *fakeEngine) Stream(ctx context.Context, p *domain.Provider, m string, params *domain.LLMParams, msgs []*domain.Message) *domain.Message {
|
||||
return &domain.Message{}
|
||||
}
|
||||
func (f *fakeEngine) Generate(ctx context.Context, p *domain.Provider, m string, msgs []*domain.Message) (string, error) {
|
||||
return f.summary, nil
|
||||
}
|
||||
|
||||
func mk(role, content string) *domain.Message {
|
||||
return &domain.Message{Role: role, Content: content}
|
||||
}
|
||||
|
||||
func TestEstimateTokens(t *testing.T) {
|
||||
if got := estimateTokens(""); got != 0 {
|
||||
t.Errorf("empty = %d", got)
|
||||
}
|
||||
if got := estimateTokens("abcd"); got != 1 {
|
||||
t.Errorf("abcd = %d", got)
|
||||
}
|
||||
if got := estimateTokens("abcde"); got != 2 {
|
||||
t.Errorf("abcde = %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldCompactThreshold(t *testing.T) {
|
||||
s := &ChatSession{
|
||||
messages: []*domain.Message{mk(string(domain.RoleUser), strings.Repeat("a", 320))}, // 80 tokens
|
||||
contextMaxTokens: 100,
|
||||
maxResponseTokens: 20,
|
||||
}
|
||||
if !s.shouldCompact("system") { // 80 + 1 >= 100-20
|
||||
t.Errorf("should compact at contextMax - maxResponse boundary")
|
||||
}
|
||||
s.maxResponseTokens = 40
|
||||
s.contextMaxTokens = 130 // seuil 130-40=90 > 82 : pas de compaction
|
||||
if s.shouldCompact("system") {
|
||||
t.Errorf("should not compact below threshold")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompactContext(t *testing.T) {
|
||||
s := &ChatSession{
|
||||
provider: &domain.Provider{},
|
||||
llmEngine: &fakeEngine{summary: "resume des echanges"},
|
||||
contextMaxTokens: 100,
|
||||
maxResponseTokens: 10,
|
||||
messages: []*domain.Message{
|
||||
mk(string(domain.RoleUser), "ancienne question 1"),
|
||||
mk(string(domain.RoleAssistant), "ancienne reponse 1"),
|
||||
mk(string(domain.RoleUser), "question courante"),
|
||||
mk(string(domain.RoleAssistant), "reponse courante"),
|
||||
},
|
||||
}
|
||||
|
||||
s.compactContext(context.Background())
|
||||
|
||||
if len(s.messages) != 3 {
|
||||
t.Fatalf("expected 3 messages after compaction, got %d", len(s.messages))
|
||||
}
|
||||
if !strings.Contains(s.messages[0].Content, "resume des echanges") {
|
||||
t.Errorf("first message should be the summary, got %q", s.messages[0].Content)
|
||||
}
|
||||
if s.messages[0].Role != string(domain.RoleUser) {
|
||||
t.Errorf("summary role = %s", s.messages[0].Role)
|
||||
}
|
||||
if s.messages[1].Content != "question courante" || s.messages[2].Content != "reponse courante" {
|
||||
t.Errorf("tail not preserved: %v", s.messages)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompactContextNoUserCut(t *testing.T) {
|
||||
s := &ChatSession{
|
||||
messages: []*domain.Message{
|
||||
mk(string(domain.RoleUser), "seule question"),
|
||||
mk(string(domain.RoleAssistant), "reponse"),
|
||||
},
|
||||
}
|
||||
s.compactContext(context.Background())
|
||||
if len(s.messages) != 2 {
|
||||
t.Errorf("nothing to compact, expected 2 messages, got %d", len(s.messages))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user