Skip to content

Commit

Permalink
azdev final
Browse files Browse the repository at this point in the history
Azdevify chat-with-your-data-solution-accelerator.
  • Loading branch information
jongio authored Feb 6, 2024
2 parents 3fbbe72 + 779065f commit cf07644
Show file tree
Hide file tree
Showing 129 changed files with 4,338 additions and 463 deletions.
5 changes: 4 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ ORCHESTRATION_STRATEGY=openai_functions
#Speech-to-text feature
AZURE_SPEECH_SERVICE_KEY=
AZURE_SPEECH_SERVICE_REGION=
AZURE_AUTH_TYPE=rbac
# Auth type related param. When your AZURE_AUTH_TYPE = rbac, please make sure setting USE_KEY_VAULT= false; When your USE_KEY_VAULT= true, please setting your key vault endpoint.
AZURE_AUTH_TYPE=keys
USE_KEY_VAULT=true
AZURE_KEY_VAULT_ENDPOINT=
6 changes: 3 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"run",
"Admin.py"
],
"cwd": "${workspaceFolder}/code/admin",
"cwd": "${workspaceFolder}/code/backend",
"preLaunchTask": "pip install (code)",
},
{
Expand All @@ -31,14 +31,14 @@
"--debug",
"run"
],
"cwd": "${workspaceFolder}/code/app",
"cwd": "${workspaceFolder}/code",
"preLaunchTask": "pip install (code)"
},
{
"name": "Launch Frontend (UI)",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/code/app/frontend",
"cwd": "${workspaceFolder}/code/frontend",
"preLaunchTask": "npm install (code)",
"runtimeExecutable": "npm",
"runtimeArgs": [
Expand Down
6 changes: 3 additions & 3 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"isBackground": true,
"dependsOn": "pip install (functions)",
"options": {
"cwd": "${workspaceFolder}/backend"
"cwd": "${workspaceFolder}/code/backend/batch"
}
},
{
Expand All @@ -26,7 +26,7 @@
},
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/backend"
"cwd": "${workspaceFolder}/code/backend"
}
},
{
Expand All @@ -44,7 +44,7 @@
"command": "npm install",
"problemMatcher": [],
"options": {
"cwd": "${workspaceFolder}/code/app/frontend"
"cwd": "${workspaceFolder}/code/frontend"
}
}
]
Expand Down
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,49 @@ az deployment group create --resource-group $RESOURCE_GROUP_NAME --template-file


![A screenshot of the chat app.](./media/web-unstructureddata.png)
### Running the sample using the Azure Developer CLI (azd)

The Azure Developer CLI (`azd`) is a developer-centric command-line interface (CLI) tool for creating Azure applications.

You need to install it before running and deploying with the Azure Developer CLI.

### Windows

```powershell
powershell -ex AllSigned -c "Invoke-RestMethod 'https://aka.ms/install-azd.ps1' | Invoke-Expression"
```

### Linux/MacOS

```
curl -fsSL https://aka.ms/install-azd.sh | bash
```

After logging in with the following command, you will be able to use the `azd` cli to quickly provision and deploy the application.

```
azd auth login
```

Then, execute the `azd init` command to initialize the environment (You do not need to run this command if you already have the code or have opened this in a Codespace or DevContainer).
```
azd init -t chat-with-your-data-solution-accelerator
```
Enter an environment name.

**Notes:** the default auth type uses keys, if you want to switch to rbac, please run `azd env set AUTH_TYPE rbac`.
```
azd env set AUTH_TYPE rbac
```

Then, run `azd up` to provision all the resources to Azure and deploy the code to those resources.
```
azd up
```

Select your desired `subscription` and `location`. Then choose a resource group or create a new resource group. Wait a moment for the resource deployment to complete, click the Website endpoint and you will see the web app page.

You can also run the sample directly locally (See below).

### [Local deployment instructions](./docs/LOCAL_DEPLOYMENT.md)
To customize the accelerator or run it locally, first, copy the .env.sample file to your development environment's .env file, and edit it according to environment variable values table. Learn more about deploying locally [here](./docs/LOCAL_DEPLOYMENT.md).
Expand Down
28 changes: 28 additions & 0 deletions azure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json

name: chat-with-your-data-solution-accelerator
metadata:
template: [email protected]

services:
web:
project: ./code
language: py
host: appservice
hooks:
prepackage:
windows:
shell: pwsh
run: cd ./frontend;npm install;npm run build;
interactive: true
continueOnError: false

adminweb:
project: ./code/backend
language: py
host: appservice

