Files
cogito/goal.go
Ettore Di Giacinto d865935087 Improve planning and add tests (#4)
* WIP

* Make test pass

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

* Fixups

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>

---------

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
2025-09-30 23:23:32 +02:00

102 lines
2.8 KiB
Go

package cogito
import (
"fmt"
"github.com/mudler/cogito/prompt"
"github.com/mudler/cogito/structures"
)
// ExtractGoal extracts a goal from a conversation
func ExtractGoal(llm LLM, f Fragment, opts ...Option) (*structures.Goal, error) {
o := defaultOptions()
o.Apply(opts...)
// First we ask the LLM if there is a goal from the conversation
prompter := o.Prompts.GetPrompt(prompt.PromptIdentifyGoalType)
goalIdentifierOptions := struct {
Context string
AdditionalContext string
}{
Context: f.String(),
}
if o.DeepContext && f.ParentFragment != nil {
goalIdentifierOptions.AdditionalContext = f.ParentFragment.AllFragmentsStrings()
}
prompt, err := prompter.Render(goalIdentifierOptions)
if err != nil {
return nil, fmt.Errorf("failed to render tool reasoner prompt: %w", err)
}
goalConv := NewEmptyFragment().AddMessage("user", prompt)
reasoningGoal, err := llm.Ask(o.Context, goalConv)
if err != nil {
return nil, fmt.Errorf("failed to ask LLM for goal identification: %w", err)
}
identifiedGoal := reasoningGoal.LastMessage()
structure, goal := structures.StructureGoal()
goalConv = NewEmptyFragment().AddMessage("user", identifiedGoal.Content)
err = goalConv.ExtractStructure(o.Context, llm, structure)
if err != nil {
return nil, fmt.Errorf("failed to extract boolean structure: %w", err)
}
return goal, nil
}
// IsGoalAchieved checks if a goal has been achieved
func IsGoalAchieved(llm LLM, f Fragment, goal *structures.Goal, opts ...Option) (*structures.Boolean, error) {
o := defaultOptions()
o.Apply(opts...)
// First we ask the LLM if there is a goal from the conversation
prompter := o.Prompts.GetPrompt(prompt.PromptGoalAchievedType)
goalAchievedOpts := struct {
Context string
AdditionalContext string
Goal string
FeedbackConversation string
}{
Context: f.String(),
}
if goal != nil {
goalAchievedOpts.Goal = goal.Goal
}
if o.DeepContext && f.ParentFragment != nil {
goalAchievedOpts.AdditionalContext = f.ParentFragment.AllFragmentsStrings()
}
var feedbackConv *Fragment
if o.FeedbackCallback != nil {
feedbackConv = o.FeedbackCallback()
goalAchievedOpts.FeedbackConversation = feedbackConv.String()
}
prompt, err := prompter.Render(goalAchievedOpts)
if err != nil {
return nil, fmt.Errorf("failed to render tool reasoner prompt: %w", err)
}
multimedias := []Multimedia{}
if feedbackConv != nil {
multimedias = feedbackConv.Multimedia
}
goalAchievedConv := NewEmptyFragment().AddMessage("user", prompt, multimedias...)
reasoningGoal, err := llm.Ask(o.Context, goalAchievedConv)
if err != nil {
return nil, fmt.Errorf("failed to ask LLM for goal identification: %w", err)
}
boolConv := NewEmptyFragment().AddMessage("user", reasoningGoal.LastMessage().Content)
return ExtractBoolean(llm, boolConv, opts...)
}