Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ AGENT_DEBUG_MODE=false
# Note: OpenRouter does not currently support embedding or reranker models.
OPENROUTER_API_KEY=

# Get your API key from: https://ai.azure.com/ TODO: will support in next PR.
# Get your API key from: https://ai.azure.com/
AZURE_OPENAI_API_KEY=
AZURE_OPENAI_ENDPOINT=
AZURE_OPENAI_API_VERSION="2024-10-21"

# Get your API key from: https://aistudio.google.com/
GOOGLE_API_KEY=
Expand Down
5 changes: 5 additions & 0 deletions python/configs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ models:
openai-compatible:
config_file: "providers/openai-compatible.yaml"
api_key_env: "OPENAI_COMPATIBLE_API_KEY"

azure:
config_file: "providers/azure.yaml"
api_key_env: "AZURE_OPENAI_API_KEY"
endpoint_env: "AZURE_OPENAI_ENDPOINT"

# Agent Configuration
agents:
Expand Down
91 changes: 91 additions & 0 deletions python/configs/providers/azure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# ============================================
# Azure OpenAI Provider Configuration
# ============================================
name: "Azure OpenAI"
provider_type: "azure"

enabled: true # Default is true if not specified

# Connection Configuration
# Azure OpenAI requires:
# - AZURE_OPENAI_API_KEY: API key from Azure Portal
# - AZURE_OPENAI_ENDPOINT: Endpoint URL (e.g., https://{resource-name}.openai.azure.com/)
connection:
api_key_env: "AZURE_OPENAI_API_KEY"
endpoint_env: "AZURE_OPENAI_ENDPOINT"
base_url: "AZURE_OPENAI_ENDPOINT"

# API Version Configuration
# Azure OpenAI uses versioned APIs
# Supported api_version: 2024-10-21 (recommended), 2024-08-01, 2024-06-01, etc.
api_version: "2024-10-21"

# Default model (deployment name in Azure)
# Note: Deployment names in Azure are NOT necessarily the same as model IDs
# Update to match your Azure deployment names
default_model: "gpt-5-2025-08-07"

# Model Parameters Defaults
defaults:
temperature: 0.7

# Available Models
# These are mapped from Azure deployment names to OpenAI model equivalents
# In Azure, you create "deployments" with specific names - update these to match your Azure deployments
models:
- id: "gpt-5-2025-08-07"
name: "GPT-5 2025-08-07"
deployment_name: "gpt-5-2025-08-07" # Azure deployment name (can differ from id)
context_length: 400000
max_output_tokens: 128000
description: "Most capable GPT-5 model with 400K context window"
supported_inputs: ["text"]
supported_outputs: ["text"]

- id: "gpt-5-mini-2025-08-07"
name: "GPT-5 Mini 2025-08-07"
deployment_name: "gpt-5-mini-2025-08-07"
context_length: 400000
max_output_tokens: 128000
description: "Lightweight GPT-5 model optimized for efficiency"
supported_inputs: ["text"]
supported_outputs: ["text"]



# ============================================
# Embedding Models Configuration
# ============================================
embedding:
# Default embedding model
default_model: "text-embedding-3-small"

# Default parameters
defaults:
encoding_format: "float"

# Available embedding models
models:
- id: "text-embedding-3-small"
name: "Text Embedding 3 Small"
deployment_name: "text-embedding-3-small"
dimensions: 1536
max_input: 8192
performance_mteb: 62.3
description: "Small embedding model with good performance and efficiency"

- id: "text-embedding-3-large"
name: "Text Embedding 3 Large"
deployment_name: "text-embedding-3-large"
dimensions: 3072
max_input: 8192
performance_mteb: 64.6
description: "Large embedding model with higher performance"

# ============================================
# Environment Variable Overrides
# ============================================
# Map environment variable names to config paths
env_overrides:
AZURE_OPENAI_API_VERSION: "api_version"
AZURE_OPENAI_DEFAULT_MODEL: "default_model"
109 changes: 100 additions & 9 deletions python/valuecell/adapters/models/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,35 +169,126 @@ def create_embedder(self, model_id: Optional[str] = None, **kwargs):


