Files
fabien 51bbb45b32 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
2026-10-05 23:46:12 +02:00

64 lines
2.1 KiB
Go

package chat
import (
"context"
"log/slog"
"strings"
"trankilou.fr/lassistanoque/backend/internal/domain"
)
// markdownDecorations liste les marqueurs markdown susceptibles d'apparaître
// dans un titre généré par un LLM.
var markdownDecorations = []string{"**", "__", "~~", "*", "_", "~", "#", "`"}
func sanitizeTitle(title string) string {
title = strings.TrimSpace(title)
// le titre doit tenir sur une ligne
title = strings.ReplaceAll(title, "\n", " ")
// guillemets et tirets d'encadrement ajoutés par le LLM
title = strings.Trim(title, `"'«»`)
// décorations markdown
for _, marker := range markdownDecorations {
title = strings.ReplaceAll(title, marker, "")
}
// espaces multiples créés par les suppressions
title = strings.Join(strings.Fields(title), " ")
return strings.TrimSpace(title)
}
func (s *Service) RefreshTitles(provider *domain.Provider, modelID string, teamID string) {
ctx := context.Background()
chats, err := s.repoChat.ListChatsWithUnfreshTitles(teamID)
if err != nil {
slog.Error("RefreshTitles.ListChats", "error", err)
}
for _, chat := range chats {
newchat, _ := s.repoChat.GetChat(chat.UserID, chat.TeamID, chat.ID)
if !chat.FreshTitle {
messages, err := s.repoChat.GetChatMessages(newchat.UserID, newchat.TeamID, newchat.ID, true)
if err != nil {
slog.Error("RefreshTitles.GetMessages", "error", err)
}
title, err := s.llmEngine.Generate(ctx, provider, modelID, append(messages, &domain.Message{
Role: string(domain.RoleSystem),
Content: "Tu génères un titre de conversation. Réponds uniquement par le titre, " +
"en texte brut : jamais de markdown (pas de **, *, _, ~, #), " +
"pas de guillemets, pas de liste, pas de ponctuation finale.",
}, &domain.Message{
Role: string(domain.RoleUser),
Content: "Résume toute la conversation dans un titre entre 5 et 10 mots, en texte brut, sans aucun formatage.",
}))
if err != nil {
slog.Error("RefreshTitles.Generate", "error", err)
}
newchat.FreshTitle = true
newchat.Title = sanitizeTitle(title)
s.repoChat.UpdateChat(newchat.UserID, newchat)
}
}
}