More random rambelings trying to use Azure Cognative Account - thats what they call a deployemnt which gives access to a endpoint, the endpoint then talks to a OpenAI AI model.
In my case, I needed one Azure OpenAI resource that could do two jobs for the chatbot app: generate chat responses and create embeddings for vector search. I also wanted the deployment names to be explicit, so the app could use them from configuration without any code changes.
This is the setup I used, and it matches what is in the app today.
1. Create the Azure OpenAI resource and deployments
The Terraform for this part is straightforward. I created a cognitive account, then deployed two models: one for embeddings and one for chat.
1 | # foundry.tf |
The important bit here is that the deployment names are stable. I use those exact names in configuration so the app does not need to know anything about the underlying model version.
Docs: Azure OpenAI resource • Deploy models in Azure OpenAI
2. Expose the endpoint and deployment names
Once the deployments are created, I output the endpoint and the deployment names so they can be consumed elsewhere.
1 | output "openai_endpoint" { |
That gives me the values I need for the app configuration:
EndpointChatDeploymentEmbeddingDeployment
3. Put the values into app settings
In the web app, I keep these values under an AzureOpenAI section.
1 | { |
The ApiKey is the secret that the app needs to authenticate to the Azure OpenAI resource. In practice, I set that from environment variables or deployment secrets rather than hard coding it.
In this app, the secret is supplied as:
1 | AzureOpenAI__ApiKey |
That is the value the app reads from configuration when it creates the client.
Docs: Configuration in ASP.NET Core • Azure OpenAI authentication
4. Use the chat deployment in the C# app
The chatbot service uses the configured endpoint and the chat deployment to send prompts to Azure OpenAI.
1 | public sealed class AzureOpenAIChatCompletionService( |
That is the critical part: the app creates an AzureOpenAIClient using the endpoint and API key, then asks for the chat client for the configured deployment name.
5. Use the embedding deployment for vector search
The same Azure OpenAI resource is also used for embeddings. The vector search layer creates an embedding client from the same endpoint and API key, but with the embedding deployment instead.
1 | public sealed class VectorSearchService : IAsyncDisposable |
This is how the app turns a user query into an embedding, then compares that embedding against stored vectors in PostgreSQL using the pgvector extension.
Docs: Azure AI Inference client library • Azure.AI.OpenAI client library
6. Configure the secrets the app expects
The app expects a few Azure OpenAI values to be present before it will run the chat flow.
The relevant options class looks like this:
1 | public sealed class AzureOpenAIOptions |
In the deployment pipeline, the secret is passed in as an environment variable so it does not live in source control.
1 | AzureOpenAI__ApiKey |
That is the one I would make sure is present in every environment where the app runs. Without it, the app reports that the chat service is not configured.
7. What this gives us
The result is a very simple mental model:
- Terraform creates the Azure OpenAI account and the two deployments.
- The app reads the endpoint, deployment names, and API key from configuration.
- The chat flow uses the chat deployment.
- The vector search flow uses the embedding deployment.
- The same Azure OpenAI resource powers both experiences.
That is the approach I used here, and it keeps the infrastructure and the application wiring aligned.