File size: 5,893 Bytes
9f491ec 8613a9c 9ca8ee5 cbd62a3 8613a9c 9ca8ee5 cbd62a3 8613a9c 9ca8ee5 cbd62a3 8613a9c 9ca8ee5 cbd62a3 8613a9c 9f491ec 5fd770b | 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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | ---
title: ACL Anthology Search API
emoji: π
sdk: docker
app_port: 7860
pinned: false
---
# ACL Anthology Search API
FastAPI service providing keyword (SQLite FTS5) and embedding-similarity (FAISS)
search over the full ACL Anthology corpus (~128k papers). Runs entirely on free
infrastructure (HF Spaces + HF Hub dataset repo + GitHub Actions). See
`docs/superpowers/specs/2026-07-03-acl-anthology-search-api-design.md` for the
full design.
## API reference
All endpoints return JSON. The service answers `503` on every route except
`/health` until the index/DB snapshot has finished loading on startup.
### `GET /health`
Liveness + readiness probe.
**Query:** none.
**Response:** `200`
```json
{
"status": "ok",
"index_size": 128618,
"last_synced_at": "2026-07-04T15:06:00.654970+00:00"
}
```
Returns `503` when the snapshot is not yet loaded. `last_synced_at` is `null`
until the first sync has run.
### `GET /search/keyword?q=<query>&limit=<n>`
Keyword search over paper titles and abstracts via SQLite FTS5 (Porter-stemmed,
ranked by BM25).
**Query parameters:**
| Param | Type | Default | Notes |
|---------|------|---------|-----------------------------------------------------------------------|
| `q` | str | β | Required. Raw FTS5 query (see below). |
| `limit` | int | `10` | Max number of results. |
**FTS5 query format:** space-separated terms are ANDed. Supports `"exact phrase"`,
`prefix*`, `term1 OR term2`, `term1 NOT term2`, and parentheses. Examples:
`q=transformer attention`, `q="neural machine"`, `q=translat*`, `q=(attention OR transformer) NOT survey`.
**Response:** `200` β array of `PaperResult`:
```json
[
{
"id": "1993.tc-1.6",
"title": "Terminology and the computer - attention shifts to the micro",
"abstract": "β¦",
"authors": "Warren Weaver",
"venue": "TC",
"year": 1993,
"url": "https://aclanthology.org/1993.tc-1.6/",
"bibtex": "@inproceedings{weaver-1993-terminology,\n title = \"Terminology and the computer - attention shifts to the micro\",\n author = \"Weaver, Warren\",\n booktitle = \"Proceedings of the β¦\",\n year = \"1993\",\n url = \"https://aclanthology.org/1993.tc-1.6/\"\n}",
"pdf_url": "https://aclanthology.org/1993.tc-1.6.pdf"
}
]
```
`year` is `null` when the anthology has no year for a paper. `bibtex` is the
canonical ACL Anthology BibTeX entry for the paper (empty when the anthology
has no citable entry, e.g. some frontmatter). `pdf_url` is the direct link to
the paper's PDF (empty when the anthology has no PDF reference). Inactive
(retracted) papers are excluded.
### `GET /search/similarity?q=<query>&k=<n>`
Embedding-similarity search. The query is embedded via the external embedding
API, then matched against the FAISS index (cosine similarity over normalized
vectors). Results are sorted by descending similarity.
**Query parameters:**
| Param | Type | Default | Notes |
|-------|------|---------|--------------------------------------------------|
| `q` | str | β | Required. Free-text query, no FTS5 syntax. |
| `k` | int | `10` | Number of nearest neighbors to return. |
**Response:** `200` β array of `SimilarityResult` (a `PaperResult` plus a
similarity `score`):
```json
[
{
"id": "N18-3011",
"title": "β¦",
"abstract": "β¦",
"authors": "β¦",
"venue": "β¦",
"year": 2018,
"url": "https://aclanthology.org/N18-3011/",
"bibtex": "@inproceedings{β¦}",
"pdf_url": "https://aclanthology.org/N18-3011.pdf",
"score": 0.8123
}
]
```
`score` is cosine similarity in `[-1, 1]` (higher is more similar).
### `GET /paper/{paper_id}`
Metadata lookup by ACL Anthology paper id (e.g. `N18-3011`, `2023.acl-long.123`).
**Response:** `200` β a single `PaperResult` (shape as in `/search/keyword`),
including the canonical `bibtex` entry for citing the paper and its `pdf_url`.
Returns `404` if the id is unknown or the paper is inactive.
### Examples
```bash
# health
curl "http://localhost:8000/health"
# keyword search
curl "http://localhost:8000/search/keyword?q=transformer%20attention&limit=5"
# similarity search
curl "http://localhost:8000/search/similarity?q=attention%20mechanism&k=5"
# paper lookup
curl "http://localhost:8000/paper/1993.tc-1.6"
```
## Configuration
Settings are read from the environment (and, for local dev, from a `.env` file
in the working directory). Required:
- `HF_REPO_ID` β dataset repo holding `index.faiss` / `papers.db` / `state.json`
- `HF_TOKEN` β token with read access to that dataset repo
- `EMBEDDING_BASE_URL` β university embedding API base URL
- `EMBEDDING_API_KEY` β university embedding API key
Optional:
- `data_dir` β local directory for the downloaded snapshot (default `./data`)
## Local development
```bash
pip install -e ".[dev]"
python -m app # serves on http://0.0.0.0:8000 with reload
```
On startup the service downloads the snapshot from the HF Hub dataset repo into
`data_dir` and loads it into memory (~1.3 GB index + ~300 MB DB). The only
outbound call at request time is to the embedding API, to embed
similarity-search queries.
## Required Space secrets
- `HF_REPO_ID` β dataset repo holding `index.faiss` / `papers.db` / `state.json`
- `HF_TOKEN` β token with read access to that dataset repo
- `EMBEDDING_BASE_URL` β university embedding API base URL
- `EMBEDDING_API_KEY` β university embedding API key
## Required GitHub Actions secrets
- `HF_REPO_ID`, `HF_TOKEN`, `EMBEDDING_BASE_URL`, `EMBEDDING_API_KEY` β same as the Space secrets above
- `HF_SPACE_ID` β e.g. `your-org/acl-anthology-search-api`, used to trigger a restart after sync
|