class AzureProvider(ModelProvider):
"""Azure OpenAI model provider"""
"""Azure OpenAI model provider

Azure OpenAI is a managed service providing OpenAI models deployed on Azure infrastructure.
It uses deployment names instead of model IDs, and requires both API key and endpoint.

Configuration:
- AZURE_OPENAI_API_KEY: API key from Azure Portal
- AZURE_OPENAI_ENDPOINT: Azure OpenAI endpoint URL
- api_version: API version for Azure OpenAI REST API (default: 2024-10-21)
"""

def create_model(self, model_id: Optional[str] = None, **kwargs):
"""Create Azure OpenAI model"""
"""Create Azure OpenAI model

Args:
model_id: Deployment name in Azure (uses default if None)
**kwargs: Additional model parameters

Returns:
AzureOpenAI model instance
"""
try:
# Try to import from agno first
from agno.models.azure import AzureOpenAI
except ImportError:
raise ImportError("No Azure OpenAI library found")
raise ImportError(
"agno package with Azure support not installed. "
"Install with: pip install agno[azure]"
)

model_id = model_id or self.config.default_model
# Use provided model_id or default
deployment_name = model_id or self.config.default_model

# Merge parameters: provider defaults < kwargs
params = {**self.config.parameters, **kwargs}

# Get API version from config (can be overridden by env var)
# The api_version field in azure.yaml is handled by env_overrides
api_version = self.config.extra_config.get("api_version", "2024-10-21")

logger.info(f"Creating Azure OpenAI model: {model_id}")
logger.info(
f"Creating Azure OpenAI model: deployment={deployment_name}, "
f"endpoint={self.config.base_url}, api_version={api_version}"
)

return AzureOpenAI(
deployment_name=model_id,
deployment_name=deployment_name,
api_key=self.config.api_key,
azure_endpoint=self.config.base_url,
api_version=api_version,
temperature=params.get("temperature"),
max_tokens=params.get("max_tokens"),
top_p=params.get("top_p"),
frequency_penalty=params.get("frequency_penalty"),
presence_penalty=params.get("presence_penalty"),
)

def create_embedder(self, model_id: Optional[str] = None, **kwargs):
"""Create embedder via Azure OpenAI (OpenAI-compatible)

Args:
model_id: Embedding deployment name in Azure (uses default if None)
**kwargs: Additional embedder parameters

Returns:
OpenAIEmbedder instance configured for Azure
"""
try:
from agno.knowledge.embedder.openai import OpenAIEmbedder
except ImportError:
raise ImportError("agno package not installed")

# Use provided model_id or default embedding model
deployment_name = model_id or self.config.default_embedding_model

if not deployment_name:
raise ValueError(
f"No embedding model specified for provider '{self.config.name}'. "
"Set 'embedding.default_model' in azure.yaml"
)

# Merge parameters: provider embedding defaults < kwargs
params = {**self.config.embedding_parameters, **kwargs}

logger.info(
f"Creating Azure OpenAI embedder: deployment={deployment_name}, "
f"endpoint={self.config.base_url}"
)

return OpenAIEmbedder(
id=deployment_name,
api_key=self.config.api_key,
base_url=self.config.base_url,
dimensions=int(params.get("dimensions", 1536))
if params.get("dimensions")
else None,
encoding_format=params.get("encoding_format", "float"),
)

def is_available(self) -> bool:
"""Azure needs both API key and endpoint"""
return bool(self.config.api_key and self.config.base_url)
"""Azure needs both API key and endpoint to be available

Returns:
True if both API key and endpoint are configured
"""
has_key = bool(self.config.api_key)
has_endpoint = bool(self.config.base_url)

if not has_key:
logger.warning(
"Azure OpenAI API key not configured. "
"Set AZURE_OPENAI_API_KEY environment variable."
)

if not has_endpoint:
logger.warning(
"Azure OpenAI endpoint not configured. "
"Set AZURE_OPENAI_ENDPOINT environment variable."
)

return has_key and has_endpoint


class SiliconFlowProvider(ModelProvider):
Expand Down
1 change: 1 addition & 0 deletions python/valuecell/config/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def primary_provider(self) -> str:
"google",
"openai",
"openai-compatible",
"azure",
]

for preferred in preferred_order:
Expand Down