wip: noaction for deciding to stop
This commit is contained in:
22
action/noreply.go
Normal file
22
action/noreply.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package action
|
||||||
|
|
||||||
|
// StopActionName is the name of the action
|
||||||
|
// used by the LLM to stop any further action
|
||||||
|
const StopActionName = "stop"
|
||||||
|
|
||||||
|
func NewStop() *StopAction {
|
||||||
|
return &StopAction{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StopAction struct{}
|
||||||
|
|
||||||
|
func (a *StopAction) Run(ActionParams) (string, error) {
|
||||||
|
return "no-op", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *StopAction) Definition() ActionDefinition {
|
||||||
|
return ActionDefinition{
|
||||||
|
Name: StopActionName,
|
||||||
|
Description: "Use this tool to stop any further action and stop the conversation.",
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -136,18 +136,33 @@ func (a *Agent) generateParameters(ctx context.Context, pickTemplate string, act
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) systemInternalActions() Actions {
|
func (a *Agent) systemInternalActions() Actions {
|
||||||
if a.options.enableHUD {
|
defaultActions := append(a.options.userActions, action.NewReply())
|
||||||
return append(a.options.userActions,
|
|
||||||
action.NewState(), action.NewReply())
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.options.initiateConversations && a.selfEvaluationInProgress { // && self-evaluation..
|
if a.options.initiateConversations && a.selfEvaluationInProgress { // && self-evaluation..
|
||||||
return append(a.options.userActions,
|
acts := append(defaultActions, action.NewConversation())
|
||||||
action.NewState(), action.NewReply(), action.NewConversation())
|
if a.options.enableHUD {
|
||||||
|
acts = append(acts, action.NewState())
|
||||||
|
}
|
||||||
|
if a.options.canStopItself {
|
||||||
|
acts = append(acts, action.NewStop())
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(a.options.userActions,
|
return acts
|
||||||
action.NewReply())
|
}
|
||||||
|
|
||||||
|
if a.options.canStopItself {
|
||||||
|
acts := append(defaultActions, action.NewStop())
|
||||||
|
if a.options.enableHUD {
|
||||||
|
acts = append(acts, action.NewState())
|
||||||
|
}
|
||||||
|
return acts
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.options.enableHUD {
|
||||||
|
return append(defaultActions, action.NewState())
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultActions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Agent) prepareHUD() PromptHUD {
|
func (a *Agent) prepareHUD() PromptHUD {
|
||||||
|
|||||||
@@ -340,6 +340,14 @@ func (a *Agent) consumeJob(job *Job, role string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if chosenAction.Definition().Name.Is(action.StopActionName) {
|
||||||
|
if a.options.debugMode {
|
||||||
|
fmt.Println("LLM decided to stop")
|
||||||
|
}
|
||||||
|
job.Result.Finish(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if chosenAction == nil {
|
if chosenAction == nil {
|
||||||
// If no action was picked up, the reasoning is the message returned by the assistant
|
// If no action was picked up, the reasoning is the message returned by the assistant
|
||||||
// so we can consume it as if it was a reply.
|
// so we can consume it as if it was a reply.
|
||||||
@@ -410,8 +418,10 @@ func (a *Agent) consumeJob(job *Job, role string) {
|
|||||||
if !chosenAction.Definition().Name.Is(action.ReplyActionName) {
|
if !chosenAction.Definition().Name.Is(action.ReplyActionName) {
|
||||||
result, err := a.runAction(chosenAction, params)
|
result, err := a.runAction(chosenAction, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
job.Result.Finish(fmt.Errorf("error running action: %w", err))
|
//job.Result.Finish(fmt.Errorf("error running action: %w", err))
|
||||||
return
|
//return
|
||||||
|
// make the LLM aware of the error of running the action instead of stopping the job here
|
||||||
|
result = fmt.Sprintf("Error running tool: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
stateResult := ActionState{ActionCurrentState{chosenAction, params.actionParams, reasoning}, result}
|
stateResult := ActionState{ActionCurrentState{chosenAction, params.actionParams, reasoning}, result}
|
||||||
@@ -585,7 +595,7 @@ func (a *Agent) periodicallyRun() {
|
|||||||
|
|
||||||
// whatNext := NewJob(WithText("Decide what to do based on the state"))
|
// whatNext := NewJob(WithText("Decide what to do based on the state"))
|
||||||
whatNext := NewJob(
|
whatNext := NewJob(
|
||||||
WithText("Decide what to based on the goal and the persistent goal."),
|
WithText(innerMonologueTemplate),
|
||||||
WithReasoningCallback(a.options.reasoningCallback),
|
WithReasoningCallback(a.options.reasoningCallback),
|
||||||
WithResultCallback(a.options.resultCallback),
|
WithResultCallback(a.options.resultCallback),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type options struct {
|
|||||||
userActions Actions
|
userActions Actions
|
||||||
enableHUD, standaloneJob, showCharacter, enableKB bool
|
enableHUD, standaloneJob, showCharacter, enableKB bool
|
||||||
debugMode bool
|
debugMode bool
|
||||||
|
canStopItself bool
|
||||||
initiateConversations bool
|
initiateConversations bool
|
||||||
characterfile string
|
characterfile string
|
||||||
statefile string
|
statefile string
|
||||||
@@ -53,7 +54,7 @@ func defaultOptions() *options {
|
|||||||
},
|
},
|
||||||
character: Character{
|
character: Character{
|
||||||
Name: "John Doe",
|
Name: "John Doe",
|
||||||
Age: 0,
|
Age: "",
|
||||||
Occupation: "Unemployed",
|
Occupation: "Unemployed",
|
||||||
Hobbies: []string{},
|
Hobbies: []string{},
|
||||||
MusicTaste: []string{},
|
MusicTaste: []string{},
|
||||||
@@ -82,6 +83,11 @@ var EnableKnowledgeBase = func(o *options) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var CanStopItself = func(o *options) error {
|
||||||
|
o.canStopItself = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func EnableKnowledgeBaseWithResults(results int) Option {
|
func EnableKnowledgeBaseWithResults(results int) Option {
|
||||||
return func(o *options) error {
|
return func(o *options) error {
|
||||||
o.enableKB = true
|
o.enableKB = true
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type PromptHUD struct {
|
|||||||
|
|
||||||
type Character struct {
|
type Character struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Age int `json:"age"`
|
Age string `json:"age"`
|
||||||
Occupation string `json:"job_occupation"`
|
Occupation string `json:"job_occupation"`
|
||||||
Hobbies []string `json:"hobbies"`
|
Hobbies []string `json:"hobbies"`
|
||||||
MusicTaste []string `json:"music_taste"`
|
MusicTaste []string `json:"music_taste"`
|
||||||
@@ -99,7 +99,7 @@ func (a *Agent) generateIdentity(guidance string) error {
|
|||||||
|
|
||||||
func (a *Agent) validCharacter() bool {
|
func (a *Agent) validCharacter() bool {
|
||||||
return a.Character.Name != "" &&
|
return a.Character.Name != "" &&
|
||||||
a.Character.Age != 0 &&
|
a.Character.Age != "" &&
|
||||||
a.Character.Occupation != "" &&
|
a.Character.Occupation != "" &&
|
||||||
len(a.Character.Hobbies) != 0 &&
|
len(a.Character.Hobbies) != 0 &&
|
||||||
len(a.Character.MusicTaste) != 0
|
len(a.Character.MusicTaste) != 0
|
||||||
@@ -107,7 +107,7 @@ func (a *Agent) validCharacter() bool {
|
|||||||
|
|
||||||
const fmtT = `=====================
|
const fmtT = `=====================
|
||||||
Name: %s
|
Name: %s
|
||||||
Age: %d
|
Age: %s
|
||||||
Occupation: %s
|
Occupation: %s
|
||||||
Hobbies: %v
|
Hobbies: %v
|
||||||
Music taste: %v
|
Music taste: %v
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ func renderTemplate(templ string, hud *PromptHUD, actions Actions, reasoning str
|
|||||||
return prompt.String(), nil
|
return prompt.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const innerMonologueTemplate = `"This is not a typical conversation between an assistant and an user.
|
||||||
|
You are thinking out loud by yourself now, and you are evaluating the current situation.
|
||||||
|
Considering the goal and the persistent goal, if you have one, and do something, or decide to plan something for later on. If you have the action available, you might also decide to engage a conversation with the user by notifying him."`
|
||||||
|
|
||||||
const hudTemplate = `{{with .HUD }}{{if .ShowCharacter}}The assistant acts like an human, has a character and the replies and actions might be influenced by it.
|
const hudTemplate = `{{with .HUD }}{{if .ShowCharacter}}The assistant acts like an human, has a character and the replies and actions might be influenced by it.
|
||||||
{{if .Character.Name}}This is the assistant name: {{.Character.Name}}
|
{{if .Character.Name}}This is the assistant name: {{.Character.Name}}
|
||||||
{{end}}{{if .Character.Age}}This is the assistant age: {{.Character.Age}}
|
{{end}}{{if .Character.Age}}This is the assistant age: {{.Character.Age}}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ type AgentConfig struct {
|
|||||||
PermanentGoal string `json:"permanent_goal" form:"permanent_goal"`
|
PermanentGoal string `json:"permanent_goal" form:"permanent_goal"`
|
||||||
EnableKnowledgeBase bool `json:"enable_kb" form:"enable_kb"`
|
EnableKnowledgeBase bool `json:"enable_kb" form:"enable_kb"`
|
||||||
KnowledgeBaseResults int `json:"kb_results" form:"kb_results"`
|
KnowledgeBaseResults int `json:"kb_results" form:"kb_results"`
|
||||||
|
CanStopItself bool `json:"can_stop_itself" form:"can_stop_itself"`
|
||||||
SystemPrompt string `json:"system_prompt" form:"system_prompt"`
|
SystemPrompt string `json:"system_prompt" form:"system_prompt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,6 +343,9 @@ func (a *AgentPool) startAgentWithConfig(name string, config *AgentConfig) error
|
|||||||
if config.StandaloneJob {
|
if config.StandaloneJob {
|
||||||
opts = append(opts, EnableStandaloneJob)
|
opts = append(opts, EnableStandaloneJob)
|
||||||
}
|
}
|
||||||
|
if config.CanStopItself {
|
||||||
|
opts = append(opts, CanStopItself)
|
||||||
|
}
|
||||||
if config.InitiateConversations {
|
if config.InitiateConversations {
|
||||||
opts = append(opts, EnableInitiateConversations)
|
opts = append(opts, EnableInitiateConversations)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,9 @@
|
|||||||
<label for="initiate_conversations" class="block text-lg font-medium text-gray-400">Initiate conversations</label>
|
<label for="initiate_conversations" class="block text-lg font-medium text-gray-400">Initiate conversations</label>
|
||||||
<input type="checkbox" name="random_identity" id="initiate_conversations" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md bg-gray-700 text-white">
|
<input type="checkbox" name="random_identity" id="initiate_conversations" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md bg-gray-700 text-white">
|
||||||
|
|
||||||
|
<label for="can_stop_itself" class="block text-lg font-medium text-gray-400">Can stop itself</label>
|
||||||
|
<input type="checkbox" name="can_stop_itself" id="can_stop_itself" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md bg-gray-700 text-white">
|
||||||
|
|
||||||
<label for="random_identity" class="block text-lg font-medium text-gray-400">Random Identity</label>
|
<label for="random_identity" class="block text-lg font-medium text-gray-400">Random Identity</label>
|
||||||
<input type="checkbox" name="random_identity" id="random_identity" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md bg-gray-700 text-white">
|
<input type="checkbox" name="random_identity" id="random_identity" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-lg border-gray-300 rounded-md bg-gray-700 text-white">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
<script src="https://unpkg.com/htmx.org"></script>
|
<script src="https://unpkg.com/htmx.org"></script>
|
||||||
<script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script>
|
<script src="https://unpkg.com/htmx.org/dist/ext/sse.js"></script>
|
||||||
<script src="https://unpkg.com/hyperscript.org@0.9.12"></script>
|
<script src="https://unpkg.com/hyperscript.org@0.9.12"></script>
|
||||||
|
|
||||||
|
<script defer src="https://unpkg.com/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/alpinejs" defer></script>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: 'Roboto', sans-serif;
|
font-family: 'Roboto', sans-serif;
|
||||||
|
|||||||
Reference in New Issue
Block a user