Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
68fc507
Initial plan for issue
Copilot May 22, 2025
0c6960e
Create Python ChatApp example for AI configuration
Copilot May 22, 2025
caf9cd0
Convert Flask web app to console app
Copilot May 22, 2025
e19bc99
Update azure-appconfiguration-provider to version 2.1.0
Copilot May 22, 2025
5d8b373
Address review feedback for Python ChatApp example
Copilot May 22, 2025
6466ad8
Implement data binding for Python ChatApp configuration
Copilot May 23, 2025
d377f84
Implement data binding without Pydantic dependency for Python ChatApp
Copilot May 23, 2025
4cfe6d2
Update Python ChatApp README.md based on review feedback
Copilot May 23, 2025
f36d608
Read API version from App Configuration
Copilot May 23, 2025
da033f9
Update ChatApp:Model description to specify JSON object with AI chat …
Copilot May 23, 2025
bf6b106
Read API key from App Configuration with Key Vault reference support
Copilot May 23, 2025
97c5be0
Revert ChatApp:Model description to focus on AI configuration
Copilot May 23, 2025
e2fd91f
Address reviewers' feedback on Python ChatApp example
Copilot May 23, 2025
7325b6f
Add Key Vault credential for loading API key from Key Vault references
Copilot May 23, 2025
e3daa4d
Fix credential parameter name from key_vault_credential to keyvault_c…
Copilot May 23, 2025
c2c1e17
Fixing
mrm9084 May 23, 2025
907227e
Fixing auth
mrm9084 May 23, 2025
00136bd
Add user input chat functionality to Python ChatApp
Copilot May 23, 2025
433030d
Updated to use black formating
mrm9084 May 23, 2025
3a0f7fe
Fixing a few pylint issues
mrm9084 May 23, 2025
334fb2c
Update examples/Python/ChatApp/app.py
mrm9084 May 23, 2025
5064f99
Updated to match dotnet
mrm9084 Jul 3, 2025
2afb137
review items
mrm9084 Jul 7, 2025
20e9d6d
review changes
mrm9084 Jul 7, 2025
b8e8a55
review comments
mrm9084 Jul 7, 2025
18fbda0
Update app.py
mrm9084 Jul 7, 2025
320a372
rework to remove global need
mrm9084 Jul 7, 2025
5fa4fff
code cleanup
mrm9084 Jul 7, 2025
0b34fc7
fixed formatting
mrm9084 Jul 7, 2025
e573db5
moved deployment type to AzureOpenAI
mrm9084 Jul 7, 2025
3ef2148
Update models.py
mrm9084 Jul 7, 2025
6cf8451
formatting
mrm9084 Jul 8, 2025
295c876
review changes
mrm9084 Jul 11, 2025
24aecfb
refresh update
mrm9084 Jul 11, 2025
d3cf9c5
review comments
mrm9084 Aug 15, 2025
c21857c
review comments
mrm9084 Aug 15, 2025
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
82 changes: 82 additions & 0 deletions examples/Python/ChatApp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Azure App Configuration - Python ChatApp Sample

This sample demonstrates using Azure App Configuration to configure Azure OpenAI settings for a chat application built with Python.

## Features

- Integrates with Azure OpenAI for chat completions
- Dynamically refreshes configuration from Azure App Configuration

## Prerequisites

- Python 3.8 or later
- An Azure subscription with access to:
- Azure App Configuration service
- Azure OpenAI service
- Required environment variables:
- `AZURE_APPCONFIG_ENDPOINT`: URL of your Azure App Configuration instance
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
- `AZURE_OPENAI_API_KEY`: API key for Azure OpenAI (optional if stored in Azure App Configuration)

## Setup

