mirror of
https://github.com/mudler/LocalAI.git
synced 2026-03-31 13:15:51 -04:00
* Revert "fix: Add timeout-based wait for model deletion completion (#8756)"
This reverts commit 9e1b0d0c82.
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* feat: add mcp prompts and resources
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* feat(ui): add client-side MCP
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* feat(ui): allow to authenticate MCP servers
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* feat(ui): add MCP Apps
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* chore: update AGENTS
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* chore: allow to collapse navbar, save state in storage
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* feat(ui): add MCP button also to home page
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
* fix(chat): populate string content
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
---------
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
91 lines
2.8 KiB
Go
91 lines
2.8 KiB
Go
package schema
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/mudler/xlog"
|
|
|
|
"github.com/mudler/LocalAI/pkg/grpc/proto"
|
|
)
|
|
|
|
type Message struct {
|
|
// The message role
|
|
Role string `json:"role,omitempty" yaml:"role"`
|
|
|
|
// The message name (used for tools calls)
|
|
Name string `json:"name,omitempty" yaml:"name"`
|
|
|
|
// The message content
|
|
Content interface{} `json:"content" yaml:"content"`
|
|
|
|
StringContent string `json:"string_content,omitempty" yaml:"string_content,omitempty"`
|
|
StringImages []string `json:"string_images,omitempty" yaml:"string_images,omitempty"`
|
|
StringVideos []string `json:"string_videos,omitempty" yaml:"string_videos,omitempty"`
|
|
StringAudios []string `json:"string_audios,omitempty" yaml:"string_audios,omitempty"`
|
|
|
|
// A result of a function call
|
|
FunctionCall interface{} `json:"function_call,omitempty" yaml:"function_call,omitempty"`
|
|
|
|
ToolCalls []ToolCall `json:"tool_calls,omitempty" yaml:"tool_call,omitempty"`
|
|
|
|
ToolCallID string `json:"tool_call_id,omitempty" yaml:"tool_call_id,omitempty"`
|
|
|
|
// Reasoning content extracted from <thinking>...</thinking> tags
|
|
Reasoning *string `json:"reasoning,omitempty" yaml:"reasoning,omitempty"`
|
|
}
|
|
|
|
type ToolCall struct {
|
|
Index int `json:"index"`
|
|
ID string `json:"id"`
|
|
Type string `json:"type"`
|
|
FunctionCall FunctionCall `json:"function"`
|
|
}
|
|
|
|
type FunctionCall struct {
|
|
Name string `json:"name,omitempty"`
|
|
Arguments string `json:"arguments"`
|
|
}
|
|
|
|
type Messages []Message
|
|
|
|
// MessagesToProto converts schema.Message slice to proto.Message slice
|
|
// It handles content conversion, tool_calls serialization, and optional fields
|
|
func (messages Messages) ToProto() []*proto.Message {
|
|
protoMessages := make([]*proto.Message, len(messages))
|
|
for i, message := range messages {
|
|
protoMessages[i] = &proto.Message{
|
|
Role: message.Role,
|
|
Name: message.Name, // needed by function calls
|
|
}
|
|
|
|
switch ct := message.Content.(type) {
|
|
case string:
|
|
protoMessages[i].Content = ct
|
|
case []interface{}:
|
|
// If using the tokenizer template, in case of multimodal we want to keep the multimodal content as and return only strings here
|
|
data, _ := json.Marshal(ct)
|
|
resultData := []struct {
|
|
Text string `json:"text"`
|
|
}{}
|
|
json.Unmarshal(data, &resultData)
|
|
for _, r := range resultData {
|
|
protoMessages[i].Content += r.Text
|
|
}
|
|
}
|
|
|
|
// Serialize tool_calls to JSON string if present
|
|
if len(message.ToolCalls) > 0 {
|
|
toolCallsJSON, err := json.Marshal(message.ToolCalls)
|
|
if err != nil {
|
|
xlog.Warn("failed to marshal tool_calls to JSON", "error", err)
|
|
} else {
|
|
protoMessages[i].ToolCalls = string(toolCallsJSON)
|
|
}
|
|
}
|
|
|
|
// Note: tool_call_id is not in schema.Message yet
|
|
// Reasoning field is now available in schema.Message but not yet in proto.Message
|
|
}
|
|
return protoMessages
|
|
}
|