function:
project: ./code/backend/batch
language: py
host: function
90 changes: 45 additions & 45 deletions code/app/app.py → code/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
import os
import logging
import requests
import openai
from openai import AzureOpenAI

# Fixing MIME types for static files under Windows
import mimetypes
from flask import Flask, Response, request, jsonify
from dotenv import load_dotenv
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from azure.keyvault.secrets import SecretClient
import sys

# Fixing MIME types for static files under Windows
Expand All @@ -26,29 +30,39 @@
def static_file(path):
return app.send_static_file(path)


@app.route("/api/config", methods=["GET"])
AZURE_AUTH_TYPE = os.environ.get("AZURE_AUTH_TYPE", "keys")
# Initialize Azure keys based on authentication type and environment settings.
# When AZURE_AUTH_TYPE is not 'rbac' and USE_KEY_VAULT environment variable is set,
# Azure keys are securely fetched from Azure Key Vault using DefaultAzureCredential.
# Otherwise, keys are obtained from environment variables, with fallbacks to None or
# an empty string depending on the AZURE_AUTH_TYPE.
if not AZURE_AUTH_TYPE == 'rbac' and os.environ.get("USE_KEY_VAULT"):
credential = DefaultAzureCredential()
secret_client = SecretClient(os.environ.get("AZURE_KEY_VAULT_ENDPOINT"), credential)
AZURE_SEARCH_KEY = secret_client.get_secret(os.environ.get("AZURE_SEARCH_KEY")).value
AZURE_OPENAI_KEY = secret_client.get_secret(os.environ.get("AZURE_OPENAI_KEY")).value
AZURE_SPEECH_KEY = secret_client.get_secret(os.environ.get("AZURE_SPEECH_SERVICE_KEY")).value
else:
AZURE_SEARCH_KEY = None if AZURE_AUTH_TYPE == 'rbac' else os.environ.get("AZURE_SEARCH_KEY")
AZURE_OPENAI_KEY = "" if AZURE_AUTH_TYPE == 'rbac' else os.environ.get("AZURE_OPENAI_KEY")
AZURE_SPEECH_KEY = None if AZURE_AUTH_TYPE == 'rbac' else os.environ.get("AZURE_SPEECH_SERVICE_KEY")

@app.route('/api/config', methods=['GET'])
def get_config():
# Retrieve the environment variables or other configuration data
azure_speech_key = os.getenv("AZURE_SPEECH_SERVICE_KEY")
azure_speech_region = os.getenv("AZURE_SPEECH_SERVICE_REGION")
azure_speech_region = os.getenv('AZURE_SPEECH_SERVICE_REGION')

# Return the configuration data as JSON
return jsonify(
{"azureSpeechKey": azure_speech_key, "azureSpeechRegion": azure_speech_region}
)

return jsonify({
'azureSpeechKey': AZURE_SPEECH_KEY,
'azureSpeechRegion': azure_speech_region
})

