返回 DeepSeek-Reasonix
imageinput.go
根目录 / internal / agent / imageinput.go
1 package agent
2
3 import (
4 "context"
5 "fmt"
6
7 "reasonix/internal/attachment"
8 "reasonix/internal/imageinput"
9 "reasonix/internal/provider"
10 "reasonix/internal/tool"
11 )
12
13 type agentImageInput struct {
14 service *imageinput.Service
15 native bool
16 }
17 type imageResult struct {
18 text string
19 summary *provider.VisionSummary
20 diagnostic error
21 }
22
23 func newImageInput(cfg *imageinput.Config, p provider.Provider) agentImageInput {
24 if cfg == nil {
25 return agentImageInput{native: supportsNativeImages(p)}
26 }
27 return agentImageInput{service: imageinput.New(*cfg), native: supportsNativeImages(p)}
28 }
29 func (a *Agent) ImageInput() *imageinput.Service { return a.imageInput.service }
30
31 // ImageRequestResolver turns durable ImageInputs into provider-visible Images
32 // on a request copy. It must not write variants or uploads back to history.
33 type ImageRequestResolver interface {
34 ResolveRequestImages(ctx context.Context, msgs []provider.Message) ([]provider.Message, error)
35 PersistToolImages(ctx context.Context, images []string) ([]attachment.ImageInput, error)
36 }
37
38 func (a *Agent) SetImageRequestResolver(resolver ImageRequestResolver) {
39 if a == nil {
40 return
41 }
42 a.imageResolver = resolver
43 if a.svc.tools == nil {
44 return
45 }
46 if item, ok := a.svc.tools.Get(tool.HostTask); ok {
47 if task, ok := item.(*TaskTool); ok {
48 task.imageResolver = resolver
49 }
50 }
51 }
52 func (a *Agent) processToolImages(ctx context.Context, text string, images []string) imageResult {
53 if len(images) == 0 {
54 return imageResult{text: text}
55 }
56 // Durable images are persisted by buildBatchToolResult first. Request
57 // assembly then selects the actual native or understanding model route.
58 if a.imageInput.native || a.imageResolver != nil {
59 return imageResult{text: text}
60 }
61 summary, err := a.imageInput.service.Understand(ctx, a.modelRef, images, a.Session().Snapshot, a.svc.sink)
62 if err != nil {
63 return imageResult{text: text + fmt.Sprintf("\n[Image understanding unavailable: %v. The tool already executed; its text result remains valid. Do not claim to have seen the image or repeat the original action to retry image understanding.]", err), diagnostic: err}
64 }
65 return imageResult{text: imageinput.AppendSummary(text, summary), summary: summary}
66 }
67
68 func supportsNativeImages(p provider.Provider) bool {
69 info, ok := p.(provider.ModelInfoProvider)
70 return ok && info.ModelInfo().SupportsInput(provider.ModalityImage)
71 }
72
72 lines GO