mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-07 03:48:44 +08:00
Use GetChatModel, remove duplicate functions in model_service.go (#14546)
### What problem does this PR solve? Use GetChatModel, remove duplicate functions in model_service.go ### Type of change - [x] Refactoring Co-authored-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
@@ -1322,10 +1322,6 @@ func (p *Parser) parseCreateProviderInstance() (*Command, error) {
|
||||
return nil, fmt.Errorf("expected instance name: %w", err)
|
||||
}
|
||||
|
||||
// Check if instance_name is "default"
|
||||
if instanceName == "default" {
|
||||
return nil, fmt.Errorf("instance name cannot be 'default'")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
if p.curToken.Type != TokenKey {
|
||||
|
||||
@@ -35,10 +35,3 @@ const (
|
||||
// ModelTypeOCR optical character recognition model
|
||||
ModelTypeOCR ModelType = "ocr"
|
||||
)
|
||||
|
||||
// ModelCredentials holds the credentials for a model
|
||||
type ModelCredentials struct {
|
||||
ProviderName string
|
||||
ModelName string
|
||||
APIKey string
|
||||
}
|
||||
|
||||
@@ -265,15 +265,6 @@ func (h *ProviderHandler) CreateProviderInstance(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if instance name is "default"
|
||||
if req.InstanceName == "default" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": common.CodeBadRequest,
|
||||
"message": "Instance name cannot be 'default'",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
userID := c.GetString("user_id")
|
||||
|
||||
_, err := h.modelProviderService.CreateProviderInstance(providerName, req.InstanceName, req.APIKey, req.BaseURL, req.Region, userID)
|
||||
|
||||
@@ -192,7 +192,7 @@ func (s *ChunkService) RetrievalTest(req *RetrievalTestRequest, userID string) (
|
||||
|
||||
// Determine meta_data_filter
|
||||
var chatID string
|
||||
var creds *entity.ModelCredentials
|
||||
var chatModelForFilter *models.ChatModel
|
||||
filter := req.Filter
|
||||
|
||||
if req.SearchID != nil && *req.SearchID != "" {
|
||||
@@ -216,28 +216,32 @@ func (s *ChunkService) RetrievalTest(req *RetrievalTestRequest, userID string) (
|
||||
if method == "auto" || method == "semi_auto" {
|
||||
modelProviderSvc := NewModelProviderService()
|
||||
if chatID != "" {
|
||||
// Use chat_id from search_config
|
||||
creds, err = modelProviderSvc.GetModelByName(chatID, tenantIDs[0])
|
||||
// Use chat_id from search_config (it's actually the model name)
|
||||
chatModelForFilter, err = modelProviderSvc.GetChatModel(tenantIDs[0], chatID)
|
||||
if err != nil {
|
||||
common.Warn("Failed to get chat model from search_config chat_id, using tenant default", zap.String("chatID", chatID), zap.Error(err))
|
||||
} else {
|
||||
common.Info("Fetched chat model (from search_config) for metadata filter",
|
||||
zap.String("chatID", chatID),
|
||||
zap.String("tenantID", tenantIDs[0]),
|
||||
zap.String("providerName", creds.ProviderName),
|
||||
zap.String("modelName", creds.ModelName))
|
||||
zap.String("tenantID", tenantIDs[0]))
|
||||
}
|
||||
}
|
||||
// If no chatID from search_config, or creds not found, use tenant default
|
||||
if creds == nil {
|
||||
creds, err = modelProviderSvc.GetDefaultModel(entity.ModelTypeChat, tenantIDs[0])
|
||||
if err != nil {
|
||||
common.Warn("Failed to get tenant default chat model for meta_data_filter", zap.Error(err))
|
||||
|
||||
// If no chatID from search_config, or chatModel not found, use tenant default
|
||||
if chatModelForFilter == nil {
|
||||
tenantSvc := NewTenantService()
|
||||
modelName, err := tenantSvc.GetDefaultModelName(tenantIDs[0], entity.ModelTypeChat)
|
||||
if err != nil || modelName == "" {
|
||||
common.Warn("Failed to get tenant default chat model name for meta_data_filter", zap.Error(err))
|
||||
} else {
|
||||
common.Info("Fetched chat model (tenant default) for metadata filter",
|
||||
zap.String("tenantID", tenantIDs[0]),
|
||||
zap.String("providerName", creds.ProviderName),
|
||||
zap.String("modelName", creds.ModelName))
|
||||
chatModelForFilter, err = modelProviderSvc.GetChatModel(tenantIDs[0], modelName)
|
||||
if err != nil {
|
||||
common.Warn("Failed to get chat model for meta_data_filter", zap.Error(err))
|
||||
} else {
|
||||
common.Info("Fetched chat model (tenant default) for metadata filter",
|
||||
zap.String("tenantID", tenantIDs[0]),
|
||||
zap.String("modelName", modelName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,7 +258,7 @@ func (s *ChunkService) RetrievalTest(req *RetrievalTestRequest, userID string) (
|
||||
common.Warn("Failed to get flatted metadata", zap.Error(err))
|
||||
} else {
|
||||
common.Info("metadata filter conditions", zap.Any("filter", filter))
|
||||
filteredDocIDs, _ := ApplyMetaDataFilter(ctx, filter, flattedMeta, req.Question, creds, req.DocIDs)
|
||||
filteredDocIDs, _ := ApplyMetaDataFilter(ctx, filter, flattedMeta, req.Question, chatModelForFilter, req.DocIDs)
|
||||
docIDs = filteredDocIDs
|
||||
common.Info("ApplyMetaDataFilter result", zap.Strings("docIDs", docIDs))
|
||||
}
|
||||
@@ -262,24 +266,30 @@ func (s *ChunkService) RetrievalTest(req *RetrievalTestRequest, userID string) (
|
||||
|
||||
// Apply cross_languages and keyword extraction with tenant default chat model
|
||||
modifiedQuestion := req.Question
|
||||
var chatModel *models.ChatModel
|
||||
|
||||
// Get chat model for cross_languages and keyword_extraction
|
||||
if len(req.CrossLanguages) > 0 || (req.Keyword != nil && *req.Keyword) {
|
||||
tenantSvc := NewTenantService()
|
||||
modelProviderSvc := NewModelProviderService()
|
||||
creds, err = modelProviderSvc.GetDefaultModel(entity.ModelTypeChat, tenantIDs[0])
|
||||
if err != nil {
|
||||
common.Warn("Failed to get default chat model for LLM transformations", zap.Error(err))
|
||||
modelName, err := tenantSvc.GetDefaultModelName(tenantIDs[0], "chat")
|
||||
if err != nil || modelName == "" {
|
||||
common.Warn("Failed to get default chat model name for LLM transformations", zap.Error(err))
|
||||
} else {
|
||||
common.Info("Fetched chat model (tenant default) for cross_languages/keyword_extraction",
|
||||
zap.String("tenantID", tenantIDs[0]),
|
||||
zap.String("providerName", creds.ProviderName),
|
||||
zap.String("modelName", creds.ModelName))
|
||||
chatModel, err = modelProviderSvc.GetChatModel(tenantIDs[0], modelName)
|
||||
if err != nil {
|
||||
common.Warn("Failed to get chat model for LLM transformations", zap.Error(err))
|
||||
} else {
|
||||
common.Info("Fetched chat model (tenant default) for cross_languages/keyword_extraction",
|
||||
zap.String("tenantID", tenantIDs[0]),
|
||||
zap.String("modelName", modelName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply cross_languages on the question (translate question)
|
||||
if creds != nil && len(req.CrossLanguages) > 0 {
|
||||
translated, err := CrossLanguages(ctx, creds, req.Question, req.CrossLanguages)
|
||||
if chatModel != nil && len(req.CrossLanguages) > 0 {
|
||||
translated, err := CrossLanguages(ctx, chatModel, req.Question, req.CrossLanguages)
|
||||
if err != nil {
|
||||
common.Warn("Failed to translate question", zap.Error(err))
|
||||
} else {
|
||||
@@ -288,8 +298,8 @@ func (s *ChunkService) RetrievalTest(req *RetrievalTestRequest, userID string) (
|
||||
}
|
||||
|
||||
// Apply keyword extraction on the question (append keywords to question)
|
||||
if creds != nil && req.Keyword != nil && *req.Keyword {
|
||||
extractedKeywords, err := KeywordExtraction(ctx, creds, modifiedQuestion, 3)
|
||||
if chatModel != nil && req.Keyword != nil && *req.Keyword {
|
||||
extractedKeywords, err := KeywordExtraction(ctx, chatModel, modifiedQuestion, 3)
|
||||
if err != nil {
|
||||
common.Warn("Failed to extract keywords from question", zap.Error(err))
|
||||
} else if extractedKeywords != "" {
|
||||
|
||||
@@ -25,18 +25,17 @@ import (
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"ragflow/internal/entity"
|
||||
modelModule "ragflow/internal/entity/models"
|
||||
)
|
||||
|
||||
// KeywordExtraction extracts keywords from content using LLM.
|
||||
// Corresponds to rag/prompts/generator.py:keyword_extraction().
|
||||
//
|
||||
// Uses ChatToModelByApiKey via ModelCredentials to call the LLM with a keyword extraction prompt.
|
||||
// Uses ChatModel to call the LLM with a keyword extraction prompt.
|
||||
// Returns comma-separated top N important keywords/phrases from the content.
|
||||
func KeywordExtraction(ctx context.Context, creds *entity.ModelCredentials, content string, topN int) (string, error) {
|
||||
if creds == nil {
|
||||
return "", fmt.Errorf("model credentials is nil")
|
||||
func KeywordExtraction(ctx context.Context, chatModel *modelModule.ChatModel, content string, topN int) (string, error) {
|
||||
if chatModel == nil {
|
||||
return "", fmt.Errorf("chat model is nil")
|
||||
}
|
||||
|
||||
if content == "" {
|
||||
@@ -65,32 +64,39 @@ func KeywordExtraction(ctx context.Context, creds *entity.ModelCredentials, cont
|
||||
{Role: "user", Content: "Output: "},
|
||||
}
|
||||
|
||||
// Call LLM using ChatWithMessagesToModelByApiKey
|
||||
modelProviderSvc := NewModelProviderService()
|
||||
responsePtr, code, err := modelProviderSvc.ChatWithMessagesToModelByApiKey(creds.ProviderName, creds.ModelName, creds.APIKey, messages)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to extract keywords: code=%d, err=%w", int(code), err)
|
||||
// Use low temperature for deterministic keyword extraction (matching Python behavior)
|
||||
modelConfig := &modelModule.ChatConfig{
|
||||
Temperature: func() *float64 { t := 0.2; return &t }(),
|
||||
}
|
||||
|
||||
response := *responsePtr
|
||||
common.Info("KeywordExtraction result", zap.String("response", response))
|
||||
// Call LLM using ChatModel
|
||||
response, err := chatModel.ModelDriver.ChatWithMessages(*chatModel.ModelName, messages, chatModel.APIConfig, modelConfig)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to extract keywords: %w", err)
|
||||
}
|
||||
|
||||
if response == nil || response.Answer == nil {
|
||||
return "", fmt.Errorf("empty response from keyword extraction")
|
||||
}
|
||||
|
||||
common.Info("KeywordExtraction result", zap.String("response", *response.Answer))
|
||||
|
||||
// Clean up response - remove thinking tags if present
|
||||
response = strings.TrimSpace(response)
|
||||
response = thinkBlockRE.ReplaceAllString(response, "")
|
||||
response = strings.TrimSpace(response)
|
||||
result := strings.TrimSpace(*response.Answer)
|
||||
result = thinkBlockRE.ReplaceAllString(result, "")
|
||||
result = strings.TrimSpace(result)
|
||||
|
||||
if strings.Contains(response, "**ERROR**") {
|
||||
if strings.Contains(result, "**ERROR**") {
|
||||
return "", fmt.Errorf("error in keyword extraction response")
|
||||
}
|
||||
|
||||
return response, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CrossLanguages translates a question into multiple languages using LLM.
|
||||
func CrossLanguages(ctx context.Context, creds *entity.ModelCredentials, query string, languages []string) (string, error) {
|
||||
if creds == nil {
|
||||
return "", fmt.Errorf("model credentials is nil")
|
||||
func CrossLanguages(ctx context.Context, chatModel *modelModule.ChatModel, query string, languages []string) (string, error) {
|
||||
if chatModel == nil {
|
||||
return "", fmt.Errorf("chat model is nil")
|
||||
}
|
||||
|
||||
if query == "" {
|
||||
@@ -125,32 +131,40 @@ func CrossLanguages(ctx context.Context, creds *entity.ModelCredentials, query s
|
||||
{Role: "user", Content: userPrompt},
|
||||
}
|
||||
|
||||
// Call LLM using ChatWithMessagesToModelByApiKey
|
||||
modelProviderSvc := NewModelProviderService()
|
||||
responsePtr, code, err := modelProviderSvc.ChatWithMessagesToModelByApiKey(creds.ProviderName, creds.ModelName, creds.APIKey, messages)
|
||||
if err != nil {
|
||||
return query, fmt.Errorf("failed to translate question: code=%d, err=%w", int(code), err)
|
||||
// Use low temperature for deterministic translation (matching Python behavior)
|
||||
modelConfig := &modelModule.ChatConfig{
|
||||
Temperature: func() *float64 { t := 0.2; return &t }(),
|
||||
}
|
||||
|
||||
response := *responsePtr
|
||||
// Call LLM using ChatModel
|
||||
response, err := chatModel.ModelDriver.ChatWithMessages(*chatModel.ModelName, messages, chatModel.APIConfig, modelConfig)
|
||||
if err != nil {
|
||||
return query, fmt.Errorf("failed to translate question: %w", err)
|
||||
}
|
||||
|
||||
if response == nil || response.Answer == nil {
|
||||
return query, fmt.Errorf("empty response from cross languages translation")
|
||||
}
|
||||
|
||||
result := *response.Answer
|
||||
|
||||
// Clean up response - remove think tags and trim
|
||||
response = strings.TrimSpace(response)
|
||||
response = thinkBlockRE.ReplaceAllString(response, "")
|
||||
response = strings.TrimSpace(response)
|
||||
result = strings.TrimSpace(result)
|
||||
result = thinkBlockRE.ReplaceAllString(result, "")
|
||||
result = strings.TrimSpace(result)
|
||||
|
||||
if strings.Contains(response, "**ERROR**") {
|
||||
if strings.Contains(result, "**ERROR**") {
|
||||
return query, nil
|
||||
}
|
||||
|
||||
// Parse response
|
||||
response = strings.TrimPrefix(response, "Output:")
|
||||
response = strings.TrimPrefix(response, "output:")
|
||||
response = regexp.MustCompile(`(?i)^output:\s*`).ReplaceAllString(response, "")
|
||||
response = regexp.MustCompile(`\n+`).ReplaceAllString(response, "")
|
||||
response = strings.TrimSpace(response)
|
||||
result = strings.TrimPrefix(result, "Output:")
|
||||
result = strings.TrimPrefix(result, "output:")
|
||||
result = regexp.MustCompile(`(?i)^output:\s*`).ReplaceAllString(result, "")
|
||||
result = regexp.MustCompile(`\n+`).ReplaceAllString(result, "")
|
||||
result = strings.TrimSpace(result)
|
||||
|
||||
parts := strings.Split(response, "===")
|
||||
parts := strings.Split(result, "===")
|
||||
var translations []string
|
||||
for _, part := range parts {
|
||||
trimmed := strings.TrimSpace(part)
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"ragflow/internal/entity"
|
||||
modelModule "ragflow/internal/entity/models"
|
||||
)
|
||||
|
||||
@@ -123,9 +122,9 @@ func genMetaFilterPrompt(metaDataJSON, question, constraintsJSON, currentDate st
|
||||
}
|
||||
|
||||
// GenMetaFilter generates filter conditions using LLM based on metadata and question.
|
||||
func GenMetaFilter(ctx context.Context, creds *entity.ModelCredentials, metaData map[string]interface{}, question string, constraints map[string]string) (*MetaFilterResult, error) {
|
||||
if creds == nil {
|
||||
return nil, fmt.Errorf("model credentials is nil")
|
||||
func GenMetaFilter(ctx context.Context, chatModel *modelModule.ChatModel, metaData map[string]interface{}, question string, constraints map[string]string) (*MetaFilterResult, error) {
|
||||
if chatModel == nil {
|
||||
return nil, fmt.Errorf("chat model is nil")
|
||||
}
|
||||
|
||||
if len(metaData) == 0 {
|
||||
@@ -164,20 +163,23 @@ func GenMetaFilter(ctx context.Context, creds *entity.ModelCredentials, metaData
|
||||
{Role: "user", Content: userMessage},
|
||||
}
|
||||
|
||||
// Call LLM using ChatWithMessagesToModelByApiKey
|
||||
modelProviderSvc := NewModelProviderService()
|
||||
response, code, err := modelProviderSvc.ChatWithMessagesToModelByApiKey(creds.ProviderName, creds.ModelName, creds.APIKey, messages)
|
||||
// Call LLM using ChatModel
|
||||
response, err := chatModel.ModelDriver.ChatWithMessages(*chatModel.ModelName, messages, chatModel.APIConfig, nil)
|
||||
if err != nil {
|
||||
common.Warn("ChatWithMessagesToModelByApiKey failed for GenMetaFilter",
|
||||
zap.String("provider", creds.ProviderName),
|
||||
zap.String("model", creds.ModelName),
|
||||
zap.Int("code", int(code)),
|
||||
common.Warn("ChatWithMessages failed for GenMetaFilter",
|
||||
zap.String("model",
|
||||
|
||||
*chatModel.ModelName),
|
||||
zap.Error(err))
|
||||
return nil, fmt.Errorf("failed to generate meta filter: %w", err)
|
||||
}
|
||||
|
||||
if response == nil || response.Answer == nil {
|
||||
return nil, fmt.Errorf("empty response from meta filter generation")
|
||||
}
|
||||
|
||||
// Clean up response
|
||||
responseStr := strings.TrimSpace(*response)
|
||||
responseStr := strings.TrimSpace(*response.Answer)
|
||||
responseStr = thinkBlockRE.ReplaceAllString(responseStr, "")
|
||||
responseStr = strings.TrimSpace(responseStr)
|
||||
|
||||
@@ -447,7 +449,7 @@ func ApplyMetaDataFilter(
|
||||
metaDataFilter map[string]interface{},
|
||||
metaData map[string]interface{},
|
||||
question string,
|
||||
creds *entity.ModelCredentials,
|
||||
chatModel *modelModule.ChatModel,
|
||||
baseDocIDs []string,
|
||||
manualValueResolver ...ManualValueResolver,
|
||||
) ([]string, bool) {
|
||||
@@ -462,7 +464,7 @@ func ApplyMetaDataFilter(
|
||||
|
||||
switch method {
|
||||
case "auto":
|
||||
filters, err := GenMetaFilter(ctx, creds, metaData, question, nil)
|
||||
filters, err := GenMetaFilter(ctx, chatModel, metaData, question, nil)
|
||||
if err != nil {
|
||||
common.Warn("Failed to generate meta filter", zap.Error(err))
|
||||
return docIDs, false
|
||||
@@ -503,7 +505,7 @@ func ApplyMetaDataFilter(
|
||||
}
|
||||
|
||||
if len(filteredMeta) > 0 {
|
||||
filters, err := GenMetaFilter(ctx, creds, filteredMeta, question, constraints)
|
||||
filters, err := GenMetaFilter(ctx, chatModel, filteredMeta, question, constraints)
|
||||
if err != nil {
|
||||
common.Warn("Failed to generate meta filter", zap.Error(err))
|
||||
return docIDs, false
|
||||
|
||||
@@ -36,8 +36,8 @@ func parseModelName(compositeName string) (modelName, instanceName, providerName
|
||||
// Format: model@instance@provider
|
||||
return parts[0], parts[1], parts[2], nil
|
||||
} else if len(parts) == 2 {
|
||||
// Format: model@provider (legacy)
|
||||
return parts[0], "", parts[1], nil
|
||||
// Format: model@provider -> instance defaults to "default"
|
||||
return parts[0], "default", parts[1], nil
|
||||
} else if len(parts) == 1 {
|
||||
return parts[0], "", "", fmt.Errorf("provider name missing in model name: %s", compositeName)
|
||||
} else {
|
||||
@@ -790,30 +790,6 @@ func (m *ModelProviderService) ChatToModelWithMessages(providerName, instanceNam
|
||||
return nil, common.CodeServerError, errors.New("model is disabled")
|
||||
}
|
||||
|
||||
// ChatWithMessagesToModelByApiKey sends multiple messages with roles and returns response
|
||||
func (m *ModelProviderService) ChatWithMessagesToModelByApiKey(providerName, modelName, apiKey string, messages []modelModule.Message) (*string, common.ErrorCode, error) {
|
||||
providerInfo := dao.GetModelProviderManager().FindProvider(providerName)
|
||||
if providerInfo == nil {
|
||||
return nil, common.CodeNotFound, errors.New("provider not found")
|
||||
}
|
||||
|
||||
_, err := dao.GetModelProviderManager().GetModelByName(providerName, modelName)
|
||||
if err != nil {
|
||||
return nil, common.CodeNotFound, errors.New(fmt.Sprintf("provider %s model %s not found", providerName, modelName))
|
||||
}
|
||||
|
||||
var response *modelModule.ChatResponse
|
||||
response, err = providerInfo.ModelDriver.ChatWithMessages(modelName, messages, &modelModule.APIConfig{ApiKey: &apiKey}, nil)
|
||||
if err != nil {
|
||||
return nil, common.CodeServerError, err
|
||||
}
|
||||
if response == nil {
|
||||
return nil, common.CodeServerError, errors.New("empty chat response")
|
||||
}
|
||||
|
||||
return response.Answer, common.CodeSuccess, nil
|
||||
}
|
||||
|
||||
// ChatToModelStreamWithSender streams chat response directly via sender function (best performance, no channel)
|
||||
func (m *ModelProviderService) ChatToModelStreamWithSender(providerName, instanceName, modelName, userID string, messages []modelModule.Message, apiConfig *modelModule.APIConfig, modelConfig *modelModule.ChatConfig, sender func(*string, *string) error) (common.ErrorCode, error) {
|
||||
// Get tenant ID from user
|
||||
@@ -903,78 +879,6 @@ func (m *ModelProviderService) ChatToModelStreamWithSender(providerName, instanc
|
||||
return common.CodeServerError, errors.New("model is disabled")
|
||||
}
|
||||
|
||||
func (m *ModelProviderService) GetDefaultModel(modelType entity.ModelType, tenantID string) (*entity.ModelCredentials, error) {
|
||||
// Get tenant record to find default model name
|
||||
tenant, err := dao.NewTenantDAO().GetByID(tenantID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tenant not found: %w", err)
|
||||
}
|
||||
|
||||
// Determine model name based on model type
|
||||
var defaultModelName string
|
||||
switch modelType {
|
||||
case entity.ModelTypeChat:
|
||||
defaultModelName = tenant.LLMID
|
||||
case entity.ModelTypeEmbedding:
|
||||
defaultModelName = tenant.EmbdID
|
||||
case entity.ModelTypeSpeech2Text:
|
||||
defaultModelName = tenant.ASRID
|
||||
case entity.ModelTypeImage2Text:
|
||||
defaultModelName = tenant.Img2TxtID
|
||||
case entity.ModelTypeRerank:
|
||||
defaultModelName = tenant.RerankID
|
||||
case entity.ModelTypeTTS:
|
||||
if tenant.TTSID != nil {
|
||||
defaultModelName = *tenant.TTSID
|
||||
}
|
||||
case entity.ModelTypeOCR:
|
||||
return nil, errors.New("OCR model name is required")
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown model type: %s", modelType)
|
||||
}
|
||||
|
||||
if defaultModelName == "" {
|
||||
return nil, fmt.Errorf("no default %s model is set", modelType)
|
||||
}
|
||||
|
||||
// Look up the TenantLLM record to get provider name and API key
|
||||
// Use GetByTenantIDAndLLMName which handles splitting model name and factory
|
||||
tenantLLM, err := dao.NewTenantLLMDAO().GetByTenantIDAndLLMName(tenantID, defaultModelName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get tenant default model: %w", err)
|
||||
}
|
||||
|
||||
if tenantLLM == nil {
|
||||
return nil, fmt.Errorf("no default %s model found for tenant", modelType)
|
||||
}
|
||||
|
||||
if tenantLLM.LLMName == nil || tenantLLM.APIKey == nil {
|
||||
return nil, fmt.Errorf("tenant model %q has missing name or api key", defaultModelName)
|
||||
}
|
||||
return &entity.ModelCredentials{
|
||||
ProviderName: tenantLLM.LLMFactory,
|
||||
ModelName: *tenantLLM.LLMName,
|
||||
APIKey: *tenantLLM.APIKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetModelByName gets model credentials by model name (chat_id from search_config)
|
||||
func (m *ModelProviderService) GetModelByName(modelName string, tenantID string) (*entity.ModelCredentials, error) {
|
||||
tenantLLM, err := dao.NewTenantLLMDAO().GetByTenantIDAndLLMName(tenantID, modelName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get model by name: %w", err)
|
||||
}
|
||||
if tenantLLM == nil {
|
||||
return nil, fmt.Errorf("model not found: %s", modelName)
|
||||
}
|
||||
|
||||
return &entity.ModelCredentials{
|
||||
ProviderName: tenantLLM.LLMFactory,
|
||||
ModelName: *tenantLLM.LLMName,
|
||||
APIKey: *tenantLLM.APIKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetEmbeddingModel returns an EmbeddingModel wrapper for the given tenant
|
||||
func (m *ModelProviderService) GetEmbeddingModel(tenantID, compositeModelName string) (*modelModule.EmbeddingModel, error) {
|
||||
driver, modelName, apiConfig, maxTokens, err := m.getModelConfig(tenantID, compositeModelName)
|
||||
@@ -1092,10 +996,6 @@ func (m *ModelProviderService) getModelConfig(tenantID, compositeModelName strin
|
||||
return nil, "", nil, 0, fmt.Errorf("provider %s not found", providerName)
|
||||
}
|
||||
|
||||
if instanceName == "" {
|
||||
instanceName = "default_instance"
|
||||
}
|
||||
|
||||
instance, err := m.modelInstanceDAO.GetByProviderIDAndInstanceName(provider.ID, instanceName)
|
||||
if err != nil {
|
||||
return nil, "", nil, 0, err
|
||||
|
||||
@@ -305,6 +305,38 @@ type DefaultModelResponse struct {
|
||||
Models []ModelItem `json:"models,omitempty"`
|
||||
}
|
||||
|
||||
// GetDefaultModelName returns the full default model ID for a tenant and model type
|
||||
// Format: modelName@instanceName@providerName or modelName@providerName
|
||||
// Returns empty string if no default model is set
|
||||
func (s *TenantService) GetDefaultModelName(tenantID string, modelType entity.ModelType) (string, error) {
|
||||
tenant, err := s.tenantDAO.GetByID(tenantID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var modelID string
|
||||
switch modelType {
|
||||
case entity.ModelTypeChat:
|
||||
modelID = tenant.LLMID
|
||||
case entity.ModelTypeEmbedding:
|
||||
modelID = tenant.EmbdID
|
||||
case entity.ModelTypeRerank:
|
||||
modelID = tenant.RerankID
|
||||
case entity.ModelTypeSpeech2Text:
|
||||
modelID = tenant.ASRID
|
||||
case entity.ModelTypeImage2Text:
|
||||
modelID = tenant.Img2TxtID
|
||||
case entity.ModelTypeTTS:
|
||||
modelID = *tenant.TTSID
|
||||
case entity.ModelTypeOCR:
|
||||
modelID = tenant.OCRID
|
||||
default:
|
||||
return "", fmt.Errorf("invalid model type: %s", modelType)
|
||||
}
|
||||
|
||||
return modelID, nil
|
||||
}
|
||||
|
||||
func (s *TenantService) GetModelInfo(tenantID string, defaultModel string, modelType string) (*string, *string, *string, bool, error) {
|
||||
// normally the model string is: modelName@instanceName@providerName, sometimes it's just modelName@providerName
|
||||
// for the 1st case, parse defaultChatModel into three parts
|
||||
|
||||
Reference in New Issue
Block a user