diff --git a/openviking/models/rerank/openai_rerank.py b/openviking/models/rerank/openai_rerank.py index 0760cb339..ec300890b 100644 --- a/openviking/models/rerank/openai_rerank.py +++ b/openviking/models/rerank/openai_rerank.py @@ -55,10 +55,26 @@ def rerank_batch(self, query: str, documents: List[str]) -> Optional[List[float] if not documents: return [] + # Filter out empty documents — rerank providers (e.g. DashScope) reject + # empty strings with HTTP 400. + valid_indices = [i for i, d in enumerate(documents) if d and d.strip()] + if not valid_indices: + return [0.0] * len(documents) + + if len(valid_indices) < len(documents): + filtered_docs = [documents[i] for i in valid_indices] + logger.debug( + "[OpenAIRerankClient] Filtered %d empty documents from %d total", + len(documents) - len(valid_indices), + len(documents), + ) + else: + filtered_docs = documents + req_body = { "model": self.model_name, "query": query, - "documents": documents, + "documents": filtered_docs, } try: @@ -75,7 +91,7 @@ def rerank_batch(self, query: str, documents: List[str]) -> Optional[List[float] result = response.json() # Update token usage tracking (estimate, OpenAI rerank doesn't provide token info) - self._extract_and_update_token_usage(result, query, documents) + self._extract_and_update_token_usage(result, query, filtered_docs) # Standard OpenAI/Cohere rerank format: results[].{index, relevance_score} results = result.get("results") @@ -83,26 +99,35 @@ def rerank_batch(self, query: str, documents: List[str]) -> Optional[List[float] logger.warning(f"[OpenAIRerankClient] Unexpected response format: {result}") return None - if len(results) != len(documents): + if len(results) != len(filtered_docs): logger.warning( "[OpenAIRerankClient] Unexpected rerank result length: expected=%s actual=%s", - len(documents), + len(filtered_docs), len(results), ) return None - # Results may not be in original order — sort by index - scores = [0.0] * len(documents) + # Map scores back to original document indices. + # Empty documents get a score of 0.0. + filtered_scores = [0.0] * len(filtered_docs) for item in results: idx = item.get("index") - if idx is None or not (0 <= idx < len(documents)): + if idx is None or not (0 <= idx < len(filtered_docs)): logger.warning( "[OpenAIRerankClient] Out-of-bounds or missing index in result: %s", item ) return None - scores[idx] = item.get("relevance_score", 0.0) + filtered_scores[idx] = item.get("relevance_score", 0.0) - logger.debug(f"[OpenAIRerankClient] Reranked {len(documents)} documents") + scores = [0.0] * len(documents) + for fi, oi in enumerate(valid_indices): + scores[oi] = filtered_scores[fi] + + logger.debug( + "[OpenAIRerankClient] Reranked %d documents (%d non-empty)", + len(documents), + len(valid_indices), + ) return scores except Exception as e: