2026-06-03 16:33:58 +08:00
|
|
|
//
|
|
|
|
|
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
//
|
|
|
|
|
|
2026-05-15 18:41:43 +08:00
|
|
|
package models
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bufio"
|
|
|
|
|
"bytes"
|
2026-06-02 03:27:26 -04:00
|
|
|
"context"
|
2026-05-15 18:41:43 +08:00
|
|
|
"encoding/json"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"mime/multipart"
|
|
|
|
|
"net/http"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type PaddleOCRModel struct {
|
2026-06-04 17:50:22 +08:00
|
|
|
baseModel BaseModel
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewPaddleOCRModel(baseURL map[string]string, urlSuffix URLSuffix) *PaddleOCRModel {
|
|
|
|
|
return &PaddleOCRModel{
|
2026-06-04 17:50:22 +08:00
|
|
|
baseModel: BaseModel{
|
|
|
|
|
BaseURL: baseURL,
|
|
|
|
|
URLSuffix: urlSuffix,
|
|
|
|
|
httpClient: &http.Client{
|
|
|
|
|
Transport: &http.Transport{
|
|
|
|
|
MaxIdleConns: 100,
|
|
|
|
|
MaxIdleConnsPerHost: 10,
|
|
|
|
|
IdleConnTimeout: 90 * time.Second,
|
|
|
|
|
DisableCompression: false,
|
|
|
|
|
},
|
2026-05-15 18:41:43 +08:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p PaddleOCRModel) NewInstance(baseURL map[string]string) ModelDriver {
|
2026-06-04 17:50:22 +08:00
|
|
|
return NewPaddleOCRModel(baseURL, p.baseModel.URLSuffix)
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) Name() string {
|
2026-05-27 14:08:35 +08:00
|
|
|
return "paddle_ocr.net"
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) ChatWithMessages(modelName string, messages []Message, apiConfig *APIConfig, chatModelConfig *ChatConfig) (*ChatResponse, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) ChatStreamlyWithSender(modelName string, messages []Message, apiConfig *APIConfig, modelConfig *ChatConfig, sender func(*string, *string) error) error {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) Embed(modelName *string, texts []string, apiConfig *APIConfig, embeddingConfig *EmbeddingConfig) ([]EmbeddingData, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) Rerank(modelName *string, query string, documents []string, apiConfig *APIConfig, rerankConfig *RerankConfig) (*RerankResponse, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) TranscribeAudio(modelName *string, file *string, apiConfig *APIConfig, asrConfig *ASRConfig) (*ASRResponse, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) TranscribeAudioWithSender(modelName *string, file *string, apiConfig *APIConfig, asrConfig *ASRConfig, sender func(*string, *string) error) error {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) AudioSpeech(modelName *string, audioContent *string, apiConfig *APIConfig, ttsConfig *TTSConfig) (*TTSResponse, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) AudioSpeechWithSender(modelName *string, audioContent *string, apiConfig *APIConfig, ttsConfig *TTSConfig, sender func(*string, *string) error) error {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type paddleSubmitResponse struct {
|
|
|
|
|
Data struct {
|
|
|
|
|
JobId string `json:"jobId"`
|
|
|
|
|
} `json:"data"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type paddlePollResponse struct {
|
|
|
|
|
Data struct {
|
|
|
|
|
State string `json:"state"`
|
|
|
|
|
ErrorMsg string `json:"errorMsg"`
|
|
|
|
|
ResultUrl struct {
|
|
|
|
|
JsonUrl string `json:"jsonUrl"`
|
|
|
|
|
} `json:"resultUrl"`
|
|
|
|
|
} `json:"data"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type paddleJsonlLine struct {
|
|
|
|
|
Result struct {
|
|
|
|
|
LayoutParsingResults []struct {
|
|
|
|
|
Markdown struct {
|
|
|
|
|
Text string `json:"text"`
|
|
|
|
|
} `json:"markdown"`
|
|
|
|
|
} `json:"layoutParsingResults"`
|
|
|
|
|
} `json:"result"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) OCRFile(modelName *string, content []byte, fileURL *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRFileResponse, error) {
|
2026-06-04 17:50:22 +08:00
|
|
|
if err := p.baseModel.APIConfigCheck(apiConfig); err != nil {
|
|
|
|
|
return nil, err
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-04 17:50:22 +08:00
|
|
|
if (content == nil || len(content) == 0) && (fileURL == nil || *fileURL == "") {
|
|
|
|
|
return nil, fmt.Errorf("content and fileURL cannot be both empty")
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-04 17:50:22 +08:00
|
|
|
resolvedBaseURL, err := p.baseModel.GetBaseURL(apiConfig)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
2026-06-04 17:50:22 +08:00
|
|
|
url := fmt.Sprintf("%s/%s", resolvedBaseURL, p.baseModel.URLSuffix.OCR)
|
2026-05-15 18:41:43 +08:00
|
|
|
|
|
|
|
|
optionalPayload := map[string]bool{
|
|
|
|
|
"useDocOrientationClassify": false,
|
|
|
|
|
"useDocUnwarping": false,
|
|
|
|
|
"useChartRecognition": false,
|
|
|
|
|
}
|
|
|
|
|
optBytes, _ := json.Marshal(optionalPayload)
|
|
|
|
|
|
2026-06-02 03:27:26 -04:00
|
|
|
// One generous deadline bounds the whole OCR operation (submit + poll +
|
|
|
|
|
// result download), so the poll loop below can no longer spin forever.
|
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), longOpCallTimeout)
|
|
|
|
|
defer cancel()
|
|
|
|
|
|
2026-05-15 18:41:43 +08:00
|
|
|
var req *http.Request
|
|
|
|
|
|
|
|
|
|
if fileURL != nil && strings.HasPrefix(*fileURL, "http") {
|
|
|
|
|
reqData := map[string]interface{}{
|
|
|
|
|
"fileUrl": *fileURL,
|
|
|
|
|
"model": *modelName,
|
|
|
|
|
"optionalPayload": optionalPayload,
|
|
|
|
|
}
|
|
|
|
|
jsonData, err := json.Marshal(reqData)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to marshal json: %w", err)
|
|
|
|
|
}
|
2026-06-02 03:27:26 -04:00
|
|
|
req, err = http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData))
|
2026-05-15 18:41:43 +08:00
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
|
} else {
|
|
|
|
|
body := &bytes.Buffer{}
|
|
|
|
|
writer := multipart.NewWriter(body)
|
|
|
|
|
|
|
|
|
|
_ = writer.WriteField("model", *modelName)
|
|
|
|
|
_ = writer.WriteField("optionalPayload", string(optBytes))
|
|
|
|
|
|
|
|
|
|
part, err := writer.CreateFormFile("file", "document.pdf")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to create form file: %w", err)
|
|
|
|
|
}
|
|
|
|
|
part.Write(content)
|
|
|
|
|
writer.Close()
|
|
|
|
|
|
2026-06-02 03:27:26 -04:00
|
|
|
req, err = http.NewRequestWithContext(ctx, "POST", url, body)
|
2026-05-15 18:41:43 +08:00
|
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
req.Header.Set("Authorization", fmt.Sprintf("bearer %s", *apiConfig.ApiKey))
|
|
|
|
|
|
2026-06-04 17:50:22 +08:00
|
|
|
resp, err := p.baseModel.httpClient.Do(req)
|
2026-05-15 18:41:43 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to submit job: %w", err)
|
|
|
|
|
}
|
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
|
|
respBody, _ := io.ReadAll(resp.Body)
|
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
|
|
|
return nil, fmt.Errorf("submit job failed: %s", string(respBody))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var submitResp paddleSubmitResponse
|
|
|
|
|
if err := json.Unmarshal(respBody, &submitResp); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to parse submit response: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jobId := submitResp.Data.JobId
|
|
|
|
|
if jobId == "" {
|
|
|
|
|
return nil, fmt.Errorf("failed to get jobId from response")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pollUrl := fmt.Sprintf("%s/%s", url, jobId)
|
|
|
|
|
var jsonlUrl string
|
|
|
|
|
|
|
|
|
|
for {
|
2026-06-02 03:27:26 -04:00
|
|
|
select {
|
|
|
|
|
case <-time.After(3 * time.Second):
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
return nil, ctx.Err()
|
|
|
|
|
}
|
2026-05-15 18:41:43 +08:00
|
|
|
|
2026-06-02 03:27:26 -04:00
|
|
|
pollReq, _ := http.NewRequestWithContext(ctx, "GET", pollUrl, nil)
|
2026-05-15 18:41:43 +08:00
|
|
|
pollReq.Header.Set("Authorization", fmt.Sprintf("bearer %s", *apiConfig.ApiKey))
|
|
|
|
|
|
2026-06-04 17:50:22 +08:00
|
|
|
pollResp, err := p.baseModel.httpClient.Do(pollReq)
|
2026-05-15 18:41:43 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to poll job status: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pollBody, _ := io.ReadAll(pollResp.Body)
|
|
|
|
|
pollResp.Body.Close()
|
|
|
|
|
|
|
|
|
|
if pollResp.StatusCode != http.StatusOK {
|
|
|
|
|
return nil, fmt.Errorf("poll job failed: %s", string(pollBody))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var pollData paddlePollResponse
|
|
|
|
|
if err = json.Unmarshal(pollBody, &pollData); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to parse poll response: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// end if 'done' or 'failed'
|
|
|
|
|
state := pollData.Data.State
|
|
|
|
|
if state == "done" {
|
|
|
|
|
jsonlUrl = pollData.Data.ResultUrl.JsonUrl
|
|
|
|
|
break
|
|
|
|
|
} else if state == "failed" {
|
|
|
|
|
return nil, fmt.Errorf("ocr job failed on server: %s", pollData.Data.ErrorMsg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if jsonlUrl == "" {
|
|
|
|
|
return nil, fmt.Errorf("job done but jsonl url is empty")
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-02 03:27:26 -04:00
|
|
|
resReq, err := http.NewRequestWithContext(ctx, "GET", jsonlUrl, nil)
|
2026-05-15 18:41:43 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to create request for jsonl: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-04 17:50:22 +08:00
|
|
|
resResp, err := p.baseModel.httpClient.Do(resReq)
|
2026-05-15 18:41:43 +08:00
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("failed to download jsonl result: %w", err)
|
|
|
|
|
}
|
|
|
|
|
defer resResp.Body.Close()
|
|
|
|
|
|
|
|
|
|
if resResp.StatusCode != http.StatusOK {
|
|
|
|
|
return nil, fmt.Errorf("failed to download jsonl, status: %d", resResp.StatusCode)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var fullMarkdown strings.Builder
|
|
|
|
|
scanner := bufio.NewScanner(resResp.Body)
|
fix(go-models): raise SSE scanner buffer so large stream chunks are not dropped (#15382)
### Summary
Closes #15381
Every provider in `internal/entity/models/` reads its streaming response
with `bufio.NewScanner(resp.Body)` and iterates over `scanner.Scan()`.
The default `bufio.Scanner` maximum token size is 64KB, so when an
upstream sends a single SSE `data:` line larger than 64KB (long content
deltas, large tool or function call argument blobs, bundled
`reasoning_content`, or providers that emit a whole message in one
event) `scanner.Scan()` returns `false` and `scanner.Err()` returns
`bufio.ErrTooLong`. Streaming chat then ends with an error partway
through the response.
This change adds `scanner.Buffer(make([]byte, 64*1024), 1024*1024)`
immediately after every SSE scanner that was still bare, raising the cap
to 1MB. 1MB is the value already used for streaming chat in `openai.go`,
`modelscope.go`, `groq.go`, `mistral.go`, `xai.go` and the other already
patched providers (the 8MB cap in the repo is reserved for TTS and
embedding paths), so this simply converges the remaining providers onto
the established pattern. Nothing else changes: line parsing, `data:`
prefix handling, `[DONE]` detection, JSON unmarshalling, error handling,
and the existing `scanner.Err()` checks all stay the same.
Providers covered (23 scanners across 22 files): 302ai, aliyun,
baichuan, baidu, cohere, deepinfra, deepseek, gitee, huggingface,
lmstudio, minimax (the chat scanner, whose TTS scanner was already
bumped), moonshot, nvidia, ollama, openrouter, orcarouter, paddleocr,
siliconflow, tokenhub, vllm, volcengine, xunfei, zhipu-ai. `jiekouai.go`
is excluded because it is covered by the in flight #15337.
A table driven regression test (`sse_scanner_buffer_test.go`) streams a
single 128KB `data:` content delta followed by `data: [DONE]` through an
`httptest` server and asserts that `ChatStreamlyWithSender` delivers the
full content with no error across a representative subset of providers.
Without the buffer fix the test fails with `bufio.Scanner: token too
long`.
This PR also removes three duplicate declarations of the package level
`roundTripperFunc` test helper that several recently merged provider PRs
each added independently, which had left the `internal/entity/models`
test package unable to compile. The helper now lives in a single place
and is shared.
### Type of change
- [x] Bug Fix (non-breaking change which fixes an issue)
2026-05-29 07:34:00 -04:00
|
|
|
scanner.Buffer(make([]byte, 64*1024), 1024*1024)
|
2026-05-15 18:41:43 +08:00
|
|
|
|
|
|
|
|
for scanner.Scan() {
|
|
|
|
|
line := strings.TrimSpace(scanner.Text())
|
|
|
|
|
if line == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lineData paddleJsonlLine
|
|
|
|
|
if err := json.Unmarshal([]byte(line), &lineData); err != nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, layoutRes := range lineData.Result.LayoutParsingResults {
|
|
|
|
|
fullMarkdown.WriteString(layoutRes.Markdown.Text)
|
|
|
|
|
fullMarkdown.WriteString("\n\n")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err = scanner.Err(); err != nil {
|
|
|
|
|
return nil, fmt.Errorf("error reading jsonl: %w", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extractedText := strings.TrimSpace(fullMarkdown.String())
|
|
|
|
|
|
|
|
|
|
return &OCRFileResponse{Text: &extractedText}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) ParseFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig) (*ParseFileResponse, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) ListModels(apiConfig *APIConfig) ([]string, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) Balance(apiConfig *APIConfig) (map[string]interface{}, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) CheckConnection(apiConfig *APIConfig) error {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) ListTasks(apiConfig *APIConfig) ([]ListTaskStatus, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *PaddleOCRModel) ShowTask(taskID string, apiConfig *APIConfig) (*TaskResponse, error) {
|
feat(go-models): add PPIO provider driver (#15099)
### What problem does this PR solve?
Closes #15089.
Adds PPIO support to the Go model-provider layer so PPIO instances can
be routed through the Go API server with the same OpenAI-compatible
chat, streaming, model listing, and connection-check flow used by other
SaaS providers.
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
## Summary
- Added a PPIO Go model driver.
- Added the PPIO provider catalog and default OpenAI-compatible API URL.
- Registered PPIO in the model factory.
- Added focused provider and provider-manager tests.
## What changed
- Implemented chat completions, SSE streaming, ListModels, and
CheckConnection for PPIO.
- Covered request shape, stream termination, reasoning fallback, model
listing, custom base URLs, safe transport setup, unsupported methods,
and provider config loading.
- Kept the provider catalog aligned with the existing RAGFlow PPIO
factory model set.
- Cleaned up pre-existing Go model package validation blockers so the
scoped provider tests can run normally with vet enabled.
## Why
The existing Python/provider catalog path includes PPIO, but the Go
model-provider layer did not have a PPIO driver, so the Go API server
could not instantiate or use PPIO as requested in #15089.
2026-05-21 20:52:18 -07:00
|
|
|
return nil, fmt.Errorf("%s, no such method", p.Name())
|
2026-05-15 18:41:43 +08:00
|
|
|
}
|