mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-07 21:13:27 -05:00
A model could write a paperclip line with a made-up file name and never call attach_file. Nothing was sent and the sender got no note. When the answer of a connector turn has a paperclip followed by the name of a sendable file, and no file went and no other note was sent, the host now adds one plain note. The answer is not changed. Prose that names a file and a paperclip alone do not match. The attach_file description and the connector guidance now say to use the exact path the tools showed, and never to write a file name or a paperclip line by hand. A spec covers a folder name with a space. Assisted-by: Claude:claude-sonnet-5-5
56 lines
2.4 KiB
Go
56 lines
2.4 KiB
Go
package studio
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/mudler/LocalAI/core/services/studio/session"
|
|
)
|
|
|
|
// connectorBlock tells the model of a chat that a messaging app started where
|
|
// its answer goes. The person reads it there, not in Studio, and the host
|
|
// attaches the files a turn makes (sendFiles) and the files the model marks
|
|
// with attach_file, so the model must not say it cannot send a file or quote a
|
|
// path of the sandbox. It is a block of the turn
|
|
// prompt, not a note: a note is cut at 400 bytes, and the text of a block is
|
|
// the same at each turn, so the harness is not restarted and the transcript
|
|
// does not grow. Other chats get nothing. canWrite says whether the chat can
|
|
// make a file at all.
|
|
func (s *Service) connectorBlock(ctx context.Context, rec session.ChatRecord, canWrite bool) string {
|
|
if rec.Origin != session.OriginConnector {
|
|
return ""
|
|
}
|
|
platform := "a messaging app"
|
|
sends, known := false, false
|
|
var limits FileLimits
|
|
if c := s.connectors; c != nil {
|
|
if b, err := c.o.Store.GetBinding(ctx, rec.OriginID); err == nil {
|
|
limits = c.FileLimits(ctx, b)
|
|
sends, known = b.SendsFiles() && limits.Send.Bytes > 0, true
|
|
platform = b.Kind
|
|
if kinds, err := c.o.Transport.Kinds(ctx); err == nil {
|
|
if k, ok := kindFor(kinds, b); ok && k.Title != "" {
|
|
platform = k.Title
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var sb strings.Builder
|
|
fmt.Fprintf(&sb, "This chat is on %s. The person reads your answer there, not in Studio, and cannot open sandbox paths.", platform)
|
|
switch {
|
|
case !canWrite:
|
|
case !known:
|
|
sb.WriteString(" Never tell them a file path.")
|
|
case !sends:
|
|
sb.WriteString(" Files are NOT sent to them: paste short content in the answer, or say you cannot attach a file. Never tell them a file path.")
|
|
default:
|
|
fmt.Fprintf(&sb, " Files you make or change in a turn are attached to your answer automatically. To give them a file that already exists, call %s with its path."+
|
|
" Use the exact path your file tools or bash showed, for a file in a folder you were given too."+
|
|
" Say the file is attached only after the call worked; never write a file name or a paperclip line yourself, never say you cannot send files, and never tell them a path."+
|
|
" Up to %d files per turn, %s each; documents, data, images, audio, video and zip only, no scripts or HTML. If one cannot be attached, say so.",
|
|
attachFileName, maxFilesPerTurn, limits.Send.sentence(limits.KindTitle))
|
|
}
|
|
return sb.String()
|
|
}
|