Introducing Assistants API on Azure OpenAI Service

Azure OpenAI Service crossed an interesting adoption milestone in early 2024. More than 53,000 customers were running production workloads on it, just over a year after general availability. Microsoft used that momentum to ship a cluster of updates in February 2024: a new Assistants API in public preview, refreshed GPT-4 Turbo and GPT-3.5 Turbo models, new text to speech voices, and a lower priced generation of embedding models. Each of these lands in a different part of a typical solution architecture, so it helps to go through them one at a time.

The problem the Assistants API solves

If you have built anything on the plain chat completions API, you already know the pain point. The API itself is stateless. Every request needs the full conversation history sent back in, and if you want the model to read files, run code, or call functions, you write and maintain that orchestration yourself. Multiply that across a few hundred concurrent user sessions and you end up building a fairly involved state management layer just to keep a chatbot coherent.

The Assistants API is Microsoft’s answer to that gap, and it runs on the same underlying models that power ChatGPT. It gives you three things you no longer have to build by hand: persistent threads that hold conversation history without you resending it on every call, file access scoped to a thread or to an assistant, and native tools, including a hosted Code Interpreter and function calling, that the model can invoke in parallel when it decides they are needed.

Threads and tools in practice

A thread behaves closer to a conversation log than to a single prompt. You create the thread once, then append messages to it as the user replies, and the service manages the model’s context window limits behind the scenes instead of you truncating history manually. This matters more than it sounds, because context window management is one of those things every team ends up reimplementing slightly differently, and it is easy to get wrong under load.

The Code Interpreter tool runs Python in a sandboxed environment hosted by Azure OpenAI Service itself, which is useful for data analysis over uploaded files or generating charts without you standing up your own execution sandbox. Function calling works the way it does in the chat completions API: you describe your application’s functions to the assistant, and the model decides when to call them and how to use the response. The difference here is that an assistant can reach for Code Interpreter and function calling in the same run, rather than you choosing one mode upfront.

A minimal .NET example of the create, thread, message, run lifecycle looks like this. It uses the Assistants preview surface of the Azure.AI.OpenAI SDK.

var client = new AssistantsClient(
    new Uri("https://<your-resource>.openai.azure.com/"),
    new AzureKeyCredential("<your-key>"));
 
Assistant assistant = await client.CreateAssistantAsync(
    new AssistantCreationOptions("gpt-4-0125-preview")
    {
        Name = "Support Ticket Triage",
        Instructions = "You triage support tickets and suggest a priority and owning team.",
        Tools = { new CodeInterpreterToolDefinition() }
    });
 
AssistantThread thread = await client.CreateThreadAsync();
 
await client.CreateMessageAsync(thread.Id, MessageRole.User,
    "Customer reports checkout fails intermittently with a 500 on payment confirm.");
 
ThreadRun run = await client.CreateRunAsync(thread.Id,
    new CreateRunOptions(assistant.Id));

This creates an assistant tied to a model deployment, opens a thread, adds a user message, and starts a run. The run executes asynchronously, so in a real application you poll its status until it reaches a terminal state before reading the assistant’s reply back from the thread’s messages. The common mistake here is treating CreateRunAsync as a synchronous call that returns the final answer directly. It does not, and code that assumes it does will read stale or empty responses.

Worth calling out from a security standpoint: Microsoft’s own guidance flags that retrieving untrusted data through function calling, Code Interpreter file input, or thread content can compromise the assistant or the application built around it. If your assistant ingests customer supplied documents or calls internal APIs based on model output, treat that input path the same way you would treat any other untrusted input, with validation and scoped permissions, not blind trust in the model’s judgment.

Fine-tuning gets cheaper and gains continuous training

Azure OpenAI Service first opened fine-tuning for Babbage-002, Davinci-002, and GPT-35-Turbo in October 2023. This update adds fine-tuning support for GPT-35-Turbo-1106, which improves instruction following, supports JSON mode, and gives you reproducible outputs. It also raises the fine-tuning context length to 16k tokens, so you can train on longer message pairs than before.

Two capabilities matter more than the model bump itself. Fine-tuning with function calling lets you teach a custom model when to invoke a function rather than just how to phrase a reply, which improves consistency in agent style workloads. Continuous fine-tuning lets you take a model you already fine-tuned and train it further on new data without losing what it already learned, so you are not forced to retrain from the base model every time you have a new batch of examples. Microsoft also cut training and hosting costs for GPT-35-Turbo fine-tuned models by half, which changes the economics of running several narrow fine-tuned models instead of one general purpose one.

Model updates rolling out through February

A refreshed GPT-4 Turbo preview model, gpt-4-0125-preview, ships with better code generation and fewer cases where the model stops short of finishing a task, along with a fix for a bug affecting non-English UTF-8 output. Microsoft’s rollout plan auto-upgrades existing deployments pinned to the 1106-preview version starting two weeks after launch, completing within a week after that. If you have prompts tuned tightly against a specific model version’s quirks, that auto-upgrade window is worth testing against before it happens to you rather than after.

GPT-3.5-Turbo-0125 arrives alongside it with meaningfully lower pricing, input tokens drop 50 percent to $0.0005 per 1K tokens and output drops 25 percent to $0.0015 per 1K tokens, plus better accuracy when the model is asked to respond in a specific format such as JSON.

Text to speech also lands as a first party capability, with two model variants. tts-1 targets real time use cases such as live voice interaction, and tts-1-hd targets output quality for things like narration or training content. Both offer six preset voices and are available through Azure OpenAI Service as well as Azure AI Speech, so you have a choice of which service surface fits your existing pipeline.

New embedding models and what the pricing drop means

The new embedding generation ships two models. text-embedding-3-small outperforms the older text-embedding-ada-002 despite being smaller, and it is priced at $0.00002 per 1K tokens, a five times reduction against ada-002. text-embedding-3-large produces embeddings with up to 3072 dimensions and is priced at $0.00013 per 1K tokens for teams that need the extra representational capacity, for example in large scale semantic search over millions of documents.

Both models support native dimension shortening, meaning you can truncate the embedding vector from the end without destroying its semantic properties. In practice this lets you store a shorter, cheaper vector in your index for coarse retrieval and re-rank with the full vector only for a smaller candidate set, which is a reasonable trade-off if your vector database costs scale with dimension count. Ada-002 is not being deprecated, so existing indexes built on it keep working if you are not ready to re-embed your corpus yet.

Where this fits and what to watch

The Assistants API is still in public preview, which means the usual caveats apply: expect API surface changes, do not build a production dependency on it without a fallback plan, and budget time to revisit your integration when it reaches general availability. For a genuinely stateful assistant with file access and tool use, it removes a real amount of undifferentiated orchestration work compared to hand rolling it on the chat completions API. For a simple single turn chatbot with no file or tool requirements, plain chat completions is still the simpler and cheaper choice, since you are not paying for thread storage and run overhead you do not need.

The pricing changes across fine-tuning, GPT-3.5-Turbo, and embeddings are the part worth acting on immediately regardless of whether you adopt Assistants. If your architecture already uses ada-002 embeddings or GPT-35-Turbo fine-tuned models, re-checking the new pricing against your current spend is a quick win with no code changes required.

Leave a Reply

Discover more from Behind the Stack

Subscribe now to keep reading and get access to the full archive.

Continue reading