1. Clone the repository
2. Install the required packages:
```bash
pip install -r requirements.txt
```
3. Configure your Azure App Configuration store with these settings:
```
ChatApp:AzureOpenAI:Endpoint - Your Azure OpenAI endpoint URL
ChatApp:AzureOpenAI:DeploymentName - Your Azure OpenAI deployment name
ChatApp:AzureOpenAI:ApiVersion - API version for Azure OpenAI (e.g., "2023-05-15")
ChatApp:AzureOpenAI:ApiKey - Your Azure OpenAI API key (preferably as a Key Vault reference)
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
ChatApp:Model - An AI configuration entry containing the following settings:
Comment thread
zhenlan marked this conversation as resolved.
- model - Model name (e.g., "gpt-35-turbo")
- max_tokens - Maximum tokens for completion (e.g., 1000)
- temperature - Temperature parameter (e.g., 0.7)
- top_p - Top p parameter (e.g., 0.95)
- messages - An array of messages with role and content for each message

Example JSON object for ChatApp:Model:
```json
{
"model": "gpt-35-turbo",
"max_tokens": 1000,
"temperature": 0.7,
"top_p": 0.95,
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Tell me about Azure App Configuration."
}
]
}
```
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
```
Comment thread
mrm9084 marked this conversation as resolved.
Outdated

4. Set the required environment variables:
```bash
export AZURE_APPCONFIG_ENDPOINT="https://your-appconfig.azconfig.io"
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
export AZURE_OPENAI_API_KEY="your-openai-api-key" # Optional if stored in Azure App Configuration
```

## Running the Application

Start the console application:
```bash
python app.py
```

The application will:
1. Display the initial configured messages from Azure App Configuration
2. Generate a response from the AI
3. Prompt you to enter your message (type 'exit' to quit)
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
4. Maintain conversation history during the session

## Configuration Refresh

The application refreshes the configuration at the beginning of each conversation cycle, so any changes made to the base configuration in Azure App Configuration will be incorporated into the model parameters (temperature, max_tokens, etc.) while maintaining your ongoing conversation history.
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
141 changes: 141 additions & 0 deletions examples/Python/ChatApp/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
"""
Azure App Configuration Chat Application using Azure OpenAI.
This module provides a simple chat application that uses configurations from Azure App Configuration
and connects to Azure OpenAI services for chat completions.
"""
import os
from typing import TypeVar, List
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from azure.appconfiguration.provider import load, SettingSelector
from openai import AzureOpenAI
from models import ModelConfiguration, Message

# Get Azure App Configuration endpoint from environment variable
ENDPOINT = os.environ.get("AZURE_APPCONFIG_ENDPOINT")
if not ENDPOINT:
raise ValueError(
"The environment variable 'AZURE_APPCONFIG_ENDPOINT' is not set or is empty."
)

# Initialize Azure credentials
credential = DefaultAzureCredential()

# Create selector for ChatApp configuration
chat_app_selector = SettingSelector(key_filter="ChatApp:*")

# Load configuration from Azure App Configuration
config = load(
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
endpoint=ENDPOINT,
selects=[chat_app_selector],
credential=credential,
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
keyvault_credential=credential, # Use the same credential for Key Vault references
trim_prefixes=["ChatApp:"],
)

T = TypeVar("T")


Comment thread
mrm9084 marked this conversation as resolved.
Outdated
# Get OpenAI configuration
def get_openai_client():
"""Create and return an Azure OpenAI client"""
endpoint = config.get("AzureOpenAI:Endpoint")
# Get API key from App Configuration or fall back to environment variable
api_key = config.get("AzureOpenAI:ApiKey", os.environ.get("AZURE_OPENAI_API_KEY"))
api_version = config.get(
"AzureOpenAI:ApiVersion", "2023-05-15"
) # Read API version from config or use default

# For DefaultAzureCredential auth if no API key is available
if not api_key:
token_provider = get_bearer_token_provider(
DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"
)
return AzureOpenAI(
azure_endpoint=endpoint,
api_version=api_version,
azure_ad_token_provider=token_provider,
)
Comment thread
mrm9084 marked this conversation as resolved.

