Files
Enterprise-Knowledge-Base/internal/models/rerank/reranker.go
T
wizardchen 53e8e17df4 feat(logger): implement LLM debug logging functionality
- Added a new logger for LLM calls, enabling detailed logging of model interactions, including request and response data.
- Introduced configuration options for enabling and specifying the log directory for LLM debug logs.
- Implemented cleanup for old log files to manage disk space effectively.
- Wrapped existing chat implementations to log calls when debug logging is enabled, enhancing traceability for model interactions.
2026-04-16 23:15:02 +08:00

124 lines
3.3 KiB
Go

package rerank
import (
"context"
"encoding/json"
"fmt"
"github.com/Tencent/WeKnora/internal/logger"
"github.com/Tencent/WeKnora/internal/models/provider"
"github.com/Tencent/WeKnora/internal/types"
)
// Reranker defines the interface for document reranking
type Reranker interface {
// Rerank reranks documents based on relevance to the query
Rerank(ctx context.Context, query string, documents []string) ([]RankResult, error)
// GetModelName returns the model name
GetModelName() string
// GetModelID returns the model ID
GetModelID() string
}
type RankResult struct {
Index int `json:"index"`
Document DocumentInfo `json:"document"`
RelevanceScore float64 `json:"relevance_score"`
}
// Handles the RelevanceScore field by checking if RelevanceScore exists first, otherwise falls back to Score field
func (r *RankResult) UnmarshalJSON(data []byte) error {
var temp struct {
Index int `json:"index"`
Document DocumentInfo `json:"document"`
RelevanceScore *float64 `json:"relevance_score"`
Score *float64 `json:"score"`
}
if err := json.Unmarshal(data, &temp); err != nil {
return fmt.Errorf("failed to unmarshal rank result: %w", err)
}
r.Index = temp.Index
r.Document = temp.Document
if temp.RelevanceScore != nil {
r.RelevanceScore = *temp.RelevanceScore
} else if temp.Score != nil {
r.RelevanceScore = *temp.Score
}
return nil
}
type DocumentInfo struct {
Text string `json:"text"`
}
// UnmarshalJSON handles both string and object formats for DocumentInfo
func (d *DocumentInfo) UnmarshalJSON(data []byte) error {
// First try to unmarshal as a string
var text string
if err := json.Unmarshal(data, &text); err == nil {
d.Text = text
return nil
}
// If that fails, try to unmarshal as an object with text field
var temp struct {
Text string `json:"text"`
}
if err := json.Unmarshal(data, &temp); err != nil {
return fmt.Errorf("failed to unmarshal DocumentInfo: %w", err)
}
d.Text = temp.Text
return nil
}
type RerankerConfig struct {
APIKey string
BaseURL string
ModelName string
Source types.ModelSource
ModelID string
Provider string // Provider identifier: openai, aliyun, zhipu, siliconflow, jina, generic
ExtraConfig map[string]string
AppID string
AppSecret string // 加密值,工厂函数调用方传入,使用前已解密
}
// NewReranker creates a reranker based on the configuration
func NewReranker(config *RerankerConfig) (Reranker, error) {
r, err := newReranker(config)
if err != nil || !logger.LLMDebugEnabled() {
return r, err
}
return &debugReranker{inner: r}, nil
}
func newReranker(config *RerankerConfig) (Reranker, error) {
// Use provider field if set, otherwise detect from URL using provider registry
providerName := provider.ProviderName(config.Provider)
if providerName == "" {
providerName = provider.DetectProvider(config.BaseURL)
}
switch providerName {
case provider.ProviderAliyun:
return NewAliyunReranker(config)
case provider.ProviderZhipu:
return NewZhipuReranker(config)
case provider.ProviderJina:
return NewJinaReranker(config)
case provider.ProviderNvidia:
return NewNvidiaReranker(config)
case provider.ProviderWeKnoraCloud:
return NewWeKnoraCloudReranker(config)
default:
return NewOpenAIReranker(config)
}
}