Most retrieval-augmented apps follow the same path. A vector search returns 30 or 50 passages, and the chat model reads all of them. Some of those passages are close but wrong. Some are right but buried. The model spends tokens on the noise and sometimes answers from the wrong paragraph.
A reranker sits between the search and the chat model. It reads the query and the candidate passages together, scores each one, and returns them in order of relevance. Your code decides how many to keep and where to cut.
Cohere Rerank v5 is now in Microsoft Foundry in two versions, Pro and Fast, and both add a feature called Context Focus. This post covers when each one fits, a table of the trade-offs, and a C# console app that calls both.
If you missed it, I covered the Cohere family in Foundry earlier in Cohere Command A+ Lands in Microsoft Foundry. Command A+ is the chat model that pairs well with a reranker like this one.
Sources for the model details below: the Foundry announcement (October 21, 2026), the Cohere Rerank 5 post, and the Cohere Rerank v5 changelog. I’ve used only one figure from Cohere’s evaluations, the calibration error, because it changes how you set thresholds. Your own queries and documents will tell you more.
What you get
Three things from the Rerank 5 release matter for .NET apps:
- Two tiers. Pro is tuned for ranking quality, especially reasoning-heavy queries and long or specialized documents. Fast is tuned for low latency and high throughput.
- Calibrated scores. The
relevance_scoreis meant to behave the same way across queries and domains. Cohere suggests a cut-off of 0.50 for Pro and 0.45 for Fast, so one number can filter results before they reach the model. - Context Focus. An optional setting that returns the most relevant character spans inside each document, so you can pass a few sentences to the chat model instead of whole pages. It is off by default.
The Foundry model cards list both models as text classification, in preview, for over 100 languages, with text and image input.
The numbers that matter for design
| Rerank v5 Pro | Rerank v5 Fast | |
|---|---|---|
| Foundry model name | Cohere-rerank-v5-pro |
Cohere-rerank-v5-fast |
| API model ID | rerank-v5.0-pro |
rerank-v5.0-fast |
| Languages | Over 100 | Over 100 |
| Score cut-off suggested by Cohere | 0.50 | 0.45 |
| Expected Calibration Error (lower is better) | ~0.06 (Rerank 4 Pro: ~0.38) | ~0.06 |
| Cohere API price | $0.05 per 1M tokens | $0.02 per 1M tokens |
| Status on Foundry | Preview | Preview |
Calibration is what makes one cut-off work across queries. Expected Calibration Error (ECE) measures how far a score sits from the real chance that a passage is useful. Cohere reports about 0.06 for both Rerank 5 models, against 0.38 for Rerank 4 Pro on human judgments (0.31 on NIST judgments). In practice, a Rerank 5 score of 0.7 is much closer to a real 70% chance of being useful, so a fixed threshold filters the same way on every query. These are Cohere’s own figures from the Rerank 5 post.
⚠️ Uncertain: Foundry price. Cohere’s own price is listed above. The Foundry model cards link to a pricing page, which is in-correct; thus rather than showing a rate, confirm the Foundry rate before you try out the samples.
Where each one fits
These are the situations where reranking earns its place. Each one has a clear reason to rerank.
1. Grounding a RAG answer
Your vector search returns 40 passages. Rerank them, keep the top 3 that clear the threshold, and send only those to the chat model. The answer is grounded in fewer, better passages, and the prompt stays small.
Use Pro here. A wrong passage in the final three is expensive, because the chat model will quote it confidently.
2. Agents that search many times per task
An agent might run 5 to 10 searches before it answers. Each search returns a candidate list that needs ordering. The latency adds up across those calls.
Use Fast here. The quality gap matters less than the time per call, and the agent can run more searches inside the same budget.
3. Help-desk article matching
A customer writes “I was charged twice this month”. Your help center has a few hundred articles. Vector search finds the likely ones, and the reranker decides which article to show first.
Use Fast for high volume, and check a sample of matches with Pro during setup.
4. Multilingual support content
Support articles are often written in one language and asked about in another. Both models cover over 100 languages, so the same reranker can order English, Spanish, German, and Japanese passages against one query.
Test both on your own languages. Cohere’s language claims are general, and your articles may behave differently.
5. Semi-structured records
Product catalogs, incident logs, and CRM entries are often JSON or tables. Cohere’s guidance is to pass each record as a YAML string so the field names stay with the values. That gives the reranker more to match on. Plain JSON may also work, so test both formats on your own records before you settle on one.
Use Pro when records are long or specialized, such as contracts or clinical notes.
6. Answer or abstain
This is the use case I’d build first. When no candidate clears the threshold, the app says “I do not know” and does not call the chat model at all. The calibrated score makes that cut-off possible without guessing.
Either model works. Set the threshold, then test it against queries you know have no answer in your data.
Pros and cons
| Model | Good for | Pros | Cons | Pick it when |
|---|---|---|---|---|
| Pro | RAG grounding, long or specialized documents, reasoning-heavy queries | Ranks complex queries better, stronger on long documents | Slower and more expensive per call than Fast | The top few results must be right, and a wrong pick costs more than the extra latency |
| Fast | Agents with many searches, high-volume help-desk matching | Low latency, high throughput, lower price | Less accurate on hard or long documents | Volume and speed matter more than the last few points of quality |
| Neither | Tiny candidate lists you can scan in code | No extra call, no extra cost | Does not scale to large lists or fuzzy queries | You have fewer than about five candidates |
Two things a reranker does not do:
- It does not search. You pass it the candidates. Keep your vector or keyword search for finding them.
- It does not write. Summaries, rewrites, and answers still belong to the chat model. The reranker decides what the chat model reads.
Calling Rerank v5 from C#
The sample reads an endpoint for Pro and one for Fast. When both models are deployed in the same Foundry resource, the two endpoints are the same URL. Each one takes an API key if you set one. If you leave the key out, the app signs in with Entra ID through DefaultAzureCredential, so run az login first. The sample sends the same query to both and prints each result with a keep or drop decision based on that model’s cut-off.
The request goes to {endpoint}/providers/cohere/v2/rerank, the Foundry route for Cohere models, with a bearer token in the Authorization header. The token is your API key if you set one, or an Entra ID token if you don’t. The model field takes the Foundry model name, Cohere-rerank-v5-pro or Cohere-rerank-v5-fast. If your deployment expects a different header or path, the code is the only part to change.
Create the project on .NET 10 and add the configuration packages:
|
1 2 3 4 5 6 |
dotnet new console –n Cohere–Rerank–v5–CSharp–Sample cd Cohere–Rerank–v5–CSharp–Sample dotnet add package Azure.Identity dotnet add package Microsoft.Extensions.Configuration.UserSecrets dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables dotnet user–secrets init |
Store the endpoints with user secrets. Use the base URL of your Foundry resource, with no path. The two API key lines are optional, so leave them out to use Entra ID:
|
1 2 3 4 |
dotnet user–secrets set “COHERE_RERANK_PRO_ENDPOINT” “https://YOUR-RESOURCE.services.ai.azure.com” dotnet user–secrets set “COHERE_RERANK_PRO_API_KEY” “your-pro-key” dotnet user–secrets set “COHERE_RERANK_FAST_ENDPOINT” “https://YOUR-RESOURCE.services.ai.azure.com” dotnet user–secrets set “COHERE_RERANK_FAST_API_KEY” “your-fast-key” |
To check what the app will read, run:
|
1 |
dotnet user–secrets list |
The project file is Cohere-Rerank-v5-CSharp-Sample.csproj. The UserSecretsId is the one dotnet user-secrets init writes:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<Project Sdk=“Microsoft.NET.Sdk”> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net10.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <UserSecretsId>b9934625-9fc9-4364-ae1e-0107ce65b680</UserSecretsId> </PropertyGroup> <ItemGroup> <PackageReference Include=“Azure.Identity” Version=“1.21.0” /> <PackageReference Include=“Microsoft.Extensions.Configuration.EnvironmentVariables” Version=“10.0.12” /> <PackageReference Include=“Microsoft.Extensions.Configuration.UserSecrets” Version=“10.0.12” /> </ItemGroup> </Project> |
Then Program.cs:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
using System.Diagnostics; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; using Azure.Core; using Azure.Identity; using Microsoft.Extensions.Configuration; var config = new ConfigurationBuilder() .AddUserSecrets<Program>() .AddEnvironmentVariables() .Build(); var credential = new DefaultAzureCredential(); var pro = ReadModel(config, “Pro”, “Cohere-rerank-v5-pro”, 0.50); var fast = ReadModel(config, “Fast”, “Cohere-rerank-v5-fast”, 0.45); var query = “What is the refund window for annual plans?”; var documents = new[] { “Monthly plans can be cancelled at any time. The change takes effect at the end of the billing period.”, “Annual plans can be refunded in full within 30 days of purchase. After 30 days, the remaining months are prorated.”, “Refund requests are submitted from the billing page under Invoices.”, “Our offices are closed on public holidays in Ottawa and Toronto.”, “Enterprise contracts follow the terms in the signed order form, not this page.”, “Gift cards cannot be refunded but can be transferred to another account.” }; using var http = new HttpClient { Timeout = TimeSpan.FromSeconds(60) }; foreach (var model in new[] { pro, fast }) { var stopwatch = Stopwatch.StartNew(); var results = await RerankAsync(http, credential, model, query, documents, topN: 3); stopwatch.Stop(); Console.WriteLine($“{model.Name} ({stopwatch.ElapsedMilliseconds} ms, threshold {model.Threshold:0.00})”); foreach (var result in results) { var decision = result.Score >= model.Threshold ? “keep” : “drop”; Console.WriteLine($” {result.Score:0.00} {decision} {documents[result.Index]}”); } var kept = results.Count(r => r.Score >= model.Threshold); Console.WriteLine(kept == 0 ? ” No passage cleared the threshold. Answer ‘I do not know’ instead of guessing.” : $” {kept} passage(s) passed to the chat model.”); Console.WriteLine(); } static RerankModel ReadModel(IConfiguration config, string name, string modelId, double threshold) { var key = name.ToUpperInvariant(); var endpoint = config[$“COHERE_RERANK_{key}_ENDPOINT”] ?? throw new InvalidOperationException($“Set COHERE_RERANK_{key}_ENDPOINT with dotnet user-secrets.”); // The API key is optional. Without one, the app signs in with Entra ID through az login. var apiKey = config[$“COHERE_RERANK_{key}_API_KEY”]; return new RerankModel(name, modelId, endpoint.TrimEnd(‘/’), apiKey, threshold); } static async Task<List<RerankResult>> RerankAsync( HttpClient http, TokenCredential credential, RerankModel model, string query, IReadOnlyList<string> documents, int topN) { var body = new JsonObject { [“model”] = model.ModelId, [“query”] = query, [“top_n”] = topN, [“documents”] = new JsonArray(documents.Select(d => (JsonNode)d).ToArray()) }; using var request = new HttpRequestMessage(HttpMethod.Post, $“{model.Endpoint}/providers/cohere/v2/rerank”); if (!string.IsNullOrWhiteSpace(model.ApiKey)) { request.Headers.Authorization = new AuthenticationHeaderValue(“Bearer”, model.ApiKey); } else { var token = await credential.GetTokenAsync( new TokenRequestContext([“https://cognitiveservices.azure.com/.default”]), CancellationToken.None); request.Headers.Authorization = new AuthenticationHeaderValue(“Bearer”, token.Token); } // StringContent sets a fixed Content-Length; JsonContent uses chunked encoding. request.Content = new StringContent(body.ToJsonString(), Encoding.UTF8, “application/json”); using var response = await http.SendAsync(request); var text = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { throw new InvalidOperationException($“{model.Name} returned {(int)response.StatusCode}: {text}”); } using var doc = JsonDocument.Parse(text); var results = new List<RerankResult>(); foreach (var item in doc.RootElement.GetProperty(“results”).EnumerateArray()) { results.Add(new RerankResult( item.GetProperty(“index”).GetInt32(), item.GetProperty(“relevance_score”).GetDouble())); } return results; } record RerankModel(string Name, string ModelId, string Endpoint, string? ApiKey, double Threshold); record RerankResult(int Index, double Score); |
Run it:
|
1 |
dotnet run |
Run it on your own query and documents before you copy the thresholds. The output shows each passage with its score, the keep or drop decision, and the time per call. Your timings and scores will differ from anyone else’s, so record them alongside your data.
Output
|
1 2 3 4 5 6 7 8 9 10 11 |
Pro (2512 ms, threshold 0.50) 0.81 keep Annual plans can be refunded in full within 30 days of purchase. After 30 days, the remaining months are prorated. 0.13 drop Refund requests are submitted from the billing page under Invoices. 0.06 drop Monthly plans can be cancelled at any time. The change takes effect at the end of the billing period. 1 passage(s) passed to the chat model. Fast (2138 ms, threshold 0.45) 0.81 keep Annual plans can be refunded in full within 30 days of purchase. After 30 days, the remaining months are prorated. 0.06 drop Refund requests are submitted from the billing page under Invoices. 0.05 drop Monthly plans can be cancelled at any time. The change takes effect at the end of the billing period. 1 passage(s) passed to the chat model. |
The sample doesn’t use Context Focus yet. To try it, add a relevant_spans object to the request body, with mode set to enabled and a threshold and max_spans. Cohere’s changelog shows the shape, and the spans come back in each result.
Final thoughts
The reranker is the cheapest quality step in a RAG pipeline. It doesn’t write anything, and it doesn’t need your whole index. You pass it the candidates your search already found, and it tells you which ones matter.
Start with Fast if you run many searches, and Pro for answers where the top passage has to be right. Whichever you pick, set the threshold on your own data, and build the “I do not know” path before you tune anything else. 🙂
Resources
- Cohere-Rerank-V5-Pro-Fast-Csharp-Sample on GitHub
- Cohere Rerank V5 is now available in Microsoft Foundry
- Cohere Rerank 5 (Cohere blog)
- Cohere Rerank v5 changelog
- Cohere on Azure: reranking
- Cohere-rerank-v5-pro in the Foundry catalog
- Cohere-rerank-v5-fast in the Foundry catalog
- Cohere Command A+ in Microsoft Foundry (previous post)

Leave a Reply