Go: implement Rerank in Aliyun driver (#14676)

### What problem does this PR solve?

The Aliyun Go driver has a stub `Rerank` method that always returns
`"Aliyun, Rerank not implemented"`. DashScope exposes an
OpenAI-compatible rerank endpoint (`compatible-mode/v1/rerank`) and
hosts dedicated bilingual rerankers (`gte-rerank-v2`, `gte-rerank`) that
are a natural pairing with the embedding models already in
`aliyun.json`. Without this, Aliyun users cannot use reranking within
RAGFlow.

Closes #14675

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
Joseff
2026-05-08 08:21:04 -04:00
committed by GitHub
parent 0552b1695a
commit 2ad854c586
2 changed files with 109 additions and 2 deletions

View File

@@ -8,6 +8,7 @@
"url_suffix": {
"chat": "compatible-mode/v1/chat/completions",
"embedding": "compatible-mode/v1/embeddings",
"rerank": "compatible-api/v1/reranks",
"models": "api/v1/deployments/models"
},
"models": [
@@ -31,6 +32,13 @@
"model_types": [
"embedding"
]
},
{
"name": "qwen3-rerank",
"max_tokens": 8192,
"model_types": [
"rerank"
]
}
],
"features": {

View File

@@ -458,9 +458,108 @@ func (z *AliyunModel) Encode(modelName *string, texts []string, apiConfig *APICo
return embeddings, nil
}
// Rerank calculates similarity scores between query and texts
type aliyunRerankRequest struct {
Model string `json:"model"`
Query string `json:"query"`
Documents []string `json:"documents"`
TopN int `json:"top_n"`
ReturnDocuments bool `json:"return_documents"`
}
type aliyunRerankResponse struct {
Results []struct {
Index int `json:"index"`
RelevanceScore float64 `json:"relevance_score"`
} `json:"results"`
}
func (z *AliyunModel) Rerank(modelName *string, query string, texts []string, apiConfig *APIConfig) ([]float64, error) {
return nil, fmt.Errorf("%s, Rerank not implemented", z.Name())
if len(texts) == 0 {
return []float64{}, nil
}
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 := z.BaseURL["default"]
if region != "default" {
if regional, ok := z.BaseURL[region]; ok && regional != "" {
baseURL = regional
}
}
if baseURL == "" {
return nil, fmt.Errorf("aliyun: no base URL configured for default region")
}
url := fmt.Sprintf("%s/%s", strings.TrimSuffix(baseURL, "/"), z.URLSuffix.Rerank)
reqBody := aliyunRerankRequest{
Model: *modelName,
Query: query,
Documents: texts,
TopN: len(texts),
ReturnDocuments: false,
}
jsonData, err := json.Marshal(reqBody)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *apiConfig.ApiKey))
resp, err := z.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("Aliyun rerank API error: %s, body: %s", resp.Status, string(body))
}
var rerankResp aliyunRerankResponse
if err = json.Unmarshal(body, &rerankResp); err != nil {
return nil, fmt.Errorf("failed to parse response: %w", err)
}
scores := make([]float64, len(texts))
seen := make([]bool, len(texts))
for _, r := range rerankResp.Results {
if r.Index < 0 || r.Index >= len(texts) {
return nil, fmt.Errorf("aliyun rerank: result index %d out of range for %d documents", r.Index, len(texts))
}
if seen[r.Index] {
return nil, fmt.Errorf("aliyun rerank: duplicate result index %d", r.Index)
}
scores[r.Index] = r.RelevanceScore
seen[r.Index] = true
}
if len(rerankResp.Results) != len(texts) {
return nil, fmt.Errorf("aliyun rerank: expected %d results, got %d", len(texts), len(rerankResp.Results))
}
return scores, nil
}
type AliyunModelItem struct {