Docs / Search API
Search a project
POST a question, get back ranked passages.
Endpoint
1POST /grape/{project}/searchExample
A real request, and the response Grape returned in 9 ms, trimmed to two passages.
1curl -X POST https://grape-inc.in/grape/$PROJECT/search \2 -H "Authorization: Bearer $GRAPE_KEY" \3 -d '{"query": "How many hearts does an octopus have?", "limit": 2}'
1{2 "total": 173,3 "coverage": 0.84,4 "terms": ["many", "heart", "octopu"],5 "hits": [6 { "path": "Octopus.txt", "line": 32, "score": 26.1,7 "text": "... They have three hearts; a systemic or main heart ..." },8 { "path": "Octopus.txt", "line": 33, "score": 18.4,9 "text": "The systemic heart has muscular contractile walls ..." }10 ]11}
Request fields
| Field | Type | Description |
|---|---|---|
| query | string | The question in plain words. Grape chooses the search terms. Required, or queries. |
| queries | array | Instead of query: one question per part. Each part is ranked on its own, then merged. |
| limit | number | How many passages to return. Defaults to 6. |
| snippet | number | Cut each passage to about this many characters, centred on the match. |
| rerank | boolean | Set to false to skip the reranker and the off-topic check. On by default. |
Response fields
| Field | Type | Description |
|---|---|---|
| hits | array | Ranked passages: path, line (and page for PDFs), score, text, and section: the heading or code definition the line sits under. |
| coverage | number | 0 to 1: how much of the question the best passage explains. |
| terms | array | The words Grape actually searched for. |
| total | number | How many lines matched before ranking. |
| refused | boolean | Present and true when the question is clearly not covered by the documents. hits is empty. |
| files | array | Present when coverage is under 0.5: up to 5 files whose name, opening line or terms share the question's words. Search again with their terms. |
| rerank_score | number | On each hit, for English questions: the reranker's score. Higher is closer. |
English questions over English passages are reranked by a small cross-encoder that runs on our server, and a clearly off-topic question comes back with refused: true. Your app can answer "Not in the documents" without calling an LLM at all.