Automatically save all conversations

This commit is contained in:
Ettore Di Giacinto
2025-03-04 22:22:16 +01:00
parent 758a73e8ab
commit d288755444
6 changed files with 79 additions and 8 deletions

View File

@@ -2,7 +2,9 @@ package agent
import (
"context"
"encoding/json"
"fmt"
"os"
"github.com/mudler/LocalAgent/core/action"
"github.com/mudler/LocalAgent/pkg/xlog"
@@ -87,6 +89,10 @@ func (a *Agent) decision(
return nil, err
}
if err := a.saveConversation(append(conversation, msg), "decision"); err != nil {
xlog.Error("Error saving conversation", "error", err)
}
return &decisionResult{actionParams: params, actioName: msg.ToolCalls[0].Function.Name, message: msg.Content}, nil
}
@@ -113,6 +119,26 @@ func (m Messages) Exist(content string) bool {
return false
}
func (m Messages) Save(path string) error {
content, err := json.MarshalIndent(m, "", " ")
if err != nil {
return err
}
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
if _, err := f.Write(content); err != nil {
return err
}
return nil
}
func (a *Agent) generateParameters(ctx context.Context, pickTemplate string, act Action, c []openai.ChatCompletionMessage, reasoning string) (*decisionResult, error) {
stateHUD, err := renderTemplate(pickTemplate, a.prepareHUD(), a.systemInternalActions(), reasoning)

View File

@@ -177,7 +177,7 @@ func (a *Agent) ResetConversation() {
// store into memory the conversation before pruning it
// TODO: Shall we summarize the conversation into a bullet list of highlights
// using the LLM instead?
a.saveCurrentConversationInMemory()
a.saveCurrentConversation()
a.currentConversation = []openai.ChatCompletionMessage{}
}
@@ -382,7 +382,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
Content: reasoning,
})
job.Result.Conversation = a.currentConversation
a.saveCurrentConversationInMemory()
a.saveCurrentConversation()
job.Result.SetResponse(reasoning)
job.Result.Finish(nil)
return
@@ -532,7 +532,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
}
a.currentConversation = append(a.currentConversation, msg)
a.saveCurrentConversationInMemory()
a.saveCurrentConversation()
job.Result.SetResponse(msg.Content)
job.Result.Conversation = a.currentConversation
job.Result.Finish(nil)
@@ -612,7 +612,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
a.currentConversation = append(a.currentConversation, msg)
job.Result.Conversation = a.currentConversation
job.Result.SetResponse(msg.Content)
a.saveCurrentConversationInMemory()
a.saveCurrentConversation()
job.Result.Finish(nil)
return
}
@@ -642,7 +642,7 @@ func (a *Agent) consumeJob(job *Job, role string) {
job.Result.SetResponse(msg.Content)
xlog.Info("Response from LLM", "response", msg.Content, "agent", a.Character.Name)
job.Result.Conversation = a.currentConversation
a.saveCurrentConversationInMemory()
a.saveCurrentConversation()
job.Result.Finish(nil)
}

View File

@@ -2,6 +2,9 @@ package agent
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/mudler/LocalAgent/pkg/xlog"
"github.com/sashabaranov/go-openai"
@@ -60,9 +63,25 @@ func (a *Agent) knowledgeBaseLookup() {
}}, a.currentConversation...)
}
func (a *Agent) saveCurrentConversationInMemory() {
func (a *Agent) saveConversation(m Messages, prefix string) error {
if a.options.conversationsPath == "" {
return nil
}
dateTime := time.Now().Format("2006-01-02-15-04-05")
fileName := a.Character.Name + "-" + dateTime + ".json"
if prefix != "" {
fileName = prefix + "-" + fileName
}
os.MkdirAll(a.options.conversationsPath, os.ModePerm)
return m.Save(filepath.Join(a.options.conversationsPath, fileName))
}
func (a *Agent) saveCurrentConversation() {
if err := a.saveConversation(a.currentConversation, ""); err != nil {
xlog.Error("Error saving conversation", "error", err)
}
if !a.options.enableLongTermMemory && !a.options.enableSummaryMemory {
xlog.Debug("Long term memory is disabled", "agent", a.Character.Name)
return

View File

@@ -40,6 +40,8 @@ type options struct {
// callbacks
reasoningCallback func(ActionCurrentState) bool
resultCallback func(ActionState)
conversationsPath string
}
func defaultOptions() *options {
@@ -97,6 +99,13 @@ func WithTimeout(timeout string) Option {
}
}
func WithConversationsPath(path string) Option {
return func(o *options) error {
o.conversationsPath = path
return nil
}
}
func EnableKnowledgeBaseWithResults(results int) Option {
return func(o *options) error {
o.enableKB = true

View File

@@ -32,6 +32,7 @@ type AgentPool struct {
connectors func(*AgentConfig) []Connector
promptBlocks func(*AgentConfig) []PromptBlock
timeout string
conversationLogs string
}
type Status struct {
@@ -94,6 +95,7 @@ func NewAgentPool(
availableActions: availableActions,
promptBlocks: promptBlocks,
timeout: timeout,
conversationLogs: filepath.Join(directory, "conversations"),
}, nil
}
@@ -116,6 +118,7 @@ func NewAgentPool(
promptBlocks: promptBlocks,
availableActions: availableActions,
timeout: timeout,
conversationLogs: filepath.Join(directory, "conversations"),
}, nil
}
@@ -272,6 +275,10 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
opts = append(opts, EnableHUD)
}
if a.conversationLogs != "" {
opts = append(opts, WithConversationsPath(a.conversationLogs))
}
if config.StandaloneJob {
opts = append(opts, EnableStandaloneJob)
}