describeImagesFallback implements the "A" half of the hybrid vision strategy: when the active model has no native vision, it routes the attached images through a separate vision-capable model that returns a textual description, which the caller folds into the prompt so a text-only provider can still
(ctx context.Context, images []models.ImageContent)
| 96 | // no vision-capable model is configured/reachable (the caller then warns and |
| 97 | // drops the image rather than sending something a model cannot read). |
| 98 | func (cli *ChatCLI) describeImagesFallback(ctx context.Context, images []models.ImageContent) (string, bool) { |
| 99 | if len(images) == 0 { |
| 100 | return "", false |
| 101 | } |
| 102 | |
| 103 | provider, model, ok := cli.resolveVisionDescribeModel() |
| 104 | if !ok { |
| 105 | return "", false |
| 106 | } |
| 107 | |
| 108 | client, err := cli.manager.GetClient(provider, model) |
| 109 | if err != nil { |
| 110 | cli.logger.Warn("vision describe-fallback: falha ao obter client", |
| 111 | zap.String("provider", provider), zap.String("model", model), zap.Error(err)) |
| 112 | return "", false |
| 113 | } |
| 114 | |
| 115 | instruction := i18n.T("vision.describe.instruction") |
| 116 | userMsg := models.Message{Role: "user", Content: instruction, Images: images} |
| 117 | |
| 118 | cli.animation.UpdateMessage(i18n.T("vision.describe.in_progress", model)) |
| 119 | desc, err := client.SendPrompt(ctx, instruction, []models.Message{userMsg}, describeMaxTokens) |
| 120 | if err != nil { |
| 121 | cli.logger.Warn("vision describe-fallback: SendPrompt falhou", |
| 122 | zap.String("provider", provider), zap.String("model", model), zap.Error(err)) |
| 123 | return "", false |
| 124 | } |
| 125 | desc = strings.TrimSpace(desc) |
| 126 | if desc == "" { |
| 127 | return "", false |
| 128 | } |
| 129 | |
| 130 | // Wrap the description so the downstream (text-only) model knows this is a |
| 131 | // machine-generated transcription of one or more attached images. |
| 132 | return "\n\n" + i18n.T("vision.describe.note", len(images), model) + "\n" + desc + "\n", true |
| 133 | } |
| 134 | |
| 135 | // resolveVisionDescribeModel picks the provider+model used to caption images |
| 136 | // for the describe-fallback. Resolution order: |
no test coverage detected