answer/pkg/agents/knowledge_integrate.go

88 lines
3.9 KiB
Go

package agents
import (
"context"
gollm "gitea.stevedudenhoeffer.com/steve/go-llm"
)
// KnowledgeIntegrate will ask the LLM to combine the gained knowledge with the current knowledge, and return the new representation of overall.
// If source is not empty, then any new Knowledge will an empty source will be given the source.
// This will override objectives, notes, and remaining questions.
func (a Agent) KnowledgeIntegrate(ctx context.Context, base Knowledge, in ...Knowledge) (Knowledge, error) {
// if there are no changes we can just return the knowledge
if len(in) == 0 {
return base, nil
} else {
// if there are no entries in Knowledge.Knowledge, Knowledge.CurrentObjectives, or Knowledge.NotesToSelf then
// we can just exit out
needToRun := false
for _, k := range in {
if len(k.Knowledge) > 0 || len(k.CurrentObjectives) > 0 || len(k.NotesToSelf) > 0 {
needToRun = true
break
}
}
if !needToRun {
return base, nil
}
}
var incoming Knowledge
for _, k := range in {
incoming.NotesToSelf = append(incoming.NotesToSelf, k.NotesToSelf...)
incoming.CurrentObjectives = append(incoming.CurrentObjectives, k.CurrentObjectives...)
incoming.Knowledge = append(incoming.Knowledge, k.Knowledge...)
}
baseMsg := base.ToSystemMessage()
incomingMsg := incoming.ToSystemMessage()
baseMsg.Text = "The original knowledge is as follows: " + baseMsg.Text
incomingMsg.Text = "The new knowledge is as follows: " + incomingMsg.Text
var result = Knowledge{
OriginalQuestions: base.OriginalQuestions,
Knowledge: append(base.Knowledge, incoming.Knowledge...),
}
tools := gollm.NewToolBox(
gollm.NewFunction(
"remaining_questions",
"Use the remaining_questions function to indicate what questions remain unanswered. Call this exactly one time. If your current questions are repetitive or not useful, then you can call this function to edit or remove them. If you have new questions, then you can call this function to add them. What is set here will be the final set of questions.",
func(ctx *gollm.Context, args struct {
RemainingQuestions []string `description:"The questions that remain unanswered."`
}) (any, error) {
result.RemainingQuestions = append(result.RemainingQuestions, args.RemainingQuestions...)
return "ok", nil
}),
gollm.NewFunction(
"notes_to_self",
"Use the notes_to_self function to leave or edit notes for yourself. Call this exactly one time. If your current notes are repetitive or not useful, then you can call this function to edit or remove them. What is set here will be the final set",
func(ctx *gollm.Context, args struct {
Notes []string `description:"The notes to leave for yourself."`
}) (any, error) {
result.NotesToSelf = append(result.NotesToSelf, args.Notes...)
return "ok", nil
}),
gollm.NewFunction(
"new_objectives",
"Use the new_objectives function to set new objectives for the LLM to work on. Call this exactly one time. If your current objectives are repetitive or not useful, then you can call this function to edit or remove them. What is set here will be the final set of objectives.",
func(ctx *gollm.Context, args struct {
Objectives []string `description:"The objectives to set for the LLM to work on."`
}) (any, error) {
result.CurrentObjectives = append(result.CurrentObjectives, args.Objectives...)
return "ok", nil
}),
)
_, err := a.WithSystemPrompt(`You are combining knowledge that has been observed in two states, the original knowledge is what was known before an action was taken, and the new knowledge is what was learned after an action was taken. If the new knowledge answers or opens any new questions, notes, or objectives you should add, edit, or remove them now.`).
WithSystemPromptSuffix(``).
WithToolbox(tools).
CallAndExecute(ctx, `The original knowledge is as follows: `+baseMsg.Text+` The new knowledge is as follows: `+incomingMsg.Text)
return result, err
}