# For API key auth
return AzureOpenAI(
azure_endpoint=endpoint, api_key=api_key, api_version=api_version
)


def get_chat_messages(messages: List[Message]):
"""Convert from model Message objects to OpenAI messages format"""
return [{"role": msg.role, "content": msg.content} for msg in messages]


def main():
"""Main entry point for the console app"""
# Get OpenAI client
client = get_openai_client()

# Get deployment name
deployment_name = config.get("AzureOpenAI:DeploymentName")

# Initialize conversation history with the configuration messages
conversation_history = []
first_run = True

print("Chat Application - type 'exit' to quit\n")

while True:
# Refresh configuration from Azure App Configuration
config.refresh()

# Get model configuration using data binding
model_config = ModelConfiguration.from_dict(config.get("Model"))

# On first run, initialize conversation history with configuration messages
# and display the initial messages
if first_run:
conversation_history = model_config.messages.copy()
for msg in conversation_history:
print(f"{msg.role}: {msg.content}")
first_run = False

# Get chat messages for the API
messages = get_chat_messages(conversation_history)

# Get response from OpenAI
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
max_tokens=model_config.max_tokens,
temperature=model_config.temperature,
top_p=model_config.top_p,
)

# Extract assistant message
assistant_message = response.choices[0].message.content

# Display the response
print(f"assistant: {assistant_message}")

# Add assistant response to conversation history
conversation_history.append(
Message(role="assistant", content=assistant_message)
)

# Get user input for the next message
print("\nuser: ", end="")
user_input = input().strip()

# Check if user wants to exit
if user_input.lower() == "exit":
print("Exiting application...")
break

# Add user input to conversation history
conversation_history.append(Message(role="user", content=user_input))


if __name__ == "__main__":
main()
63 changes: 63 additions & 0 deletions examples/Python/ChatApp/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
"""
Model classes for Azure OpenAI Chat Application.
This module provides data classes for representing chat messages and model configurations
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
used in the Azure OpenAI-powered chat application.
"""
from typing import List, Optional, Dict, Any


Comment thread
mrm9084 marked this conversation as resolved.
class Message:
"""
Represents a chat message with a role and content.
Maps to configuration values with keys 'role' and 'content'.
"""

def __init__(self, role: Optional[str] = None, content: Optional[str] = None):
"""Initialize a Message instance with role and content."""
self.role = role
self.content = content

@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Message":
"""Create a Message instance from a dictionary."""
return cls(role=data.get("role"), content=data.get("content"))


class ModelConfiguration:
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
"""
Represents the configuration for an AI model including messages and parameters.
Comment thread
mrm9084 marked this conversation as resolved.
Maps to configuration values with keys 'model', 'messages', 'max_tokens', 'temperature', and 'top_p'.
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
"""

def __init__(
self,
model: Optional[str] = None,
messages: Optional[List[Message]] = None,
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
max_tokens: int = 1024,
temperature: float = 0.7,
top_p: float = 0.95,
):
"""Initialize model configuration with parameters for OpenAI API calls."""
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
self.model = model
self.messages = messages or []
self.max_tokens = int(max_tokens) if max_tokens is not None else 1024
self.temperature = float(temperature) if temperature is not None else 0.7
self.top_p = float(top_p) if top_p is not None else 0.95

@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "ModelConfiguration":
Comment thread
mrm9084 marked this conversation as resolved.
Outdated
"""Create a ModelConfiguration instance from a dictionary."""
messages = [Message.from_dict(msg) for msg in data.get("messages", [])]

return cls(
model=data.get("model"),
messages=messages,
max_tokens=data.get("max_tokens", 1024),
temperature=data.get("temperature", 0.7),
top_p=data.get("top_p", 0.95),
)
3 changes: 3 additions & 0 deletions examples/Python/ChatApp/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
azure-identity
azure-appconfiguration-provider
openai
Comment thread
mrm9084 marked this conversation as resolved.
Outdated