From a38d1154657aab08d0220b3b543d34860572d627 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 24 Feb 2026 09:32:19 +0800 Subject: [PATCH] Refactor LLM capabilities handling and remove deprecated model loading - Remove the `LoadModelCapabilities` test and associated model capabilities initialization from the agent, streamlining the loading process. - Update the LLM provider implementations to utilize a unified `Capabilities` structure, replacing references to `openai.Capabilities` with `llm.Capabilities`. - Enhance capability retrieval methods to simplify the extraction of connector capabilities, ensuring compatibility across different LLM providers. - Clean up unused functions and variables related to model capabilities, improving code maintainability. --- agent/assistant/agent.go | 8 +- agent/assistant/load.go | 9 +- agent/assistant/load_system.go | 10 -- agent/context/output.go | 5 +- agent/context/types.go | 4 +- agent/context/types_llm.go | 6 +- agent/llm/capabilities.go | 94 +++---------------- agent/llm/jsapi.go | 8 +- agent/llm/providers/anthropic/anthropic.go | 26 +---- .../llm/providers/anthropic/anthropic_test.go | 9 +- agent/llm/providers/base/base.go | 6 +- agent/llm/providers/factory.go | 8 -- agent/llm/providers/openai/openai.go | 8 +- agent/load.go | 34 ------- agent/load_test.go | 6 -- agent/output/message/types.go | 4 +- agent/types/types.go | 8 +- openapi/llm/llm.go | 31 +----- 18 files changed, 49 insertions(+), 235 deletions(-) diff --git a/agent/assistant/agent.go b/agent/assistant/agent.go index e1fcdda0..416e818b 100644 --- a/agent/assistant/agent.go +++ b/agent/assistant/agent.go @@ -6,7 +6,7 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/yaoapp/gou/connector" - "github.com/yaoapp/gou/connector/openai" + goullm "github.com/yaoapp/gou/llm" "github.com/yaoapp/yao/agent/assistant/handlers" "github.com/yaoapp/yao/agent/context" "github.com/yaoapp/yao/agent/i18n" @@ -570,7 +570,7 @@ func (ast *Assistant) Stream(ctx *context.Context, inputMessages []context.Messa // GetConnector get the connector object, capabilities, and error with priority: opts.Connector > ast.Connector // Note: opts.Connector may be set by Create hook's applyOptionsAdjustments // Returns: (connector, capabilities, error) -func (ast *Assistant) GetConnector(ctx *context.Context, opts ...*context.Options) (connector.Connector, *openai.Capabilities, error) { +func (ast *Assistant) GetConnector(ctx *context.Context, opts ...*context.Options) (connector.Connector, *goullm.Capabilities, error) { // Determine connector ID with priority: opts.Connector > ast.Connector connectorID := ast.Connector if len(opts) > 0 && opts[0] != nil && opts[0].Connector != "" { @@ -588,9 +588,7 @@ func (ast *Assistant) GetConnector(ctx *context.Context, opts ...*context.Option return nil, nil, err } - // Get connector capabilities from settings - // Uses unified capability getter: 1. User-defined models.yml, 2. connector's Setting()["capabilities"], 3. default - capabilities := llm.GetCapabilitiesFromConn(conn, modelCapabilities) + capabilities := llm.GetCapabilitiesFromConn(conn) return conn, capabilities, nil } diff --git a/agent/assistant/load.go b/agent/assistant/load.go index cbf30559..b22e6a26 100644 --- a/agent/assistant/load.go +++ b/agent/assistant/load.go @@ -9,7 +9,6 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/spf13/cast" "github.com/yaoapp/gou/application" - gouOpenAI "github.com/yaoapp/gou/connector/openai" "github.com/yaoapp/gou/fs" "github.com/yaoapp/yao/agent/context" "github.com/yaoapp/yao/agent/i18n" @@ -21,8 +20,7 @@ import ( // loaded the loaded assistant var loaded = NewCache(200) // 200 is the default capacity var storage store.Store = nil -var storeSetting *store.Setting = nil // store setting from agent.yml -var modelCapabilities map[string]gouOpenAI.Capabilities = map[string]gouOpenAI.Capabilities{} +var storeSetting *store.Setting = nil // store setting from agent.yml var defaultConnector string = "" // default connector var globalUses *context.Uses = nil // global uses configuration from agent.yml var globalPrompts []store.Prompt = nil // global prompts from agent/prompts.yml @@ -140,11 +138,6 @@ func GetStorage() store.Store { return storage } -// SetModelCapabilities set the model capabilities configuration -func SetModelCapabilities(capabilities map[string]gouOpenAI.Capabilities) { - modelCapabilities = capabilities -} - // SetConnector set the connector func SetConnector(c string) { defaultConnector = c diff --git a/agent/assistant/load_system.go b/agent/assistant/load_system.go index e8e2c187..271bc989 100644 --- a/agent/assistant/load_system.go +++ b/agent/assistant/load_system.go @@ -256,20 +256,11 @@ func resolveSystemConnector(agentID string) string { // findCapableConnector finds the first connector that supports tool calling func findCapableConnector() string { - // Get all registered connectors for id, conn := range connector.Connectors { if !conn.Is(connector.OPENAI) { continue } - // Check from modelCapabilities (user-defined in models.yml) - if caps, exists := modelCapabilities[id]; exists { - if caps.ToolCalls { - return id - } - } - - // Check capabilities from connector's Options if connOpenAI, ok := conn.(*gouOpenAI.Connector); ok { if connOpenAI.Options.Capabilities != nil && connOpenAI.Options.Capabilities.ToolCalls { return id @@ -277,7 +268,6 @@ func findCapableConnector() string { } } - // No capable connector found, return empty return "" } diff --git a/agent/context/output.go b/agent/context/output.go index 7c85f864..6b3896e9 100644 --- a/agent/context/output.go +++ b/agent/context/output.go @@ -3,7 +3,7 @@ package context import ( "time" - "github.com/yaoapp/gou/connector/openai" + "github.com/yaoapp/gou/llm" "github.com/yaoapp/yao/agent/output" "github.com/yaoapp/yao/agent/output/message" ) @@ -571,9 +571,8 @@ func (ctx *Context) getOutput() (*output.Output, error) { Accept: string(ctx.Accept), } - // Set ModelCapabilities (now using openai.Capabilities directly) if ctx.Capabilities != nil { - caps := openai.Capabilities(*ctx.Capabilities) + caps := llm.Capabilities(*ctx.Capabilities) options.Capabilities = &caps } diff --git a/agent/context/types.go b/agent/context/types.go index b873b3b7..34a20af9 100644 --- a/agent/context/types.go +++ b/agent/context/types.go @@ -5,7 +5,7 @@ import ( "sync" "time" - "github.com/yaoapp/gou/connector/openai" + "github.com/yaoapp/gou/llm" "github.com/yaoapp/gou/store" "github.com/yaoapp/yao/agent/memory" "github.com/yaoapp/yao/agent/output" @@ -253,7 +253,7 @@ type Context struct { sandboxExecutor SandboxExecutor `json:"-"` // Sandbox executor for hooks (set by assistant when sandbox is configured) // Model capabilities (set by assistant, used by output adapters) - Capabilities *openai.Capabilities `json:"-"` // Model capabilities for the current connector + Capabilities *llm.Capabilities `json:"-"` // Model capabilities for the current connector // Interrupt control (all interrupt-related logic is encapsulated in InterruptController) Interrupt *InterruptController `json:"-"` // Interrupt controller for handling user interrupts during streaming diff --git a/agent/context/types_llm.go b/agent/context/types_llm.go index 760caeec..0d419f14 100644 --- a/agent/context/types_llm.go +++ b/agent/context/types_llm.go @@ -1,7 +1,7 @@ package context import ( - "github.com/yaoapp/gou/connector/openai" + "github.com/yaoapp/gou/llm" "github.com/yaoapp/yao/agent/output/message" ) @@ -38,7 +38,7 @@ const ( ) // GetVisionSupport returns whether vision is supported and the format -func GetVisionSupport(cap *openai.Capabilities) (bool, VisionFormat) { +func GetVisionSupport(cap *llm.Capabilities) (bool, VisionFormat) { if cap == nil || cap.Vision == nil { return false, VisionFormatNone } @@ -70,7 +70,7 @@ func GetVisionSupport(cap *openai.Capabilities) (bool, VisionFormat) { type CompletionOptions struct { // Model capabilities (used by LLM to select appropriate provider) // nil means capabilities are not specified/checked - Capabilities *openai.Capabilities `json:"capabilities,omitempty"` + Capabilities *llm.Capabilities `json:"capabilities,omitempty"` // User-specified tools for vision, audio, search, and fetch processing Uses *Uses `json:"uses,omitempty"` diff --git a/agent/llm/capabilities.go b/agent/llm/capabilities.go index 3608f24d..cf08669a 100644 --- a/agent/llm/capabilities.go +++ b/agent/llm/capabilities.go @@ -2,92 +2,48 @@ package llm import ( "github.com/yaoapp/gou/connector" - "github.com/yaoapp/gou/connector/anthropic" - "github.com/yaoapp/gou/connector/openai" + goullm "github.com/yaoapp/gou/llm" ) // GetCapabilities get the capabilities of a connector by connector ID -// This is a unified function to get connector capabilities with proper priority: -// 1. User-defined model capabilities from agent/models.yml (passed via modelCapabilities map) -// 2. Connector's Setting()["capabilities"] (default capabilities from connector) -// 3. Fallback to minimal default capabilities -// -// Usage in Agent with user-defined models: -// -// capabilities := llm.GetCapabilities(connectorID, modelCapabilities) -// -// Usage in API (without user-defined models): -// -// capabilities := llm.GetCapabilities(connectorID, nil) -func GetCapabilities(connectorID string, modelCapabilities map[string]openai.Capabilities) *openai.Capabilities { +// Reads capabilities from connector's Setting()["capabilities"], with fallback to defaults. +func GetCapabilities(connectorID string) *goullm.Capabilities { if connectorID == "" { return getDefaultCapabilities() } - // Priority 1: Check user-defined model capabilities from agent/models.yml - if modelCapabilities != nil { - if modelCaps, exists := modelCapabilities[connectorID]; exists { - return &modelCaps - } - } - - // Priority 2: Get connector and extract capabilities from Setting() conn, err := connector.Select(connectorID) if err != nil { - // If connector not found, return default return getDefaultCapabilities() } - return GetCapabilitiesFromConn(conn, modelCapabilities) + return GetCapabilitiesFromConn(conn) } // GetCapabilitiesFromConn get the capabilities from a connector instance -// This is useful when you already have the connector object -func GetCapabilitiesFromConn(conn connector.Connector, modelCapabilities map[string]openai.Capabilities) *openai.Capabilities { +func GetCapabilitiesFromConn(conn connector.Connector) *goullm.Capabilities { if conn == nil { return getDefaultCapabilities() } - connectorID := conn.ID() - - // Priority 1: Check user-defined model capabilities from agent/models.yml - if modelCapabilities != nil { - if modelCaps, exists := modelCapabilities[connectorID]; exists { - return &modelCaps - } - } - - // Priority 2: Get capabilities from connector's Setting() method settings := conn.Setting() if settings != nil { if caps, ok := settings["capabilities"]; ok { - // Try to convert to *openai.Capabilities - if capabilities, ok := caps.(*openai.Capabilities); ok { + if capabilities, ok := caps.(*goullm.Capabilities); ok { return capabilities } - // Try to convert to openai.Capabilities (value type) - if capabilities, ok := caps.(openai.Capabilities); ok { + if capabilities, ok := caps.(goullm.Capabilities); ok { return &capabilities } - // Try to convert from *anthropic.Capabilities - if capabilities, ok := caps.(*anthropic.Capabilities); ok { - return convertAnthropicCaps(capabilities) - } - // Try to convert from anthropic.Capabilities (value type) - if capabilities, ok := caps.(anthropic.Capabilities); ok { - return convertAnthropicCaps(&capabilities) - } } } - // Priority 3: Fallback to minimal default capabilities return getDefaultCapabilities() } // getDefaultCapabilities returns minimal default capabilities -// This should rarely be used as modern connectors provide capabilities via Setting() -func getDefaultCapabilities() *openai.Capabilities { - return &openai.Capabilities{ +func getDefaultCapabilities() *goullm.Capabilities { + return &goullm.Capabilities{ Vision: false, ToolCalls: false, Audio: false, @@ -95,14 +51,13 @@ func getDefaultCapabilities() *openai.Capabilities { Streaming: false, JSON: false, Multimodal: false, - TemperatureAdjustable: true, // Default to true for non-reasoning models + TemperatureAdjustable: true, } } // GetCapabilitiesMap get capabilities as map[string]interface{} for API responses -// This is useful for OpenAPI responses that need JSON-serializable format -func GetCapabilitiesMap(connectorID string, modelCapabilities map[string]openai.Capabilities) map[string]interface{} { - caps := GetCapabilities(connectorID, modelCapabilities) +func GetCapabilitiesMap(connectorID string) map[string]interface{} { + caps := GetCapabilities(connectorID) if caps == nil { return nil } @@ -110,16 +65,14 @@ func GetCapabilitiesMap(connectorID string, modelCapabilities map[string]openai. return ToMap(caps) } -// ToMap converts openai.Capabilities to map[string]interface{} -// This is useful for JSON serialization in API responses -func ToMap(caps *openai.Capabilities) map[string]interface{} { +// ToMap converts Capabilities to map[string]interface{} +func ToMap(caps *goullm.Capabilities) map[string]interface{} { if caps == nil { return nil } result := make(map[string]interface{}) - // Handle Vision field specially as it can be bool or string if caps.Vision != nil { result["vision"] = caps.Vision } @@ -135,22 +88,3 @@ func ToMap(caps *openai.Capabilities) map[string]interface{} { return result } - -// convertAnthropicCaps converts anthropic.Capabilities to openai.Capabilities -// This provides a unified capabilities interface across connector types -func convertAnthropicCaps(caps *anthropic.Capabilities) *openai.Capabilities { - if caps == nil { - return getDefaultCapabilities() - } - return &openai.Capabilities{ - Vision: caps.Vision, - Audio: caps.Audio, - STT: caps.STT, - ToolCalls: caps.ToolCalls, - Reasoning: caps.Reasoning, - Streaming: caps.Streaming, - JSON: caps.JSON, - Multimodal: caps.Multimodal, - TemperatureAdjustable: caps.TemperatureAdjustable, - } -} diff --git a/agent/llm/jsapi.go b/agent/llm/jsapi.go index afd5ac82..4acbcddd 100644 --- a/agent/llm/jsapi.go +++ b/agent/llm/jsapi.go @@ -203,7 +203,7 @@ func parseToolCalls(toolCalls []interface{}) []agentContext.ToolCall { // buildCompletionOptions creates CompletionOptions from JS opts map func buildCompletionOptions(conn connector.Connector, opts map[string]interface{}) *agentContext.CompletionOptions { // Get capabilities from connector - capabilities := GetCapabilitiesFromConn(conn, nil) + capabilities := GetCapabilitiesFromConn(conn) completionOptions := &agentContext.CompletionOptions{ Capabilities: capabilities, @@ -737,12 +737,6 @@ func (api *JSAPI) executeRace(requests []*Request) []interface{} { return []interface{}{result} } -// executeSingleRequest executes a single LLM request using the original context -// This is used for single calls (not batch) -func (api *JSAPI) executeSingleRequest(request *Request) interface{} { - return api.StreamWithHandler(request.Connector, request.Messages, request.Options, request.Handler) -} - // executeSingleRequestWithForkedContext executes a single LLM request with a forked context // This is used by batch operations (All/Any/Race) to avoid race conditions // when multiple goroutines access shared context state diff --git a/agent/llm/providers/anthropic/anthropic.go b/agent/llm/providers/anthropic/anthropic.go index decfb949..6e6669cf 100644 --- a/agent/llm/providers/anthropic/anthropic.go +++ b/agent/llm/providers/anthropic/anthropic.go @@ -9,9 +9,8 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/yaoapp/gou/connector" - gouAnthropicConn "github.com/yaoapp/gou/connector/anthropic" - gouOpenAI "github.com/yaoapp/gou/connector/openai" "github.com/yaoapp/gou/http" + goullm "github.com/yaoapp/gou/llm" "github.com/yaoapp/kun/log" "github.com/yaoapp/yao/agent/context" "github.com/yaoapp/yao/agent/i18n" @@ -27,34 +26,15 @@ type Provider struct { } // New create a new Anthropic provider -func New(conn connector.Connector, capabilities *gouOpenAI.Capabilities) *Provider { +func New(conn connector.Connector, capabilities *goullm.Capabilities) *Provider { return &Provider{ Provider: base.NewProvider(conn, capabilities), adapters: buildAdapters(capabilities), } } -// NewFromAnthropicCaps create a new Anthropic provider from Anthropic capabilities -func NewFromAnthropicCaps(conn connector.Connector, caps *gouAnthropicConn.Capabilities) *Provider { - // Convert anthropic capabilities to openai capabilities for base provider compatibility - openaiCaps := &gouOpenAI.Capabilities{ - Vision: caps.Vision, - Audio: caps.Audio, - ToolCalls: caps.ToolCalls, - Reasoning: caps.Reasoning, - Streaming: caps.Streaming, - JSON: caps.JSON, - Multimodal: caps.Multimodal, - TemperatureAdjustable: caps.TemperatureAdjustable, - } - return &Provider{ - Provider: base.NewProvider(conn, openaiCaps), - adapters: buildAdapters(openaiCaps), - } -} - // buildAdapters builds capability adapters based on model capabilities -func buildAdapters(cap *gouOpenAI.Capabilities) []adapters.CapabilityAdapter { +func buildAdapters(cap *goullm.Capabilities) []adapters.CapabilityAdapter { if cap == nil { return []adapters.CapabilityAdapter{} } diff --git a/agent/llm/providers/anthropic/anthropic_test.go b/agent/llm/providers/anthropic/anthropic_test.go index d1475f41..d98dbd33 100644 --- a/agent/llm/providers/anthropic/anthropic_test.go +++ b/agent/llm/providers/anthropic/anthropic_test.go @@ -7,7 +7,7 @@ import ( "testing" "github.com/yaoapp/gou/connector" - "github.com/yaoapp/gou/connector/openai" + goullm "github.com/yaoapp/gou/llm" "github.com/yaoapp/yao/agent/context" "github.com/yaoapp/yao/agent/llm" "github.com/yaoapp/yao/agent/output/message" @@ -34,9 +34,8 @@ func TestAnthropicStreamBasic(t *testing.T) { t.Fatal("Connector is not ANTHROPIC type") } - // Use openai.Capabilities — SelectProvider auto-detects Anthropic format from connector type options := &context.CompletionOptions{ - Capabilities: &openai.Capabilities{ + Capabilities: &goullm.Capabilities{ Streaming: true, ToolCalls: true, }, @@ -111,7 +110,7 @@ func TestAnthropicStreamWithToolCalls(t *testing.T) { } options := &context.CompletionOptions{ - Capabilities: &openai.Capabilities{ + Capabilities: &goullm.Capabilities{ Streaming: true, ToolCalls: true, }, @@ -226,7 +225,7 @@ func TestAnthropicStreamRetry(t *testing.T) { } options := &context.CompletionOptions{ - Capabilities: &openai.Capabilities{ + Capabilities: &goullm.Capabilities{ Streaming: true, ToolCalls: true, }, diff --git a/agent/llm/providers/base/base.go b/agent/llm/providers/base/base.go index 10ebc12e..e0e916b4 100644 --- a/agent/llm/providers/base/base.go +++ b/agent/llm/providers/base/base.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/yaoapp/gou/connector" - "github.com/yaoapp/gou/connector/openai" + "github.com/yaoapp/gou/llm" "github.com/yaoapp/yao/agent/context" ) @@ -12,11 +12,11 @@ import ( // Provides common functionality for all LLM providers type Provider struct { Connector connector.Connector - Capabilities *openai.Capabilities + Capabilities *llm.Capabilities } // NewProvider create a new base provider -func NewProvider(conn connector.Connector, capabilities *openai.Capabilities) *Provider { +func NewProvider(conn connector.Connector, capabilities *llm.Capabilities) *Provider { return &Provider{ Connector: conn, Capabilities: capabilities, diff --git a/agent/llm/providers/factory.go b/agent/llm/providers/factory.go index ede08740..0901873c 100644 --- a/agent/llm/providers/factory.go +++ b/agent/llm/providers/factory.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/yaoapp/gou/connector" - gouAnthropicConn "github.com/yaoapp/gou/connector/anthropic" "github.com/yaoapp/yao/agent/context" "github.com/yaoapp/yao/agent/llm/providers/anthropic" "github.com/yaoapp/yao/agent/llm/providers/openai" @@ -43,13 +42,6 @@ func SelectProvider(conn connector.Connector, options *context.CompletionOptions return openai.New(conn, options.Capabilities), nil case "anthropic": - // Anthropic Messages API (Claude, Kimi Code, etc.) - // Check if connector has native Anthropic capabilities - settings := conn.Setting() - if caps, ok := settings["capabilities"].(*gouAnthropicConn.Capabilities); ok { - return anthropic.NewFromAnthropicCaps(conn, caps), nil - } - // Fallback: use OpenAI capabilities (converted from connector settings) return anthropic.New(conn, options.Capabilities), nil default: diff --git a/agent/llm/providers/openai/openai.go b/agent/llm/providers/openai/openai.go index 264b5a80..a53224d4 100644 --- a/agent/llm/providers/openai/openai.go +++ b/agent/llm/providers/openai/openai.go @@ -8,8 +8,8 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/yaoapp/gou/connector" - gouOpenAI "github.com/yaoapp/gou/connector/openai" "github.com/yaoapp/gou/http" + goullm "github.com/yaoapp/gou/llm" "github.com/yaoapp/kun/log" "github.com/yaoapp/yao/agent/context" "github.com/yaoapp/yao/agent/i18n" @@ -137,7 +137,7 @@ func buildAPIURL(host, endpoint string) string { } // New create a new OpenAI provider with capability adapters -func New(conn connector.Connector, capabilities *gouOpenAI.Capabilities) *Provider { +func New(conn connector.Connector, capabilities *goullm.Capabilities) *Provider { return &Provider{ Provider: base.NewProvider(conn, capabilities), adapters: buildAdapters(capabilities), @@ -145,7 +145,7 @@ func New(conn connector.Connector, capabilities *gouOpenAI.Capabilities) *Provid } // buildAdapters builds capability adapters based on model capabilities -func buildAdapters(cap *gouOpenAI.Capabilities) []adapters.CapabilityAdapter { +func buildAdapters(cap *goullm.Capabilities) []adapters.CapabilityAdapter { if cap == nil { return []adapters.CapabilityAdapter{} } @@ -182,7 +182,7 @@ func buildAdapters(cap *gouOpenAI.Capabilities) []adapters.CapabilityAdapter { } // detectReasoningFormat detects the reasoning format based on capabilities -func detectReasoningFormat(cap *gouOpenAI.Capabilities) adapters.ReasoningFormat { +func detectReasoningFormat(cap *goullm.Capabilities) adapters.ReasoningFormat { // TODO: Implement better detection logic // For now, default to OpenAI o1 format if reasoning is supported if cap.Reasoning { diff --git a/agent/load.go b/agent/load.go index b554ea7d..37208fa8 100644 --- a/agent/load.go +++ b/agent/load.go @@ -6,7 +6,6 @@ import ( "github.com/yaoapp/gou/application" "github.com/yaoapp/gou/connector" - gouOpenAI "github.com/yaoapp/gou/connector/openai" "github.com/yaoapp/yao/agent/assistant" "github.com/yaoapp/yao/agent/context" "github.com/yaoapp/yao/agent/i18n" @@ -75,12 +74,6 @@ func Load(cfg config.Config) error { return err } - // Initialize model capabilities - err = initModelCapabilities() - if err != nil { - return err - } - // Initialize Global I18n err = initGlobalI18n() if err != nil { @@ -148,29 +141,6 @@ func GetGlobalPrompts(ctx map[string]string) []store.Prompt { return store.Prompts(agentDSL.GlobalPrompts).Parse(ctx) } -// initModelCapabilities initialize the model capabilities configuration -func initModelCapabilities() error { - path := filepath.Join("agent", "models.yml") - if exists, _ := application.App.Exists(path); !exists { - return nil - } - - // Read the model capabilities configuration - bytes, err := application.App.Read(path) - if err != nil { - return err - } - - var models map[string]gouOpenAI.Capabilities = map[string]gouOpenAI.Capabilities{} - err = application.Parse("models.yml", bytes, &models) - if err != nil { - return err - } - - agentDSL.Models = models - return nil -} - // initStore initialize the store func initStore() error { @@ -231,10 +201,6 @@ func initAssistant() error { assistant.SetGlobalPrompts(agentDSL.GlobalPrompts) } - if agentDSL.Models != nil { - assistant.SetModelCapabilities(agentDSL.Models) - } - if agentDSL.KB != nil { assistant.SetGlobalKBSetting(agentDSL.KB) } diff --git a/agent/load_test.go b/agent/load_test.go index fd34d01f..3b219c00 100644 --- a/agent/load_test.go +++ b/agent/load_test.go @@ -54,12 +54,6 @@ func TestLoad(t *testing.T) { assert.Contains(t, agent.GlobalPrompts[0].Content, "$SYS.") }) - t.Run("LoadModelCapabilities", func(t *testing.T) { - // Model capabilities should be loaded from agent/models.yml - assert.NotNil(t, agent.Models) - assert.Greater(t, len(agent.Models), 0) - }) - t.Run("LoadKBConfig", func(t *testing.T) { // KB configuration should be loaded from agent/kb.yml assert.NotNil(t, agent.KB) diff --git a/agent/output/message/types.go b/agent/output/message/types.go index 3cf7698d..8f92c273 100644 --- a/agent/output/message/types.go +++ b/agent/output/message/types.go @@ -3,7 +3,7 @@ package message import ( "net/http" - "github.com/yaoapp/gou/connector/openai" + "github.com/yaoapp/gou/llm" traceTypes "github.com/yaoapp/yao/trace/types" ) @@ -13,7 +13,7 @@ type Options struct { Accept string Writer http.ResponseWriter Trace traceTypes.Manager - Capabilities *openai.Capabilities + Capabilities *llm.Capabilities Locale string } diff --git a/agent/types/types.go b/agent/types/types.go index f63d1359..cf01e7ca 100644 --- a/agent/types/types.go +++ b/agent/types/types.go @@ -1,7 +1,6 @@ package types import ( - "github.com/yaoapp/gou/connector/openai" "github.com/yaoapp/yao/agent/assistant" searchTypes "github.com/yaoapp/yao/agent/search/types" store "github.com/yaoapp/yao/agent/store/types" @@ -23,11 +22,10 @@ type DSL struct { // If not set, fallback to the first connector that supports the required capabilities System *System `json:"system,omitempty" yaml:"system,omitempty"` - // Global External Settings - model capabilities, tools, etc. + // Global External Settings // =============================== - Models map[string]openai.Capabilities `json:"models,omitempty" yaml:"models,omitempty"` // The model capabilities configuration - KB *store.KBSetting `json:"kb,omitempty" yaml:"kb,omitempty"` // The knowledge base configuration loaded from agent/kb.yml - Search *searchTypes.Config `json:"search,omitempty" yaml:"search,omitempty"` // The search configuration loaded from agent/search.yao + KB *store.KBSetting `json:"kb,omitempty" yaml:"kb,omitempty"` // The knowledge base configuration loaded from agent/kb.yml + Search *searchTypes.Config `json:"search,omitempty" yaml:"search,omitempty"` // The search configuration loaded from agent/search.yao // Internal // =============================== diff --git a/openapi/llm/llm.go b/openapi/llm/llm.go index 762b2d4a..53b16627 100644 --- a/openapi/llm/llm.go +++ b/openapi/llm/llm.go @@ -5,8 +5,6 @@ import ( "github.com/gin-gonic/gin" "github.com/yaoapp/gou/connector" - "github.com/yaoapp/gou/connector/openai" - "github.com/yaoapp/yao/agent" agentllm "github.com/yaoapp/yao/agent/llm" oauthTypes "github.com/yaoapp/yao/openapi/oauth/types" "github.com/yaoapp/yao/openapi/response" @@ -21,16 +19,6 @@ type Provider struct { Capabilities map[string]interface{} `json:"capabilities"` // Model capabilities from connector settings } -// getModelCapabilities returns user-defined model capabilities from agent DSL -// Returns nil if agent not initialized or no models configured -func getModelCapabilities() map[string]openai.Capabilities { - agentDSL := agent.GetAgent() - if agentDSL != nil && agentDSL.Models != nil { - return agentDSL.Models - } - return nil -} - // Attach attaches the LLM management handlers to the router with OAuth protection func Attach(group *gin.RouterGroup, oauth oauthTypes.OAuth) { @@ -56,23 +44,15 @@ func listProviders(c *gin.Context) { } } - // Get user-defined model capabilities once at the start of request - modelCapabilities := getModelCapabilities() - - // Get all LLM connectors from AIConnectors - // Note: All AI type connectors (openai, anthropic, fastembed) are automatically added to AIConnectors during loading - // See gou/connector/connector.go LoadSource() for details for _, opt := range connector.AIConnectors { connType := getConnectorType(opt.Value) - // Include OpenAI-compatible and Anthropic LLM connectors if connType == "openai" || connType == "anthropic" { conn, ok := connector.Connectors[opt.Value] if !ok { continue } - // Get capabilities from connector settings - capabilities := getCapabilitiesWithModels(conn, modelCapabilities) + capabilities := getCapabilitiesFromConn(conn) // Apply capability filters if len(filters) > 0 && !matchesFilters(capabilities, filters) { @@ -110,16 +90,13 @@ func getConnectorType(id string) string { return "unknown" } -// getCapabilitiesWithModels extracts capabilities from connector settings -// Uses the unified capability getter from agent/llm package -// Takes modelCapabilities as parameter to avoid repeated calls to getModelCapabilities() -func getCapabilitiesWithModels(conn connector.Connector, modelCapabilities map[string]openai.Capabilities) map[string]interface{} { +// getCapabilitiesFromConn extracts capabilities from connector settings +func getCapabilitiesFromConn(conn connector.Connector) map[string]interface{} { if conn == nil { return nil } - // Use unified capability getter with user-defined model capabilities - caps := agentllm.GetCapabilitiesFromConn(conn, modelCapabilities) + caps := agentllm.GetCapabilitiesFromConn(conn) return agentllm.ToMap(caps) }