use options
This commit is contained in:
@@ -63,12 +63,11 @@ func New(opts ...Option) (*Agent, error) {
|
|||||||
|
|
||||||
// Ask is a pre-emptive, blocking call that returns the response as soon as it's ready.
|
// Ask is a pre-emptive, blocking call that returns the response as soon as it's ready.
|
||||||
// It discards any other computation.
|
// It discards any other computation.
|
||||||
func (a *Agent) Ask(text, image string) []string {
|
func (a *Agent) Ask(opts ...JobOption) []string {
|
||||||
//a.StopAction()
|
//a.StopAction()
|
||||||
j := NewJob(text, image)
|
j := NewJob(opts...)
|
||||||
fmt.Println("Job created", text)
|
// fmt.Println("Job created", text)
|
||||||
a.jobQueue <- j
|
a.jobQueue <- j
|
||||||
fmt.Println("Waiting for result")
|
|
||||||
|
|
||||||
return j.Result.WaitResult()
|
return j.Result.WaitResult()
|
||||||
}
|
}
|
||||||
@@ -94,26 +93,18 @@ func (a *Agent) Run() error {
|
|||||||
|
|
||||||
// Expose a REST API to interact with the agent to ask it things
|
// Expose a REST API to interact with the agent to ask it things
|
||||||
|
|
||||||
fmt.Println("Agent is running")
|
|
||||||
clearConvTimer := time.NewTicker(1 * time.Minute)
|
clearConvTimer := time.NewTicker(1 * time.Minute)
|
||||||
for {
|
for {
|
||||||
fmt.Println("Agent loop")
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case job := <-a.jobQueue:
|
case job := <-a.jobQueue:
|
||||||
fmt.Println("job from the queue")
|
|
||||||
|
|
||||||
// Consume the job and generate a response
|
// Consume the job and generate a response
|
||||||
// TODO: Give a short-term memory to the agent
|
// TODO: Give a short-term memory to the agent
|
||||||
a.consumeJob(job)
|
a.consumeJob(job)
|
||||||
case <-a.context.Done():
|
case <-a.context.Done():
|
||||||
fmt.Println("Context canceled, agent is stopping...")
|
|
||||||
|
|
||||||
// Agent has been canceled, return error
|
// Agent has been canceled, return error
|
||||||
return ErrContextCanceled
|
return ErrContextCanceled
|
||||||
case <-clearConvTimer.C:
|
case <-clearConvTimer.C:
|
||||||
fmt.Println("Removing chat history...")
|
|
||||||
|
|
||||||
// TODO: decide to do something on its own with the conversation result
|
// TODO: decide to do something on its own with the conversation result
|
||||||
// before clearing it out
|
// before clearing it out
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,12 @@ var _ = Describe("Agent test", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
go agent.Run()
|
go agent.Run()
|
||||||
defer agent.Stop()
|
defer agent.Stop()
|
||||||
res := agent.Ask("can you get the weather in boston, and afterward of Milano, Italy?", "")
|
res := agent.Ask(
|
||||||
|
WithReasoningCallback(func(a Action, ap action.ActionParams, s string) {
|
||||||
|
fmt.Println("Reasoning", s)
|
||||||
|
}),
|
||||||
|
WithText("can you get the weather in boston, and afterward of Milano, Italy?"),
|
||||||
|
)
|
||||||
Expect(res).To(ContainElement(testActionResult), fmt.Sprint(res))
|
Expect(res).To(ContainElement(testActionResult), fmt.Sprint(res))
|
||||||
Expect(res).To(ContainElement(testActionResult2), fmt.Sprint(res))
|
Expect(res).To(ContainElement(testActionResult2), fmt.Sprint(res))
|
||||||
})
|
})
|
||||||
@@ -75,7 +80,9 @@ var _ = Describe("Agent test", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
go agent.Run()
|
go agent.Run()
|
||||||
defer agent.Stop()
|
defer agent.Stop()
|
||||||
res := agent.Ask("can you get the weather in boston?", "")
|
res := agent.Ask(
|
||||||
|
WithText("can you get the weather in boston?"),
|
||||||
|
)
|
||||||
Expect(res).To(ContainElement(testActionResult), fmt.Sprint(res))
|
Expect(res).To(ContainElement(testActionResult), fmt.Sprint(res))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -14,52 +14,82 @@ type Job struct {
|
|||||||
// The job is a request to the agent to do something
|
// The job is a request to the agent to do something
|
||||||
// It can be a question, a command, or a request to do something
|
// It can be a question, a command, or a request to do something
|
||||||
// The agent will try to do it, and return a response
|
// The agent will try to do it, and return a response
|
||||||
Text string
|
Text string
|
||||||
Image string // base64 encoded image
|
Image string // base64 encoded image
|
||||||
Result *JobResult
|
Result *JobResult
|
||||||
|
reasoningCallback func(Action, action.ActionParams, string)
|
||||||
|
resultCallback func(Action, action.ActionParams, string, string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JobResult is the result of a job
|
// JobResult is the result of a job
|
||||||
type JobResult struct {
|
type JobResult struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
// The result of a job
|
// The result of a job
|
||||||
Data []string
|
Data []string
|
||||||
reasoningCallback func(Action, action.ActionParams, string)
|
Error error
|
||||||
resultCallback func(Action, action.ActionParams, string, string)
|
ready chan bool
|
||||||
ready chan bool
|
}
|
||||||
|
|
||||||
|
type JobOption func(*Job)
|
||||||
|
|
||||||
|
func WithReasoningCallback(f func(Action, action.ActionParams, string)) JobOption {
|
||||||
|
return func(r *Job) {
|
||||||
|
r.reasoningCallback = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithResultCallback(f func(Action, action.ActionParams, string, string)) JobOption {
|
||||||
|
return func(r *Job) {
|
||||||
|
r.resultCallback = f
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewJobResult creates a new job result
|
// NewJobResult creates a new job result
|
||||||
func NewJobResult() *JobResult {
|
func NewJobResult() *JobResult {
|
||||||
return &JobResult{
|
r := &JobResult{
|
||||||
ready: make(chan bool),
|
ready: make(chan bool),
|
||||||
}
|
}
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JobResult) Callback(a Action, p action.ActionParams, s string) {
|
func (j *Job) Callback(a Action, p action.ActionParams, s string) {
|
||||||
if j.reasoningCallback == nil {
|
if j.reasoningCallback == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
j.reasoningCallback(a, p, s)
|
j.reasoningCallback(a, p, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *JobResult) CallbackWithResult(a Action, p action.ActionParams, s, r string) {
|
func (j *Job) CallbackWithResult(a Action, p action.ActionParams, s, r string) {
|
||||||
if j.resultCallback == nil {
|
if j.resultCallback == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
j.resultCallback(a, p, s, r)
|
j.resultCallback(a, p, s, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithImage(image string) JobOption {
|
||||||
|
return func(j *Job) {
|
||||||
|
j.Image = image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithText(text string) JobOption {
|
||||||
|
return func(j *Job) {
|
||||||
|
j.Text = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewJob creates a new job
|
// NewJob creates a new job
|
||||||
// It is a request to the agent to do something
|
// It is a request to the agent to do something
|
||||||
// It has a JobResult to get the result asynchronously
|
// It has a JobResult to get the result asynchronously
|
||||||
// To wait for a Job result, use JobResult.WaitResult()
|
// To wait for a Job result, use JobResult.WaitResult()
|
||||||
func NewJob(text, image string) *Job {
|
func NewJob(opts ...JobOption) *Job {
|
||||||
return &Job{
|
j := &Job{
|
||||||
Text: text,
|
|
||||||
Image: image,
|
|
||||||
Result: NewJobResult(),
|
Result: NewJobResult(),
|
||||||
}
|
}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(j)
|
||||||
|
}
|
||||||
|
return j
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetResult sets the result of a job
|
// SetResult sets the result of a job
|
||||||
@@ -71,10 +101,11 @@ func (j *JobResult) SetResult(text string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetResult sets the result of a job
|
// SetResult sets the result of a job
|
||||||
func (j *JobResult) Finish() {
|
func (j *JobResult) Finish(e error) {
|
||||||
j.Lock()
|
j.Lock()
|
||||||
defer j.Unlock()
|
defer j.Unlock()
|
||||||
|
|
||||||
|
j.Error = e
|
||||||
close(j.ready)
|
close(j.ready)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +196,7 @@ func (a *Agent) consumeJob(job *Job) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
job.Result.Callback(chosenAction, params.actionParams, reasoning)
|
job.Callback(chosenAction, params.actionParams, reasoning)
|
||||||
|
|
||||||
if params.actionParams == nil {
|
if params.actionParams == nil {
|
||||||
fmt.Println("no parameters")
|
fmt.Println("no parameters")
|
||||||
@@ -186,7 +217,7 @@ func (a *Agent) consumeJob(job *Job) {
|
|||||||
}
|
}
|
||||||
fmt.Printf("Action run result: %v\n", result)
|
fmt.Printf("Action run result: %v\n", result)
|
||||||
job.Result.SetResult(result)
|
job.Result.SetResult(result)
|
||||||
job.Result.CallbackWithResult(chosenAction, params.actionParams, reasoning, result)
|
job.CallbackWithResult(chosenAction, params.actionParams, reasoning, result)
|
||||||
|
|
||||||
// calling the function
|
// calling the function
|
||||||
messages = append(messages, openai.ChatCompletionMessage{
|
messages = append(messages, openai.ChatCompletionMessage{
|
||||||
@@ -220,8 +251,6 @@ func (a *Agent) consumeJob(job *Job) {
|
|||||||
} else if !chosenAction.Definition().Name.Is(action.ReplyActionName) {
|
} else if !chosenAction.Definition().Name.Is(action.ReplyActionName) {
|
||||||
// We need to do another action (?)
|
// We need to do another action (?)
|
||||||
// The agent decided to do another action
|
// The agent decided to do another action
|
||||||
fmt.Println("Another action to do: ", followingAction.Definition().Name)
|
|
||||||
fmt.Println("Reasoning: ", reasoning)
|
|
||||||
// call ourselves again
|
// call ourselves again
|
||||||
a.currentReasoning = reasoning
|
a.currentReasoning = reasoning
|
||||||
a.nextAction = followingAction
|
a.nextAction = followingAction
|
||||||
@@ -249,5 +278,5 @@ func (a *Agent) consumeJob(job *Job) {
|
|||||||
msg.Content)
|
msg.Content)
|
||||||
|
|
||||||
a.currentConversation = append(a.currentConversation, msg)
|
a.currentConversation = append(a.currentConversation, msg)
|
||||||
job.Result.Finish()
|
job.Result.Finish(nil)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user