diff --git a/conf/models/gitee.json b/conf/models/gitee.json index a6d1869a74..8940759949 100644 --- a/conf/models/gitee.json +++ b/conf/models/gitee.json @@ -9,7 +9,8 @@ "status": "", "balance": "tokens/packages/balance", "embedding": "embedding", - "rerank": "rerank" + "rerank": "rerank", + "ocr": "images/ocr" }, "models": [ { @@ -46,6 +47,30 @@ "model_types": [ "embedding" ] + }, + { + "name": "GOT-OCR2_0", + "model_types": [ + "ocr" + ] + }, + { + "name": "DeepSeek-OCR-2", + "model_types": [ + "ocr" + ] + }, + { + "name": "PaddleOCR-VL-1.5", + "model_types": [ + "ocr" + ] + }, + { + "name": "HunyuanOCR", + "model_types": [ + "ocr" + ] } ] } \ No newline at end of file diff --git a/internal/cli/user_command.go b/internal/cli/user_command.go index abc06c443d..f0f025cee2 100644 --- a/internal/cli/user_command.go +++ b/internal/cli/user_command.go @@ -2092,22 +2092,36 @@ func (c *RAGFlowClient) OCRUserCommand(cmd *Command) (ResponseIf, error) { return nil, fmt.Errorf("model name not provided and no current model set. Use 'use model' command first") } - filename, ok := cmd.Params["file"].(string) - if !ok { - return nil, fmt.Errorf("text not provided") + var filename string + var fileURL string + var ok bool + var fileContent []byte + + filename, ok = cmd.Params["file"].(string) + if ok { + // read file and convert to base64 + var err error + fileContent, err = os.ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("failed to read file: %w", err) + } + } else { + fileURL, ok = cmd.Params["url"].(string) + if !ok { + return nil, fmt.Errorf("file or url not provided") + } } - // read file and convert to base64 - text, err := os.ReadFile(filename) - if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) - } - base64Text := base64.StdEncoding.EncodeToString(text) payload := map[string]interface{}{ "provider_name": providerName, "instance_name": instanceName, "model_name": modelName, - "content": base64Text, + } + + if fileContent != nil { + payload["content"] = fileContent + } else { + payload["url"] = fileURL } url := "/file/ocr" @@ -2119,7 +2133,7 @@ func (c *RAGFlowClient) OCRUserCommand(cmd *Command) (ResponseIf, error) { if resp.StatusCode != 200 { return nil, fmt.Errorf("failed to OCR document: HTTP %d, body: %s", resp.StatusCode, string(resp.Body)) } - var result CommonResponse + var result CommonDataResponse if err = json.Unmarshal(resp.Body, &result); err != nil { return nil, fmt.Errorf("OCR document failed: invalid JSON (%w)", err) } diff --git a/internal/cli/user_parser.go b/internal/cli/user_parser.go index 5c98b52f42..b1e2e2ed55 100644 --- a/internal/cli/user_parser.go +++ b/internal/cli/user_parser.go @@ -2822,20 +2822,33 @@ func (p *Parser) parseOCRCommand() (*Command, error) { } p.nextToken() - if p.curToken.Type != TokenFile { - return nil, fmt.Errorf("expected FILE to OCR") - } - p.nextToken() // consume FILE - - file, err := p.parseQuotedString() - if err != nil { - return nil, err - } - p.nextToken() - cmd := NewCommand("ocr_user_command") + + switch p.curToken.Type { + case TokenFile: + p.nextToken() + var file string + file, err = p.parseQuotedString() + if err != nil { + return nil, err + } + cmd.Params["file"] = file + p.nextToken() + case TokenURL: + p.nextToken() + var url string + url, err = p.parseQuotedString() + if err != nil { + return nil, err + } + cmd.Params["url"] = url + p.nextToken() + default: + return nil, fmt.Errorf("expected FILE or URL") + } + cmd.Params["composite_model_name"] = compositeModelName - cmd.Params["file"] = file + return cmd, nil } diff --git a/internal/entity/model.go b/internal/entity/model.go index 08a2958a5f..a0b69f7020 100644 --- a/internal/entity/model.go +++ b/internal/entity/model.go @@ -230,8 +230,10 @@ func NewProviderManager(dirPath string) (*ProviderManager, error) { // if the prefix of mode.Name is matched with keys of modelSupportThinking if provider.Class == "" { pos := strings.Index(model.Name, "-") - modelClass := model.Name[0:pos] - model.Class = &modelClass + if pos >= 0 { + modelClass := model.Name[0:pos] + model.Class = &modelClass + } } else { model.Class = &provider.Name } diff --git a/internal/entity/models/aliyun.go b/internal/entity/models/aliyun.go index e010bfecdc..c89a959685 100644 --- a/internal/entity/models/aliyun.go +++ b/internal/entity/models/aliyun.go @@ -579,7 +579,7 @@ func (z *AliyunModel) AudioSpeechWithSender(modelName *string, audioContent *str } // OCRFile OCR file -func (z *AliyunModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (z *AliyunModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", z.Name()) } diff --git a/internal/entity/models/baichuan.go b/internal/entity/models/baichuan.go index 1b0cf78a9f..51ac9ae9d6 100644 --- a/internal/entity/models/baichuan.go +++ b/internal/entity/models/baichuan.go @@ -399,7 +399,7 @@ func (z *BaichuanModel) AudioSpeechWithSender(modelName *string, audioContent *s } // OCRFile OCR file -func (z *BaichuanModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (z *BaichuanModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", z.Name()) } diff --git a/internal/entity/models/baidu.go b/internal/entity/models/baidu.go index 470dbc3f5d..42576c1341 100644 --- a/internal/entity/models/baidu.go +++ b/internal/entity/models/baidu.go @@ -626,7 +626,7 @@ func (z *BaiduModel) AudioSpeechWithSender(modelName *string, audioContent *stri } // OCRFile OCR file -func (b *BaiduModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (b *BaiduModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", b.Name()) } diff --git a/internal/entity/models/cohere.go b/internal/entity/models/cohere.go index 61dc60551b..c094bdd3c9 100644 --- a/internal/entity/models/cohere.go +++ b/internal/entity/models/cohere.go @@ -504,7 +504,7 @@ func (z *CoHereModel) AudioSpeechWithSender(modelName *string, audioContent *str } // OCRFile OCR file -func (c *CoHereModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (c *CoHereModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", c.Name()) } diff --git a/internal/entity/models/deepseek.go b/internal/entity/models/deepseek.go index 8b52418cb7..9d9a2406d0 100644 --- a/internal/entity/models/deepseek.go +++ b/internal/entity/models/deepseek.go @@ -609,6 +609,6 @@ func (z *DeepSeekModel) AudioSpeechWithSender(modelName *string, audioContent *s } // OCRFile OCR file -func (d *DeepSeekModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (d *DeepSeekModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", d.Name()) } diff --git a/internal/entity/models/dummy.go b/internal/entity/models/dummy.go index 2dd29e0929..d2fb85095f 100644 --- a/internal/entity/models/dummy.go +++ b/internal/entity/models/dummy.go @@ -98,6 +98,6 @@ func (z *DummyModel) AudioSpeechWithSender(modelName *string, audioContent *stri } // OCRFile OCR file -func (d *DummyModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (d *DummyModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", d.Name()) } diff --git a/internal/entity/models/fishaudio.go b/internal/entity/models/fishaudio.go index 66ff4b1dda..1e9f0aa9d5 100644 --- a/internal/entity/models/fishaudio.go +++ b/internal/entity/models/fishaudio.go @@ -81,7 +81,7 @@ func (z *FishAudioModel) AudioSpeechWithSender(modelName *string, audioContent * } // OCRFile OCR file -func (f *FishAudioModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (f *FishAudioModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", f.Name()) } diff --git a/internal/entity/models/gitee.go b/internal/entity/models/gitee.go index ac7424bfde..ad66dcd96e 100644 --- a/internal/entity/models/gitee.go +++ b/internal/entity/models/gitee.go @@ -23,6 +23,7 @@ import ( "encoding/json" "fmt" "io" + "mime/multipart" "net/http" "ragflow/internal/common" "strings" @@ -616,9 +617,103 @@ func (z *GiteeModel) AudioSpeechWithSender(modelName *string, audioContent *stri return fmt.Errorf("%s, no such method", z.Name()) } +type giteeOCRResponse struct { + Text string `json:"text_result"` + Prompt string `json:"prompt"` +} + // OCRFile OCR file -func (g *GiteeModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { - return nil, fmt.Errorf("%s, no such method", g.Name()) +func (g *GiteeModel) OCRFile(modelName *string, content []byte, imageURL *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { + if imageURL == nil && content == nil { + return nil, fmt.Errorf("url or content is required") + } + + if apiConfig == nil || apiConfig.ApiKey == nil || *apiConfig.ApiKey == "" { + return nil, fmt.Errorf("api key is required") + } + + if modelName == nil || *modelName == "" { + return nil, fmt.Errorf("model name is required") + } + + region := "default" + if apiConfig.Region != nil && *apiConfig.Region != "" { + region = *apiConfig.Region + } + + baseURL := g.BaseURL["default"] + if region != "default" { + if regional, ok := g.BaseURL[region]; ok && regional != "" { + baseURL = regional + } + } + if baseURL == "" { + return nil, fmt.Errorf("gitee: no base URL configured for default region") + } + + url := fmt.Sprintf("%s/%s", strings.TrimSuffix(baseURL, "/"), g.URLSuffix.OCR) + + payload := &bytes.Buffer{} + writer := multipart.NewWriter(payload) + + if err := writer.WriteField("model", *modelName); err != nil { + return nil, fmt.Errorf("failed to write model field: %w", err) + } + + if imageURL != nil { + if err := writer.WriteField("image", *imageURL); err != nil { + return nil, fmt.Errorf("failed to write image URL: %w", err) + } + } else if content != nil && len(content) > 0 { + part, err := writer.CreateFormFile("image", "image") + if err != nil { + return nil, fmt.Errorf("failed to create image form file: %w", err) + } + if _, err = part.Write(content); err != nil { + return nil, fmt.Errorf("failed to write image content: %w", err) + } + } else { + return nil, fmt.Errorf("image or image URL is required") + } + + writer.Close() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, "POST", url, payload) + if err != nil { + return nil, fmt.Errorf("failed to create request: %w", err) + } + + req.Header.Set("Content-Type", writer.FormDataContentType()) + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *apiConfig.ApiKey)) + + resp, err := g.httpClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response: %w", err) + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("gitee OCR API error: %s, body: %s", resp.Status, string(body)) + } + + var giteeResponse giteeOCRResponse + if err = json.Unmarshal(body, &giteeResponse); err != nil { + return nil, fmt.Errorf("failed to parse response: %w", err) + } + + var ocrResponse = OCRResponse{ + Text: &giteeResponse.Text, + } + + return &ocrResponse, nil } func (g *GiteeModel) ListModels(apiConfig *APIConfig) ([]string, error) { diff --git a/internal/entity/models/google.go b/internal/entity/models/google.go index b0bcbf4026..2e1f103dae 100644 --- a/internal/entity/models/google.go +++ b/internal/entity/models/google.go @@ -364,6 +364,6 @@ func (z *GoogleModel) AudioSpeechWithSender(modelName *string, audioContent *str } // OCRFile OCR file -func (g *GoogleModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (g *GoogleModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", g.Name()) } diff --git a/internal/entity/models/huggingface.go b/internal/entity/models/huggingface.go index b2dedbc7f5..41aee10f42 100644 --- a/internal/entity/models/huggingface.go +++ b/internal/entity/models/huggingface.go @@ -435,7 +435,7 @@ func (z *HuggingFaceModel) AudioSpeechWithSender(modelName *string, audioContent } // OCRFile OCR file -func (h *HuggingFaceModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (h *HuggingFaceModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", h.Name()) } diff --git a/internal/entity/models/jina.go b/internal/entity/models/jina.go index 15efd4adbb..7a9f1c02c7 100644 --- a/internal/entity/models/jina.go +++ b/internal/entity/models/jina.go @@ -270,6 +270,6 @@ func (z *JinaModel) AudioSpeechWithSender(modelName *string, audioContent *strin } // OCRFile OCR file -func (z *JinaModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (z *JinaModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", z.Name()) } diff --git a/internal/entity/models/lmstudio.go b/internal/entity/models/lmstudio.go index e62814a505..fa2e2dbf95 100644 --- a/internal/entity/models/lmstudio.go +++ b/internal/entity/models/lmstudio.go @@ -471,7 +471,7 @@ func (z *LmStudioModel) AudioSpeechWithSender(modelName *string, audioContent *s } // OCRFile OCR file -func (l *LmStudioModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (l *LmStudioModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", l.Name()) } diff --git a/internal/entity/models/longcat.go b/internal/entity/models/longcat.go index 17c1e9a808..b954318846 100644 --- a/internal/entity/models/longcat.go +++ b/internal/entity/models/longcat.go @@ -459,6 +459,6 @@ func (l *LongCatModel) AudioSpeechWithSender(modelName *string, audioContent *st } // OCRFile is not exposed by the LongCat API. -func (l *LongCatModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (l *LongCatModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", l.Name()) } diff --git a/internal/entity/models/minimax.go b/internal/entity/models/minimax.go index 9919933bd6..e761a22866 100644 --- a/internal/entity/models/minimax.go +++ b/internal/entity/models/minimax.go @@ -472,6 +472,6 @@ func (z *MinimaxModel) AudioSpeechWithSender(modelName *string, audioContent *st } // OCRFile OCR file -func (m *MinimaxModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *MinimaxModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/mistral.go b/internal/entity/models/mistral.go index ee2388ea49..11ba87ae97 100644 --- a/internal/entity/models/mistral.go +++ b/internal/entity/models/mistral.go @@ -583,6 +583,6 @@ func (z *MistralModel) AudioSpeechWithSender(modelName *string, audioContent *st } // OCRFile OCR file -func (z *MistralModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (z *MistralModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", z.Name()) } diff --git a/internal/entity/models/moonshot.go b/internal/entity/models/moonshot.go index 9e8e5a99a9..652433b7aa 100644 --- a/internal/entity/models/moonshot.go +++ b/internal/entity/models/moonshot.go @@ -512,6 +512,6 @@ func (z *MoonshotModel) AudioSpeechWithSender(modelName *string, audioContent *s } // OCRFile OCR file -func (m *MoonshotModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *MoonshotModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/novita.go b/internal/entity/models/novita.go index 50db75b727..ef48886e87 100644 --- a/internal/entity/models/novita.go +++ b/internal/entity/models/novita.go @@ -657,6 +657,7 @@ func (n *NovitaModel) AudioSpeechWithSender(modelName *string, audioContent *str return fmt.Errorf("%s, no such method", n.Name()) } -func (n *NovitaModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +// OCRFile OCR file +func (n *NovitaModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", n.Name()) } diff --git a/internal/entity/models/nvidia.go b/internal/entity/models/nvidia.go index 9dc9763510..e1cb9daaba 100644 --- a/internal/entity/models/nvidia.go +++ b/internal/entity/models/nvidia.go @@ -576,7 +576,7 @@ func (z *NvidiaModel) AudioSpeechWithSender(modelName *string, audioContent *str } // OCRFile OCR file -func (m *NvidiaModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *NvidiaModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/ollama.go b/internal/entity/models/ollama.go index 2ba36b27f3..01465c8405 100644 --- a/internal/entity/models/ollama.go +++ b/internal/entity/models/ollama.go @@ -469,7 +469,7 @@ func (z *OllamaModel) AudioSpeechWithSender(modelName *string, audioContent *str } // OCRFile OCR file -func (m *OllamaModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *OllamaModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/openai.go b/internal/entity/models/openai.go index 69ea5cf190..0f96386dd9 100644 --- a/internal/entity/models/openai.go +++ b/internal/entity/models/openai.go @@ -618,6 +618,6 @@ func (z *OpenAIModel) AudioSpeechWithSender(modelName *string, audioContent *str } // OCRFile OCR file -func (m *OpenAIModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *OpenAIModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/openrouter.go b/internal/entity/models/openrouter.go index 41bed6f81e..d401ba02bb 100644 --- a/internal/entity/models/openrouter.go +++ b/internal/entity/models/openrouter.go @@ -553,7 +553,7 @@ func (z *OpenRouterModel) AudioSpeechWithSender(modelName *string, audioContent } // OCRFile OCR file -func (m *OpenRouterModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *OpenRouterModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/siliconflow.go b/internal/entity/models/siliconflow.go index a530086850..b31d53898b 100644 --- a/internal/entity/models/siliconflow.go +++ b/internal/entity/models/siliconflow.go @@ -745,6 +745,6 @@ func (z *SiliconflowModel) AudioSpeechWithSender(modelName *string, audioContent } // OCRFile OCR file -func (m *SiliconflowModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *SiliconflowModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/stepfun.go b/internal/entity/models/stepfun.go index 2fd0a9e829..d632313d98 100644 --- a/internal/entity/models/stepfun.go +++ b/internal/entity/models/stepfun.go @@ -477,6 +477,6 @@ func (z *StepFunModel) AudioSpeechWithSender(modelName *string, audioContent *st } // OCRFile OCR file -func (z *StepFunModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (z *StepFunModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", z.Name()) } diff --git a/internal/entity/models/types.go b/internal/entity/models/types.go index 991ceedbce..d4e6e0502e 100644 --- a/internal/entity/models/types.go +++ b/internal/entity/models/types.go @@ -33,7 +33,7 @@ type ModelDriver interface { AudioSpeech(modelName *string, audioContent *string, apiConfig *APIConfig, asrConfig *TTSConfig) (*TTSResponse, error) AudioSpeechWithSender(modelName *string, audioContent *string, apiConfig *APIConfig, ttsConfig *TTSConfig, sender func(*string, *string) error) error // OCRFile OCR file - OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) + OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) // ListModels List supported models ListModels(apiConfig *APIConfig) ([]string, error) @@ -68,6 +68,7 @@ type TTSResponse struct { } type OCRResponse struct { + Text *string `json:"text"` } // URLSuffix represents the URL suffixes for different API endpoints @@ -77,6 +78,7 @@ type URLSuffix struct { AsyncResult string `json:"async_result"` Embedding string `json:"embedding"` Rerank string `json:"rerank"` + OCR string `json:"ocr"` Models string `json:"models"` Balance string `json:"balance"` Files string `json:"files"` diff --git a/internal/entity/models/upstage.go b/internal/entity/models/upstage.go index c68abcce08..2991bb82ce 100644 --- a/internal/entity/models/upstage.go +++ b/internal/entity/models/upstage.go @@ -604,6 +604,6 @@ func (z *UpstageModel) AudioSpeechWithSender(modelName *string, audioContent *st } // OCRFile OCR file -func (z *UpstageModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (z *UpstageModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", z.Name()) } diff --git a/internal/entity/models/vllm.go b/internal/entity/models/vllm.go index 2fe1f78fd7..4933f48fc2 100644 --- a/internal/entity/models/vllm.go +++ b/internal/entity/models/vllm.go @@ -576,6 +576,6 @@ func (z *VllmModel) AudioSpeechWithSender(modelName *string, audioContent *strin } // OCRFile OCR file -func (m *VllmModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *VllmModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/volcengine.go b/internal/entity/models/volcengine.go index e5ad964525..5ab5f1f107 100644 --- a/internal/entity/models/volcengine.go +++ b/internal/entity/models/volcengine.go @@ -529,7 +529,7 @@ func (z *VolcEngine) AudioSpeechWithSender(modelName *string, audioContent *stri } // OCRFile OCR file -func (m *VolcEngine) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *VolcEngine) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/xai.go b/internal/entity/models/xai.go index bc0391adb7..253f1bd195 100644 --- a/internal/entity/models/xai.go +++ b/internal/entity/models/xai.go @@ -512,6 +512,6 @@ func (z *XAIModel) AudioSpeechWithSender(modelName *string, audioContent *string } // OCRFile OCR file -func (m *XAIModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *XAIModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/entity/models/zhipu-ai.go b/internal/entity/models/zhipu-ai.go index 742314e4c5..5a7c88acb5 100644 --- a/internal/entity/models/zhipu-ai.go +++ b/internal/entity/models/zhipu-ai.go @@ -686,6 +686,6 @@ func (z *ZhipuAIModel) AudioSpeechWithSender(modelName *string, audioContent *st } // OCRFile OCR file -func (m *ZhipuAIModel) OCRFile(modelName *string, fileContent *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { +func (m *ZhipuAIModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRResponse, error) { return nil, fmt.Errorf("%s, no such method", m.Name()) } diff --git a/internal/handler/providers.go b/internal/handler/providers.go index f71f1220a4..58dba8352b 100644 --- a/internal/handler/providers.go +++ b/internal/handler/providers.go @@ -1287,7 +1287,8 @@ type OCRFileRequest struct { ProviderName *string `json:"provider_name"` InstanceName *string `json:"instance_name"` ModelName *string `json:"model_name"` - File *string `json:"file"` + Content []byte `json:"content"` + URL *string `json:"url"` } func (h *ProviderHandler) OCRFile(c *gin.Context) { @@ -1339,7 +1340,7 @@ func (h *ProviderHandler) OCRFile(c *gin.Context) { var errorCode common.ErrorCode var err error - response, errorCode, err = h.modelProviderService.OCRFile(*req.ProviderName, *req.InstanceName, *req.ModelName, userID, req.File, &apiConfig, &OCRConfig) + response, errorCode, err = h.modelProviderService.OCRFile(*req.ProviderName, *req.InstanceName, *req.ModelName, userID, req.Content, req.URL, &apiConfig, &OCRConfig) if err != nil { c.JSON(http.StatusOK, gin.H{ diff --git a/internal/service/model_service.go b/internal/service/model_service.go index dcbdeeeb17..bd23026d72 100644 --- a/internal/service/model_service.go +++ b/internal/service/model_service.go @@ -1531,7 +1531,7 @@ func (m *ModelProviderService) AudioSpeechStream(providerName, instanceName, mod return common.CodeServerError, errors.New("model is disabled") } -func (m *ModelProviderService) OCRFile(providerName, instanceName, modelName, userID string, fileContent *string, apiConfig *modelModule.APIConfig, ocrConfig *modelModule.OCRConfig) (*modelModule.OCRResponse, common.ErrorCode, error) { +func (m *ModelProviderService) OCRFile(providerName, instanceName, modelName, userID string, content []byte, url *string, apiConfig *modelModule.APIConfig, ocrConfig *modelModule.OCRConfig) (*modelModule.OCRResponse, common.ErrorCode, error) { if apiConfig == nil { apiConfig = &modelModule.APIConfig{} } @@ -1576,7 +1576,7 @@ func (m *ModelProviderService) OCRFile(providerName, instanceName, modelName, us } if !model.ModelTypeMap["ocr"] { - return nil, common.CodeNotFound, errors.New(fmt.Sprintf("provider %s model %s is not a TTS model", providerName, modelName)) + return nil, common.CodeNotFound, errors.New(fmt.Sprintf("provider %s model %s is not a OCR model", providerName, modelName)) } var extra map[string]string @@ -1590,7 +1590,7 @@ func (m *ModelProviderService) OCRFile(providerName, instanceName, modelName, us apiConfig.ApiKey = &instance.APIKey var response *modelModule.OCRResponse - response, err = providerInfo.ModelDriver.OCRFile(&modelName, fileContent, apiConfig, ocrConfig) + response, err = providerInfo.ModelDriver.OCRFile(&modelName, content, url, apiConfig, ocrConfig) if err != nil { return nil, common.CodeServerError, err } @@ -1627,7 +1627,7 @@ func (m *ModelProviderService) OCRFile(providerName, instanceName, modelName, us newProviderInfo := providerInfo.ModelDriver.NewInstance(newURL) var response *modelModule.OCRResponse - response, err = newProviderInfo.OCRFile(&modelName, fileContent, apiConfig, ocrConfig) + response, err = newProviderInfo.OCRFile(&modelName, content, url, apiConfig, ocrConfig) if err != nil { return nil, common.CodeServerError, err }