-
Notifications
You must be signed in to change notification settings - Fork 792
Expand file tree
/
Copy pathapp_config.py
More file actions
188 lines (152 loc) · 6.57 KB
/
Copy pathapp_config.py
File metadata and controls
188 lines (152 loc) · 6.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# app_config.py
import logging
import os
from typing import Optional
from azure.ai.projects.aio import AIProjectClient
from azure.cosmos.aio import CosmosClient
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv
from semantic_kernel.kernel import Kernel
# Load environment variables from .env file
load_dotenv()
class AppConfig:
"""Application configuration class that loads settings from environment variables."""
def __init__(self):
"""Initialize the application configuration with environment variables."""
# Azure authentication settings
self.AZURE_TENANT_ID = self._get_optional("AZURE_TENANT_ID")
self.AZURE_CLIENT_ID = self._get_optional("AZURE_CLIENT_ID")
self.AZURE_CLIENT_SECRET = self._get_optional("AZURE_CLIENT_SECRET")
# CosmosDB settings
self.COSMOSDB_ENDPOINT = self._get_optional("COSMOSDB_ENDPOINT")
self.COSMOSDB_DATABASE = self._get_optional("COSMOSDB_DATABASE")
self.COSMOSDB_CONTAINER = self._get_optional("COSMOSDB_CONTAINER")
# Azure OpenAI settings
self.AZURE_OPENAI_DEPLOYMENT_NAME = self._get_required(
"AZURE_OPENAI_DEPLOYMENT_NAME", "gpt-4o"
)
self.AZURE_OPENAI_API_VERSION = self._get_required(
"AZURE_OPENAI_API_VERSION", "2024-11-20"
)
self.AZURE_OPENAI_ENDPOINT = self._get_required("AZURE_OPENAI_ENDPOINT")
self.AZURE_OPENAI_SCOPES = [
f"{self._get_optional('AZURE_OPENAI_SCOPE', 'https://cognitiveservices.azure.com/.default')}"
]
# Frontend settings
self.FRONTEND_SITE_NAME = self._get_optional(
"FRONTEND_SITE_NAME", "http://127.0.0.1:3000"
)
# Azure AI settings
self.AZURE_AI_SUBSCRIPTION_ID = self._get_required("AZURE_AI_SUBSCRIPTION_ID")
self.AZURE_AI_RESOURCE_GROUP = self._get_required("AZURE_AI_RESOURCE_GROUP")
self.AZURE_AI_PROJECT_NAME = self._get_required("AZURE_AI_PROJECT_NAME")
self.AZURE_AI_AGENT_ENDPOINT = self._get_required("AZURE_AI_AGENT_ENDPOINT")
# Cached clients and resources
self._azure_credentials = None
self._cosmos_client = None
self._cosmos_database = None
self._ai_project_client = None
def _get_required(self, name: str, default: Optional[str] = None) -> str:
"""Get a required configuration value from environment variables.
Args:
name: The name of the environment variable
default: Optional default value if not found
Returns:
The value of the environment variable or default if provided
Raises:
ValueError: If the environment variable is not found and no default is provided
"""
if name in os.environ:
return os.environ[name]
if default is not None:
logging.warning(
"Environment variable %s not found, using default value", name
)
return default
raise ValueError(
f"Environment variable {name} not found and no default provided"
)
def _get_optional(self, name: str, default: str = "") -> str:
"""Get an optional configuration value from environment variables.
Args:
name: The name of the environment variable
default: Default value if not found (default: "")
Returns:
The value of the environment variable or the default value
"""
if name in os.environ:
return os.environ[name]
return default
def _get_bool(self, name: str) -> bool:
"""Get a boolean configuration value from environment variables.
Args:
name: The name of the environment variable
Returns:
True if the environment variable exists and is set to 'true' or '1', False otherwise
"""
return name in os.environ and os.environ[name].lower() in ["true", "1"]
def get_azure_credentials(self):
"""Get Azure credentials using DefaultAzureCredential.
Returns:
DefaultAzureCredential instance for Azure authentication
"""
# Cache the credentials object
if self._azure_credentials is not None:
return self._azure_credentials
try:
self._azure_credentials = DefaultAzureCredential()
return self._azure_credentials
except Exception as exc:
logging.warning("Failed to create DefaultAzureCredential: %s", exc)
return None
def get_cosmos_database_client(self):
"""Get a Cosmos DB client for the configured database.
Returns:
A Cosmos DB database client
"""
try:
if self._cosmos_client is None:
self._cosmos_client = CosmosClient(
self.COSMOSDB_ENDPOINT, credential=self.get_azure_credentials()
)
if self._cosmos_database is None:
self._cosmos_database = self._cosmos_client.get_database_client(
self.COSMOSDB_DATABASE
)
return self._cosmos_database
except Exception as exc:
logging.error(
"Failed to create CosmosDB client: %s. CosmosDB is required for this application.",
exc,
)
raise
def create_kernel(self):
"""Creates a new Semantic Kernel instance.
Returns:
A new Semantic Kernel instance
"""
# Create a new kernel instance without manually configuring OpenAI services
# The agents will be created using Azure AI Agent Project pattern instead
kernel = Kernel()
return kernel
def get_ai_project_client(self):
"""Create and return an AIProjectClient for Azure AI Foundry using from_connection_string.
Returns:
An AIProjectClient instance
"""
if self._ai_project_client is not None:
return self._ai_project_client
try:
credential = self.get_azure_credentials()
if credential is None:
raise RuntimeError(
"Unable to acquire Azure credentials; ensure DefaultAzureCredential is configured"
)
endpoint = self.AZURE_AI_AGENT_ENDPOINT
self._ai_project_client = AIProjectClient(endpoint=endpoint, credential=credential)
return self._ai_project_client
except Exception as exc:
logging.error("Failed to create AIProjectClient: %s", exc)
raise
# Create a global instance of AppConfig
config = AppConfig()