From 8bc34219f5ec5aa2e169e5a3e1d0b928c7979a70 Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Thu, 6 Aug 2026 13:36:04 +0800 Subject: [PATCH] Go: fix plenty of warnings (#17918) Signed-off-by: Jin Hai --- .../component/production_chain_fixes_test.go | 8 ++-- internal/entity/dataset.go | 2 +- internal/entity/models/anthropic.go | 10 ++--- internal/entity/models/base_model.go | 9 ---- internal/entity/models/cometapi.go | 28 ++++++------ internal/entity/models/gitee.go | 10 ++--- internal/entity/models/google_test.go | 2 +- internal/entity/models/greenpt.go | 8 ++-- internal/entity/models/llm_test.go | 4 +- internal/entity/models/lmstudio.go | 1 - internal/entity/models/model.go | 31 +------------ internal/entity/models/model_test.go | 5 --- internal/entity/models/n1n.go | 3 -- internal/entity/models/nvidia.go | 42 +++++++++--------- internal/entity/models/nvidia_test.go | 2 +- internal/entity/models/openai.go | 44 ------------------- internal/entity/models/openai_test.go | 2 +- internal/entity/models/paddleocr.go | 2 +- internal/entity/models/replicate.go | 36 +++++++-------- internal/entity/models/types.go | 2 +- internal/entity/models/usage_parser_test.go | 2 +- internal/entity/skill_search.go | 2 +- internal/entity/skill_space.go | 2 +- 23 files changed, 83 insertions(+), 174 deletions(-) diff --git a/internal/agent/component/production_chain_fixes_test.go b/internal/agent/component/production_chain_fixes_test.go index 615764e18b..3234d340d8 100644 --- a/internal/agent/component/production_chain_fixes_test.go +++ b/internal/agent/component/production_chain_fixes_test.go @@ -227,17 +227,17 @@ func TestRetrieval_LegacyQueryStringNormalized(t *testing.T) { t.Fatalf("failed to unwrap sql db: %v", err) } sqlDB.SetMaxOpenConns(1) - if err := db.AutoMigrate(&entity.Knowledgebase{}); err != nil { + if err = db.AutoMigrate(&entity.Knowledgebase{}); err != nil { t.Fatalf("failed to migrate knowledgebase: %v", err) } - if err := db.AutoMigrate(&entity.UserTenant{}); err != nil { + if err = db.AutoMigrate(&entity.UserTenant{}); err != nil { t.Fatalf("failed to migrate user_tenant: %v", err) } origDB := dao.DB dao.DB = db t.Cleanup(func() { dao.DB = origDB }) activeStatus := "1" - if err := db.Create(&entity.UserTenant{ + if err = db.Create(&entity.UserTenant{ ID: "ut-1", UserID: "user-1", TenantID: "tenant-1", @@ -248,7 +248,7 @@ func TestRetrieval_LegacyQueryStringNormalized(t *testing.T) { t.Fatalf("failed to seed user_tenant: %v", err) } - if err := db.Create(&entity.Knowledgebase{ + if err = db.Create(&entity.Knowledgebase{ ID: "kb-da1", Name: "da1", TenantID: "tenant-1", diff --git a/internal/entity/dataset.go b/internal/entity/dataset.go index 0a4cc6299f..45ce1a2f22 100644 --- a/internal/entity/dataset.go +++ b/internal/entity/dataset.go @@ -130,7 +130,7 @@ type Knowledgebase struct { } // TableName returns the table name for Knowledgebase model -func (Knowledgebase) TableName() string { +func (kb *Knowledgebase) TableName() string { return "knowledgebase" } diff --git a/internal/entity/models/anthropic.go b/internal/entity/models/anthropic.go index 2f00af7617..18832053e2 100644 --- a/internal/entity/models/anthropic.go +++ b/internal/entity/models/anthropic.go @@ -396,9 +396,8 @@ func (a *AnthropicModel) ListModels(ctx context.Context, apiConfig *APIConfig) ( baseURLRegion := a.region(apiConfig) baseURLConfig := &APIConfig{Region: &baseURLRegion} - if apiConfig != nil { - baseURLConfig.BaseURL = apiConfig.BaseURL - } + baseURLConfig.BaseURL = apiConfig.BaseURL + baseURL, err := a.baseModel.GetBaseURL(baseURLConfig) if err != nil { return nil, err @@ -469,9 +468,8 @@ func (a *AnthropicModel) ChatStreamlyWithSender(ctx context.Context, modelName s baseURLRegion := a.region(apiConfig) baseURLConfig := &APIConfig{Region: &baseURLRegion} - if apiConfig != nil { - baseURLConfig.BaseURL = apiConfig.BaseURL - } + baseURLConfig.BaseURL = apiConfig.BaseURL + baseURL, err := a.baseModel.GetBaseURL(baseURLConfig) if err != nil { return err diff --git a/internal/entity/models/base_model.go b/internal/entity/models/base_model.go index 07e55a8d72..c0b0d2d4fb 100644 --- a/internal/entity/models/base_model.go +++ b/internal/entity/models/base_model.go @@ -256,15 +256,6 @@ func (b *BaseModel) doGetRequest(ctx context.Context, url string, apiConfig *API return body, nil } -// mustMarshal marshals v to JSON, panicking on error. -func mustMarshal(v any) []byte { - b, err := json.Marshal(v) - if err != nil { - panic(fmt.Sprintf("failed to marshal: %v", err)) - } - return b -} - // doStreamRequest sends a JSON POST request and calls handler with the response body. func (b *BaseModel) doStreamRequest(ctx context.Context, url string, apiConfig *APIConfig, reqBody map[string]any, timeout time.Duration, handler func(io.ReadCloser) error) error { ctx, cancel := context.WithTimeout(ctx, timeout) diff --git a/internal/entity/models/cometapi.go b/internal/entity/models/cometapi.go index 610b1e6e31..952a661919 100644 --- a/internal/entity/models/cometapi.go +++ b/internal/entity/models/cometapi.go @@ -107,7 +107,7 @@ func (c *CometAPIModel) ChatWithMessages(ctx context.Context, modelName string, return nil, fmt.Errorf("messages is empty") } - url, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Chat) + baseURL, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Chat) if err != nil { return nil, err } @@ -122,7 +122,7 @@ func (c *CometAPIModel) ChatWithMessages(ctx context.Context, modelName string, } } - body, err := c.baseModel.doRequest(ctx, url, apiConfig, reqBody, nonStreamCallTimeout) + body, err := c.baseModel.doRequest(ctx, baseURL, apiConfig, reqBody, nonStreamCallTimeout) if err != nil { return nil, err } @@ -148,7 +148,7 @@ func (c *CometAPIModel) ChatStreamlyWithSender(ctx context.Context, modelName st return fmt.Errorf("messages is empty") } - url, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Chat) + baseURL, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Chat) if err != nil { return err } @@ -175,7 +175,7 @@ func (c *CometAPIModel) ChatStreamlyWithSender(ctx context.Context, modelName st } reqBody["stream_options"] = map[string]interface{}{"include_usage": true} - return c.baseModel.doStreamRequest(ctx, url, apiConfig, reqBody, streamCallTimeout, func(body io.ReadCloser) error { + return c.baseModel.doStreamRequest(ctx, baseURL, apiConfig, reqBody, streamCallTimeout, func(body io.ReadCloser) error { return HandleStreamingResponse(body, modelUsage, chatModelConfig, OpenAIParserConfig, sender) }) } @@ -206,7 +206,7 @@ func (c *CometAPIModel) Embed(ctx context.Context, modelName *string, texts []st return nil, fmt.Errorf("model name is required") } - url, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Embedding) + baseURL, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Embedding) if err != nil { return nil, err } @@ -219,7 +219,7 @@ func (c *CometAPIModel) Embed(ctx context.Context, modelName *string, texts []st reqBody["dimensions"] = embeddingConfig.Dimension } - body, err := c.baseModel.doRequest(ctx, url, apiConfig, reqBody, nonStreamCallTimeout) + body, err := c.baseModel.doRequest(ctx, baseURL, apiConfig, reqBody, nonStreamCallTimeout) if err != nil { return nil, err } @@ -255,7 +255,7 @@ func (c *CometAPIModel) Embed(ctx context.Context, modelName *string, texts []st // ListModels returns the public CometAPI model catalog. func (c *CometAPIModel) ListModels(ctx context.Context, apiConfig *APIConfig) ([]ListModelResponse, error) { - url, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Models) + baseURL, err := c.endpointURL(cometapiRegion(apiConfig), c.baseModel.URLSuffix.Models) if err != nil { return nil, err } @@ -263,7 +263,7 @@ func (c *CometAPIModel) ListModels(ctx context.Context, apiConfig *APIConfig) ([ ctx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + req, err := http.NewRequestWithContext(ctx, "GET", baseURL, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -362,7 +362,7 @@ func (c *CometAPIModel) TranscribeAudio(ctx context.Context, modelName *string, if err != nil { return nil, err } - url := fmt.Sprintf("%s/%s", resolvedBaseURL, c.baseModel.URLSuffix.ASR) + baseURL := fmt.Sprintf("%s/%s", resolvedBaseURL, c.baseModel.URLSuffix.ASR) // multipart body var body bytes.Buffer @@ -427,7 +427,7 @@ func (c *CometAPIModel) TranscribeAudio(ctx context.Context, modelName *string, } // build request - req, err := http.NewRequest("POST", url, &body) + req, err := http.NewRequest("POST", baseURL, &body) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -482,7 +482,7 @@ func (c *CometAPIModel) AudioSpeech(ctx context.Context, modelName *string, audi if err != nil { return nil, err } - url := fmt.Sprintf("%s/%s", resolvedBaseURL, c.baseModel.URLSuffix.TTS) + baseURL := fmt.Sprintf("%s/%s", resolvedBaseURL, c.baseModel.URLSuffix.TTS) reqBody := map[string]interface{}{ "model": *modelName, @@ -503,7 +503,7 @@ func (c *CometAPIModel) AudioSpeech(ctx context.Context, modelName *string, audi return nil, fmt.Errorf("failed to marshal request: %w", err) } - req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) + req, err := http.NewRequest("POST", baseURL, bytes.NewBuffer(jsonData)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -534,11 +534,11 @@ func (c *CometAPIModel) AudioSpeechWithSender(ctx context.Context, modelName *st } // OCRFile OCR file -func (c *CometAPIModel) OCRFile(ctx context.Context, modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig, modelUsage *common.ModelUsage) (*OCRFileResponse, error) { +func (c *CometAPIModel) OCRFile(ctx context.Context, modelName *string, content []byte, baseURL *string, apiConfig *APIConfig, ocrConfig *OCRConfig, modelUsage *common.ModelUsage) (*OCRFileResponse, error) { return nil, fmt.Errorf("%s, no such method", c.Name()) } -func (c *CometAPIModel) ParseFile(ctx context.Context, modelName *string, content []byte, url *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig, modelUsage *common.ModelUsage) (*ParseFileResponse, error) { +func (c *CometAPIModel) ParseFile(ctx context.Context, modelName *string, content []byte, baseURL *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig, modelUsage *common.ModelUsage) (*ParseFileResponse, error) { return nil, fmt.Errorf("%s, no such method", c.Name()) } diff --git a/internal/entity/models/gitee.go b/internal/entity/models/gitee.go index 976cdf4427..ea873075cd 100644 --- a/internal/entity/models/gitee.go +++ b/internal/entity/models/gitee.go @@ -394,12 +394,12 @@ func (g *GiteeModel) OCRFile(ctx context.Context, modelName *string, content []b payload := &bytes.Buffer{} writer := multipart.NewWriter(payload) - if err := writer.WriteField("model", *modelName); err != nil { + if err = writer.WriteField("model", *modelName); err != nil { return nil, fmt.Errorf("failed to write model field: %w", err) } if imageURL != nil { - if err := writer.WriteField("image", *imageURL); err != nil { + if err = writer.WriteField("image", *imageURL); err != nil { return nil, fmt.Errorf("failed to write image URL: %w", err) } } else if content != nil && len(content) > 0 { @@ -491,12 +491,12 @@ func (g *GiteeModel) ParseFile(ctx context.Context, modelName *string, content [ payload := &bytes.Buffer{} writer := multipart.NewWriter(payload) - if err := writer.WriteField("model", *modelName); err != nil { + if err = writer.WriteField("model", *modelName); err != nil { return nil, fmt.Errorf("failed to write model field: %w", err) } if documentURL != nil { - if err := writer.WriteField("file", *documentURL); err != nil { + if err = writer.WriteField("file", *documentURL); err != nil { return nil, fmt.Errorf("failed to write file URL: %w", err) } } else if content != nil && len(content) > 0 { @@ -853,7 +853,7 @@ func (g *GiteeModel) ListTasks(ctx context.Context, apiConfig *APIConfig) ([]Lis return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body)) } - taskListResp := []ListTaskStatus{} + var taskListResp []ListTaskStatus for _, item := range giteeTaskList.Items { taskListResp = append(taskListResp, ListTaskStatus{ TaskID: item.TaskID, diff --git a/internal/entity/models/google_test.go b/internal/entity/models/google_test.go index d6a3a274a2..cd52ac0961 100644 --- a/internal/entity/models/google_test.go +++ b/internal/entity/models/google_test.go @@ -534,7 +534,7 @@ func TestGoogleGenerateContentConfigRejectsMaxTokensOverflow(t *testing.T) { t.Fatalf("cfg = %#v, want nil on error", cfg) } - maxInt32 := int(math.MaxInt32) + maxInt32 := math.MaxInt32 cfg, err = googleGenerateContentConfig(&ChatConfig{MaxTokens: &maxInt32}, nil) if err != nil { t.Fatalf("googleGenerateContentConfig error = %v", err) diff --git a/internal/entity/models/greenpt.go b/internal/entity/models/greenpt.go index 3711d293c5..309ea41ba5 100644 --- a/internal/entity/models/greenpt.go +++ b/internal/entity/models/greenpt.go @@ -81,7 +81,7 @@ func (m *GreenPTModel) ChatWithMessages(ctx context.Context, modelName string, m if err != nil { return nil, err } - url := fmt.Sprintf("%s/%s", resolvedBaseURL, m.baseModel.URLSuffix.Chat) + baseURL := fmt.Sprintf("%s/%s", resolvedBaseURL, m.baseModel.URLSuffix.Chat) // Build request body reqBody := buildRequestBody(chatModelConfig, modelName, messages, false) @@ -98,7 +98,7 @@ func (m *GreenPTModel) ChatWithMessages(ctx context.Context, modelName string, m } } - body, err := m.baseModel.doRequest(ctx, url, apiConfig, reqBody, nonStreamCallTimeout) + body, err := m.baseModel.doRequest(ctx, baseURL, apiConfig, reqBody, nonStreamCallTimeout) if err != nil { return nil, err } @@ -124,7 +124,7 @@ func (m *GreenPTModel) ChatStreamlyWithSender(ctx context.Context, modelName str if err != nil { return err } - url := fmt.Sprintf("%s/%s", resolvedBaseURL, m.baseModel.URLSuffix.Chat) + baseURL := fmt.Sprintf("%s/%s", resolvedBaseURL, m.baseModel.URLSuffix.Chat) // Build request body with streaming enabled reqBody := buildRequestBody(chatModelConfig, modelName, messages, true) @@ -144,7 +144,7 @@ func (m *GreenPTModel) ChatStreamlyWithSender(ctx context.Context, modelName str } } - return m.baseModel.doStreamRequest(ctx, url, apiConfig, reqBody, streamCallTimeout, func(body io.ReadCloser) error { + return m.baseModel.doStreamRequest(ctx, baseURL, apiConfig, reqBody, streamCallTimeout, func(body io.ReadCloser) error { return HandleStreamingResponse(body, modelUsage, chatModelConfig, OpenAIParserConfig, sender) }) } diff --git a/internal/entity/models/llm_test.go b/internal/entity/models/llm_test.go index 7f00028c76..9eef1cadba 100644 --- a/internal/entity/models/llm_test.go +++ b/internal/entity/models/llm_test.go @@ -64,7 +64,7 @@ func TestEinoChatModelGenerateSendsBoundTools(t *testing.T) { Name: "search_my_dateset", Desc: "Search datasets.", ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{ - "query": &schema.ParameterInfo{Type: schema.String, Required: true}, + "query": {Type: schema.String, Required: true}, }), }, }) @@ -122,7 +122,7 @@ func TestEinoChatModelStreamWithToolsYieldsToolCalls(t *testing.T) { Name: "search_my_dateset", Desc: "Search datasets.", ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{ - "query": &schema.ParameterInfo{Type: schema.String, Required: true}, + "query": {Type: schema.String, Required: true}, }), }, }) diff --git a/internal/entity/models/lmstudio.go b/internal/entity/models/lmstudio.go index af815a0678..8fa3272a4d 100644 --- a/internal/entity/models/lmstudio.go +++ b/internal/entity/models/lmstudio.go @@ -32,7 +32,6 @@ type LmStudioModel struct { baseModel BaseModel } -// NewLmStudioModel func NewLmStudioModel(baseURL map[string]string, urlSuffix URLSuffix) *LmStudioModel { return &LmStudioModel{ baseModel: BaseModel{ diff --git a/internal/entity/models/model.go b/internal/entity/models/model.go index c97d10e007..0d7b4e186f 100644 --- a/internal/entity/models/model.go +++ b/internal/entity/models/model.go @@ -60,13 +60,11 @@ type Reasoning struct { RawType string `json:"type"` } -// Reasoning represents the reasoning capability (can be one of three types) type ClearReasoningContent struct { DefaultValue bool `json:"default_value"` SupportedModels []string `json:"supported_models"` } -// Reasoning represents the reasoning capability (can be one of three types) type Thinking struct { DefaultValue bool `json:"default_value"` SupportedModels []string `json:"supported_models"` @@ -233,7 +231,7 @@ func GetProviderManager() *ProviderManager { // InitProviderManager creates a new ProviderManager by reading all JSON files from a directory func InitProviderManager(dirPath string) error { - providers := []Provider{} + var providers []Provider // Read all files in the directory files, err := os.ReadDir(dirPath) @@ -351,7 +349,6 @@ func InitProviderManager(dirPath string) error { return nil } -// 1. List all providers func (pm *ProviderManager) ListProviders() ([]map[string]interface{}, error) { var providers []map[string]interface{} @@ -447,7 +444,6 @@ func (pm *ProviderManager) GetModelByNameOrAlias(modelName string) *Model { return nil } -// 2. Show specific provider information (including base_url) func (pm *ProviderManager) GetProviderByName(providerName string) (map[string]interface{}, error) { provider := pm.FindProvider(providerName) @@ -464,14 +460,13 @@ func (pm *ProviderManager) GetProviderByName(providerName string) (map[string]in return providerInfo, nil } -// 3. List models under a specific provider func (pm *ProviderManager) ListModels(providerName string) ([]map[string]interface{}, error) { provider := pm.FindProvider(providerName) if provider == nil { return nil, fmt.Errorf("provider '%s' not found", providerName) } - modelList := []map[string]interface{}{} + var modelList []map[string]interface{} for _, model := range provider.Models { // Field name "model_type" (singular) matches the IInstanceModel // contract in web/src/interfaces/database/llm.ts:75 and Python's @@ -622,7 +617,6 @@ func (pm *ProviderManager) SearchModelInfo(providerName, modelName string, filte return resp } -// 5. Display models with specific features func (pm *ProviderManager) SearchByFeature(featureType string) ModelResponse { resp := ModelResponse{ Code: 0, @@ -653,7 +647,6 @@ func (pm *ProviderManager) SearchByFeature(featureType string) ModelResponse { return resp } -// 6. Display models with specific type func (pm *ProviderManager) SearchByType(modelType string) ModelResponse { resp := ModelResponse{ Code: 0, @@ -750,24 +743,6 @@ func getFeaturesMap(features Features) map[string]interface{} { return featuresMap } -// Helper: Check if model has a specific feature -func modelHasFeature(features Features, featureType string) bool { - switch strings.ToLower(featureType) { - case "multimodal": - return features.Multimodal != nil && features.Multimodal.Enabled - case "reasoning": - return features.Reasoning != nil - case "reasoning_simple": - return features.Reasoning != nil && features.Reasoning.RawType == "simple" - case "reasoning_budget": - return features.Reasoning != nil && features.Reasoning.RawType == "budget" - case "reasoning_effort": - return features.Reasoning != nil && features.Reasoning.RawType == "effort" - default: - return false - } -} - // findRepoRoot walks up from CWD until it finds the repo root (marked by // conf/all_models.json). This makes tests work regardless of the Go test // binary's CWD (which is set to the package directory by go test). @@ -785,7 +760,6 @@ func findRepoRoot() string { return "." } -// Helper: Find provider by name func (pm *ProviderManager) FindProvider(name string) *Provider { for i := range pm.Providers { if strings.EqualFold(pm.Providers[i].Name, name) { @@ -795,7 +769,6 @@ func (pm *ProviderManager) FindProvider(name string) *Provider { return nil } -// Helper: Find model by name func (pm *ProviderManager) FindModel(provider *Provider, modelName string) *Model { for i := range provider.Models { if strings.EqualFold(provider.Models[i].Name, modelName) { diff --git a/internal/entity/models/model_test.go b/internal/entity/models/model_test.go index 6f524f1922..13856594c3 100644 --- a/internal/entity/models/model_test.go +++ b/internal/entity/models/model_test.go @@ -50,11 +50,6 @@ func readProviderConfig(t *testing.T, fileName string) []byte { return nil } -func readPPIOProviderConfig(t *testing.T) []byte { - t.Helper() - return readProviderConfig(t, "ppio.json") -} - // setupProviderTestDir creates a temporary directory populated with provider // config files and conf/all_models.json, then changes the working directory to // it. InitProviderManager hardcodes a read of conf/all_models.json relative to diff --git a/internal/entity/models/n1n.go b/internal/entity/models/n1n.go index 6d80446bb1..44a4c5cba9 100644 --- a/internal/entity/models/n1n.go +++ b/internal/entity/models/n1n.go @@ -407,7 +407,6 @@ func (n *N1NModel) Balance(ctx context.Context, apiConfig *APIConfig) (map[strin return nil, fmt.Errorf("%s, no such method", n.Name()) } -// TranscribeAudio: n1n.ai exposes /v1/audio/transcriptions func (n *N1NModel) TranscribeAudio(ctx context.Context, modelName *string, file *string, apiConfig *APIConfig, asrConfig *ASRConfig, modelUsage *common.ModelUsage) (*ASRResponse, error) { return nil, fmt.Errorf("%s, no such method", n.Name()) } @@ -416,7 +415,6 @@ func (n *N1NModel) TranscribeAudioWithSender(ctx context.Context, modelName *str return fmt.Errorf("%s, no such method", n.Name()) } -// AudioSpeech: n1n.ai exposes /v1/audio/speech func (n *N1NModel) AudioSpeech(ctx context.Context, modelName *string, audioContent *string, apiConfig *APIConfig, ttsConfig *TTSConfig, modelUsage *common.ModelUsage) (*TTSResponse, error) { return nil, fmt.Errorf("%s, no such method", n.Name()) } @@ -435,7 +433,6 @@ func (n *N1NModel) ParseFile(ctx context.Context, modelName *string, content []b return nil, fmt.Errorf("%s, no such method", n.Name()) } -// ListTasks: n1n.ai has /v1/contents/generations/tasks func (n *N1NModel) ListTasks(ctx context.Context, apiConfig *APIConfig) ([]ListTaskStatus, error) { return nil, fmt.Errorf("%s, no such method", n.Name()) } diff --git a/internal/entity/models/nvidia.go b/internal/entity/models/nvidia.go index 75631fd984..586090b30e 100644 --- a/internal/entity/models/nvidia.go +++ b/internal/entity/models/nvidia.go @@ -60,7 +60,7 @@ func (n *NvidiaModel) NewInstance(baseURL map[string]string) ModelDriver { return NewNvidiaModel(baseURL, n.baseModel.URLSuffix) } -func (n NvidiaModel) Name() string { +func (n *NvidiaModel) Name() string { return "nvidia" } @@ -77,7 +77,7 @@ func (n *NvidiaModel) ChatWithMessages(ctx context.Context, modelName string, me if err != nil { return nil, err } - url := fmt.Sprintf("%s/%s", resolvedBaseURL, n.baseModel.URLSuffix.Chat) + baseURL := fmt.Sprintf("%s/%s", resolvedBaseURL, n.baseModel.URLSuffix.Chat) reqBody := buildRequestBody(chatModelConfig, modelName, messages, false) if chatModelConfig != nil { @@ -90,7 +90,7 @@ func (n *NvidiaModel) ChatWithMessages(ctx context.Context, modelName string, me } } - body, err := n.baseModel.doRequest(ctx, url, apiConfig, reqBody, nonStreamCallTimeout) + body, err := n.baseModel.doRequest(ctx, baseURL, apiConfig, reqBody, nonStreamCallTimeout) if err != nil { return nil, err } @@ -112,7 +112,7 @@ func (n *NvidiaModel) ChatStreamlyWithSender(ctx context.Context, modelName stri if err != nil { return err } - url := fmt.Sprintf("%s/%s", resolvedBaseURL, n.baseModel.URLSuffix.Chat) + baseURL := fmt.Sprintf("%s/%s", resolvedBaseURL, n.baseModel.URLSuffix.Chat) reqBody := buildRequestBody(modelConfig, modelName, messages, true) if modelConfig != nil { @@ -127,7 +127,7 @@ func (n *NvidiaModel) ChatStreamlyWithSender(ctx context.Context, modelName stri reqBody["stream_options"] = map[string]any{"include_usage": true} - return n.baseModel.doStreamRequest(ctx, url, apiConfig, reqBody, streamCallTimeout, func(body io.ReadCloser) error { + return n.baseModel.doStreamRequest(ctx, baseURL, apiConfig, reqBody, streamCallTimeout, func(body io.ReadCloser) error { return HandleStreamingResponse(body, modelUsage, modelConfig, OpenAIParserConfig, sender) }) } @@ -139,7 +139,7 @@ type nvidiaEmbeddingResponse struct { } `json:"data"` } -func (n NvidiaModel) Embed(ctx context.Context, modelName *string, texts []string, apiConfig *APIConfig, embeddingConfig *EmbeddingConfig, modelUsage *common.ModelUsage) ([]EmbeddingData, error) { +func (n *NvidiaModel) Embed(ctx context.Context, modelName *string, texts []string, apiConfig *APIConfig, embeddingConfig *EmbeddingConfig, modelUsage *common.ModelUsage) ([]EmbeddingData, error) { if err := n.baseModel.APIConfigCheck(apiConfig); err != nil { return nil, err } @@ -157,7 +157,7 @@ func (n NvidiaModel) Embed(ctx context.Context, modelName *string, texts []strin return nil, err } - url := fmt.Sprintf("%s/%s", strings.TrimSuffix(resolvedBaseURL, "/"), n.baseModel.URLSuffix.Embedding) + baseURL := fmt.Sprintf("%s/%s", strings.TrimSuffix(resolvedBaseURL, "/"), n.baseModel.URLSuffix.Embedding) reqBody := map[string]interface{}{ "model": *modelName, @@ -178,7 +178,7 @@ func (n NvidiaModel) Embed(ctx context.Context, modelName *string, texts []strin ctx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData)) + req, err := http.NewRequestWithContext(ctx, "POST", baseURL, bytes.NewBuffer(jsonData)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -252,7 +252,7 @@ type nvidiaRerankResponse struct { // RerankResult entries are in the API's ranking order; callers that // need original-input order should sort by Index. Same return-shape // contract as the Aliyun and ZhipuAI Rerank drivers. -func (n NvidiaModel) Rerank(ctx context.Context, modelName *string, query string, documents []string, apiConfig *APIConfig, rerankConfig *RerankConfig, modelUsage *common.ModelUsage) (*RerankResponse, error) { +func (n *NvidiaModel) Rerank(ctx context.Context, modelName *string, query string, documents []string, apiConfig *APIConfig, rerankConfig *RerankConfig, modelUsage *common.ModelUsage) (*RerankResponse, error) { if err := n.baseModel.APIConfigCheck(apiConfig); err != nil { return nil, err } @@ -269,7 +269,7 @@ func (n NvidiaModel) Rerank(ctx context.Context, modelName *string, query string return nil, err } - url := fmt.Sprintf("%s/%s", strings.TrimSuffix(resolvedBaseURL, "/"), n.baseModel.URLSuffix.Rerank) + baseURL := fmt.Sprintf("%s/%s", strings.TrimSuffix(resolvedBaseURL, "/"), n.baseModel.URLSuffix.Rerank) topN := len(documents) if rerankConfig != nil && rerankConfig.TopN > 0 && rerankConfig.TopN < topN { @@ -297,7 +297,7 @@ func (n NvidiaModel) Rerank(ctx context.Context, modelName *string, query string ctx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData)) + req, err := http.NewRequestWithContext(ctx, "POST", baseURL, bytes.NewBuffer(jsonData)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -358,12 +358,12 @@ func (n *NvidiaModel) AudioSpeechWithSender(ctx context.Context, modelName *stri } // OCRFile OCR file -func (n *NvidiaModel) OCRFile(ctx context.Context, modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig, modelUsage *common.ModelUsage) (*OCRFileResponse, error) { +func (n *NvidiaModel) OCRFile(ctx context.Context, modelName *string, content []byte, baseURL *string, apiConfig *APIConfig, ocrConfig *OCRConfig, modelUsage *common.ModelUsage) (*OCRFileResponse, error) { return nil, fmt.Errorf("%s, no such method", n.Name()) } // ParseFile parse file -func (n *NvidiaModel) ParseFile(ctx context.Context, modelName *string, content []byte, url *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig, modelUsage *common.ModelUsage) (*ParseFileResponse, error) { +func (n *NvidiaModel) ParseFile(ctx context.Context, modelName *string, content []byte, baseURL *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig, modelUsage *common.ModelUsage) (*ParseFileResponse, error) { return nil, fmt.Errorf("%s, no such method", n.Name()) } @@ -371,7 +371,7 @@ func (n *NvidiaModel) ParseFile(ctx context.Context, modelName *string, content // and returns the list of available model ids. The endpoint is // OpenAI-compatible, so the parsing follows the same shape used by // the moonshot, xai, and openai drivers. -func (n NvidiaModel) ListModels(ctx context.Context, apiConfig *APIConfig) ([]ListModelResponse, error) { +func (n *NvidiaModel) ListModels(ctx context.Context, apiConfig *APIConfig) ([]ListModelResponse, error) { if err := n.baseModel.APIConfigCheck(apiConfig); err != nil { return nil, err } @@ -380,12 +380,12 @@ func (n NvidiaModel) ListModels(ctx context.Context, apiConfig *APIConfig) ([]Li if err != nil { return nil, err } - url := fmt.Sprintf("%s/%s", strings.TrimRight(resolvedBaseURL, "/"), strings.TrimLeft(n.baseModel.URLSuffix.Models, "/")) + baseURL := fmt.Sprintf("%s/%s", strings.TrimRight(resolvedBaseURL, "/"), strings.TrimLeft(n.baseModel.URLSuffix.Models, "/")) modelListCtx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - req, err := http.NewRequestWithContext(modelListCtx, "GET", url, nil) + req, err := http.NewRequestWithContext(modelListCtx, "GET", baseURL, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -465,12 +465,12 @@ type nvidiaCatalogResponse struct { Results []nvidiaCatalogGroup `json:"results"` } -func (n NvidiaModel) usesHostedCatalog(baseURL string) bool { +func (n *NvidiaModel) usesHostedCatalog(baseURL string) bool { parsed, err := url.Parse(baseURL) return err == nil && strings.EqualFold(parsed.Hostname(), n.hostedAPIHost) } -func (n NvidiaModel) fetchHostedCatalog(ctx context.Context) (*nvidiaCatalogResponse, error) { +func (n *NvidiaModel) fetchHostedCatalog(ctx context.Context) (*nvidiaCatalogResponse, error) { parsed, err := url.Parse(n.catalogURL) if err != nil { return nil, fmt.Errorf("failed to parse Nvidia endpoint catalog URL: %w", err) @@ -538,7 +538,7 @@ func (n NvidiaModel) fetchHostedCatalog(ctx context.Context) (*nvidiaCatalogResp return merged, nil } -func (n NvidiaModel) fetchHostedCatalogPage(ctx context.Context, pageURL string) (*nvidiaCatalogResponse, error) { +func (n *NvidiaModel) fetchHostedCatalogPage(ctx context.Context, pageURL string) (*nvidiaCatalogResponse, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, pageURL, nil) if err != nil { return nil, fmt.Errorf("failed to create Nvidia endpoint catalog request: %w", err) @@ -713,7 +713,7 @@ func parseNvidiaModelList(modelList ModelList, provider *Provider) []ListModelRe return models } -func (n NvidiaModel) Balance(ctx context.Context, apiConfig *APIConfig) (map[string]interface{}, error) { +func (n *NvidiaModel) Balance(ctx context.Context, apiConfig *APIConfig) (map[string]interface{}, error) { return nil, fmt.Errorf("no such method") } @@ -721,7 +721,7 @@ func (n NvidiaModel) Balance(ctx context.Context, apiConfig *APIConfig) (map[str // is reachable and that the API key is accepted, by issuing a // lightweight ListModels call. Mirrors the pattern used by the xai, // moonshot, deepseek, aliyun, and gitee drivers. -func (n NvidiaModel) CheckConnection(ctx context.Context, apiConfig *APIConfig) error { +func (n *NvidiaModel) CheckConnection(ctx context.Context, apiConfig *APIConfig) error { _, err := n.ListModels(ctx, apiConfig) return err } diff --git a/internal/entity/models/nvidia_test.go b/internal/entity/models/nvidia_test.go index a4b61b7e99..61659e05a1 100644 --- a/internal/entity/models/nvidia_test.go +++ b/internal/entity/models/nvidia_test.go @@ -168,7 +168,7 @@ func TestNvidiaFetchHostedCatalogPaginates(t *testing.T) { start := query.Page * query.PageSize end := min(start+query.PageSize, len(resources)) - pageResources := []nvidiaCatalogResource{} + var pageResources []nvidiaCatalogResource if start < len(resources) { pageResources = resources[start:end] } diff --git a/internal/entity/models/openai.go b/internal/entity/models/openai.go index 3da7e98438..eee9373192 100644 --- a/internal/entity/models/openai.go +++ b/internal/entity/models/openai.go @@ -729,47 +729,3 @@ func (o *OpenAIModel) ListTasks(ctx context.Context, apiConfig *APIConfig) ([]Li func (o *OpenAIModel) ShowTask(ctx context.Context, taskID string, apiConfig *APIConfig) (*TaskResponse, error) { return nil, fmt.Errorf("%s, no such method", o.Name()) } - -// extractUsageFromMap reads the "usage" key from an OpenAI-style API -// response and returns (prompt_tokens, completion_tokens, total_tokens). -// All return values are zero when the response carries no usage block. -func extractUsageFromMap(raw map[string]interface{}) (int, int, int) { - if raw == nil { - return 0, 0, 0 - } - ru, ok := raw["usage"] - if !ok { - return 0, 0, 0 - } - usage, ok := ru.(map[string]interface{}) - if !ok { - return 0, 0, 0 - } - get := func(keys ...string) int { - for _, k := range keys { - v, ok := usage[k] - if !ok { - continue - } - switch val := v.(type) { - case float64: - return int(val) - case int: - return val - case json.Number: - n, err := val.Int64() - if err == nil { - return int(n) - } - } - } - return 0 - } - pt := get("prompt_tokens", "input_tokens") - ct := get("completion_tokens", "output_tokens") - tt := get("total_tokens") - if tt == 0 { - tt = pt + ct - } - return pt, ct, tt -} diff --git a/internal/entity/models/openai_test.go b/internal/entity/models/openai_test.go index bb71848e35..9aee8001c5 100644 --- a/internal/entity/models/openai_test.go +++ b/internal/entity/models/openai_test.go @@ -250,7 +250,7 @@ func TestOpenAIAudioSpeechPostsJSONToAudioEndpoint(t *testing.T) { if body["response_format"] != "wav" { t.Errorf("response_format=%v, want wav", body["response_format"]) } - if body["speed"] != float64(1.25) { + if body["speed"] != 1.25 { t.Errorf("speed=%v, want 1.25", body["speed"]) } diff --git a/internal/entity/models/paddleocr.go b/internal/entity/models/paddleocr.go index 69a0562a2f..e036e097ed 100644 --- a/internal/entity/models/paddleocr.go +++ b/internal/entity/models/paddleocr.go @@ -45,7 +45,7 @@ func NewPaddleOCRModel(baseURL map[string]string, urlSuffix URLSuffix) *PaddleOC } } -func (p PaddleOCRModel) NewInstance(baseURL map[string]string) ModelDriver { +func (p *PaddleOCRModel) NewInstance(baseURL map[string]string) ModelDriver { return NewPaddleOCRModel(baseURL, p.baseModel.URLSuffix) } diff --git a/internal/entity/models/replicate.go b/internal/entity/models/replicate.go index c75a33cc55..3c6a658721 100644 --- a/internal/entity/models/replicate.go +++ b/internal/entity/models/replicate.go @@ -208,7 +208,7 @@ func replicateOutputToString(output interface{}) (string, error) { } } -func (r *ReplicateModel) createPrediction(ctx context.Context, url string, version string, input map[string]interface{}, stream bool, apiKey string, preferWait bool) (*replicatePrediction, error) { +func (r *ReplicateModel) createPrediction(ctx context.Context, baseURL string, version string, input map[string]interface{}, stream bool, apiKey string, preferWait bool) (*replicatePrediction, error) { body := map[string]interface{}{ "input": input, "stream": stream, @@ -222,7 +222,7 @@ func (r *ReplicateModel) createPrediction(ctx context.Context, url string, versi return nil, fmt.Errorf("failed to marshal request: %w", err) } - req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewBuffer(jsonData)) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, baseURL, bytes.NewBuffer(jsonData)) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -264,8 +264,8 @@ func replicatePredictionSucceeded(status string) bool { return status == "successful" } -func (r *ReplicateModel) getPrediction(ctx context.Context, url string, apiKey string) (*replicatePrediction, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) +func (r *ReplicateModel) getPrediction(ctx context.Context, baseURL string, apiKey string) (*replicatePrediction, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -336,7 +336,7 @@ func (r *ReplicateModel) ChatWithMessages(ctx context.Context, modelName string, return nil, fmt.Errorf("messages is empty") } - url, version, err := r.predictionEndpoint(apiConfig, modelName) + baseURL, version, err := r.predictionEndpoint(apiConfig, modelName) if err != nil { return nil, err } @@ -344,7 +344,7 @@ func (r *ReplicateModel) ChatWithMessages(ctx context.Context, modelName string, ctx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - prediction, err := r.createPrediction(ctx, url, version, replicateInputFromMessages(messages, chatModelConfig), false, *apiConfig.ApiKey, true) + prediction, err := r.createPrediction(ctx, baseURL, version, replicateInputFromMessages(messages, chatModelConfig), false, *apiConfig.ApiKey, true) if err != nil { return nil, err } @@ -382,12 +382,12 @@ func (r *ReplicateModel) ChatStreamlyWithSender(ctx context.Context, modelName s return fmt.Errorf("stream must be true in ChatStreamlyWithSender") } - url, version, err := r.predictionEndpoint(apiConfig, modelName) + baseURL, version, err := r.predictionEndpoint(apiConfig, modelName) if err != nil { return err } - prediction, err := r.createPrediction(ctx, url, version, replicateInputFromMessages(messages, chatModelConfig), true, *apiConfig.ApiKey, false) + prediction, err := r.createPrediction(ctx, baseURL, version, replicateInputFromMessages(messages, chatModelConfig), true, *apiConfig.ApiKey, false) if err != nil { return err } @@ -414,8 +414,8 @@ func (r *ReplicateModel) ChatStreamlyWithSender(ctx context.Context, modelName s return r.readPredictionStream(ctx, prediction.URLs.Stream, *apiConfig.ApiKey, sender) } -func (r *ReplicateModel) readPredictionStream(ctx context.Context, url string, apiKey string, sender func(*string, *string) error) error { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) +func (r *ReplicateModel) readPredictionStream(ctx context.Context, baseURL string, apiKey string, sender func(*string, *string) error) error { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL, nil) if err != nil { return fmt.Errorf("failed to create request: %w", err) } @@ -504,7 +504,7 @@ func (r *ReplicateModel) ListModels(ctx context.Context, apiConfig *APIConfig) ( return nil, err } - url, err := r.endpoint(apiConfig, r.baseModel.URLSuffix.Models) + baseURL, err := r.endpoint(apiConfig, r.baseModel.URLSuffix.Models) if err != nil { return nil, err } @@ -512,7 +512,7 @@ func (r *ReplicateModel) ListModels(ctx context.Context, apiConfig *APIConfig) ( ctx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) } @@ -686,7 +686,7 @@ func (r *ReplicateModel) Embed(ctx context.Context, modelName *string, texts []s return nil, fmt.Errorf("model name is required") } - url, version, err := r.predictionEndpoint(apiConfig, *modelName) + baseURL, version, err := r.predictionEndpoint(apiConfig, *modelName) if err != nil { return nil, err } @@ -699,7 +699,7 @@ func (r *ReplicateModel) Embed(ctx context.Context, modelName *string, texts []s ctx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - prediction, err := r.createPrediction(ctx, url, version, input, false, *apiConfig.ApiKey, true) + prediction, err := r.createPrediction(ctx, baseURL, version, input, false, *apiConfig.ApiKey, true) if err != nil { return nil, err } @@ -777,7 +777,7 @@ func (r *ReplicateModel) Rerank(ctx context.Context, modelName *string, query st return nil, fmt.Errorf("model name is required") } - url, version, err := r.predictionEndpoint(apiConfig, *modelName) + baseURL, version, err := r.predictionEndpoint(apiConfig, *modelName) if err != nil { return nil, err } @@ -790,7 +790,7 @@ func (r *ReplicateModel) Rerank(ctx context.Context, modelName *string, query st ctx, cancel := context.WithTimeout(ctx, nonStreamCallTimeout) defer cancel() - prediction, err := r.createPrediction(ctx, url, version, input, false, *apiConfig.ApiKey, true) + prediction, err := r.createPrediction(ctx, baseURL, version, input, false, *apiConfig.ApiKey, true) if err != nil { return nil, err } @@ -849,11 +849,11 @@ func (r *ReplicateModel) AudioSpeechWithSender(ctx context.Context, modelName *s return fmt.Errorf("%s, no such method", r.Name()) } -func (r *ReplicateModel) OCRFile(ctx context.Context, modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig, modelUsage *common.ModelUsage) (*OCRFileResponse, error) { +func (r *ReplicateModel) OCRFile(ctx context.Context, modelName *string, content []byte, baseURL *string, apiConfig *APIConfig, ocrConfig *OCRConfig, modelUsage *common.ModelUsage) (*OCRFileResponse, error) { return nil, fmt.Errorf("%s, no such method", r.Name()) } -func (r *ReplicateModel) ParseFile(ctx context.Context, modelName *string, content []byte, url *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig, modelUsage *common.ModelUsage) (*ParseFileResponse, error) { +func (r *ReplicateModel) ParseFile(ctx context.Context, modelName *string, content []byte, baseURL *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig, modelUsage *common.ModelUsage) (*ParseFileResponse, error) { return nil, fmt.Errorf("%s, no such method", r.Name()) } diff --git a/internal/entity/models/types.go b/internal/entity/models/types.go index 3f4ae7f4b1..bfcc887df9 100644 --- a/internal/entity/models/types.go +++ b/internal/entity/models/types.go @@ -24,7 +24,7 @@ type ToolCallSession interface { ToolCall(name string, arguments map[string]interface{}) (string, error) } -// EmbeddingModel interface for embedding models +// ModelDriver interface for model functionality type ModelDriver interface { NewInstance(baseURL map[string]string) ModelDriver diff --git a/internal/entity/models/usage_parser_test.go b/internal/entity/models/usage_parser_test.go index 674eca7709..21ef441c74 100644 --- a/internal/entity/models/usage_parser_test.go +++ b/internal/entity/models/usage_parser_test.go @@ -131,7 +131,7 @@ func TestExtractOpenAIStreamUsage(t *testing.T) { func TestExtractToken(t *testing.T) { m := map[string]any{ "a": float64(1), - "b": int(2), + "b": 2, "c": int64(3), } diff --git a/internal/entity/skill_search.go b/internal/entity/skill_search.go index 5b71fcf692..f4aed6de6f 100644 --- a/internal/entity/skill_search.go +++ b/internal/entity/skill_search.go @@ -60,7 +60,7 @@ type SkillSearchConfig struct { } // TableName returns the table name for SkillSearchConfig model -func (SkillSearchConfig) TableName() string { +func (s *SkillSearchConfig) TableName() string { return "skill_search_configs" } diff --git a/internal/entity/skill_space.go b/internal/entity/skill_space.go index 88e45d550c..935def9929 100644 --- a/internal/entity/skill_space.go +++ b/internal/entity/skill_space.go @@ -40,7 +40,7 @@ type SkillSpace struct { } // TableName returns the table name for SkillSpace model -func (SkillSpace) TableName() string { +func (s *SkillSpace) TableName() string { return "skill_spaces" }