mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-24 15:38:12 +02:00
Chat : les images ne sont plus réécrites en base64 à chaque tour
Repris d'AJEAN 0.15.7 (chat_images.go et son test), adapté. Une image jointe (ou une capture de web_screenshot) vivait en base64 dans les messages de la conversation, et persist() réécrit la conversation ENTIÈRE à chaque fin de tour : une photo de téléphone, c'étaient des Mo remis sur disque à chaque réponse. Elle est désormais rangée une fois sous $LOKI_HOME/chatimg/<empreinte>.<ext> (hors du dossier de travail, que l'IA peut vider) ; l'historique n'en garde que « loki-img:<nom> ». Juste avant l'envoi, expandImageRefs remet les octets exacts (cache mémoire borné à 64 Mo) : pour le modèle, rien ne change. DEUX ÉCARTS AVEC L'AMONT - Copie à l'écriture : l'amont remplace l'URL en place. Chez nous, persist peut tourner pendant qu'un runChat sérialise ces mêmes maps (compactage en vol, bascule de projet) — « concurrent map read and map write », fatal. Les parties modifiées sont donc recopiées. - Le rechargement reste éphémère : stripImageParts retire toujours les images d'une conversation rouverte (garde-fou contre un modèle sans vision qui lirait le base64 comme du texte). L'amont, lui, les garde ; on pourra le suivre plus tard si l'on veut. Pas de migration des archives : une conversation rouverte est allégée par stripImageParts, comme avant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1db987844e
commit
f7a4ee71e7
4 files changed
+283
-1
No files matched your search
@@ -0,0 +1,46 @@
|
||||
package loki
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Une image en base64 part sur disque et revient identique à l'envoi au modèle ;
|
||||
// l'historique ne garde qu'une référence de quelques octets.
|
||||
func TestImageRefsRoundTrip(t *testing.T) {
|
||||
testHome(t)
|
||||
raw := []byte(strings.Repeat("\x89PNG-fake-image-bytes", 5000))
|
||||
url := "data:image/png;base64," + base64.StdEncoding.EncodeToString(raw)
|
||||
msgs := []Message{
|
||||
{Role: "user", Content: []map[string]any{
|
||||
{"type": "text", "text": "regarde"},
|
||||
{"type": "image_url", "image_url": map[string]any{"url": url}},
|
||||
}},
|
||||
{Role: "assistant", Content: "vu"},
|
||||
}
|
||||
// Relu depuis le JSON (forme []any), comme après un redémarrage.
|
||||
var reread []Message
|
||||
b, _ := json.Marshal(msgs)
|
||||
_ = json.Unmarshal(b, &reread)
|
||||
|
||||
for _, set := range [][]Message{msgs, reread} {
|
||||
if !hasInlineImages(set) || !refImagesInMessages(set) || hasInlineImages(set) {
|
||||
t.Fatal("l'image aurait dû être rangée par référence")
|
||||
}
|
||||
js, _ := json.Marshal(set)
|
||||
if len(js) > 500 || !strings.Contains(string(js), imgRefScheme) {
|
||||
t.Fatalf("historique encore lourd : %d octets", len(js))
|
||||
}
|
||||
out := expandImageRefs(set)
|
||||
_, got := partImageURL(contentParts(out[0].Content)[1])
|
||||
if got != url {
|
||||
t.Fatal("l'image renvoyée au modèle diffère de l'originale")
|
||||
}
|
||||
// L'historique lui-même n'est pas modifié par l'expansion.
|
||||
if _, u := partImageURL(contentParts(set[0].Content)[1]); !strings.HasPrefix(u, imgRefScheme) {
|
||||
t.Fatal("expandImageRefs ne doit pas toucher l'historique")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user