├── .env.template ├── .github └── workflows │ ├── docker-build.yaml │ └── terraform-validate.yaml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── app ├── assets │ ├── app-info.md │ ├── diagram-small.png │ └── diagram.png ├── requirements.txt └── streamlit_app.py ├── docs └── 2022-chevrolet-colorado-ebrochure.pdf ├── main.tf ├── terraform.tfvars └── variables.tf /.env.template: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY= 2 | OPENAI_API_BASE=https://anton-tf-openai.openai.azure.com/ 3 | OPENAI_COMPLETIONS_ENGINE=text-davinci-003 4 | OPENAI_EMBEDDINGS_ENGINE=text-embedding-ada-002 5 | OPENAI_API_TYPE=azure 6 | OPENAI_API_VERSION=2022-12-01 7 | REDIS_HOST=.eastus.redisenterprise.cache.azure.net 8 | REDIS_PORT=10000 9 | REDIS_PASSWORD= 10 | STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=;AccountKey=;EndpointSuffix=core.windows.net 11 | CONTAINER_NAME=data 12 | TOKENIZERS_PARALLELISM=false 13 | -------------------------------------------------------------------------------- /.github/workflows/docker-build.yaml: -------------------------------------------------------------------------------- 1 | name: Docker build 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Build Docker image 14 | run: docker build -t samplapp . -------------------------------------------------------------------------------- /.github/workflows/terraform-validate.yaml: -------------------------------------------------------------------------------- 1 | name: Terraform validate 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | 7 | jobs: 8 | tf_code_check: 9 | name: Terraform Validation 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Setup Terraform CLI 15 | uses: hashicorp/setup-terraform@v2 16 | 17 | - name: Terraform init and validate 18 | run: | 19 | echo `pwd` 20 | echo "** Running Terraform Init**" 21 | terraform init 22 | 23 | echo "** Running Terraform Validate**" 24 | terraform validate 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .terraform 3 | terraform.tfstate* 4 | .terraform.lock.hcl 5 | .DS_Store 6 | .terraform.tfstate.lock.info 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9.10-slim-buster 2 | 3 | #RUN apt-get update && apt-get install python-tk python3-tk tk-dev -y 4 | 5 | WORKDIR /app 6 | 7 | COPY ./app/requirements.txt . 8 | 9 | RUN pip install -r requirements.txt 10 | 11 | COPY ./app/ . 12 | 13 | EXPOSE 80 14 | 15 | CMD ["streamlit", "run", "streamlit_app.py", "--server.port", "80", "--server.enableXsrfProtection", "false"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Anton Umnikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Azure OpenAI Redis Deployment Template 2 | 3 | The terraform template automates the end-to-end deployment of Azure OpenAI applications using Redis Enterprise as a vector database. 4 | 5 | ![Azure OpenAI Redis](app/assets/diagram.png) 6 | 7 | In a single terraform script it deploys: 8 | 9 | - Azure OpenAI instance with `text-davinci-003` and `text-embedding-ada-002` models 10 | - Azure Redis Enterprise as a vector Database 11 | - Azure Storage bucket with all the files from the `./docs` folder 12 | - Azure Web App 13 | 14 | ## Example application 15 | 16 | An example application used in this repo allows you to use ChatGPT to analyze the documents, previously unknown to ChatGPT and/or internal to your organization. 17 | 18 | There are two data flows in the app. First - batch generation of embedding from the document context. These embeddings are stored in Azure Redis Enterprise. Second - using these embeddings to generate the context-aware prompt to ChatGPT, so it answers questions, based on the context of the internal documents. 19 | 20 | Questions you can try: 21 | 22 | - What are the main differences between the three engine types available for the Chevy Colorado? Format the response as a table with the model as a first column 23 | 24 | - What color options are available? Format as a list 25 | 26 | App credits - https://github.com/RedisVentures/LLM-Document-Chat 27 | 28 | 29 | ## Deploying the app 30 | 31 | Authenticate Azure CLI to your Azure account: 32 | 33 | ``` 34 | az login 35 | ``` 36 | Deploy terraform configuration: 37 | ``` 38 | terraform init 39 | terraform apply 40 | ``` 41 | 42 | You can add your own documents to the `./docs` folder (PDF or plain text), so they can be uploaded to the bucket during the deployment. 43 | 44 | It might take up to 20 minutes to provision all the required infrastructure. 45 | 46 | At the end terraform script would output a bunch of the variables. 47 | ``` 48 | app-url = "redis-openai-83903-webapp.azurewebsites.net" 49 | openai-endpoint = "https://redis-openai-83903.openai.azure.com/" 50 | openai-key = 51 | redis-endpoint = "redis-openai-83903-redisenterprise.southcentralus.redisenterprise.cache.azure.net" 52 | redis-password = 53 | redis-port = 10000 54 | storage-account = "redisopenai83903bucket" 55 | storage-account-connection-string = 56 | storage-container = "data" 57 | ``` 58 | 59 | app-url can be used to immediately access the application. 60 | 61 | ## Configuration 62 | 63 | Use `terraform.tfvars` or `terraform apply -var="name_prefix=my-deployment"` to override the default resource name prefix and container image to deploy with the webapp. 64 | 65 | To change the application, deployed as an Azure Web App - change `app_docker_image` and `app_docker_tag` values in the `terraform.tfvars`. The source code for the default application is included in this repo under the `./app` folder. 66 | 67 | ## Pererequisites and Limitations 68 | 69 | Azure account, Azure CLI, Terraform CLI installed locally. 70 | 71 | Azure Open AI currently (May 2023) is in the private preview. You need to [submit the request](https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR7en2Ais5pxKtso_Pz4b1_xUOFA5Qk1UWDRBMjg0WFhPMkIzTzhKQ1dWNyQlQCN0PWcu) to Microsoft to enable it for your account. 72 | 73 | Azure OpenAI embedding API currently has strict limits on the request frequency, which might make it not feasible for a bulk embedding generation. Consider using local embedding such as: 74 | ``` 75 | from langchain.embeddings import HuggingFaceEmbeddings 76 | embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2") 77 | ``` 78 | 79 | ## Testing locally 80 | 81 | While Azure OpenAI and Azure Redis Enterprise can not be deployed locally, you can use your local machine for testing the application itself. 82 | 83 | After running the `terraform apply` you can use the generated Azure services to test your application code locally. Use .env.template as an example and populate it with actual keys and URLs. 84 | 85 | ``` 86 | docker build -t llm-chat . 87 | docker run -it -p 80:80 --env-file=.env llm-chat 88 | ``` 89 | 90 | Building/pushing the multiplatform image (useful for local development on Mac/ARM): 91 | 92 | ``` 93 | docker buildx build --platform linux/amd64,linux/arm64 -t antonum/llmchat:latest --push . 94 | ``` 95 | 96 | ## Troubleshooting 97 | 98 | - **Problem:** `azurerm_cognitive_account.openai` stuck in `creating` phase. 99 | 100 | At the time of writing (May 2023) Azure occasionally experiencing problems deploying OpenAI services. Try deploying the stack in another region. For instance set `azure_region = "southcentralus"` instead of `eastus`. 101 | 102 | - **Problem**: Deployment fails with an error: `SpecialFeatureOrQuotaIdRequired: The subscription does not have QuotaId/Feature required by SKU 'S0' from kind 'OpenAI'` 103 | 104 | Your Azure account does not have Azure OpenAI enabled. At the time of writing (May 2023) Azure OpenAI is in private preview. You need to [submit the request](https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR7en2Ais5pxKtso_Pz4b1_xUOFA5Qk1UWDRBMjg0WFhPMkIzTzhKQ1dWNyQlQCN0PWcu) to Microsoft to enable it for your subscription. 105 | 106 | ## Cleanup 107 | 108 | To destroy all the resources deployed run: 109 | ``` 110 | terraform destroy 111 | ``` 112 | -------------------------------------------------------------------------------- /app/assets/app-info.md: -------------------------------------------------------------------------------- 1 | # Redis Azure OpenAI Template 2 | 3 | ![Azure OpenAI Redis](https://github.com/redisventures/azure-openai-redis-deployment/blob/main/app/assets/diagram-small.png?raw=true) 4 | 5 | Example application allows you to use ChatGPT to analyze the documents, previoslyy unknown to ChatGPT and/or internal to your organization. 6 | 7 | There are two data flows in the app. First - batch generation of embedding from the document context. Resulted embedding are stored in Azure Redis Enterprise. Second - using these embeddings to generate the context aware prompt to ChatGPT, so it answers questions, based on the context of the internal documents. 8 | 9 | Questions you can try: 10 | 11 | - What are the main differences between the three engine types available for the Chevy Colorado? Format response as a table with model as a first column 12 | 13 | - What color options are available? Format as a list 14 | 15 | -------------------------------------------------------------------------------- /app/assets/diagram-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-applied-ai/azure-openai-redis-deployment/e188a18764f94fa4acd39b9520995933d1785152/app/assets/diagram-small.png -------------------------------------------------------------------------------- /app/assets/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-applied-ai/azure-openai-redis-deployment/e188a18764f94fa4acd39b9520995933d1785152/app/assets/diagram.png -------------------------------------------------------------------------------- /app/requirements.txt: -------------------------------------------------------------------------------- 1 | streamlit 2 | azure.storage.blob 3 | pypdf 4 | PyPDF2 5 | llama_index==0.8.26 6 | redis 7 | langchain==0.0.262 8 | openai -------------------------------------------------------------------------------- /app/streamlit_app.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import os 3 | from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient 4 | from PyPDF2 import PdfReader 5 | # Import 6 | #import textwrap 7 | import openai 8 | from langchain.llms import AzureOpenAI, OpenAI 9 | from langchain.embeddings import OpenAIEmbeddings 10 | from llama_index.vector_stores import RedisVectorStore 11 | from llama_index import LangchainEmbedding 12 | from llama_index import ( 13 | GPTVectorStoreIndex, 14 | SimpleDirectoryReader, 15 | LLMPredictor, 16 | PromptHelper, 17 | ServiceContext, 18 | StorageContext 19 | ) 20 | 21 | import sys 22 | 23 | import logging 24 | logging.basicConfig(stream=sys.stdout, level=logging.INFO) # logging.DEBUG for more verbose output 25 | logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout)) 26 | 27 | REDIS_HOST = os.getenv("REDIS_HOST", "localhost") 28 | REDIS_PORT = os.getenv("REDIS_PORT", "6379") 29 | REDIS_PASSWORD = os.getenv("REDIS_PASSWORD", "") 30 | 31 | OPENAI_API_TYPE = os.getenv("OPENAI_API_TYPE", "") 32 | OPENAI_COMPLETIONS_ENGINE = os.getenv("OPENAI_COMPLETIONS_ENGINE", "text-davinci-003") 33 | OPENAI_EMBEDDINGS_ENGINE = os.getenv("OPENAI_EMBEDDINGS_ENGINE", "text-embedding-ada-002") 34 | 35 | 36 | STORAGE_CONNECTION_STRING=os.getenv("STORAGE_CONNECTION_STRING", "") 37 | CONTAINER_NAME=os.getenv("CONTAINER_NAME", "data") 38 | 39 | def get_embeddings(): 40 | if OPENAI_API_TYPE=="azure": 41 | #currently Azure OpenAI embeddings require request for service limit increase to be useful 42 | #using build-in HuggingFace instead 43 | #from langchain.embeddings import HuggingFaceEmbeddings 44 | #embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2") 45 | 46 | from langchain.embeddings import OpenAIEmbeddings 47 | embeddings = OpenAIEmbeddings(deployment=OPENAI_EMBEDDINGS_ENGINE, chunk_size=1 ) 48 | else: 49 | from langchain.embeddings import OpenAIEmbeddings 50 | # Init OpenAI Embeddings 51 | embeddings = OpenAIEmbeddings() 52 | return embeddings 53 | 54 | def get_llm(): 55 | if OPENAI_API_TYPE=="azure": 56 | openai.api_type = "azure" 57 | openai.api_base = os.getenv("OPENAI_API_BASE") 58 | openai.api_version = os.getenv("OPENAI_API_VERSION") 59 | openai.api_key = os.getenv("OPENAI_API_KEY") 60 | text_model_deployment = OPENAI_COMPLETIONS_ENGINE 61 | from langchain.llms import AzureOpenAI 62 | llm = AzureOpenAI(deployment_name=text_model_deployment, model_kwargs={ 63 | "api_key": openai.api_key, 64 | "api_base": openai.api_base, 65 | "api_type": openai.api_type, 66 | "api_version": openai.api_version, 67 | }) 68 | #llm_predictor = LLMPredictor(llm=llm) 69 | else: 70 | from langchain.llms import OpenAI 71 | llm=OpenAI() 72 | return llm 73 | 74 | 75 | @st.cache_resource 76 | def get_query_engine(): 77 | 78 | blob_service_client = BlobServiceClient.from_connection_string(STORAGE_CONNECTION_STRING) 79 | container_client = blob_service_client.get_container_client(container=CONTAINER_NAME) 80 | download_file_path = "/tmp/docs" 81 | isExist = os.path.exists(download_file_path) 82 | if not isExist: 83 | os.makedirs(download_file_path) 84 | 85 | # List the blobs in the container 86 | blob_list = container_client.list_blobs() 87 | for blob in blob_list: 88 | print("\t" + blob.name) 89 | if not os.path.exists( download_file_path+ "/" + blob.name): 90 | print("\nDownloading blob to \n\t" + download_file_path+ "/" + blob.name) 91 | with open(file=download_file_path + "/" + blob.name, mode="wb") as download_file: 92 | download_file.write(container_client.download_blob(blob.name).readall()) 93 | else: 94 | print("\nSkipping \n\t" + download_file_path+ "/" + blob.name) 95 | 96 | # load documents 97 | documents = SimpleDirectoryReader(download_file_path).load_data() 98 | print('Document ID:', documents[0].doc_id) 99 | 100 | 101 | from llama_index.storage.storage_context import StorageContext 102 | 103 | vector_store = RedisVectorStore( 104 | index_name="chevy_docs", 105 | index_prefix="llama", 106 | redis_url="rediss://default:{}@{}:{}".format(REDIS_PASSWORD,REDIS_HOST,REDIS_PORT), 107 | overwrite=True 108 | ) 109 | 110 | llm_predictor = LLMPredictor(llm=get_llm()) 111 | llm_embedding = LangchainEmbedding(get_embeddings()) 112 | service_context = ServiceContext.from_defaults( 113 | llm_predictor=llm_predictor, 114 | embed_model=llm_embedding, 115 | ) 116 | storage_context = StorageContext.from_defaults( 117 | vector_store=vector_store 118 | ) 119 | index = GPTVectorStoreIndex.from_documents( 120 | documents, 121 | storage_context=storage_context, 122 | service_context=service_context 123 | ) 124 | 125 | 126 | return index.as_query_engine() 127 | 128 | file = open("assets/app-info.md", "r") 129 | st.markdown(file.read()) 130 | query_engine = get_query_engine() 131 | user_query = st.text_input("Query:", 'What types of variants are available for the Chevrolet Colorado?') 132 | try: 133 | response = query_engine.query(user_query) 134 | except Exception as e: 135 | response = "Error: %s" % str(e) 136 | st.markdown(str(response)) 137 | #print(str(response)) -------------------------------------------------------------------------------- /docs/2022-chevrolet-colorado-ebrochure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis-applied-ai/azure-openai-redis-deployment/e188a18764f94fa4acd39b9520995933d1785152/docs/2022-chevrolet-colorado-ebrochure.pdf -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | provider "azurerm" { 2 | features {} 3 | } 4 | 5 | # Generate a random integer to create a globally unique name 6 | resource "random_integer" "ri" { 7 | min = 10000 8 | max = 99999 9 | } 10 | 11 | resource "azurerm_resource_group" "rg" { 12 | name = "${var.name_prefix}-${random_integer.ri.result}-rg" 13 | location = var.azure_region 14 | } 15 | 16 | resource "azurerm_cognitive_account" "openai" { 17 | name = "${var.name_prefix}-${random_integer.ri.result}-openai" 18 | location = azurerm_resource_group.rg.location 19 | resource_group_name = azurerm_resource_group.rg.name 20 | kind = "OpenAI" 21 | sku_name = "S0" 22 | custom_subdomain_name = "${var.name_prefix}-${random_integer.ri.result}" 23 | timeouts { 24 | create = "60m" 25 | } 26 | } 27 | 28 | resource "azurerm_cognitive_deployment" "gen-model" { 29 | name = var.generative_model 30 | cognitive_account_id = azurerm_cognitive_account.openai.id 31 | model { 32 | format = "OpenAI" 33 | name = var.generative_model 34 | version = var.generative_model_version 35 | } 36 | scale { 37 | type = "Standard" 38 | } 39 | depends_on = [ azurerm_cognitive_account.openai] 40 | 41 | } 42 | resource "azurerm_cognitive_deployment" "embeddings_model" { 43 | name = var.embeddings_model 44 | cognitive_account_id = azurerm_cognitive_account.openai.id 45 | model { 46 | format = "OpenAI" 47 | name = var.embeddings_model 48 | version = var.embeddings_model_version 49 | 50 | } 51 | scale { 52 | type = "Standard" 53 | } 54 | depends_on = [ azurerm_cognitive_deployment.gen-model, azurerm_cognitive_account.openai] 55 | } 56 | 57 | resource "azurerm_redis_enterprise_cluster" "redisenterprise" { 58 | name = "${var.name_prefix}-${random_integer.ri.result}-redisenterprise" 59 | resource_group_name = azurerm_resource_group.rg.name 60 | location = azurerm_resource_group.rg.location 61 | #version = 6 62 | sku_name = "Enterprise_E10-2" 63 | } 64 | 65 | resource "azurerm_redis_enterprise_database" "redis-db" { 66 | name = "default" 67 | cluster_id = azurerm_redis_enterprise_cluster.redisenterprise.id 68 | clustering_policy = "EnterpriseCluster" 69 | eviction_policy = "NoEviction" 70 | #client_protocol = "Plaintext" 71 | 72 | module { 73 | name = "RediSearch" 74 | } 75 | } 76 | 77 | 78 | resource "azurerm_storage_account" "storage-acct" { 79 | name = "${replace(var.name_prefix, "-", "")}${random_integer.ri.result}bucket" 80 | resource_group_name = azurerm_resource_group.rg.name 81 | location = azurerm_resource_group.rg.location 82 | account_tier = "Standard" 83 | account_replication_type = "LRS" 84 | } 85 | 86 | resource "azurerm_storage_container" "storage-acct-container" { 87 | name = "data" 88 | storage_account_name = azurerm_storage_account.storage-acct.name 89 | container_access_type = "blob" 90 | } 91 | 92 | resource "azurerm_storage_blob" "tamopsblobs" { 93 | for_each = fileset(path.module, "docs/*") 94 | 95 | name = trim(each.key, "docs/") 96 | storage_account_name = azurerm_storage_account.storage-acct.name 97 | storage_container_name = azurerm_storage_container.storage-acct-container.name 98 | type = "Block" 99 | source = each.key 100 | } 101 | 102 | 103 | resource "azurerm_service_plan" "plan" { 104 | name = "${var.name_prefix}-${random_integer.ri.result}-serviceplan" 105 | location = azurerm_resource_group.rg.location 106 | resource_group_name = azurerm_resource_group.rg.name 107 | os_type = "Linux" 108 | sku_name = "P1v2" 109 | } 110 | 111 | resource "azurerm_linux_web_app" "app" { 112 | name = "${var.name_prefix}-${random_integer.ri.result}-webapp" 113 | location = azurerm_resource_group.rg.location 114 | resource_group_name = azurerm_resource_group.rg.name 115 | service_plan_id = azurerm_service_plan.plan.id 116 | https_only = true 117 | 118 | app_settings = { 119 | OPENAI_API_KEY = azurerm_cognitive_account.openai.primary_access_key 120 | OPENAI_API_BASE = azurerm_cognitive_account.openai.endpoint 121 | OPENAI_COMPLETIONS_ENGINE = var.generative_model 122 | OPENAI_EMBEDDINGS_ENGINE = var.embeddings_model 123 | OPENAI_API_TYPE = "azure" 124 | OPENAI_API_VERSION = "2023-05-15" 125 | REDIS_HOST = azurerm_redis_enterprise_cluster.redisenterprise.hostname 126 | REDIS_PORT = azurerm_redis_enterprise_database.redis-db.port 127 | REDIS_PASSWORD = azurerm_redis_enterprise_database.redis-db.primary_access_key 128 | STORAGE_CONNECTION_STRING = azurerm_storage_account.storage-acct.primary_connection_string 129 | CONTAINER_NAME = azurerm_storage_container.storage-acct-container.name 130 | } 131 | 132 | site_config { 133 | application_stack { 134 | docker_image = var.app_docker_image 135 | docker_image_tag = var.app_docker_tag 136 | } 137 | } 138 | } 139 | 140 | output "app-url" { 141 | value = azurerm_linux_web_app.app.default_hostname 142 | } 143 | 144 | output "storage-account" { 145 | value = azurerm_storage_account.storage-acct.name 146 | } 147 | 148 | output "storage-container" { 149 | value = azurerm_storage_container.storage-acct-container.name 150 | } 151 | 152 | output "storage-account-connection-string" { 153 | sensitive = true 154 | value = azurerm_storage_account.storage-acct.primary_connection_string 155 | } 156 | 157 | output "openai-endpoint" { 158 | value = azurerm_cognitive_account.openai.endpoint 159 | } 160 | 161 | output "openai-key" { 162 | sensitive = true 163 | value = azurerm_cognitive_account.openai.primary_access_key 164 | } 165 | 166 | output "redis-password" { 167 | sensitive = true 168 | value = azurerm_redis_enterprise_database.redis-db.primary_access_key 169 | } 170 | output "redis-port" { 171 | value = azurerm_redis_enterprise_database.redis-db.port 172 | } 173 | output "redis-endpoint" { 174 | value = azurerm_redis_enterprise_cluster.redisenterprise.hostname 175 | } 176 | -------------------------------------------------------------------------------- /terraform.tfvars: -------------------------------------------------------------------------------- 1 | azure_region = "eastus" 2 | name_prefix = "redis-openai" 3 | 4 | app_docker_image = "antonum/llmchat" 5 | app_docker_tag = "latest" 6 | 7 | generative_model = "gpt-35-turbo" 8 | generative_model_version = "0301" 9 | 10 | embeddings_model = "text-embedding-ada-002" 11 | embeddings_model_version = "2" -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "azure_region" { 2 | description = "Azure region" 3 | type = string 4 | default = "eastus" 5 | } 6 | 7 | variable "name_prefix" { 8 | description = "common prefix for naming Azure resources" 9 | type = string 10 | default = "anton-tf-" 11 | } 12 | variable "generative_model" { 13 | description = "Generative model to use" 14 | type = string 15 | default = "gpt-35-turbo" 16 | } 17 | variable "embeddings_model" { 18 | description = "Embeddings model to use" 19 | type = string 20 | default = "text-embedding-ada-002" 21 | } 22 | variable "generative_model_version" { 23 | description = "Generative model version to use" 24 | type = string 25 | default = "0613" 26 | } 27 | variable "embeddings_model_version" { 28 | description = "Embeddings model version to use" 29 | type = string 30 | default = "2" 31 | } 32 | variable "app_docker_image" { 33 | description = "docker image to use for the web app. Image should expose port 80" 34 | type = string 35 | default = "antonum/llmchat" 36 | } 37 | 38 | variable "app_docker_tag" { 39 | description = "docker image tag to use for the web app." 40 | type = string 41 | default = "latest" 42 | } 43 | --------------------------------------------------------------------------------