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.
This commit is contained in:
parent
1e4e1224e2
commit
a38d115465
18 changed files with 49 additions and 235 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// ===============================
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue