--- license: apache-2.0 language: - en tags: - ros2 - ros - robotics - rag - retrieval - faiss - documentation - qwen - offline pipeline_tag: sentence-similarity library_name: sentence-transformers --- # ROS 2 coding assistant A retrieval index over the ROS 2 documentation, built to give a local coding assistant current, citable answers — offline, on CPU, with every claim traceable to the page it came from. - **Space:** https://huggingface.co/spaces/eoinedge/ros2 - **Model repo:** https://huggingface.co/eoinedge/ros2 - **Source:** https://github.com/eoinjordan/ros2-coding-assistant - **Companion build for Zephyr RTOS:** https://github.com/eoinjordan/zephyrproject-rag ## Why this exists ROS 2 changes across distributions, and a general coding model will happily give you a Foxy answer for a Rolling question, or reach for a ROS 1 habit that has no ROS 2 equivalent. On robotics work that surfaces late — often on hardware. Retrieval fixes the currency problem without retraining anything. The index is rebuilt from the documentation source, so it is exactly as current as the commit it was built from, and `--ref` selects the distribution. ## Current index | | | |---|---| | Documents | 341 | | Chunks | 5,134 | | Embedding model | `sentence-transformers/all-MiniLM-L6-v2` (384-dim) | | Index | FAISS `IndexFlatIP`, cosine over normalised vectors | | Source | `ros2/ros2_documentation` `rolling` @ `a74c8f1` | ## Quick start ```bash git clone https://github.com/eoinjordan/ros2-coding-assistant cd ros2-coding-assistant python -m venv .venv && .venv\Scripts\Activate.ps1 pip install -r requirements.txt python scripts/fetch_docs.py # rolling by default python scripts/fetch_docs.py --ref jazzy # or a specific distribution python scripts/build_index.py python scripts/ask.py "How do I write a lifecycle node?" --retrieve-only ``` `--retrieve-only` skips the generator: no model download, CPU-only, sub-second. Drop the flag to generate with Qwen Coder over the retrieved passages, or run the app: ```bash python app.py # http://localhost:7860 ``` ## Shared pipeline This runs the same chunker, retriever and trainer as the Zephyr build. Everything project-specific lives in [`scripts/source_config.py`](scripts/source_config.py): the repository, the doc root, the URL template, the skip rules and the example questions. Adding a third project is a config file, not a fork. Two things differ from Zephyr and are worth knowing if you adapt this again: - **Docs live in `source/`, not `doc/`**, and each distribution is a branch rather than a tag, so `--ref` picks the distribution. - **Changelogs are nested** under `Get-Started/Releases/`. A pattern anchored at the start of the path missed them entirely, and a Kilted Kaiju changelog outranked the tutorials until that was fixed. ## How the corpus is built **Source is the RST, not the rendered site.** Rendered pages carry navigation, the version switcher and generated API listings; all of it lands in chunks and competes with prose during retrieval. **Chunking follows document structure** — RST section underlines rather than a character count — so a chunk stays on one topic and can cite its section. Chunks are bounded at 1,600 characters through three levels: paragraph, then line, then whitespace. The third exists because ROS 2 changelogs put an entire release's bullets on a single 3,223-character line that the first two could not divide. **Changelogs and release pages are down-weighted at query time** unless the question is about a version or a change. ## Fine-tuning the retriever `scripts/train_embeddings.py` adapts the embedding model to ROS 2 vocabulary using pairs mined from heading/body structure, with `MultipleNegativesRankingLoss` for in-batch negatives. It reports recall@5 on held-out pairs before and after, and refuses to save a model that did not beat the baseline. ```bash python scripts/train_embeddings.py --eval-only # baseline python scripts/train_embeddings.py --epochs 1 python scripts/build_index.py --model data/embedding-model ``` Worth stating plainly: this trains the **retriever**, not the generator. It does not teach Qwen Coder about ROS 2 — it makes the passages Qwen is handed more likely to be the right ones. Both are worth doing; a LoRA on Qwen is separate work. ## Offline use Everything runs locally once fetched. Index ~13 MB, embedding model ~90 MB, `Qwen2.5-Coder-1.5B-Instruct` ~3 GB. No network calls at query time, no API keys. ## Licence Apache-2.0. Indexed content is ROS 2 documentation, copyright its contributors, under CC-BY-4.0 — this repository redistributes derived chunks with their source paths intact so attribution survives retrieval.