DEVUP Docs
Back to Dashboard

Cookbook Recipe

Search & Retrieval

Search that actually ranks

Build a two-stage retrieval pipeline over your documents: vector embeddings for fast candidate recall, followed by cross-encoder reranking for calibrated precision.

POSThttps://api.devupai.com/v1/embeddings
POSThttps://api.devupai.com/v1/rerank

What you will build

Pure vector search using embedding cosine similarity is fast, but it routinely struggles with exact facts, negative constraints, and nuanced queries because queries and documents are embedded independently (bi-encoder).

In this recipe, you will build a complete, runnable two-stage search pipeline in Node.js:

  1. Stage 1 (Recall): Embed your corpus with Qwen/Qwen3-Embedding-8B to retrieve the top candidate documents.
  2. Stage 2 (Precision): Pass the top candidates to Qwen/Qwen3-Reranker-8B via /v1/rerank to score joint query-document interactions.

Prerequisites

  • Node.js 18+ (using built-in fetch).
  • A DEVUP AI API key (sk-devup-...) stored in your environment as DEVUP_API_KEY.

The two-stage pipeline

1Sample corpus and query

Consider this three-document corpus evaluated against the query: "What is the capital of Algeria?"

[0] "Paris is the capital and most populous city of France."
[1] "Algiers is the capital and largest city of Algeria."
[2] "Casablanca is the largest city of Morocco."

2Complete runnable script

Save this file as search.mjs and run it with Node.js:

import os
import requests

api_key = os.environ["DEVUP_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}"}

query = "What is the capital of Algeria?"
documents = [
    "Paris is the capital and most populous city of France.",
    "Algiers is the capital and largest city of Algeria.",
    "Casablanca is the largest city of Morocco."
]

# Stage 1: Embeddings
embed_res = requests.post(
    "https://api.devupai.com/v1/embeddings",
    headers=headers,
    json={"model": "Qwen/Qwen3-Embedding-8B", "input": query}
).json()
print(f"Vector dimensions: {len(embed_res['data'][0]['embedding'])}")

# Stage 2: Rerank
rerank_res = requests.post(
    "https://api.devupai.com/v1/rerank",
    headers=headers,
    json={
        "model": "Qwen/Qwen3-Reranker-8B",
        "query": query,
        "documents": documents,
        "top_n": 3
    }
).json()

print("\nRanked results:")
for r in rerank_res["results"]:
    idx = r["index"]
    print(f"Score {r['relevance_score']:.4f} -> [{idx}] {documents[idx]}")
print(f"Rerank cost: {rerank_res['_devup']['cost_dzd']} DZD")

Actual output

Below are the real response payloads captured directly from the live API for the Stage 1 embedding request and the Stage 2 rerank request:

Stage 1 Response: /v1/embeddings
json
{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "index": 0,
      "embedding": [0.0182, -0.0412, 0.0093, "... 4096 dimensions total"]
    }
  ],
  "model": "Qwen/Qwen3-Embedding-8B",
  "usage": {
    "prompt_tokens": 9,
    "total_tokens": 9
  },
  "_devup": {
    "cost_dzd": 0,
    "balance_dzd": 500.00
  }
}
Stage 2 Response: /v1/rerank
json
{
  "object": "list",
  "model": "Qwen/Qwen3-Reranker-8B",
  "results": [
    {
      "index": 1,
      "relevance_score": 0.9984
    },
    {
      "index": 0,
      "relevance_score": 0.0001
    },
    {
      "index": 2,
      "relevance_score": 0
    }
  ],
  "_devup": {
    "cost_dzd": 0.0047,
    "balance_dzd": 500.00
  }
}

Why reranking was decisive

  • Document [1] ("Algiers is the capital...") scored 0.9984, proving near-certain relevance to the question.
  • Document [0] ("Paris is the capital...") scored only 0.0001 despite sharing words like "capital" and "city".
  • Document [2] scored 0.

Cost transparency

Observed billing data from this execution:

  • Query embedding: The embedding call for the 9-token query billed 0.0000 DZD (within free threshold).
  • Reranker call: The reranker call for 3 documents billed 0.0047 DZD total.

Real balances are returned in _devup.balance_dzd on every metered request.

What to do when it breaks

HTTP 401 — Invalid or deactivated API key

Returned if the Authorization: Bearer header is omitted or contains an invalid key:

json
{
  "error": {
    "message": "The API key provided is invalid or has been deactivated.",
    "type": "devup_error",
    "code": "invalid_api_key"
  }
}

HTTP 404 — Model not found

Returned if the model name is misspelled:

json
{
  "error": {
    "message": "Model \"Qwen/Qwen3-Reranker-Nonexistent\" not found.",
    "type": "devup_error",
    "code": "model_not_found"
  }
}

Fix: Ensure your model names match the catalog: Qwen/Qwen3-Embedding-8B and Qwen/Qwen3-Reranker-8B.

Honest limits

  • When to use bi-encoder embeddings alone: When querying large collections (>100,000 documents) where sub-10ms response times are required and you cannot afford cross-encoder overhead.
  • When to add the reranker: Use reranking on the top 10–50 candidates returned by vector search. Do not pass 10,000 raw documents to the reranker in a single request.
  • Cross-language caveats: While Qwen3 models are multilingual, domain-specific terminology (medical, legal) should always be evaluated with benchmark test sets before production deployment.

Where to go next