revit-api-docs 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/CHANGELOG.md +112 -1
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/PKG-INFO +64 -29
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/README.md +62 -27
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/api_parser/parse_chm.py +23 -12
- revit_api_docs-0.3.0/pipeline/build_data_v1_1.py +992 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/embedder/embed.py +64 -27
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pyproject.toml +2 -2
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/__init__.py +1 -1
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/config.py +2 -1
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/data.py +14 -6
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/default_config.yaml +4 -2
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/reranker.py +57 -20
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/retriever.py +475 -112
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/server.py +33 -7
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/conftest.py +63 -3
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_bm25_index.py +12 -10
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_data.py +2 -2
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_rerank.py +90 -4
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_retriever.py +33 -25
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_server.py +37 -0
- revit_api_docs-0.3.0/tests/test_shipped_db.py +160 -0
- revit_api_docs-0.3.0/tests/test_vector_search.py +364 -0
- revit_api_docs-0.2.0/tests/test_shipped_db.py +0 -82
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/.gitignore +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/LICENSE +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/api_parser/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/api_parser/quality_agent.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/demo_dual_store.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/demo_production_real.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/demo_real_golden.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/demo_real_scoring.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/demo_scoring.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/demo_sdk_cleaning.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/embedder/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/knowledge_builder/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/run_all.ipynb +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/sdk_parser/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/sdk_parser/extract.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/pipeline/sdk_parser/quality_agent.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/__main__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/bm25.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/base.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/google.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/embedder/providers/openai.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/environment.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/environment.yaml +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/llm_client.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/__init__.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/loader.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage1_no_html.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage1_system.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage1_with_html.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage2.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.api_quality_stage2_system.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.rewrite_query.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.rewrite_query_system.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_extract_readme_system.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_extract_readme_user.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_golden_code.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_golden_code_system.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_file_batch.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_file_system.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_project.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/revit_api_docs/prompts/pipeline.sdk_quality_project_system.md +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/fixtures/retrieval_queries.yaml +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/fixtures/retrieval_queries_v2.yaml +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_bm25_recall.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_environment.py +0 -0
- {revit_api_docs-0.2.0 → revit_api_docs-0.3.0}/tests/test_package.py +0 -0
|
@@ -6,6 +6,116 @@ All notable changes to this project are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.3.0] - 2026-10-26
|
|
10
|
+
|
|
11
|
+
Vector hits now come back as the entries they describe and count also
|
|
12
|
+
without a reranker; reranking picks its provider from the keys that are set.
|
|
13
|
+
The data set `v1.1-data` adds constructor and interface member pages, and its
|
|
14
|
+
vector store lines up with the SQLite rows.
|
|
15
|
+
|
|
16
|
+
**Upgrading from 0.2.0** (`uvx --refresh revit-api-docs`): on the first start the server replaces an installed
|
|
17
|
+
`v1.0-data` (its `manifest.json` names the old release) with `v1.1-data`, a
|
|
18
|
+
download of 267 MB (all four files); a data directory without a
|
|
19
|
+
manifest (a hand-copied tree) is used as it is. With an embedding key and a
|
|
20
|
+
tree that still holds `v1.0-data`, the first vector query logs the warning
|
|
21
|
+
`vector_store_misaligned`: its record ids do not line up with the SQLite rows,
|
|
22
|
+
and hits are matched by entry name. Without any key nothing changes beyond the
|
|
23
|
+
new entries. Reranker choice: with only `COHERE_API_KEY` set Cohere still
|
|
24
|
+
reranks; with `TYPESAFE_API_KEY` set Jev now reranks without
|
|
25
|
+
`REVIT_API_DOCS_RERANK_PROVIDER=jev` (set the provider to `cohere` to keep
|
|
26
|
+
Cohere).
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Data set `v1.1-data` (`RELEASE_TAG`; the download URL and SHA-256 list in
|
|
31
|
+
`data.py` follow it): the 27,596 entries of `v1.0-data` are kept unchanged
|
|
32
|
+
under the same ids, and 1,266 pages of the same reference are appended
|
|
33
|
+
(ids 27,597-28,862): 1,040 constructor pages (`XYZ(Double, Double, Double)
|
|
34
|
+
Constructor`, `Transaction(Document, String) Constructor`, overload lists)
|
|
35
|
+
and 226 members whose C# signature has no `public`, mostly interface
|
|
36
|
+
members (`IExternalEventHandler.Execute`, `IConnector.Origin`,
|
|
37
|
+
`IFailuresPreprocessor.PreprocessFailures`) and explicit interface
|
|
38
|
+
implementations. 28,862 entries in all. Source: `RevitAPI.chm` of the
|
|
39
|
+
Revit 2026.3 SDK, whose pages are the same set as the Revit 2026 reference
|
|
40
|
+
the first release was built from. The API vector store is rebuilt from the
|
|
41
|
+
new SQLite with the same model (`text-embedding-3-large`, 3072 dimensions):
|
|
42
|
+
one record per row and every record id is its row id, so the first vector
|
|
43
|
+
query no longer logs `vector_store_misaligned` (`download` reports
|
|
44
|
+
`aligned`). The SDK files (`revit_sdk.db`, `chromadb_code.tar.gz`) are the
|
|
45
|
+
`v1.0-data` ones.
|
|
46
|
+
- The vector documents are now `name : summary` (`v1.0-data` embedded mostly
|
|
47
|
+
the entry name alone: 21,952 of its 28,863 records); on the 223 test
|
|
48
|
+
queries this raised fused nDCG@5 without a reranker from 0.610 to 0.647
|
|
49
|
+
(task requests 0.438 to 0.459) and left it with Jev at 0.842 against 0.846
|
|
50
|
+
(task requests 0.778 against 0.794).
|
|
51
|
+
- `pipeline/build_data_v1_1.py` (sdist only): builds `v1.1-data` from the
|
|
52
|
+
`v1.0-data` SQLite and the CHM pages: appends the pages the base lacks
|
|
53
|
+
(pages whose name is in the base under another `full_id`, or whose content
|
|
54
|
+
is a base row's under a name the v1.0 rewrite changed, are listed and not
|
|
55
|
+
appended), runs the quality agent on the new rows only, re-embeds every
|
|
56
|
+
row, packages the four release files with `SHA256SUMS.txt` and checks the
|
|
57
|
+
vector store against the rows without an API call.
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- Vector search returned unrelated entries. The vector store of the
|
|
62
|
+
`v1.0-data` release numbers its 28,863 API records independently of the
|
|
63
|
+
27,596 rows of `revit_api.db` (2 ids name the same entry in both), and hits
|
|
64
|
+
were looked up by record id. A hit is now matched to the row whose entry
|
|
65
|
+
name equals the record's `name` metadata (the row with the record's own id
|
|
66
|
+
when it carries that name; among rows sharing a name the one with the
|
|
67
|
+
record's `full_id` or `info`, else the lowest id). 27,591 records (95.6%)
|
|
68
|
+
reach 27,512 rows (99.7%); records without a row are dropped. The SDK sample
|
|
69
|
+
store's ids match its rows, and matching by project name keeps them. The
|
|
70
|
+
name map is built on the first vector query and kept in memory.
|
|
71
|
+
- Consistency probe: on the first vector query 50 records of each vector
|
|
72
|
+
collection are compared with SQLite. When fewer than 90% of the sampled ids
|
|
73
|
+
name the same entry as the row with that id, the warning
|
|
74
|
+
`vector_store_misaligned` is logged and hits are matched by name (`v1.0-data`:
|
|
75
|
+
0/50 ids, 49/50 names). When fewer than 50% of the sampled names are found
|
|
76
|
+
either, vector search is off for the process and keyword search answers
|
|
77
|
+
alone. `revit-api-docs download` prints the check for the installed data set.
|
|
78
|
+
- A second retriever in the same process could not open the vector store
|
|
79
|
+
("An instance of Chroma already exists ... with different settings"): each
|
|
80
|
+
ChromaDB client now gets its own `Settings` object.
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
|
|
84
|
+
- Hybrid ranking by reciprocal rank fusion: the vector hits and the BM25 hits,
|
|
85
|
+
`retrieval.api.top_k` (30) of each, are fused with score = sum of
|
|
86
|
+
1 / (60 + rank), and the best 30 go to the reranker; without a reranker they
|
|
87
|
+
are cut to `top_k`. On equal scores a keyword hit comes first. Before, the
|
|
88
|
+
two lists were merged by distances on different scales, so without a
|
|
89
|
+
reranker vector-only hits never reached the top 5, and up to 60 candidates
|
|
90
|
+
went to the reranker. Without an embedding key the BM25 order and results
|
|
91
|
+
are unchanged. On 223 English test queries without reranking (measured on
|
|
92
|
+
`v1.1-data`): nDCG@5 0.557 with BM25 alone, 0.647 fused, and 0.355 -> 0.459
|
|
93
|
+
on the 113 multi-step task requests, whose answer is among the top 30 for
|
|
94
|
+
82% instead of 72% of them.
|
|
95
|
+
- The default rerank provider is `auto`: Jev when `TYPESAFE_API_KEY` is set,
|
|
96
|
+
otherwise Cohere when `COHERE_API_KEY` is set, otherwise none.
|
|
97
|
+
`REVIT_API_DOCS_RERANK_PROVIDER` (now `auto`, `jev`, `cohere` or `none`)
|
|
98
|
+
still wins, and the `Rerank:` line names the provider that ran. README:
|
|
99
|
+
Jev is the recommended reranker, Cohere optional and the fallback for Jev.
|
|
100
|
+
- Cohere requests time out after 20 s instead of 10 s (the same as Jev); 10 s
|
|
101
|
+
cut off about 1% of calls.
|
|
102
|
+
- `search_revit_api` and `get_code_examples` are unchanged: names,
|
|
103
|
+
parameters and the first output line. The tool description now counts
|
|
104
|
+
28,862 entries.
|
|
105
|
+
- CHM parser (`pipeline/api_parser/parse_chm.py`): `parse_single_html` and
|
|
106
|
+
`parse_all_api_html` take `keep_constructors` (default `False`, the old
|
|
107
|
+
behaviour); the C# signature no longer has to contain `public` (interface
|
|
108
|
+
members such as `void Execute(UIApplication app)` were skipped as a whole
|
|
109
|
+
page); a page with neither a signature nor a members table is still
|
|
110
|
+
skipped.
|
|
111
|
+
- `pipeline.embedder.embed.embed_api_data(..., resume=False,
|
|
112
|
+
document_template="NS")`: with `resume=True` the collection is kept and
|
|
113
|
+
only missing row ids are embedded; `document_template` picks the embedded
|
|
114
|
+
text per API row (`NS` `name : summary`, the default and the `v1.1-data`
|
|
115
|
+
store; `FS` `full_id : summary`, the earlier behaviour; `N` the entry name)
|
|
116
|
+
and is recorded in `meta.json`. `pipeline/build_data_v1_1.py
|
|
117
|
+
--document-template` passes it on (default `NS`).
|
|
118
|
+
|
|
9
119
|
## [0.2.0] - 2026-10-26
|
|
10
120
|
|
|
11
121
|
Better candidates without any key, and an opt-in relevance check: BM25 keyword
|
|
@@ -147,6 +257,7 @@ no git history).
|
|
|
147
257
|
- CI (tests + build on Linux/Windows, Python 3.11/3.13) and PyPI Trusted
|
|
148
258
|
Publishing on version tags.
|
|
149
259
|
|
|
150
|
-
[Unreleased]: https://github.com/revitbridge/revit-api-docs/compare/v0.
|
|
260
|
+
[Unreleased]: https://github.com/revitbridge/revit-api-docs/compare/v0.3.0...HEAD
|
|
261
|
+
[0.3.0]: https://github.com/revitbridge/revit-api-docs/compare/v0.2.0...v0.3.0
|
|
151
262
|
[0.2.0]: https://github.com/revitbridge/revit-api-docs/compare/v0.1.0...v0.2.0
|
|
152
263
|
[0.1.0]: https://github.com/revitbridge/revit-api-docs/releases/tag/v0.1.0
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: revit-api-docs
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Revit API reference search for MCP hosts: local semantic + keyword lookup over the Revit 2026 API docs and SDK samples
|
|
5
5
|
Project-URL: Homepage, https://github.com/revitbridge/revit-api-docs
|
|
6
6
|
Project-URL: Issues, https://github.com/revitbridge/revit-api-docs/issues
|
|
7
7
|
Project-URL: Changelog, https://github.com/revitbridge/revit-api-docs/blob/main/CHANGELOG.md
|
|
8
|
-
Project-URL: Data, https://github.com/revitbridge/revit-api-docs/releases/tag/v1.
|
|
8
|
+
Project-URL: Data, https://github.com/revitbridge/revit-api-docs/releases/tag/v1.1-data
|
|
9
9
|
Author: revitbridge
|
|
10
10
|
License-Expression: MIT
|
|
11
11
|
License-File: LICENSE
|
|
@@ -35,8 +35,8 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
# revit-api-docs
|
|
36
36
|
|
|
37
37
|
Revit API reference search as an MCP server: two read-only tools over a local
|
|
38
|
-
copy of the Revit 2026 API documentation (
|
|
39
|
-
and enums) and the official SDK samples (153 projects).
|
|
38
|
+
copy of the Revit 2026 API documentation (28,862 classes, constructors,
|
|
39
|
+
methods, properties and enums) and the official SDK samples (153 projects).
|
|
40
40
|
|
|
41
41
|
**Optional.** It exists for models that do not know the Revit API well. If
|
|
42
42
|
your model already writes correct Revit code, you do not need it;
|
|
@@ -97,8 +97,8 @@ keep it on a loopback address, or put it behind a reverse proxy that
|
|
|
97
97
|
authenticates; the server logs a warning when `--host` is not a loopback
|
|
98
98
|
address.
|
|
99
99
|
|
|
100
|
-
On the first start the server downloads the data set (
|
|
101
|
-
this repository's [`v1.
|
|
100
|
+
On the first start the server downloads the data set (267 MB, four files) from
|
|
101
|
+
this repository's [`v1.1-data` release](https://github.com/revitbridge/revit-api-docs/releases/tag/v1.1-data)
|
|
102
102
|
into `%LOCALAPPDATA%\revit-api-docs` (Windows) or `~/.local/share/revit-api-docs`
|
|
103
103
|
(Linux; `~/Library/Application Support/revit-api-docs` on macOS), verifies each
|
|
104
104
|
file's SHA-256 and unpacks the vector stores. Tool calls made while that runs
|
|
@@ -133,11 +133,13 @@ reference: BM25 over a full-text index of entry names, IDs, summaries and
|
|
|
133
133
|
signatures, where identifiers also match by their camel-case parts, so a
|
|
134
134
|
misspelt or unknown name still gets candidates. The index (11.8 MB) is built
|
|
135
135
|
next to the data set on first use (under a second). With an embedding key it
|
|
136
|
-
adds semantic search over the vector store
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
adds semantic search over the vector store and fuses the two rankings by rank,
|
|
137
|
+
which helps most with task descriptions that do not name the API. With a
|
|
138
|
+
TypeSafe key it reranks the candidates with Jev, which returns a calibrated
|
|
139
|
+
relevance per entry; with only a Cohere key it reranks with Cohere. With a Jev
|
|
140
|
+
threshold set and no entry reaching it, the output starts with an abstention
|
|
141
|
+
line and then lists the candidates with their relevance, for reference. See
|
|
142
|
+
Configure.
|
|
141
143
|
|
|
142
144
|
Try it from a terminal (installs the data set if needed):
|
|
143
145
|
|
|
@@ -158,39 +160,72 @@ All settings are environment variables; there is no config file to edit.
|
|
|
158
160
|
| `REVIT_API_DOCS_EMBEDDING_API_KEY` | *(unset)* | Key for the embedding endpoint; turns on semantic (vector) search. `OPENROUTER_API_KEY` is used when this is unset |
|
|
159
161
|
| `REVIT_API_DOCS_EMBEDDING_BASE_URL` | `https://openrouter.ai/api/v1` | Any OpenAI-compatible `/embeddings` endpoint |
|
|
160
162
|
| `REVIT_API_DOCS_EMBEDDING_MODEL` | `openai/text-embedding-3-large` | Must produce the same 3072-dimensional space the shipped vectors were built with (`text-embedding-3-large`); another model makes vector search return noise |
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
163
|
+
| `TYPESAFE_API_KEY` | *(unset)* | Key for TypeSafe System One (Jev), the recommended reranker: with the default provider `auto` setting this key is enough. At most 30 candidates per request, 2 requests in flight, 2 retries, 20 s timeout |
|
|
164
|
+
| `COHERE_API_KEY` | *(unset)* | Optional. Cohere `rerank-v3.5` (native REST API, 20 s timeout): reranks when it is the only rerank key set, and is the fallback for a failed Jev call when both are set |
|
|
165
|
+
| `REVIT_API_DOCS_RERANK_PROVIDER` | `auto` | `auto`, `jev`, `cohere` or `none`. `auto` reranks with Jev when `TYPESAFE_API_KEY` is set, otherwise with Cohere when `COHERE_API_KEY` is set, otherwise not at all; an explicit value wins. With Jev, a failed or unconfigured call falls back to Cohere when `COHERE_API_KEY` is set, otherwise to no reranking; the first output line says which one ran |
|
|
164
166
|
| `REVIT_API_DOCS_JEV_MODEL` | `jev-latest` | Jev model or alias; pin a version such as `jev-1.14.0` for reproducible results |
|
|
165
167
|
| `REVIT_API_DOCS_MIN_RELEVANCE` | *(unset)* | Probability 0-1 (`retrieval.api.min_relevance`). Only honoured while Jev ranks the results, and it only decides whether to abstain: no entry is dropped, every result keeps its `Relevance` line. When no entry reaches it, `search_revit_api` starts with "No entry in the Revit 2026 data set scored high enough for this query", notes that the member may be absent from this version or listed under a different name or wording, and lists the low-scoring candidates for reference. No effect with Cohere or without reranking. See "Reranking with Jev" below |
|
|
166
|
-
| `REVIT_API_DOCS_RELEASE_URL` | this repository's `v1.
|
|
168
|
+
| `REVIT_API_DOCS_RELEASE_URL` | this repository's `v1.1-data` release | Mirror for the data files; the SHA-256 checks still apply |
|
|
167
169
|
| `HTTPS_PROXY` / `HTTP_PROXY` | *(unset)* | Proxy for the embedding and rerank calls |
|
|
168
170
|
|
|
169
171
|
Pass them through the `env` block of your MCP host's server entry.
|
|
170
172
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
173
|
+
Recommended setup: a `TYPESAFE_API_KEY` (Jev reranking), plus an embedding key
|
|
174
|
+
when requests describe multi-step tasks rather than name APIs. Without any key
|
|
175
|
+
the server runs on BM25 keyword search alone.
|
|
176
|
+
|
|
177
|
+
**Reranking with Jev.** Jev is the recommended reranker, and the default
|
|
178
|
+
provider (`auto`) uses it whenever `TYPESAFE_API_KEY` is set. Cohere is
|
|
179
|
+
optional: `auto` uses it when only `COHERE_API_KEY` is set, and with both keys
|
|
180
|
+
it is the fallback for a failed Jev call. Measured on `v1.0-data`: on 60
|
|
181
|
+
English test queries (50 with a known answer) over the keyword (BM25)
|
|
182
|
+
candidates, with no embedding key, Jev raised nDCG@5 from 0.675 to 0.871 and
|
|
183
|
+
never turned a correct top-5 answer into a miss. On 223 further queries over
|
|
184
|
+
the same candidates Jev reached an nDCG@5 of 0.788 against Cohere's 0.674. Input tokens cost about $0.23 per 1,000
|
|
185
|
+
queries; Cohere bills $2 per 1,000 searches.
|
|
177
186
|
`REVIT_API_DOCS_MIN_RELEVANCE` stays unset by default. Set to 0.15 it filters
|
|
178
187
|
out clearly unrelated queries (questions that are not about Revit, types this
|
|
179
188
|
data set does not have), abstaining on about 2.5% of the queries that do have
|
|
180
|
-
an answer. It cannot spot a misspelt or misplaced
|
|
181
|
-
usually gets the closest real API as the first
|
|
182
|
-
compile check. **Do not use 0.5**: it
|
|
183
|
-
have an answer. What TypeSafe keeps: see the `jev-data-handling` note
|
|
189
|
+
an answer (measured on `v1.0-data`). It cannot spot a misspelt or misplaced
|
|
190
|
+
member name: such a query usually gets the closest real API as the first
|
|
191
|
+
result, to be confirmed with a compile check. **Do not use 0.5**: it
|
|
192
|
+
abstained on 14% of the queries that have an answer. What TypeSafe keeps: see the `jev-data-handling` note
|
|
184
193
|
(`uvx revit-api-docs environment typesafe`).
|
|
185
194
|
|
|
195
|
+
**Vector search.** An embedding key (`REVIT_API_DOCS_EMBEDDING_API_KEY`, or
|
|
196
|
+
`OPENROUTER_API_KEY`) turns it on; each query then costs one embedding request
|
|
197
|
+
(about 0.9 s). The vector hits and the BM25 hits, 30 of each, are fused by
|
|
198
|
+
reciprocal rank (score = sum of 1 / (60 + rank)) and the best 30 go to the
|
|
199
|
+
reranker; without a reranker they are cut to `top_k`. On 223 English test
|
|
200
|
+
queries without reranking (measured on `v1.1-data`), fusion raises nDCG@5
|
|
201
|
+
from 0.557 (BM25 alone) to 0.647, and on the 113 of them that describe a
|
|
202
|
+
multi-step task from 0.355 to 0.459, with an answer among the top 30 for 82%
|
|
203
|
+
of those instead of 72%. Each
|
|
204
|
+
vector hit is matched to its entry by name. On the first vector query the
|
|
205
|
+
server samples 50 records of each vector collection: when the record ids do
|
|
206
|
+
not line up with the rows it logs the warning `vector_store_misaligned` and
|
|
207
|
+
keeps matching by name (the older `v1.0-data` vector store numbers its records
|
|
208
|
+
differently from the rows of `revit_api.db`; `v1.1-data` is aligned and logs
|
|
209
|
+
nothing); when the names are not found either, it turns vector search off
|
|
210
|
+
until the server restarts and answers from keyword search. `revit-api-docs download`
|
|
211
|
+
prints the same check for the installed data set.
|
|
212
|
+
|
|
186
213
|
Privacy: with an embedding, Cohere or TypeSafe key the query text and the
|
|
187
214
|
candidate API entries (public documentation) are sent to that provider. Keep
|
|
188
215
|
queries to API names and generic task descriptions, in English.
|
|
189
216
|
|
|
190
|
-
Data set: the
|
|
191
|
-
2026
|
|
192
|
-
|
|
193
|
-
|
|
217
|
+
Data set (`v1.1-data`): the API reference comes from `RevitAPI.chm` of the
|
|
218
|
+
Revit 2026.3 SDK (the same pages as the Revit 2026 reference) and includes
|
|
219
|
+
constructor pages and interface members such as
|
|
220
|
+
`IExternalEventHandler.Execute`: 28,862 entries, of which the 27,596 of
|
|
221
|
+
`v1.0-data` are unchanged under the same ids. The SDK samples (153 projects)
|
|
222
|
+
come from the Revit 2026 SDK. The SQLite databases and ChromaDB indexes were
|
|
223
|
+
built with the pipeline in `pipeline/` (`uv sync --extra pipeline`; needs the
|
|
224
|
+
CHM, the SDK and OpenRouter/Cohere keys in the environment). `v1.1-data` was
|
|
225
|
+
built from `v1.0-data` with `uv run python -m pipeline.build_data_v1_1
|
|
226
|
+
--html-dir <CHM html dir> --base-db <v1.0-data dir>/sqlite/revit_api.db`, which
|
|
227
|
+
appends the pages `v1.0-data` lacked and rebuilds the API vector store so that
|
|
228
|
+
every record id is its row id. The server does not need any of that.
|
|
194
229
|
|
|
195
230
|
Development:
|
|
196
231
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# revit-api-docs
|
|
2
2
|
|
|
3
3
|
Revit API reference search as an MCP server: two read-only tools over a local
|
|
4
|
-
copy of the Revit 2026 API documentation (
|
|
5
|
-
and enums) and the official SDK samples (153 projects).
|
|
4
|
+
copy of the Revit 2026 API documentation (28,862 classes, constructors,
|
|
5
|
+
methods, properties and enums) and the official SDK samples (153 projects).
|
|
6
6
|
|
|
7
7
|
**Optional.** It exists for models that do not know the Revit API well. If
|
|
8
8
|
your model already writes correct Revit code, you do not need it;
|
|
@@ -63,8 +63,8 @@ keep it on a loopback address, or put it behind a reverse proxy that
|
|
|
63
63
|
authenticates; the server logs a warning when `--host` is not a loopback
|
|
64
64
|
address.
|
|
65
65
|
|
|
66
|
-
On the first start the server downloads the data set (
|
|
67
|
-
this repository's [`v1.
|
|
66
|
+
On the first start the server downloads the data set (267 MB, four files) from
|
|
67
|
+
this repository's [`v1.1-data` release](https://github.com/revitbridge/revit-api-docs/releases/tag/v1.1-data)
|
|
68
68
|
into `%LOCALAPPDATA%\revit-api-docs` (Windows) or `~/.local/share/revit-api-docs`
|
|
69
69
|
(Linux; `~/Library/Application Support/revit-api-docs` on macOS), verifies each
|
|
70
70
|
file's SHA-256 and unpacks the vector stores. Tool calls made while that runs
|
|
@@ -99,11 +99,13 @@ reference: BM25 over a full-text index of entry names, IDs, summaries and
|
|
|
99
99
|
signatures, where identifiers also match by their camel-case parts, so a
|
|
100
100
|
misspelt or unknown name still gets candidates. The index (11.8 MB) is built
|
|
101
101
|
next to the data set on first use (under a second). With an embedding key it
|
|
102
|
-
adds semantic search over the vector store
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
adds semantic search over the vector store and fuses the two rankings by rank,
|
|
103
|
+
which helps most with task descriptions that do not name the API. With a
|
|
104
|
+
TypeSafe key it reranks the candidates with Jev, which returns a calibrated
|
|
105
|
+
relevance per entry; with only a Cohere key it reranks with Cohere. With a Jev
|
|
106
|
+
threshold set and no entry reaching it, the output starts with an abstention
|
|
107
|
+
line and then lists the candidates with their relevance, for reference. See
|
|
108
|
+
Configure.
|
|
107
109
|
|
|
108
110
|
Try it from a terminal (installs the data set if needed):
|
|
109
111
|
|
|
@@ -124,39 +126,72 @@ All settings are environment variables; there is no config file to edit.
|
|
|
124
126
|
| `REVIT_API_DOCS_EMBEDDING_API_KEY` | *(unset)* | Key for the embedding endpoint; turns on semantic (vector) search. `OPENROUTER_API_KEY` is used when this is unset |
|
|
125
127
|
| `REVIT_API_DOCS_EMBEDDING_BASE_URL` | `https://openrouter.ai/api/v1` | Any OpenAI-compatible `/embeddings` endpoint |
|
|
126
128
|
| `REVIT_API_DOCS_EMBEDDING_MODEL` | `openai/text-embedding-3-large` | Must produce the same 3072-dimensional space the shipped vectors were built with (`text-embedding-3-large`); another model makes vector search return noise |
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
129
|
+
| `TYPESAFE_API_KEY` | *(unset)* | Key for TypeSafe System One (Jev), the recommended reranker: with the default provider `auto` setting this key is enough. At most 30 candidates per request, 2 requests in flight, 2 retries, 20 s timeout |
|
|
130
|
+
| `COHERE_API_KEY` | *(unset)* | Optional. Cohere `rerank-v3.5` (native REST API, 20 s timeout): reranks when it is the only rerank key set, and is the fallback for a failed Jev call when both are set |
|
|
131
|
+
| `REVIT_API_DOCS_RERANK_PROVIDER` | `auto` | `auto`, `jev`, `cohere` or `none`. `auto` reranks with Jev when `TYPESAFE_API_KEY` is set, otherwise with Cohere when `COHERE_API_KEY` is set, otherwise not at all; an explicit value wins. With Jev, a failed or unconfigured call falls back to Cohere when `COHERE_API_KEY` is set, otherwise to no reranking; the first output line says which one ran |
|
|
130
132
|
| `REVIT_API_DOCS_JEV_MODEL` | `jev-latest` | Jev model or alias; pin a version such as `jev-1.14.0` for reproducible results |
|
|
131
133
|
| `REVIT_API_DOCS_MIN_RELEVANCE` | *(unset)* | Probability 0-1 (`retrieval.api.min_relevance`). Only honoured while Jev ranks the results, and it only decides whether to abstain: no entry is dropped, every result keeps its `Relevance` line. When no entry reaches it, `search_revit_api` starts with "No entry in the Revit 2026 data set scored high enough for this query", notes that the member may be absent from this version or listed under a different name or wording, and lists the low-scoring candidates for reference. No effect with Cohere or without reranking. See "Reranking with Jev" below |
|
|
132
|
-
| `REVIT_API_DOCS_RELEASE_URL` | this repository's `v1.
|
|
134
|
+
| `REVIT_API_DOCS_RELEASE_URL` | this repository's `v1.1-data` release | Mirror for the data files; the SHA-256 checks still apply |
|
|
133
135
|
| `HTTPS_PROXY` / `HTTP_PROXY` | *(unset)* | Proxy for the embedding and rerank calls |
|
|
134
136
|
|
|
135
137
|
Pass them through the `env` block of your MCP host's server entry.
|
|
136
138
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
Recommended setup: a `TYPESAFE_API_KEY` (Jev reranking), plus an embedding key
|
|
140
|
+
when requests describe multi-step tasks rather than name APIs. Without any key
|
|
141
|
+
the server runs on BM25 keyword search alone.
|
|
142
|
+
|
|
143
|
+
**Reranking with Jev.** Jev is the recommended reranker, and the default
|
|
144
|
+
provider (`auto`) uses it whenever `TYPESAFE_API_KEY` is set. Cohere is
|
|
145
|
+
optional: `auto` uses it when only `COHERE_API_KEY` is set, and with both keys
|
|
146
|
+
it is the fallback for a failed Jev call. Measured on `v1.0-data`: on 60
|
|
147
|
+
English test queries (50 with a known answer) over the keyword (BM25)
|
|
148
|
+
candidates, with no embedding key, Jev raised nDCG@5 from 0.675 to 0.871 and
|
|
149
|
+
never turned a correct top-5 answer into a miss. On 223 further queries over
|
|
150
|
+
the same candidates Jev reached an nDCG@5 of 0.788 against Cohere's 0.674. Input tokens cost about $0.23 per 1,000
|
|
151
|
+
queries; Cohere bills $2 per 1,000 searches.
|
|
143
152
|
`REVIT_API_DOCS_MIN_RELEVANCE` stays unset by default. Set to 0.15 it filters
|
|
144
153
|
out clearly unrelated queries (questions that are not about Revit, types this
|
|
145
154
|
data set does not have), abstaining on about 2.5% of the queries that do have
|
|
146
|
-
an answer. It cannot spot a misspelt or misplaced
|
|
147
|
-
usually gets the closest real API as the first
|
|
148
|
-
compile check. **Do not use 0.5**: it
|
|
149
|
-
have an answer. What TypeSafe keeps: see the `jev-data-handling` note
|
|
155
|
+
an answer (measured on `v1.0-data`). It cannot spot a misspelt or misplaced
|
|
156
|
+
member name: such a query usually gets the closest real API as the first
|
|
157
|
+
result, to be confirmed with a compile check. **Do not use 0.5**: it
|
|
158
|
+
abstained on 14% of the queries that have an answer. What TypeSafe keeps: see the `jev-data-handling` note
|
|
150
159
|
(`uvx revit-api-docs environment typesafe`).
|
|
151
160
|
|
|
161
|
+
**Vector search.** An embedding key (`REVIT_API_DOCS_EMBEDDING_API_KEY`, or
|
|
162
|
+
`OPENROUTER_API_KEY`) turns it on; each query then costs one embedding request
|
|
163
|
+
(about 0.9 s). The vector hits and the BM25 hits, 30 of each, are fused by
|
|
164
|
+
reciprocal rank (score = sum of 1 / (60 + rank)) and the best 30 go to the
|
|
165
|
+
reranker; without a reranker they are cut to `top_k`. On 223 English test
|
|
166
|
+
queries without reranking (measured on `v1.1-data`), fusion raises nDCG@5
|
|
167
|
+
from 0.557 (BM25 alone) to 0.647, and on the 113 of them that describe a
|
|
168
|
+
multi-step task from 0.355 to 0.459, with an answer among the top 30 for 82%
|
|
169
|
+
of those instead of 72%. Each
|
|
170
|
+
vector hit is matched to its entry by name. On the first vector query the
|
|
171
|
+
server samples 50 records of each vector collection: when the record ids do
|
|
172
|
+
not line up with the rows it logs the warning `vector_store_misaligned` and
|
|
173
|
+
keeps matching by name (the older `v1.0-data` vector store numbers its records
|
|
174
|
+
differently from the rows of `revit_api.db`; `v1.1-data` is aligned and logs
|
|
175
|
+
nothing); when the names are not found either, it turns vector search off
|
|
176
|
+
until the server restarts and answers from keyword search. `revit-api-docs download`
|
|
177
|
+
prints the same check for the installed data set.
|
|
178
|
+
|
|
152
179
|
Privacy: with an embedding, Cohere or TypeSafe key the query text and the
|
|
153
180
|
candidate API entries (public documentation) are sent to that provider. Keep
|
|
154
181
|
queries to API names and generic task descriptions, in English.
|
|
155
182
|
|
|
156
|
-
Data set: the
|
|
157
|
-
2026
|
|
158
|
-
|
|
159
|
-
|
|
183
|
+
Data set (`v1.1-data`): the API reference comes from `RevitAPI.chm` of the
|
|
184
|
+
Revit 2026.3 SDK (the same pages as the Revit 2026 reference) and includes
|
|
185
|
+
constructor pages and interface members such as
|
|
186
|
+
`IExternalEventHandler.Execute`: 28,862 entries, of which the 27,596 of
|
|
187
|
+
`v1.0-data` are unchanged under the same ids. The SDK samples (153 projects)
|
|
188
|
+
come from the Revit 2026 SDK. The SQLite databases and ChromaDB indexes were
|
|
189
|
+
built with the pipeline in `pipeline/` (`uv sync --extra pipeline`; needs the
|
|
190
|
+
CHM, the SDK and OpenRouter/Cohere keys in the environment). `v1.1-data` was
|
|
191
|
+
built from `v1.0-data` with `uv run python -m pipeline.build_data_v1_1
|
|
192
|
+
--html-dir <CHM html dir> --base-db <v1.0-data dir>/sqlite/revit_api.db`, which
|
|
193
|
+
appends the pages `v1.0-data` lacked and rebuilds the API vector store so that
|
|
194
|
+
every record id is its row id. The server does not need any of that.
|
|
160
195
|
|
|
161
196
|
Development:
|
|
162
197
|
|
|
@@ -19,13 +19,19 @@ from pathlib import Path
|
|
|
19
19
|
from bs4 import BeautifulSoup
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def parse_single_html(html_path: str) -> dict | None:
|
|
22
|
+
def parse_single_html(html_path: str, *, keep_constructors: bool = False) -> dict | None:
|
|
23
23
|
"""
|
|
24
24
|
解析单个 API HTML 文件,提取结构化数据
|
|
25
25
|
|
|
26
|
+
Args:
|
|
27
|
+
html_path: HTML 文件路径
|
|
28
|
+
keep_constructors: True 时保留构造函数页(data release v1.1 起收录);
|
|
29
|
+
默认 False,与旧行为相同(丢弃构造函数页)
|
|
30
|
+
|
|
26
31
|
Returns:
|
|
27
32
|
dict with keys: name, full_id, namespace, content_type, info, summary,
|
|
28
|
-
remark, parameters, exceptions, members, keywords
|
|
33
|
+
remark, parameters, exceptions, members, keywords,
|
|
34
|
+
_source_file(源 HTML 路径,供 quality_agent 读取原文;不入 SQLite)
|
|
29
35
|
如果不是有效的 API 文档页面返回 None
|
|
30
36
|
"""
|
|
31
37
|
try:
|
|
@@ -52,8 +58,9 @@ def parse_single_html(html_path: str) -> dict | None:
|
|
|
52
58
|
return None
|
|
53
59
|
|
|
54
60
|
# --- 过滤构造函数页面(ctor) ---
|
|
55
|
-
#
|
|
56
|
-
|
|
61
|
+
# 旧版默认丢弃构造函数页;keep_constructors=True 时保留(v1.1-data 起收录,
|
|
62
|
+
# `new XYZ(x, y, z)`、`new Transaction(doc, name)` 之类的查询需要它们)
|
|
63
|
+
if not keep_constructors and _is_constructor_page(title, full_id):
|
|
57
64
|
return None
|
|
58
65
|
|
|
59
66
|
# 命名空间
|
|
@@ -184,8 +191,10 @@ def _extract_api_fullname(soup: BeautifulSoup, title: str) -> str | None:
|
|
|
184
191
|
|
|
185
192
|
def _extract_csharp_signature(soup: BeautifulSoup) -> str:
|
|
186
193
|
"""
|
|
187
|
-
从 HTML 中提取 C#
|
|
188
|
-
对应旧版 get_csharp_full_name
|
|
194
|
+
从 HTML 中提取 C# 签名(IDAB_code_Div1 的 <pre>,非空即可)。
|
|
195
|
+
对应旧版 get_csharp_full_name 逻辑;旧版只保留含 public 的签名,接口成员
|
|
196
|
+
(如 `void Execute(UIApplication app)`)与显式接口实现因此被整页跳过,
|
|
197
|
+
现在不再要求 public。
|
|
189
198
|
"""
|
|
190
199
|
div = soup.find("div", id="IDAB_code_Div1")
|
|
191
200
|
if not div:
|
|
@@ -196,7 +205,7 @@ def _extract_csharp_signature(soup: BeautifulSoup) -> str:
|
|
|
196
205
|
return ""
|
|
197
206
|
|
|
198
207
|
text = pre.get_text(separator=" ", strip=True)
|
|
199
|
-
if
|
|
208
|
+
if not text:
|
|
200
209
|
return ""
|
|
201
210
|
|
|
202
211
|
# 归一化空白
|
|
@@ -345,16 +354,18 @@ def _extract_members_table(topic_content) -> str:
|
|
|
345
354
|
return "\n".join(members)
|
|
346
355
|
|
|
347
356
|
|
|
348
|
-
def parse_all_api_html(html_dir: str, *, limit: int | None = None
|
|
357
|
+
def parse_all_api_html(html_dir: str, *, limit: int | None = None,
|
|
358
|
+
keep_constructors: bool = False) -> list[dict]:
|
|
349
359
|
"""
|
|
350
360
|
解析目录下所有(或前 limit 个)API HTML 文件
|
|
351
361
|
|
|
352
362
|
Args:
|
|
353
|
-
html_dir:
|
|
354
|
-
limit:
|
|
363
|
+
html_dir: CHM 解压后的 HTML 文件目录
|
|
364
|
+
limit: 仅解析前 N 个文件(调试用),None 表示全量
|
|
365
|
+
keep_constructors: True 时保留构造函数页(见 parse_single_html)
|
|
355
366
|
|
|
356
367
|
Returns:
|
|
357
|
-
list of parsed API data dicts
|
|
368
|
+
list of parsed API data dicts(已过滤命名空间页等噪音;默认也过滤构造函数)
|
|
358
369
|
"""
|
|
359
370
|
results = []
|
|
360
371
|
html_dir = Path(html_dir)
|
|
@@ -372,7 +383,7 @@ def parse_all_api_html(html_dir: str, *, limit: int | None = None) -> list[dict]
|
|
|
372
383
|
if i % 1000 == 0 and i > 0:
|
|
373
384
|
print(f" 解析进度: {i}/{total} 有效={len(results)} ctor跳过={skipped_ctor} 噪音跳过={skipped_noise}")
|
|
374
385
|
try:
|
|
375
|
-
data = parse_single_html(str(html_file))
|
|
386
|
+
data = parse_single_html(str(html_file), keep_constructors=keep_constructors)
|
|
376
387
|
if data:
|
|
377
388
|
results.append(data)
|
|
378
389
|
else:
|