Files
photoprism/internal/ai/vision/api_response.go
2025-04-10 16:49:34 +02:00

92 lines
3.1 KiB
Go

package vision
import (
"math"
"net/http"
"github.com/photoprism/photoprism/internal/ai/classify"
"github.com/photoprism/photoprism/internal/ai/face"
"github.com/photoprism/photoprism/internal/ai/nsfw"
"github.com/photoprism/photoprism/pkg/clean"
)
// ApiResponse represents a Vision API service response.
type ApiResponse struct {
Id string `yaml:"Id,omitempty" json:"id,omitempty"`
Code int `yaml:"Code,omitempty" json:"code,omitempty"`
Error string `yaml:"Error,omitempty" json:"error,omitempty"`
Model *Model `yaml:"Model,omitempty" json:"model,omitempty"`
Result *ApiResult `yaml:"Result,omitempty" json:"result,omitempty"`
}
// ApiResult represents the model response(s) to a Vision API service
// request and can optionally include data from multiple models.
type ApiResult struct {
Labels []LabelResult `yaml:"Labels,omitempty" json:"labels,omitempty"`
Nsfw []nsfw.Result `yaml:"Nsfw,omitempty" json:"nsfw,omitempty"`
Embeddings []face.Embeddings `yaml:"Embeddings,omitempty" json:"embeddings,omitempty"`
Caption *CaptionResult `yaml:"Caption,omitempty" json:"caption,omitempty"`
}
// CaptionResult represents the result generated by a caption generation model.
type CaptionResult struct {
Text string `yaml:"Text,omitempty" json:"text,omitempty"`
Confidence float32 `yaml:"Confidence,omitempty" json:"confidence,omitempty"`
}
// LabelResult represents a label generated by an image classification model.
type LabelResult struct {
Name string `yaml:"Name,omitempty" json:"name"`
Source string `yaml:"Source,omitempty" json:"source"`
Priority int `yaml:"Priority,omitempty" json:"priority,omitempty"`
Confidence float32 `yaml:"Confidence,omitempty" json:"confidence,omitempty"`
Topicality float32 `yaml:"Topicality,omitempty" json:"topicality,omitempty"`
Categories []string `yaml:"Categories,omitempty" json:"categories,omitempty"`
}
// ToClassify returns the label results as classify.Label.
func (r LabelResult) ToClassify() classify.Label {
uncertainty := math.RoundToEven(float64(100 - r.Confidence*100))
return classify.Label{
Name: r.Name,
Source: r.Source,
Priority: r.Priority,
Uncertainty: int(uncertainty),
Categories: r.Categories}
}
// NewApiError generates a Vision API error response based on the specified HTTP status code.
func NewApiError(id string, code int) ApiResponse {
return ApiResponse{
Id: clean.Type(id),
Code: code,
Error: http.StatusText(code),
}
}
// NewLabelsResponse generates a new Vision API image classification service response.
func NewLabelsResponse(id string, model *Model, results classify.Labels) ApiResponse {
if model == nil {
model = NasnetModel
}
var labels = make([]LabelResult, 0, len(results))
for _, label := range results {
labels = append(labels, LabelResult{
Name: label.Name,
Source: label.Source,
Priority: label.Priority,
Confidence: label.Confidence(),
Categories: label.Categories})
}
return ApiResponse{
Id: clean.Type(id),
Code: http.StatusOK,
Model: model,
Result: &ApiResult{Labels: labels},
}
}