fix: make new_conversation to work (#112)

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2025-03-29 00:21:00 +01:00
committed by GitHub
parent 5fdd464fad
commit c940141e61
2 changed files with 59 additions and 14 deletions

View File

@@ -71,6 +71,7 @@ func New(opts ...Option) (*Agent, error) {
Character: options.character, Character: options.character,
currentState: &action.AgentInternalState{}, currentState: &action.AgentInternalState{},
context: types.NewActionContext(ctx, cancel), context: types.NewActionContext(ctx, cancel),
newConversations: make(chan openai.ChatCompletionMessage),
newMessagesSubscribers: options.newConversationsSubscribers, newMessagesSubscribers: options.newConversationsSubscribers,
} }
@@ -104,8 +105,6 @@ func New(opts ...Option) (*Agent, error) {
"model", a.options.LLMAPI.Model, "model", a.options.LLMAPI.Model,
) )
a.startNewConversationsConsumer()
return a, nil return a, nil
} }
@@ -117,6 +116,7 @@ func (a *Agent) startNewConversationsConsumer() {
return return
case msg := <-a.newConversations: case msg := <-a.newConversations:
xlog.Debug("New conversation", "agent", a.Character.Name, "message", msg.Content)
a.subscriberMutex.Lock() a.subscriberMutex.Lock()
subs := a.newMessagesSubscribers subs := a.newMessagesSubscribers
a.subscriberMutex.Unlock() a.subscriberMutex.Unlock()
@@ -577,25 +577,28 @@ func (a *Agent) consumeJob(job *types.Job, role string) {
if selfEvaluation && a.options.initiateConversations && if selfEvaluation && a.options.initiateConversations &&
chosenAction.Definition().Name.Is(action.ConversationActionName) { chosenAction.Definition().Name.Is(action.ConversationActionName) {
xlog.Info("LLM decided to initiate a new conversation", "agent", a.Character.Name)
message := action.ConversationActionResponse{} message := action.ConversationActionResponse{}
if err := actionParams.Unmarshal(&message); err != nil { if err := actionParams.Unmarshal(&message); err != nil {
xlog.Error("Error unmarshalling conversation response", "error", err)
job.Result.Finish(fmt.Errorf("error unmarshalling conversation response: %w", err)) job.Result.Finish(fmt.Errorf("error unmarshalling conversation response: %w", err))
return return
} }
conv = []openai.ChatCompletionMessage{ msg := openai.ChatCompletionMessage{
{
Role: "assistant",
Content: message.Message,
},
}
go func() {
a.newConversations <- openai.ChatCompletionMessage{
Role: "assistant", Role: "assistant",
Content: message.Message, Content: message.Message,
} }
}()
job.Result.Conversation = conv go func(agent *Agent) {
xlog.Info("Sending new conversation to channel", "agent", agent.Character.Name, "message", msg.Content)
agent.newConversations <- msg
}(a)
job.Result.Conversation = []openai.ChatCompletionMessage{
msg,
}
job.Result.SetResponse("decided to initiate a new conversation") job.Result.SetResponse("decided to initiate a new conversation")
job.Result.Finish(nil) job.Result.Finish(nil)
return return
@@ -881,6 +884,9 @@ func (a *Agent) periodicallyRun(timer *time.Timer) {
} }
func (a *Agent) Run() error { func (a *Agent) Run() error {
a.startNewConversationsConsumer()
xlog.Debug("Agent is now running", "agent", a.Character.Name)
// The agent run does two things: // The agent run does two things:
// picks up requests from a queue // picks up requests from a queue
// and generates a response/perform actions // and generates a response/perform actions

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"strings" "strings"
"sync"
"github.com/mudler/LocalAgent/pkg/xlog" "github.com/mudler/LocalAgent/pkg/xlog"
"github.com/mudler/LocalAgent/services/actions" "github.com/mudler/LocalAgent/services/actions"
@@ -12,6 +13,7 @@ import (
"github.com/mudler/LocalAgent/core/types" "github.com/mudler/LocalAgent/core/types"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/sashabaranov/go-openai"
"github.com/sashabaranov/go-openai/jsonschema" "github.com/sashabaranov/go-openai/jsonschema"
) )
@@ -235,6 +237,43 @@ var _ = Describe("Agent test", func() {
}) })
It("Can initiate conversations", func() {
message := openai.ChatCompletionMessage{}
mu := &sync.Mutex{}
agent, err := New(
WithLLMAPIURL(apiURL),
WithModel(testModel),
WithLLMAPIKey(apiKeyURL),
WithNewConversationSubscriber(func(m openai.ChatCompletionMessage) {
mu.Lock()
message = m
mu.Unlock()
}),
WithActions(
actions.NewSearch(map[string]string{}),
),
EnablePlanning,
EnableForceReasoning,
EnableInitiateConversations,
EnableStandaloneJob,
EnableHUD,
WithPeriodicRuns("1s"),
WithPermanentGoal("use the new_conversation tool"),
// EnableStandaloneJob,
// WithRandomIdentity(),
)
Expect(err).ToNot(HaveOccurred())
go agent.Run()
defer agent.Stop()
Eventually(func() string {
mu.Lock()
defer mu.Unlock()
return message.Content
}, "10m", "10s").ShouldNot(BeEmpty())
})
/* /*
It("it automatically performs things in the background", func() { It("it automatically performs things in the background", func() {
agent, err := New( agent, err := New(