Ranking Formulas
Complete reference for the rankBy expression language and custom ranking in repository search.
Repository search supports custom ranking formulas via the rankBy parameter. This allows you to control how semantic similarity, popularity, and activity signals are combined.
How Ranking Works
Section titled “How Ranking Works”Repository search uses a multi-query strategy:
- Vector query - Semantic similarity via ANN search on embeddings
- Popularity query - Repositories with high star counts
- Activity query - Repositories with many closed issues
- Recency query - Recently updated repositories
Results from all queries are deduplicated, then scored using your rankBy formula.
Performance optimization: The API automatically detects if your rankBy only uses ann and skips multi-query for better performance and lower cost.
Default Formula
Section titled “Default Formula”The default formula is log-normalized 70/20/10:
0.7 × ann + 0.2 × log₁₀(stars) / log₁₀(500k) + 0.1 × log₁₀(issues_closed) / log₁₀(200k)This balances:
- 70% semantic similarity - Finds conceptually relevant repos
- 20% popularity - Boosts well-established projects
- 10% activity - Boosts actively maintained repos
Available Attributes
Section titled “Available Attributes”| Attribute | Type | Description | Range |
|---|---|---|---|
ann | number | Vector similarity score | 0-1 (1 = most similar) |
stars | number | Repository star count | 0 - ∞ |
issues_closed | number | Total closed issues | 0 - ∞ |
age | number | Days since repository creation | 0 - ∞ |
recency | number | Days since last update | 0 - ∞ |
Expression Operations
Section titled “Expression Operations”Add multiple scores together.
{ "type": "Sum", "exprs": [ { "type": "Attr", "name": "ann" }, { "type": "Attr", "name": "stars" } ]}Multiply two expressions.
{ "type": "Mult", "exprs": [ { "type": "Const", "value": 0.7 }, { "type": "Attr", "name": "ann" } ]}Divide one expression by another.
{ "type": "Div", "exprs": [ { "type": "Attr", "name": "stars" }, { "type": "Const", "value": 1000 } ]}Return the maximum of multiple expressions.
{ "type": "Max", "exprs": [ { "type": "Attr", "name": "stars" }, { "type": "Const", "value": 1 } ]}Return the minimum of multiple expressions.
{ "type": "Min", "exprs": [ { "type": "Attr", "name": "ann" }, { "type": "Const", "value": 0.9 } ]}Logarithm with custom base.
{ "type": "Log", "base": 10, "expr": { "type": "Attr", "name": "stars" }}Reference an attribute value.
{ "type": "Attr", "name": "ann" }A constant numeric value.
{ "type": "Const", "value": 0.5 }Formula Examples
Section titled “Formula Examples”Pure Semantic (Fastest)
Section titled “Pure Semantic (Fastest)”Uses only vector search - skips multi-query automatically.
await client.searchRepos.search({ query: "react hooks", rankBy: { type: "Attr", name: "ann" },});When to use: Prototyping, exploratory search, when quality signals don’t matter.
Popularity-Focused
Section titled “Popularity-Focused”Emphasizes popular projects.
{ "type": "Sum", "exprs": [ { "type": "Attr", "name": "ann" }, { "type": "Mult", "exprs": [ { "type": "Const", "value": 0.0002 }, { "type": "Attr", "name": "stars" } ] } ]}When to use: Finding “best” or “most popular” libraries in a category.
Activity-Focused
Section titled “Activity-Focused”Emphasizes actively maintained projects.
{ "type": "Sum", "exprs": [ { "type": "Attr", "name": "ann" }, { "type": "Mult", "exprs": [ { "type": "Const", "value": 0.0001 }, { "type": "Attr", "name": "issues_closed" } ] } ]}When to use: Finding actively maintained projects, excluding abandoned repos.
Balanced (Default Formula)
Section titled “Balanced (Default Formula)”The full default formula with log normalization:
{ "type": "Sum", "exprs": [ { "type": "Mult", "exprs": [ { "type": "Const", "value": 0.7 }, { "type": "Attr", "name": "ann" } ] }, { "type": "Mult", "exprs": [ { "type": "Const", "value": 0.2 }, { "type": "Div", "exprs": [ { "type": "Log", "base": 10, "expr": { "type": "Max", "exprs": [ { "type": "Attr", "name": "stars" }, { "type": "Const", "value": 1 } ] } }, { "type": "Const", "value": 5.699 } ] } ] }, { "type": "Mult", "exprs": [ { "type": "Const", "value": 0.1 }, { "type": "Div", "exprs": [ { "type": "Log", "base": 10, "expr": { "type": "Max", "exprs": [ { "type": "Attr", "name": "issues_closed" }, { "type": "Const", "value": 1 } ] } }, { "type": "Const", "value": 5.301 } ] } ] } ]}SDK Helper Functions
Section titled “SDK Helper Functions”The TypeScript SDK provides helper functions for building expressions:
import { sum, mult, div, max, log, attr, c, logNorm } from "@bountylab/sdk";
// Balanced formulaconst rankBy = sum( mult(c(0.7), attr("ann")), mult(c(0.2), logNorm("stars", 500000)), mult(c(0.1), logNorm("issues_closed", 200000)),);
await client.searchRepos.search({ query: "web framework", rankBy,});Available Helpers
Section titled “Available Helpers”| Helper | Description | Example |
|---|---|---|
sum(...exprs) | Add expressions | sum(attr('ann'), attr('stars')) |
mult(a, b) | Multiply two expressions | mult(c(0.5), attr('ann')) |
div(a, b) | Divide expressions | div(attr('stars'), c(1000)) |
max(...exprs) | Maximum value | max(attr('stars'), c(1)) |
min(...exprs) | Minimum value | min(attr('ann'), c(0.9)) |
log(expr, base) | Logarithm | log(attr('stars'), 10) |
attr(name) | Attribute reference | attr('ann') |
c(value) | Constant value | c(0.7) |
logNorm(attr, max) | Log-normalized attribute | logNorm('stars', 500000) |
Performance Characteristics
Section titled “Performance Characteristics”| rankBy Type | Multi-Query | Cost | Speed |
|---|---|---|---|
Pure ANN (ann only) | No | 1x | Fastest |
| With quality signals | Yes | 4x | Slower |
| Custom (quality signals) | Auto-detected | 4-5x | Slower |
Best Practices
Section titled “Best Practices”- Start with default - The 70/20/10 formula works well for most use cases
- Use pure ANN for prototyping - Skip multi-query for faster iteration
- Combine with filters - Use
stargazerCount >= 100filter instead of relying solely on rankBy - Log-normalize large numbers - Raw star counts overwhelm other signals
- Test with real queries - Different formulas work better for different query types
String Parser (Alternative)
Section titled “String Parser (Alternative)”For simple expressions, you can use a string format:
await client.searchRepos.search({ query: "react", rankBy: "Sum(ann, Mult(stars, 0.0001))",});Supported syntax:
Sum(expr1, expr2, ...)Mult(expr1, expr2)Max(expr1, ...)- Attribute names:
ann,stars,issues_closed,age,recency - Numbers:
0.5,1000, etc.