tools *Toolbox
request ModelRequest
take func() []Message
+ images *ImageStore
}
// Run runs the chain from input, the input of its first request, and returns
request.Input = input
response, err := c.client.Create(ctx, request)
if err != nil {
- return "", err
+ return "", fmt.Errorf("create model response: %w", err)
}
var text string
+
input, text, err = c.handle(ctx, input, response)
if err != nil {
return "", err
// the messages of take. After the final answer it returns no input, and the
// replies of the answer as its text.
func (c *Chain) handle(ctx context.Context, input []any, response ModelResponse) ([]any, string, error) {
- var outputs []any
- var replies []string
+ var (
+ outputs []any
+ replies []string
+ )
+
for _, raw := range response.Output {
item, err := chainInputItem(raw)
if err != nil {
input = append(input, item)
var call ChainFunctionCall
+
err = json.Unmarshal(raw, &call)
if err != nil {
return nil, "", fmt.Errorf("decode output item: %w", err)
input = append(input, outputs...)
for _, message := range c.take() {
- input = append(input, modelUserMessage(message.Text))
+ item, err := imageUserMessage(c.images, message.Text)
+ if err != nil {
+ return nil, "", fmt.Errorf("read queued images: %w", err)
+ }
+
+ input = append(input, item)
}
return input, "", nil
type ChainFunctionCallOutput struct {
Type string `json:"type"`
CallID string `json:"call_id"`
- Output string `json:"output"`
+ Output any `json:"output"`
}
// chainInputItem returns an output item as an input item for the next request.
// id.
func chainInputItem(raw json.RawMessage) (map[string]any, error) {
var item map[string]any
+
err := json.Unmarshal(raw, &item)
if err != nil {
return nil, fmt.Errorf("decode output item: %w", err)