Skip to content

Commit 7980999

Browse files
gen-ai mock server: serve Cohere v2 rerank
Add POST /v2/rerank to the Cohere mock. It returns the SDK's V2RerankResponse shape, ranking the request's documents in order and trimming to top_n, so the same request always gets the same bytes.
1 parent 1c1097b commit 7980999

3 files changed

Lines changed: 54 additions & 1 deletion

File tree

‎tools/gen-ai/mock-server/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ The conformance runner starts it for you: a directory declares it under
2323
| `assistants` | OpenAI Assistants, threads and runs |
2424
| `bedrock` | `converse`, `converse-stream`, `invoke` |
2525
| `bedrock_agent`, `bedrock_agentcore` | agent invocation and the memory APIs |
26-
| `cohere` | `/v1` and `/v2` chat and embed |
26+
| `cohere` | `/v1` and `/v2` chat and embed, `/v2` rerank |
2727
| `google_genai` | Gemini `generateContent` / streaming, and the Vertex `projects/…` paths |
2828
| `mistral` | chat completions, FIM and embeddings, under `/mistral/v1/…` |
2929
| `ollama` | `/api/chat`, including tool use and NDJSON streaming, and `/api/embed` |

‎tools/gen-ai/mock-server/src/genai_mock_server/cohere.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,21 @@ def cohere_embed():
197197
@bp.route("/v1/embed", methods=["POST"])
198198
def cohere_embed_v1():
199199
return _embed_response(request.get_json(silent=True) or {}, "1")
200+
201+
202+
@bp.route("/v2/rerank", methods=["POST"])
203+
def cohere_rerank():
204+
body = request.get_json(silent=True) or {}
205+
documents = body.get("documents") or []
206+
top_n = body.get("top_n") or len(documents)
207+
return {
208+
"id": "cohere-rerank-mock-001",
209+
"results": [
210+
{"index": index, "relevance_score": round(0.99 / (index + 1), 4)}
211+
for index in range(min(top_n, len(documents)))
212+
],
213+
"meta": {
214+
"api_version": {"version": "2"},
215+
"billed_units": {"search_units": 1},
216+
},
217+
}

‎tools/gen-ai/mock-server/tests/test_mock_server.py‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,17 @@
122122
"/v2/embed",
123123
{"model": "embed-v4.0", "texts": ["hi", "there"], "input_type": "search_document"},
124124
),
125+
(
126+
"cohere-rerank",
127+
"post",
128+
"/v2/rerank",
129+
{
130+
"model": "rerank-v3.5",
131+
"query": "hi",
132+
"documents": ["one", "two", "three"],
133+
"top_n": 2,
134+
},
135+
),
125136
(
126137
"mistral-chat",
127138
"post",
@@ -353,6 +364,30 @@ def test_embeddings_survive_an_unusable_dimension_count(client):
353364
assert len(response.json["data"][0]["embedding"]) == 256
354365

355366

367+
def test_cohere_rerank_ranks_within_the_requested_candidates(client):
368+
def rerank(**extra):
369+
response = client.post(
370+
"/v2/rerank",
371+
json={
372+
"model": "rerank-v3.5",
373+
"query": "hi",
374+
"documents": ["one", "two", "three"],
375+
**extra,
376+
},
377+
)
378+
assert response.status_code == 200
379+
return response.json["results"]
380+
381+
top_two = rerank(top_n=2)
382+
assert [result["index"] for result in top_two] == [0, 1]
383+
scores = [result["relevance_score"] for result in top_two]
384+
assert scores == sorted(scores, reverse=True)
385+
assert all(0 < score <= 1 for score in scores)
386+
387+
assert len(rerank()) == 3
388+
assert len(rerank(top_n=10)) == 3
389+
390+
356391
def test_chat_reports_the_service_tier_that_served_the_request(client):
357392
def tier(requested):
358393
response = client.post(

0 commit comments

Comments
 (0)