# ACS Integration Settings
AZURE_SEARCH_SERVICE = os.environ.get("AZURE_SEARCH_SERVICE")
AZURE_SEARCH_INDEX = os.environ.get("AZURE_SEARCH_INDEX")
AZURE_SEARCH_KEY = os.environ.get("AZURE_SEARCH_KEY")
AZURE_SEARCH_USE_SEMANTIC_SEARCH = os.environ.get(
"AZURE_SEARCH_USE_SEMANTIC_SEARCH", "False"
)
AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG = os.environ.get(
"AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG", "default"
)
AZURE_SEARCH_USE_SEMANTIC_SEARCH = os.environ.get("AZURE_SEARCH_USE_SEMANTIC_SEARCH", "False")
AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG = os.environ.get("AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG", "default")
AZURE_SEARCH_TOP_K = os.environ.get("AZURE_SEARCH_TOP_K", 5)
AZURE_SEARCH_ENABLE_IN_DOMAIN = os.environ.get("AZURE_SEARCH_ENABLE_IN_DOMAIN", "true")
AZURE_SEARCH_CONTENT_COLUMNS = os.environ.get("AZURE_SEARCH_CONTENT_COLUMNS")
Expand All @@ -59,7 +73,6 @@ def get_config():
# AOAI Integration Settings
AZURE_OPENAI_RESOURCE = os.environ.get("AZURE_OPENAI_RESOURCE")
AZURE_OPENAI_MODEL = os.environ.get("AZURE_OPENAI_MODEL")
AZURE_OPENAI_KEY = os.environ.get("AZURE_OPENAI_KEY")
AZURE_OPENAI_TEMPERATURE = os.environ.get("AZURE_OPENAI_TEMPERATURE", 0)
AZURE_OPENAI_TOP_P = os.environ.get("AZURE_OPENAI_TOP_P", 1.0)
AZURE_OPENAI_MAX_TOKENS = os.environ.get("AZURE_OPENAI_MAX_TOKENS", 1000)
Expand All @@ -72,10 +85,8 @@ def get_config():
"AZURE_OPENAI_API_VERSION", "2023-06-01-preview"
)
AZURE_OPENAI_STREAM = os.environ.get("AZURE_OPENAI_STREAM", "true")
AZURE_OPENAI_MODEL_NAME = os.environ.get(
"AZURE_OPENAI_MODEL_NAME", "gpt-35-turbo"
) # Name of the model, e.g. 'gpt-35-turbo' or 'gpt-4'
AZURE_AUTH_TYPE = os.environ.get("AZURE_AUTH_TYPE", "keys")
AZURE_OPENAI_MODEL_NAME = os.environ.get("AZURE_OPENAI_MODEL_NAME", "gpt-35-turbo") # Name of the model, e.g. 'gpt-35-turbo' or 'gpt-4'
AZURE_TOKEN_PROVIDER = get_bearer_token_provider(DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default")

SHOULD_STREAM = True if AZURE_OPENAI_STREAM.lower() == "true" else False

Expand Down Expand Up @@ -241,20 +252,21 @@ def stream_without_data(response):


def conversation_without_data(request):
openai.api_type = "azure"
openai.api_base = f"https://{AZURE_OPENAI_RESOURCE}.openai.azure.com/"
openai.api_version = "2023-03-15-preview"
openai.api_key = AZURE_OPENAI_KEY
azure_endpoint = f"https://{AZURE_OPENAI_RESOURCE}.openai.azure.com/"
if AZURE_AUTH_TYPE == 'rbac':
openai_client = AzureOpenAI(azure_endpoint=azure_endpoint, api_version=AZURE_OPENAI_API_VERSION, azure_ad_token_provider=AZURE_TOKEN_PROVIDER)
else:
openai_client = AzureOpenAI(azure_endpoint=azure_endpoint, api_version=AZURE_OPENAI_API_VERSION, api_key=AZURE_OPENAI_KEY)

request_messages = request.json["messages"]
messages = [{"role": "system", "content": AZURE_OPENAI_SYSTEM_MESSAGE}]

for message in request_messages:
messages.append({"role": message["role"], "content": message["content"]})

response = openai.ChatCompletion.create(
engine=AZURE_OPENAI_MODEL,
messages=messages,
response = openai_client.chat.completions.create(
model=AZURE_OPENAI_MODEL,
messages = messages,
temperature=float(AZURE_OPENAI_TEMPERATURE),
max_tokens=int(AZURE_OPENAI_MAX_TOKENS),
top_p=float(AZURE_OPENAI_TOP_P),
Expand Down Expand Up @@ -315,8 +327,7 @@ def conversation_azure_byod():

@app.route("/api/conversation/custom", methods=["GET", "POST"])
def conversation_custom():
from utilities.helpers.OrchestratorHelper import Orchestrator

from backend.batch.utilities.helpers.OrchestratorHelper import Orchestrator, OrchestrationSettings
message_orchestrator = Orchestrator()

try:
Expand All @@ -331,20 +342,9 @@ def conversation_custom():
chat_history = []
for i, k in enumerate(user_assistant_messages):
if i % 2 == 0:
chat_history.append(
(
user_assistant_messages[i]["content"],
user_assistant_messages[i + 1]["content"],
)
)
from utilities.helpers.ConfigHelper import ConfigHelper

messages = message_orchestrator.handle_message(
user_message=user_message,
chat_history=chat_history,
conversation_id=conversation_id,
orchestrator=ConfigHelper.get_active_config_or_default().orchestrator,
)
chat_history.append((user_assistant_messages[i]['content'],user_assistant_messages[i+1]['content']))
from backend.batch.utilities.helpers.ConfigHelper import ConfigHelper
messages = message_orchestrator.handle_message(user_message=user_message, chat_history=chat_history, conversation_id=conversation_id, orchestrator=ConfigHelper.get_active_config_or_default().orchestrator)

response_obj = {
"id": "response.id",
Expand All @@ -370,4 +370,4 @@ def conversation_custom():


if __name__ == "__main__":
app.run()
app.run()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit cf07644

Please sign in to comment.