Refactor model capabilities to use OpenAI struct
- Updated the model capabilities throughout the agent to utilize the new gouOpenAI.Capabilities struct instead of the previous ModelCapabilities. - Adjusted related methods and types to ensure compatibility with the new capabilities structure, enhancing clarity and maintainability. - Improved context handling and message processing by directly integrating OpenAI capabilities, streamlining the overall architecture.
This commit is contained in:
parent
7e8b2d8d9f
commit
3dd63e5530
21 changed files with 244 additions and 363 deletions
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/kun/log"
|
"github.com/yaoapp/kun/log"
|
||||||
"github.com/yaoapp/yao/agent/assistant/handlers"
|
"github.com/yaoapp/yao/agent/assistant/handlers"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
|
|
@ -303,7 +304,7 @@ func (ast *Assistant) Stream(ctx *context.Context, inputMessages []context.Messa
|
||||||
// GetConnector get the connector object, capabilities, and error with priority: createResponse > ctx > ast
|
// GetConnector get the connector object, capabilities, and error with priority: createResponse > ctx > ast
|
||||||
// Note: createResponse.Connector is already applied to ctx.Connector by applyContextAdjustments in create.go
|
// Note: createResponse.Connector is already applied to ctx.Connector by applyContextAdjustments in create.go
|
||||||
// Returns: (connector, capabilities, error)
|
// Returns: (connector, capabilities, error)
|
||||||
func (ast *Assistant) GetConnector(ctx *context.Context) (connector.Connector, *context.ModelCapabilities, error) {
|
func (ast *Assistant) GetConnector(ctx *context.Context) (connector.Connector, *openai.Capabilities, error) {
|
||||||
// Determine connector ID with priority
|
// Determine connector ID with priority
|
||||||
connectorID := ast.Connector
|
connectorID := ast.Connector
|
||||||
if ctx.Connector != "" {
|
if ctx.Connector != "" {
|
||||||
|
|
@ -328,62 +329,27 @@ func (ast *Assistant) GetConnector(ctx *context.Context) (connector.Connector, *
|
||||||
}
|
}
|
||||||
|
|
||||||
// getConnectorCapabilities get the capabilities of a connector from settings
|
// getConnectorCapabilities get the capabilities of a connector from settings
|
||||||
func (ast *Assistant) getConnectorCapabilities(connectorID string) *context.ModelCapabilities {
|
func (ast *Assistant) getConnectorCapabilities(connectorID string) *openai.Capabilities {
|
||||||
// Initialize with default capabilities (all disabled)
|
|
||||||
falseVal := false
|
|
||||||
capabilities := &context.ModelCapabilities{
|
|
||||||
Vision: falseVal,
|
|
||||||
ToolCalls: &falseVal,
|
|
||||||
Audio: &falseVal,
|
|
||||||
Reasoning: &falseVal,
|
|
||||||
Streaming: &falseVal,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get model capabilities from global configuration
|
// Get model capabilities from global configuration
|
||||||
modelCaps, exists := modelCapabilities[connectorID]
|
modelCaps, exists := modelCapabilities[connectorID]
|
||||||
if !exists {
|
if !exists {
|
||||||
// Return default capabilities if model not found in configuration
|
// Return default capabilities if model not found in configuration
|
||||||
return capabilities
|
falseVal := false
|
||||||
|
return &openai.Capabilities{
|
||||||
|
Vision: falseVal,
|
||||||
|
ToolCalls: false,
|
||||||
|
Audio: false,
|
||||||
|
Reasoning: false,
|
||||||
|
Streaming: false,
|
||||||
|
JSON: false,
|
||||||
|
Multimodal: false,
|
||||||
|
TemperatureAdjustable: true, // Default to true for non-reasoning models
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update capabilities based on model configuration
|
// Return capabilities directly
|
||||||
// Vision can be bool or string (VisionFormat)
|
// Note: TemperatureAdjustable is automatically set in connector.Setting() based on Reasoning flag
|
||||||
if modelCaps.Vision != nil {
|
return &modelCaps
|
||||||
capabilities.Vision = modelCaps.Vision
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle both Tools (deprecated) and ToolCalls
|
|
||||||
if modelCaps.ToolCalls || modelCaps.Tools {
|
|
||||||
v := true
|
|
||||||
capabilities.ToolCalls = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
if modelCaps.Audio {
|
|
||||||
v := true
|
|
||||||
capabilities.Audio = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
if modelCaps.Reasoning {
|
|
||||||
v := true
|
|
||||||
capabilities.Reasoning = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
if modelCaps.Streaming {
|
|
||||||
v := true
|
|
||||||
capabilities.Streaming = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
if modelCaps.JSON {
|
|
||||||
v := true
|
|
||||||
capabilities.JSON = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
if modelCaps.Multimodal {
|
|
||||||
v := true
|
|
||||||
capabilities.Multimodal = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
return capabilities
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info get the assistant information
|
// Info get the assistant information
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
"github.com/yaoapp/gou/application"
|
"github.com/yaoapp/gou/application"
|
||||||
|
gouOpenAI "github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/fs"
|
"github.com/yaoapp/gou/fs"
|
||||||
v8 "github.com/yaoapp/gou/runtime/v8"
|
v8 "github.com/yaoapp/gou/runtime/v8"
|
||||||
"github.com/yaoapp/yao/agent/assistant/hook"
|
"github.com/yaoapp/yao/agent/assistant/hook"
|
||||||
|
|
@ -26,7 +27,7 @@ import (
|
||||||
var loaded = NewCache(200) // 200 is the default capacity
|
var loaded = NewCache(200) // 200 is the default capacity
|
||||||
var storage store.Store = nil
|
var storage store.Store = nil
|
||||||
var search interface{} = nil
|
var search interface{} = nil
|
||||||
var modelCapabilities map[string]ModelCapabilities = map[string]ModelCapabilities{}
|
var modelCapabilities map[string]gouOpenAI.Capabilities = map[string]gouOpenAI.Capabilities{}
|
||||||
var defaultConnector string = "" // default connector
|
var defaultConnector string = "" // default connector
|
||||||
var globalUses *context.Uses = nil // global uses configuration from agent.yml
|
var globalUses *context.Uses = nil // global uses configuration from agent.yml
|
||||||
|
|
||||||
|
|
@ -131,7 +132,7 @@ func SetStorage(s store.Store) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetModelCapabilities set the model capabilities configuration
|
// SetModelCapabilities set the model capabilities configuration
|
||||||
func SetModelCapabilities(capabilities map[string]ModelCapabilities) {
|
func SetModelCapabilities(capabilities map[string]gouOpenAI.Capabilities) {
|
||||||
modelCapabilities = capabilities
|
modelCapabilities = capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package assistant
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/kun/log"
|
"github.com/yaoapp/kun/log"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/i18n"
|
"github.com/yaoapp/yao/agent/i18n"
|
||||||
|
|
@ -48,7 +49,7 @@ func (ast *Assistant) traceCreateHook(agentNode types.Node, createResponse *cont
|
||||||
}
|
}
|
||||||
|
|
||||||
// traceConnectorCapabilities logs the connector capabilities to the agent trace node
|
// traceConnectorCapabilities logs the connector capabilities to the agent trace node
|
||||||
func (ast *Assistant) traceConnectorCapabilities(agentNode types.Node, capabilities *context.ModelCapabilities) {
|
func (ast *Assistant) traceConnectorCapabilities(agentNode types.Node, capabilities *openai.Capabilities) {
|
||||||
if agentNode == nil {
|
if agentNode == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,19 +40,6 @@ type Assistant struct {
|
||||||
// toolCalls bool // Whether this assistant supports tool_calls
|
// toolCalls bool // Whether this assistant supports tool_calls
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModelCapabilities defines the capabilities of a language model
|
|
||||||
// This configuration is loaded from agent/models.yml
|
|
||||||
type ModelCapabilities struct {
|
|
||||||
Vision interface{} `json:"vision,omitempty" yaml:"vision,omitempty"` // Supports vision/image input: bool or VisionFormat string ("openai", "claude"/"base64", "default")
|
|
||||||
Tools bool `json:"tools,omitempty" yaml:"tools,omitempty"` // Supports tool/function calling (deprecated, use ToolCalls)
|
|
||||||
ToolCalls bool `json:"tool_calls,omitempty" yaml:"tool_calls,omitempty"` // Supports tool/function calling
|
|
||||||
Audio bool `json:"audio,omitempty" yaml:"audio,omitempty"` // Supports audio input/output
|
|
||||||
Reasoning bool `json:"reasoning,omitempty" yaml:"reasoning,omitempty"` // Supports reasoning/thinking mode (o1, DeepSeek R1)
|
|
||||||
Streaming bool `json:"streaming,omitempty" yaml:"streaming,omitempty"` // Supports streaming responses
|
|
||||||
JSON bool `json:"json,omitempty" yaml:"json,omitempty"` // Supports JSON mode
|
|
||||||
Multimodal bool `json:"multimodal,omitempty" yaml:"multimodal,omitempty"` // Supports multimodal input
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisionCapableModels list of LLM models that support vision capabilities
|
// VisionCapableModels list of LLM models that support vision capabilities
|
||||||
var VisionCapableModels = map[string]bool{
|
var VisionCapableModels = map[string]bool{
|
||||||
// OpenAI Models
|
// OpenAI Models
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package context
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/yao/agent/output"
|
"github.com/yaoapp/yao/agent/output"
|
||||||
"github.com/yaoapp/yao/agent/output/message"
|
"github.com/yaoapp/yao/agent/output/message"
|
||||||
)
|
)
|
||||||
|
|
@ -290,18 +291,10 @@ func (ctx *Context) getOutput() (*output.Output, error) {
|
||||||
Accept: string(ctx.Accept),
|
Accept: string(ctx.Accept),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert ModelCapabilities to message.ModelCapabilities
|
// Set ModelCapabilities (now using openai.Capabilities directly)
|
||||||
if ctx.Capabilities != nil {
|
if ctx.Capabilities != nil {
|
||||||
options.Capabilities = &message.ModelCapabilities{
|
caps := openai.Capabilities(*ctx.Capabilities)
|
||||||
Vision: ctx.Capabilities.Vision,
|
options.Capabilities = &caps
|
||||||
ToolCalls: ctx.Capabilities.ToolCalls,
|
|
||||||
Audio: ctx.Capabilities.Audio,
|
|
||||||
Reasoning: ctx.Capabilities.Reasoning,
|
|
||||||
Streaming: ctx.Capabilities.Streaming,
|
|
||||||
JSON: ctx.Capabilities.JSON,
|
|
||||||
Multimodal: ctx.Capabilities.Multimodal,
|
|
||||||
TemperatureAdjustable: ctx.Capabilities.TemperatureAdjustable,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/plan"
|
"github.com/yaoapp/gou/plan"
|
||||||
"github.com/yaoapp/gou/store"
|
"github.com/yaoapp/gou/store"
|
||||||
"github.com/yaoapp/yao/agent/output"
|
"github.com/yaoapp/yao/agent/output"
|
||||||
|
|
@ -238,7 +239,7 @@ type Context struct {
|
||||||
Skip *Skip `json:"skip,omitempty"` // Skip configuration (history, trace, etc.), nil means don't skip anything
|
Skip *Skip `json:"skip,omitempty"` // Skip configuration (history, trace, etc.), nil means don't skip anything
|
||||||
|
|
||||||
// Model capabilities (set by assistant, used by output adapters)
|
// Model capabilities (set by assistant, used by output adapters)
|
||||||
Capabilities *ModelCapabilities `json:"-"` // Model capabilities for the current connector
|
Capabilities *openai.Capabilities `json:"-"` // Model capabilities for the current connector
|
||||||
|
|
||||||
// Interrupt control (all interrupt-related logic is encapsulated in InterruptController)
|
// Interrupt control (all interrupt-related logic is encapsulated in InterruptController)
|
||||||
Interrupt *InterruptController `json:"-"` // Interrupt controller for handling user interrupts during streaming
|
Interrupt *InterruptController `json:"-"` // Interrupt controller for handling user interrupts during streaming
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import "github.com/yaoapp/yao/agent/output/message"
|
import (
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
|
"github.com/yaoapp/yao/agent/output/message"
|
||||||
|
)
|
||||||
|
|
||||||
// Uses represents the wrapper configurations for assistant
|
// Uses represents the wrapper configurations for assistant
|
||||||
// Used to specify which assistant or MCP server to use for vision, audio, search, and fetch operations
|
// Used to specify which assistant or MCP server to use for vision, audio, search, and fetch operations
|
||||||
|
|
@ -28,17 +31,13 @@ const (
|
||||||
VisionFormatDefault VisionFormat = "default"
|
VisionFormatDefault VisionFormat = "default"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ModelCapabilities defines the capabilities of a language model
|
|
||||||
// Used by LLM to select appropriate provider and validate requests
|
|
||||||
type ModelCapabilities message.ModelCapabilities
|
|
||||||
|
|
||||||
// GetVisionSupport returns whether vision is supported and the format
|
// GetVisionSupport returns whether vision is supported and the format
|
||||||
func (m *ModelCapabilities) GetVisionSupport() (bool, VisionFormat) {
|
func GetVisionSupport(cap *openai.Capabilities) (bool, VisionFormat) {
|
||||||
if m == nil || m.Vision == nil {
|
if cap == nil || cap.Vision == nil {
|
||||||
return false, VisionFormatNone
|
return false, VisionFormatNone
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v := m.Vision.(type) {
|
switch v := cap.Vision.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
// Legacy bool format
|
// Legacy bool format
|
||||||
return v, VisionFormatDefault
|
return v, VisionFormatDefault
|
||||||
|
|
@ -65,7 +64,7 @@ func (m *ModelCapabilities) GetVisionSupport() (bool, VisionFormat) {
|
||||||
type CompletionOptions struct {
|
type CompletionOptions struct {
|
||||||
// Model capabilities (used by LLM to select appropriate provider)
|
// Model capabilities (used by LLM to select appropriate provider)
|
||||||
// nil means capabilities are not specified/checked
|
// nil means capabilities are not specified/checked
|
||||||
Capabilities *ModelCapabilities `json:"capabilities,omitempty"`
|
Capabilities *openai.Capabilities `json:"capabilities,omitempty"`
|
||||||
|
|
||||||
// User-specified tools for vision, audio, search, and fetch processing
|
// User-specified tools for vision, audio, search, and fetch processing
|
||||||
Uses *Uses `json:"uses,omitempty"`
|
Uses *Uses `json:"uses,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package adapters
|
package adapters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -28,7 +29,7 @@ type ReasoningAdapter struct {
|
||||||
|
|
||||||
// NewReasoningAdapter creates a new reasoning adapter
|
// NewReasoningAdapter creates a new reasoning adapter
|
||||||
// If cap.TemperatureAdjustable is provided, it overrides the default behavior
|
// If cap.TemperatureAdjustable is provided, it overrides the default behavior
|
||||||
func NewReasoningAdapter(format ReasoningFormat, cap *context.ModelCapabilities) *ReasoningAdapter {
|
func NewReasoningAdapter(format ReasoningFormat, cap *openai.Capabilities) *ReasoningAdapter {
|
||||||
supportsEffort := false
|
supportsEffort := false
|
||||||
supportsTemperature := true
|
supportsTemperature := true
|
||||||
|
|
||||||
|
|
@ -49,8 +50,8 @@ func NewReasoningAdapter(format ReasoningFormat, cap *context.ModelCapabilities)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override with explicit capability if provided
|
// Override with explicit capability if provided
|
||||||
if cap != nil && cap.TemperatureAdjustable != nil {
|
if cap != nil {
|
||||||
supportsTemperature = *cap.TemperatureAdjustable
|
supportsTemperature = cap.TemperatureAdjustable
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ReasoningAdapter{
|
return &ReasoningAdapter{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -11,11 +12,11 @@ import (
|
||||||
// Provides common functionality for all LLM providers
|
// Provides common functionality for all LLM providers
|
||||||
type Provider struct {
|
type Provider struct {
|
||||||
Connector connector.Connector
|
Connector connector.Connector
|
||||||
Capabilities *context.ModelCapabilities
|
Capabilities *openai.Capabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProvider create a new base provider
|
// NewProvider create a new base provider
|
||||||
func NewProvider(conn connector.Connector, capabilities *context.ModelCapabilities) *Provider {
|
func NewProvider(conn connector.Connector, capabilities *openai.Capabilities) *Provider {
|
||||||
return &Provider{
|
return &Provider{
|
||||||
Connector: conn,
|
Connector: conn,
|
||||||
Capabilities: capabilities,
|
Capabilities: capabilities,
|
||||||
|
|
@ -74,33 +75,33 @@ func (p *Provider) SupportsVision() bool {
|
||||||
if p.Capabilities == nil {
|
if p.Capabilities == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
supported, _ := p.Capabilities.GetVisionSupport()
|
supported, _ := context.GetVisionSupport(p.Capabilities)
|
||||||
return supported
|
return supported
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportsAudio check if this provider supports audio
|
// SupportsAudio check if this provider supports audio
|
||||||
func (p *Provider) SupportsAudio() bool {
|
func (p *Provider) SupportsAudio() bool {
|
||||||
return p.Capabilities != nil && p.Capabilities.Audio != nil && *p.Capabilities.Audio
|
return p.Capabilities != nil && p.Capabilities.Audio
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportsTools check if this provider supports tool calls
|
// SupportsTools check if this provider supports tool calls
|
||||||
func (p *Provider) SupportsTools() bool {
|
func (p *Provider) SupportsTools() bool {
|
||||||
return p.Capabilities != nil && p.Capabilities.ToolCalls != nil && *p.Capabilities.ToolCalls
|
return p.Capabilities != nil && p.Capabilities.ToolCalls
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportsStreaming check if this provider supports streaming
|
// SupportsStreaming check if this provider supports streaming
|
||||||
func (p *Provider) SupportsStreaming() bool {
|
func (p *Provider) SupportsStreaming() bool {
|
||||||
return p.Capabilities != nil && p.Capabilities.Streaming != nil && *p.Capabilities.Streaming
|
return p.Capabilities != nil && p.Capabilities.Streaming
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportsJSON check if this provider supports JSON mode
|
// SupportsJSON check if this provider supports JSON mode
|
||||||
func (p *Provider) SupportsJSON() bool {
|
func (p *Provider) SupportsJSON() bool {
|
||||||
return p.Capabilities != nil && p.Capabilities.JSON != nil && *p.Capabilities.JSON
|
return p.Capabilities != nil && p.Capabilities.JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportsReasoning check if this provider supports reasoning mode
|
// SupportsReasoning check if this provider supports reasoning mode
|
||||||
func (p *Provider) SupportsReasoning() bool {
|
func (p *Provider) SupportsReasoning() bool {
|
||||||
return p.Capabilities != nil && p.Capabilities.Reasoning != nil && *p.Capabilities.Reasoning
|
return p.Capabilities != nil && p.Capabilities.Reasoning
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConnectorSetting gets a setting value from the connector
|
// GetConnectorSetting gets a setting value from the connector
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/plan"
|
"github.com/yaoapp/gou/plan"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/llm"
|
"github.com/yaoapp/yao/agent/llm"
|
||||||
|
|
@ -60,15 +61,13 @@ func TestClaudeSonnet4StreamBasic(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
Reasoning: &falseVal, // Claude Sonnet 4 (non-thinking) doesn't expose reasoning
|
Reasoning: false, // Claude Sonnet 4 (non-thinking) doesn't expose reasoning
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
Vision: &trueVal,
|
Vision: "claude", // Claude requires base64 format
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,15 +139,13 @@ func TestClaudeSonnet4PostBasic(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &falseVal,
|
Streaming: false,
|
||||||
Reasoning: &falseVal,
|
Reasoning: false,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
Vision: &trueVal,
|
Vision: "claude", // Claude requires base64 format
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,15 +203,13 @@ func TestClaudeSonnet4WithToolCalls(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &falseVal,
|
Streaming: false,
|
||||||
Reasoning: &falseVal,
|
Reasoning: false,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
Vision: &trueVal,
|
Vision: "claude", // Claude requires base64 format
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,8 +239,8 @@ func TestClaudeSonnet4WithToolCalls(t *testing.T) {
|
||||||
options.Tools = []map[string]interface{}{simpleTool}
|
options.Tools = []map[string]interface{}{simpleTool}
|
||||||
options.ToolChoice = "auto"
|
options.ToolChoice = "auto"
|
||||||
|
|
||||||
// Set lower max_tokens for faster response
|
// Set enough tokens for tool call response
|
||||||
maxTokens := 50
|
maxTokens := 150
|
||||||
options.MaxTokens = &maxTokens
|
options.MaxTokens = &maxTokens
|
||||||
|
|
||||||
llmInstance, err := llm.New(conn, options)
|
llmInstance, err := llm.New(conn, options)
|
||||||
|
|
@ -256,7 +251,7 @@ func TestClaudeSonnet4WithToolCalls(t *testing.T) {
|
||||||
messages := []context.Message{
|
messages := []context.Message{
|
||||||
{
|
{
|
||||||
Role: context.RoleUser,
|
Role: context.RoleUser,
|
||||||
Content: "Call get_info with query='A' and count=1",
|
Content: "Please use the get_info function to retrieve information. Pass 'A' as the query parameter and 1 as the count parameter.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -299,15 +294,13 @@ func TestClaudeSonnet4Vision(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &falseVal,
|
Streaming: false,
|
||||||
Reasoning: &falseVal,
|
Reasoning: false,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
Vision: &trueVal,
|
Vision: "claude", // Claude requires base64 format
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,15 +369,13 @@ func TestClaudeSonnet4ThinkingStream(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
Reasoning: &trueVal, // Claude Thinking mode exposes reasoning
|
Reasoning: true, // Claude Thinking mode exposes reasoning
|
||||||
ToolCalls: &falseVal,
|
ToolCalls: false,
|
||||||
Vision: &trueVal,
|
Vision: "claude", // Claude requires base64 format
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -456,15 +447,13 @@ func TestClaudeSonnet4ThinkingPost(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &falseVal,
|
Streaming: false,
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
ToolCalls: &falseVal,
|
ToolCalls: false,
|
||||||
Vision: &trueVal,
|
Vision: "claude", // Claude requires base64 format
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -550,14 +539,12 @@ func TestClaudeTemperatureHandling(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &falseVal,
|
Streaming: false,
|
||||||
Reasoning: &tt.reasoning,
|
Reasoning: tt.reasoning,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
Vision: &trueVal,
|
Vision: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/plan"
|
"github.com/yaoapp/gou/plan"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/llm"
|
"github.com/yaoapp/yao/agent/llm"
|
||||||
|
|
@ -28,16 +29,14 @@ func TestDeepSeekR1StreamBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance with capabilities
|
// Create LLM instance with capabilities
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
Reasoning: &trueVal, // DeepSeek R1 supports reasoning
|
Reasoning: true, // DeepSeek R1 supports reasoning
|
||||||
ToolCalls: &falseVal, // R1 doesn't support native tool calls
|
ToolCalls: false, // R1 doesn't support native tool calls
|
||||||
Vision: &falseVal,
|
Vision: false,
|
||||||
Audio: &falseVal,
|
Audio: false,
|
||||||
Multimodal: &falseVal,
|
Multimodal: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,15 +206,13 @@ func TestDeepSeekR1PostBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance
|
// Create LLM instance
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
ToolCalls: &falseVal,
|
ToolCalls: false,
|
||||||
Vision: &falseVal,
|
Vision: false,
|
||||||
Audio: &falseVal,
|
Audio: false,
|
||||||
Multimodal: &falseVal,
|
Multimodal: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,16 +292,14 @@ func TestDeepSeekR1LogicPuzzle(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
ToolCalls: &falseVal,
|
ToolCalls: false,
|
||||||
Vision: &falseVal,
|
Vision: false,
|
||||||
Audio: &falseVal,
|
Audio: false,
|
||||||
Multimodal: &falseVal,
|
Multimodal: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/plan"
|
"github.com/yaoapp/gou/plan"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/llm"
|
"github.com/yaoapp/yao/agent/llm"
|
||||||
|
|
@ -24,16 +25,14 @@ func TestDeepSeekV3StreamBasic(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
Reasoning: &falseVal, // V3 doesn't support reasoning
|
Reasoning: false, // V3 doesn't support reasoning
|
||||||
ToolCalls: &trueVal, // V3 supports tool calls
|
ToolCalls: true, // V3 supports tool calls
|
||||||
Vision: &falseVal,
|
Vision: false,
|
||||||
Audio: &falseVal,
|
Audio: false,
|
||||||
Multimodal: &falseVal,
|
Multimodal: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,15 +134,13 @@ func TestDeepSeekV3PostBasic(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &falseVal,
|
Reasoning: false,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
Vision: &falseVal,
|
Vision: false,
|
||||||
Audio: &falseVal,
|
Audio: false,
|
||||||
Multimodal: &falseVal,
|
Multimodal: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,12 +223,10 @@ func TestDeepSeekV3WithToolCalls(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &falseVal,
|
Reasoning: false,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -318,13 +313,11 @@ func TestDeepSeekV3NoReasoningEffort(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
effort := "high"
|
effort := "high"
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &falseVal, // V3 doesn't support reasoning
|
Reasoning: false, // V3 doesn't support reasoning
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
ReasoningEffort: &effort, // Should be ignored by adapter
|
ReasoningEffort: &effort, // Should be ignored by adapter
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/plan"
|
"github.com/yaoapp/gou/plan"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/llm"
|
"github.com/yaoapp/yao/agent/llm"
|
||||||
|
|
@ -24,14 +25,13 @@ func TestGPT5StreamBasic(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
Reasoning: &trueVal, // GPT-5 supports reasoning
|
Reasoning: true, // GPT-5 supports reasoning
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
Vision: &trueVal,
|
Vision: true,
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,11 +105,10 @@ func TestGPT5ReasoningEffort(t *testing.T) {
|
||||||
|
|
||||||
for _, effort := range effortLevels {
|
for _, effort := range effortLevels {
|
||||||
t.Run("effort_"+effort, func(t *testing.T) {
|
t.Run("effort_"+effort, func(t *testing.T) {
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
ReasoningEffort: &effort,
|
ReasoningEffort: &effort,
|
||||||
}
|
}
|
||||||
|
|
@ -172,11 +171,10 @@ func TestGPT5PostWithToolCalls(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,12 +257,11 @@ func TestGPT5Vision(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
Vision: &trueVal,
|
Vision: true,
|
||||||
Multimodal: &trueVal,
|
Multimodal: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -331,13 +328,11 @@ func TestGPT5ReasoningEffortWithGPT4o(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
effort := "high"
|
effort := "high"
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &falseVal, // GPT-4o doesn't support reasoning
|
Reasoning: false, // GPT-4o doesn't support reasoning
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
ReasoningEffort: &effort, // Should be ignored by adapter
|
ReasoningEffort: &effort, // Should be ignored by adapter
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
gouOpenAI "github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/http"
|
"github.com/yaoapp/gou/http"
|
||||||
"github.com/yaoapp/kun/log"
|
"github.com/yaoapp/kun/log"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
|
|
@ -142,7 +143,7 @@ func buildAPIURL(host, endpoint string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New create a new OpenAI provider with capability adapters
|
// New create a new OpenAI provider with capability adapters
|
||||||
func New(conn connector.Connector, capabilities *context.ModelCapabilities) *Provider {
|
func New(conn connector.Connector, capabilities *gouOpenAI.Capabilities) *Provider {
|
||||||
return &Provider{
|
return &Provider{
|
||||||
Provider: base.NewProvider(conn, capabilities),
|
Provider: base.NewProvider(conn, capabilities),
|
||||||
adapters: buildAdapters(capabilities),
|
adapters: buildAdapters(capabilities),
|
||||||
|
|
@ -150,7 +151,7 @@ func New(conn connector.Connector, capabilities *context.ModelCapabilities) *Pro
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildAdapters builds capability adapters based on model capabilities
|
// buildAdapters builds capability adapters based on model capabilities
|
||||||
func buildAdapters(cap *context.ModelCapabilities) []adapters.CapabilityAdapter {
|
func buildAdapters(cap *gouOpenAI.Capabilities) []adapters.CapabilityAdapter {
|
||||||
if cap == nil {
|
if cap == nil {
|
||||||
return []adapters.CapabilityAdapter{}
|
return []adapters.CapabilityAdapter{}
|
||||||
}
|
}
|
||||||
|
|
@ -158,12 +159,10 @@ func buildAdapters(cap *context.ModelCapabilities) []adapters.CapabilityAdapter
|
||||||
result := make([]adapters.CapabilityAdapter, 0)
|
result := make([]adapters.CapabilityAdapter, 0)
|
||||||
|
|
||||||
// Tool call adapter
|
// Tool call adapter
|
||||||
if cap.ToolCalls != nil {
|
result = append(result, adapters.NewToolCallAdapter(cap.ToolCalls))
|
||||||
result = append(result, adapters.NewToolCallAdapter(*cap.ToolCalls))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Vision adapter
|
// Vision adapter
|
||||||
visionSupport, visionFormat := cap.GetVisionSupport()
|
visionSupport, visionFormat := context.GetVisionSupport(cap)
|
||||||
if visionSupport {
|
if visionSupport {
|
||||||
result = append(result, adapters.NewVisionAdapter(true, visionFormat))
|
result = append(result, adapters.NewVisionAdapter(true, visionFormat))
|
||||||
} else if cap.Vision != nil {
|
} else if cap.Vision != nil {
|
||||||
|
|
@ -172,31 +171,27 @@ func buildAdapters(cap *context.ModelCapabilities) []adapters.CapabilityAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Audio adapter
|
// Audio adapter
|
||||||
if cap.Audio != nil {
|
result = append(result, adapters.NewAudioAdapter(cap.Audio))
|
||||||
result = append(result, adapters.NewAudioAdapter(*cap.Audio))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reasoning adapter (always add to handle reasoning_effort and temperature parameters)
|
// Reasoning adapter (always add to handle reasoning_effort and temperature parameters)
|
||||||
// Even if the model doesn't support reasoning, we need the adapter to strip reasoning_effort
|
// Even if the model doesn't support reasoning, we need the adapter to strip reasoning_effort
|
||||||
if cap.Reasoning != nil {
|
if cap.Reasoning {
|
||||||
if *cap.Reasoning {
|
// Detect reasoning format based on capabilities
|
||||||
// Detect reasoning format based on capabilities
|
format := detectReasoningFormat(cap)
|
||||||
format := detectReasoningFormat(cap)
|
result = append(result, adapters.NewReasoningAdapter(format, cap))
|
||||||
result = append(result, adapters.NewReasoningAdapter(format, cap))
|
} else {
|
||||||
} else {
|
// Model doesn't support reasoning, use None format to strip reasoning parameters
|
||||||
// Model doesn't support reasoning, use None format to strip reasoning parameters
|
result = append(result, adapters.NewReasoningAdapter(adapters.ReasoningFormatNone, cap))
|
||||||
result = append(result, adapters.NewReasoningAdapter(adapters.ReasoningFormatNone, cap))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// detectReasoningFormat detects the reasoning format based on capabilities
|
// detectReasoningFormat detects the reasoning format based on capabilities
|
||||||
func detectReasoningFormat(cap *context.ModelCapabilities) adapters.ReasoningFormat {
|
func detectReasoningFormat(cap *gouOpenAI.Capabilities) adapters.ReasoningFormat {
|
||||||
// TODO: Implement better detection logic
|
// TODO: Implement better detection logic
|
||||||
// For now, default to OpenAI o1 format if reasoning is supported
|
// For now, default to OpenAI o1 format if reasoning is supported
|
||||||
if cap.Reasoning != nil && *cap.Reasoning {
|
if cap.Reasoning {
|
||||||
return adapters.ReasoningFormatOpenAI
|
return adapters.ReasoningFormatOpenAI
|
||||||
}
|
}
|
||||||
return adapters.ReasoningFormatNone
|
return adapters.ReasoningFormatNone
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/plan"
|
"github.com/yaoapp/gou/plan"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/llm"
|
"github.com/yaoapp/yao/agent/llm"
|
||||||
|
|
@ -29,11 +30,10 @@ func TestOpenAIStreamBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance with capabilities
|
// Create LLM instance with capabilities
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,10 +117,9 @@ func TestOpenAIPostBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance
|
// Create LLM instance
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,11 +191,10 @@ func TestOpenAIStreamWithToolCalls(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance with tool call capabilities
|
// Create LLM instance with tool call capabilities
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -307,10 +305,9 @@ func TestOpenAIPostWithToolCalls(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance with tool call capabilities
|
// Create LLM instance with tool call capabilities
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -424,11 +421,10 @@ func TestOpenAIStreamWithInvalidToolCall(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance
|
// Create LLM instance
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -523,11 +519,10 @@ func TestOpenAIStreamRetry(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create LLM instance
|
// Create LLM instance
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal, // Need this to select OpenAI provider
|
ToolCalls: true, // Need this to select OpenAI provider
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -582,11 +577,10 @@ func TestOpenAIStreamChunkTypes(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -649,11 +643,10 @@ func TestOpenAIStreamErrorCallback(t *testing.T) {
|
||||||
t.Fatalf("Failed to create test connector: %v", err)
|
t.Fatalf("Failed to create test connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -711,11 +704,10 @@ func TestOpenAIToolCallValidationRetry(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
Tools: []map[string]interface{}{
|
Tools: []map[string]interface{}{
|
||||||
{
|
{
|
||||||
|
|
@ -815,11 +807,10 @@ func TestOpenAIJSONMode(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
ResponseFormat: &context.ResponseFormat{
|
ResponseFormat: &context.ResponseFormat{
|
||||||
Type: context.ResponseFormatJSON,
|
Type: context.ResponseFormatJSON,
|
||||||
|
|
@ -902,10 +893,9 @@ func TestOpenAIJSONModePost(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
ResponseFormat: &context.ResponseFormat{
|
ResponseFormat: &context.ResponseFormat{
|
||||||
Type: context.ResponseFormatJSON,
|
Type: context.ResponseFormatJSON,
|
||||||
|
|
@ -973,8 +963,6 @@ func TestOpenAIJSONSchema(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
|
|
||||||
// Define a strict JSON schema
|
// Define a strict JSON schema
|
||||||
// Note: For OpenAI strict mode, 'required' must include ALL properties
|
// Note: For OpenAI strict mode, 'required' must include ALL properties
|
||||||
schema := map[string]interface{}{
|
schema := map[string]interface{}{
|
||||||
|
|
@ -1009,9 +997,9 @@ func TestOpenAIJSONSchema(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
ResponseFormat: &context.ResponseFormat{
|
ResponseFormat: &context.ResponseFormat{
|
||||||
Type: context.ResponseFormatJSONSchema,
|
Type: context.ResponseFormatJSONSchema,
|
||||||
|
|
@ -1019,7 +1007,7 @@ func TestOpenAIJSONSchema(t *testing.T) {
|
||||||
Name: "user_info",
|
Name: "user_info",
|
||||||
Description: "User information schema",
|
Description: "User information schema",
|
||||||
Schema: schema,
|
Schema: schema,
|
||||||
Strict: &trueVal,
|
Strict: func() *bool { v := true; return &v }(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -1121,8 +1109,6 @@ func TestOpenAIJSONSchemaPost(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
|
|
||||||
// Simple schema for testing
|
// Simple schema for testing
|
||||||
// Note: For OpenAI strict mode, 'required' must include ALL properties
|
// Note: For OpenAI strict mode, 'required' must include ALL properties
|
||||||
schema := map[string]interface{}{
|
schema := map[string]interface{}{
|
||||||
|
|
@ -1144,8 +1130,8 @@ func TestOpenAIJSONSchemaPost(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
ResponseFormat: &context.ResponseFormat{
|
ResponseFormat: &context.ResponseFormat{
|
||||||
Type: context.ResponseFormatJSONSchema,
|
Type: context.ResponseFormatJSONSchema,
|
||||||
|
|
@ -1153,7 +1139,7 @@ func TestOpenAIJSONSchemaPost(t *testing.T) {
|
||||||
Name: "api_response",
|
Name: "api_response",
|
||||||
Description: "API response format",
|
Description: "API response format",
|
||||||
Schema: schema,
|
Schema: schema,
|
||||||
Strict: &trueVal,
|
Strict: func() *bool { v := true; return &v }(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -1263,11 +1249,10 @@ func TestOpenAIStreamLifecycleEvents(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1369,11 +1354,10 @@ func TestOpenAIStreamContextCancellation(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1443,13 +1427,12 @@ func TestOpenAIStreamWithTemperature(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
temperature := 0.7 // Moderate temperature
|
temperature := 0.7 // Moderate temperature
|
||||||
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Streaming: &trueVal,
|
Streaming: true,
|
||||||
ToolCalls: &trueVal, // Need this to select OpenAI provider
|
ToolCalls: true, // Need this to select OpenAI provider
|
||||||
},
|
},
|
||||||
Temperature: &temperature,
|
Temperature: &temperature,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/gou/plan"
|
"github.com/yaoapp/gou/plan"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/llm"
|
"github.com/yaoapp/yao/agent/llm"
|
||||||
|
|
@ -23,11 +24,10 @@ func TestTemperatureGPT5AutoReset(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
invalidTemp := 0.7 // GPT-5 doesn't support this
|
invalidTemp := 0.7 // GPT-5 doesn't support this
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
},
|
},
|
||||||
Temperature: &invalidTemp, // Should be reset to 1.0
|
Temperature: &invalidTemp, // Should be reset to 1.0
|
||||||
}
|
}
|
||||||
|
|
@ -73,11 +73,10 @@ func TestTemperatureDeepSeekR1AutoReset(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
invalidTemp := 0.5 // DeepSeek R1 doesn't support this
|
invalidTemp := 0.5 // DeepSeek R1 doesn't support this
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
},
|
},
|
||||||
Temperature: &invalidTemp, // Should be reset to 1.0
|
Temperature: &invalidTemp, // Should be reset to 1.0
|
||||||
}
|
}
|
||||||
|
|
@ -126,13 +125,11 @@ func TestTemperatureGPT4oPreserved(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
customTemp := 0.3 // GPT-4o should preserve this
|
customTemp := 0.3 // GPT-4o should preserve this
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &falseVal, // Not a reasoning model
|
Reasoning: false, // Not a reasoning model
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
Temperature: &customTemp, // Should be preserved
|
Temperature: &customTemp, // Should be preserved
|
||||||
}
|
}
|
||||||
|
|
@ -178,13 +175,11 @@ func TestTemperatureDeepSeekV3Preserved(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
customTemp := 0.8 // DeepSeek V3 should preserve this
|
customTemp := 0.8 // DeepSeek V3 should preserve this
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &falseVal, // Not a reasoning model
|
Reasoning: false, // Not a reasoning model
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
Temperature: &customTemp, // Should be preserved
|
Temperature: &customTemp, // Should be preserved
|
||||||
}
|
}
|
||||||
|
|
@ -230,11 +225,10 @@ func TestTemperatureGPT5Default(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
defaultTemp := 1.0 // GPT-5's valid temperature
|
defaultTemp := 1.0 // GPT-5's valid temperature
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &trueVal,
|
Reasoning: true,
|
||||||
},
|
},
|
||||||
Temperature: &defaultTemp, // Should work fine
|
Temperature: &defaultTemp, // Should work fine
|
||||||
}
|
}
|
||||||
|
|
@ -293,16 +287,14 @@ func TestTemperatureNoTemperatureProvided(t *testing.T) {
|
||||||
t.Fatalf("Failed to select connector: %v", err)
|
t.Fatalf("Failed to select connector: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
trueVal := true
|
|
||||||
falseVal := false
|
|
||||||
options := &context.CompletionOptions{
|
options := &context.CompletionOptions{
|
||||||
Capabilities: &context.ModelCapabilities{
|
Capabilities: &openai.Capabilities{
|
||||||
Reasoning: &falseVal,
|
Reasoning: false,
|
||||||
ToolCalls: &trueVal,
|
ToolCalls: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if tc.reasoning {
|
if tc.reasoning {
|
||||||
options.Capabilities.Reasoning = &trueVal
|
options.Capabilities.Reasoning = true
|
||||||
}
|
}
|
||||||
// Temperature not set - should use API default
|
// Temperature not set - should use API default
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/yaoapp/gou/application"
|
"github.com/yaoapp/gou/application"
|
||||||
"github.com/yaoapp/gou/connector"
|
"github.com/yaoapp/gou/connector"
|
||||||
|
gouOpenAI "github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/yao/agent/assistant"
|
"github.com/yaoapp/yao/agent/assistant"
|
||||||
"github.com/yaoapp/yao/agent/context"
|
"github.com/yaoapp/yao/agent/context"
|
||||||
"github.com/yaoapp/yao/agent/i18n"
|
"github.com/yaoapp/yao/agent/i18n"
|
||||||
|
|
@ -116,7 +117,7 @@ func initModelCapabilities() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var models map[string]assistant.ModelCapabilities = map[string]assistant.ModelCapabilities{}
|
var models map[string]gouOpenAI.Capabilities = map[string]gouOpenAI.Capabilities{}
|
||||||
err = application.Parse("models.yml", bytes, &models)
|
err = application.Parse("models.yml", bytes, &models)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type AdapterConfig struct {
|
||||||
Locale string
|
Locale string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModelCapabilities is a simplified version of context.ModelCapabilities
|
// ModelCapabilities is a simplified version of openai.Capabilities
|
||||||
// We use a local type to avoid circular dependencies
|
// We use a local type to avoid circular dependencies
|
||||||
type ModelCapabilities struct {
|
type ModelCapabilities struct {
|
||||||
Reasoning *bool // Supports reasoning/thinking mode (o1, DeepSeek R1)
|
Reasoning *bool // Supports reasoning/thinking mode (o1, DeepSeek R1)
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,10 @@ type Writer struct {
|
||||||
func NewWriter(options message.Options) (*Writer, error) {
|
func NewWriter(options message.Options) (*Writer, error) {
|
||||||
// Get model capabilities from context (set by assistant)
|
// Get model capabilities from context (set by assistant)
|
||||||
var capabilities *ModelCapabilities
|
var capabilities *ModelCapabilities
|
||||||
if options.Capabilities != nil && options.Capabilities.Reasoning != nil {
|
if options.Capabilities != nil && options.Capabilities.Reasoning {
|
||||||
|
v := true
|
||||||
capabilities = &ModelCapabilities{
|
capabilities = &ModelCapabilities{
|
||||||
Reasoning: options.Capabilities.Reasoning,
|
Reasoning: &v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package message
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
traceTypes "github.com/yaoapp/yao/trace/types"
|
traceTypes "github.com/yaoapp/yao/trace/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -12,23 +13,10 @@ type Options struct {
|
||||||
Accept string
|
Accept string
|
||||||
Writer http.ResponseWriter
|
Writer http.ResponseWriter
|
||||||
Trace traceTypes.Manager
|
Trace traceTypes.Manager
|
||||||
Capabilities *ModelCapabilities
|
Capabilities *openai.Capabilities
|
||||||
Locale string
|
Locale string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModelCapabilities defines the capabilities of a language model
|
|
||||||
// Used by LLM to select appropriate provider and validate requests
|
|
||||||
type ModelCapabilities struct {
|
|
||||||
Vision interface{} `json:"vision,omitempty"` // Supports vision/image input: bool or VisionFormat string ("openai", "claude"/"base64", "default")
|
|
||||||
ToolCalls *bool `json:"tool_calls,omitempty"` // Supports tool/function calling
|
|
||||||
Audio *bool `json:"audio,omitempty"` // Supports audio input/output
|
|
||||||
Reasoning *bool `json:"reasoning,omitempty"` // Supports reasoning/thinking mode (o1, DeepSeek R1)
|
|
||||||
Streaming *bool `json:"streaming,omitempty"` // Supports streaming responses
|
|
||||||
JSON *bool `json:"json,omitempty"` // Supports JSON mode
|
|
||||||
Multimodal *bool `json:"multimodal,omitempty"` // Supports multimodal input (text + images + audio)
|
|
||||||
TemperatureAdjustable *bool `json:"temperature_adjustable,omitempty"` // Supports temperature adjustment (reasoning models typically don't)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message represents a universal message structure (DSL)
|
// Message represents a universal message structure (DSL)
|
||||||
// All messages are expressed through Type + Props, without predefining specific types
|
// All messages are expressed through Type + Props, without predefining specific types
|
||||||
type Message struct {
|
type Message struct {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/yaoapp/gou/connector/openai"
|
||||||
"github.com/yaoapp/yao/agent/assistant"
|
"github.com/yaoapp/yao/agent/assistant"
|
||||||
store "github.com/yaoapp/yao/agent/store/types"
|
store "github.com/yaoapp/yao/agent/store/types"
|
||||||
)
|
)
|
||||||
|
|
@ -16,7 +17,7 @@ type DSL struct {
|
||||||
|
|
||||||
// Global External Settings - model capabilities, tools, etc.
|
// Global External Settings - model capabilities, tools, etc.
|
||||||
// ===============================
|
// ===============================
|
||||||
Models map[string]assistant.ModelCapabilities `json:"models,omitempty" yaml:"models,omitempty"` // The model capabilities configuration
|
Models map[string]openai.Capabilities `json:"models,omitempty" yaml:"models,omitempty"` // The model capabilities configuration
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
// ===============================
|
// ===============================
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue