关于 Bike Router
Bike Router 是面向骑行者、基于 OSM 的可自托管路线规划器,提供 Web 界面、API 和命令行。它依据路线引擎数据并明确呈现不确定性,不会猜测含糊地点或路线细节。
主要功能
- 01基于 OSM 的骑行路线规划
- 02支持多种路线与地理编码服务
- 03路线评分与说明
- 04导出 GeoJSON 和 GPX
- 05Web 规划器、API 与命令行
适用场景
- 01按起点、终点和车型规划骑行
- 02在规划前确认含糊的地点名称
- 03比较路线选项及其地图元数据
- 04将规划路线导出为 GeoJSON 或 GPX
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
bike-routing-agent
一个基于 OSM 的骑行路线规划服务:包含类型化、与服务提供商无关的领域模型、 完整的 openrouteservice API 客户端及路线规划适配器,以及一个 LangGraph 工作流,可将经过验证的路线请求转换为可解释、可导出的骑行路线。
LLM(如使用)可以解析自由文本、提出澄清问题并解释所选路线。它不会凭空编造坐标、几何形状、高程或路线适用性——所有这些都来自基于 OSM 的路线引擎。
轻松安装(无需编程)
从 Releases 页面下载
pybikerouter-easy-<version>.zip,解压,安装
Docker Desktop,然后双击适用于你电脑的 Start
文件。首次启动时会询问一个问题——你在哪里骑行——随后下载该区域的地图数据,并在浏览器中打开规划器。以下是简单明了的分步说明:
docs/easy-install.md(以及下载包中的 START-HERE.txt)。
文档
完整文档集位于 docs/:
| 文档 | 内容 |
|---|---|
| 架构 | 图节点、状态、分支、终止状态、错误模型 |
| API | 端点契约、响应状态、产物提供 |
| 配置 | 所有环境变量、验证规则、部署说明 |
| 服务提供商 | 协议、ORS 客户端/适配器行为、地理编码器、BRouter/Valhalla 适配器、添加后端 |
| 后端比较 | 按自行车类型测得的 ORS 与 BRouter 行为、结合两种引擎 |
| 地理编码 | Nominatim 与 Pelias、置信度/歧义语义、调优 |
| 评分与导出 | 评分计算、不确定性策略、解释规则、GeoJSON/GPX |
| 用文字规划 | 用一句话描述骑行路线;可选的 LLM 会将其转换为结构化请求(绝不生成坐标) |
| 天气 | 出发时间沿途的天气预报:温度、降雨、相对于骑行方向的风(免费、无需密钥的服务提供商) |
| 可自托管的技术栈 | 使用一份 OSM 提取数据在本地运行路线规划和/或地理编码;硬件要求及小型 PC 选项 |
| 测试 | 测试布局、模拟约定、实时测试、CI |
| 网页规划器 | 将地点添加到行程中;点击地图上的某个点,并选择它在路线中的位置 |
| iPhone/Tailscale | 通过 tailnet 将规划器作为主屏幕应用在 iPhone 上使用 |
| 路线图 | 计划中的工作和明确的非目标 |
架构
FastAPI
|
v
LangGraph RouteAgentState
|
+--> parse_request (structured input first; LLM extraction is an injectable dependency)
+--> validate_request (Pydantic)
+--> geocode_locations (Nominatim by default, public or self-hosted; ambiguity -> clarification, never a guess)
+--> route_with_provider (openrouteservice; engine-neutral RoutingRequest in, RouteCandidate out)
+--> score_candidates (deterministic distance/elevation/warning scoring)
+--> explain_and_export (facts-only explanation + GeoJSON/GPX export)
|
v
JSON response + GeoJSON/GPX artifacts
图分支:
START -> parse_request
-> validate_request -> (invalid | awaiting_clarification) -> END
-> geocode_locations -> (awaiting_clarification | provider_failure) -> END
-> route_with_provider -> (no_route | provider_failure) -> END
-> score_candidates -> (no_route) -> END
-> explain_and_export -> END
每条路径都会以明确的 status 结束;只有验证和地理编码均成功后,图才会调用路线规划服务提供商,并且始终会以终止状态返回。
设置
需要 Python 3.11+ 和 Poetry。
poetry install
cp .env.example .env
poetry install 会在项目内创建虚拟环境(.venv/,参见
poetry.toml),并安装运行时和开发依赖项。使用 poetry run <command> 在其中运行任意命令,或运行 poetry shell 直接激活环境。
编辑 .env 并将 ORS_API_KEY 设置为有效的
openrouteservice API 密钥。
环境变量
| 变量 | 用途 | 默认值 |
|---|---|---|
ORS_API_KEY | openrouteservice API 密钥 | (实时路线规划必需) |
ORS_BASE_URL | openrouteservice 基础 URL | https://api.openrouteservice.org |
ORS_TIMEOUT_S | ORS 请求超时时间(秒) | 10.0 |
ORS_MAX_RETRIES | 超时或 5xx 错误时的重试次数 | 2 |
GEOCODER_PROVIDER | 地理编码器后端:nominatim(公共或可自托管)或 pelias(需要在 ORS_BASE_URL 后配置 Pelias API,参见 docs/geocoding.md;启动时会拒绝使用公共 ORS URL) | nominatim |
GEOCODER_BASE_URL | Nominatim 基础 URL(当 GEOCODER_PROVIDER=pelias 时忽略) | https://nominatim.openstreetmap.org |
GEOCODER_TIMEOUT_S | 地理编码器请求超时时间 | 5.0 |
GEOCODER_USER_AGENT | Nominatim 使用政策要求的值 | bike-routing-agent/0.1 |
GEOCODER_CACHE_TTL_S | 内存中的地理编码缓存 TTL | 3600 |
GEOCODER_AMBIGUITY_MARGIN | 前两个结果被视为“有歧义”时的置信度差值上限 | 0.05 |
GEOCODER_MIN_CONFIDENCE | 自动接受排名第一结果所需的最低置信度 | 0.3 |
VALHALLA_BASE_URL | 可自托管的 Valhalla(meili)服务基础 URL | http://localhost:8002 |
VALHALLA_TIMEOUT_S | 每个 Valhalla 请求的超时时间(秒) | 30.0 |
VALHALLA_MAX_RETRIES | Valhalla 超时或 5xx 错误时的重试次数 | 1 |
EXPORT_DIR | 存放 GeoJSON/GPX 产物的本地目录 | exports |
DATABASE_URL | PostgreSQL/PostGIS URL:记录路线历史记录,启用 /v1/history/*(docs/persistence.md) | 未设置 |
ARTIFACT_BACKEND | local 或 database(产物存储在 PostgreSQL 中) | local |
LOG_LEVEL | 日志级别 | INFO |
运行 API
poetry run uvicorn bike_routing_agent.api:app --reload
应用还会在 http://localhost:8000/ 提供内置 Web UI(基于地图的路线规划器),交互式 API 文档位于 /docs。
命令行界面
安装软件包后会提供 bike-router 命令(也可通过
python -m bike_routing_agent.cli 运行),命令按子命令组组织:
bike-router route plan --origin "Berlin Hbf" --destination "Potsdam" \
--bike-type gravel --target-distance-km 30 --output plan.json
bike-router serve start --port 8000
bike-router docker up # docker compose -f docker/compose.yaml up -d --build
bike-router docker logs -f
bike-router config show # effective settings, secrets redacted
bike-router config check # validate settings against the environment
bike-router providers list # provider names and bike-type -> ORS profile map
bike-router route plan ... --format text --gpx best.gpx # alternatives, sight stops, exports
bike-router route show plan.json # a saved plan again; `route export` writes any alternative
bike-router poi along --route plan.json # sights near a route, ranked by fame
bike-router brouter needed|info|download # BRouter map tiles (asks before downloading)
bike-router history list|show|stats # past plans (needs DATABASE_URL)
bike-router status show # readiness of every component and the active features
bike-router chat start # plan routes by chatting (docs/chat.md)
API 和 Web 表单支持的所有功能都可通过 CLI 使用——参见 docs/cli.md。
route plan --text "50 km gravel loop from Braunschweig" 使用可选的 LLM 解析器(docs/llm-parser.md)。
route plan 接受 lat,lon 坐标对或地点文本,用于 --origin、
--destination 和可重复指定的 --via 路径点;命令会输出 JSON 结果,并在状态为 ready 时以退出码 0 退出,在需要澄清或提供方失败时以 1 退出,在用法错误时以 2 退出。设置 DATABASE_URL 后,还会尽力将规划记录到路线历史记录中(输出包含 plan_id,可使用 --no-record 跳过记录),并提供路线沿线在 --departure-time 的天气预报(docs/weather.md);bike-router db migrate / db status 用于管理数据库架构(docs/persistence.md)。
使用 Docker 运行
所有容器相关资源都位于 docker/:
cp .env.example .env # set ORS_API_KEY
docker compose -f docker/compose.yaml up --build
打开 http://localhost:8000/ 使用 Web UI。路线产物存储在名为
pybikerouter-exports 的卷中。可选的本地路线规划/地理编码技术栈详见
docs/self-hosted.md,其中包括所需条件,以及如何在小型机器上仅运行其中一部分。
请求示例
curl -X POST http://localhost:8000/v1/route/plan \
-H 'Content-Type: application/json' \
-d '{
"origin": "Braunschweig Hauptbahnhof",
"destination": "Wolfenbüttel",
"constraints": {
"bike_type": "gravel",
"avoid_high_traffic_roads": true,
"max_ascent_m": 500
}
}'
响应示例
{
"status": "ready",
"route": {
"provider": "ors",
"provider_profile": "cycling-regular",
"geometry_geojson": {"type": "LineString", "coordinates": []},
"metrics": {
"distance_m": 12500,
"duration_s": 2700,
"ascent_m": 85,
"descent_m": 90,
"surface_coverage": {},
"unknown_surface_fraction": null
},
"score": 0.91,
"score_breakdown": {"distance_fit": 1.0, "elevation_fit": 1.0, "warning_penalty": 0.0},
"warnings": [],
"provenance": {"provider": "ors", "profile": "cycling-regular"}
},
"candidates": [
{"provider": "ors", "provider_profile": "cycling-regular", "score": 0.91},
{"provider": "brouter", "provider_profile": "trekking", "score": 0.84}
],
"explanation": "...",
"artifacts": {
"geojson_url": "/v1/routes/<id>.geojson",
"gpx_url": "/v1/routes/<id>.gpx"
},
"clarification": [],
"errors": []
}
如果 origin/destination 有歧义或无法解析,status 将为
awaiting_clarification,而 clarification 会列出可供选择的候选地点——不会根据猜测生成路线。
自行车类型
constraints.bike_type 按引擎选择路由配置文件,默认值为
gravel。支持的值:road、gravel、touring、mountain、city、
ebike、commuter(快速、低交通量)、recumbent。ORS 提供四种骑行
配置文件,例如,ebike 使用 cycling-electric,而 commuter 使用
cycling-regular;可自托管的 BRouter 提供商区分得更细——
gravel、touring、mountain、city、commuter 和 recumbent 各自使用
独立的配置文件,而 road 和 ebike 共用 fastbike(BRouter 没有
电助力成本模型)(参见 docs/configuration.md)。
Make 目标
make 会列出日常命令;这些命令使用项目的 .venv(或当前激活的环境):
make install # poetry install
make hooks # the git hooks (commit: lint + types; push: the whole suite)
make run # the API with auto-reload (HOST=127.0.0.1 PORT=8000)
make check # lint + types + tests without coverage, stops at the first failure
make ci # what CI runs: lint, types, tests with the 80 % coverage floor
make test-fast ARGS="tests/nodes -k geocode" # a part of the suite (no coverage floor)
make deploy # build and restart the local container (bike-router deploy up)
代码检查和类型检查
poetry run ruff check .
poetry run mypy src
每次推送和拉取请求时,CI 都会运行这两项检查(参见
.github/workflows/ci.yml)。
运行测试
poetry run pytest
每次运行都会收集覆盖率,且测试套件的覆盖率低于 80% 时会失败
(tool.pytest.ini_options.addopts 中的 --cov-fail-under=80;当前总覆盖率为 97%,
每个模块均 ≥84%)。
访问真实外部服务的实时测试标记为 @pytest.mark.live,
默认不运行(参见 pyproject.toml 中的 tool.pytest.ini_options.addopts)。显式运行这些测试:
poetry run pytest -m live
Pre-commit 钩子
每次提交或推送前,pre-commit 都会自动运行质量检查。
执行 poetry install 后,安装这两个 git 钩子阶段:
poetry run pre-commit install --hook-type pre-commit --hook-type pre-push
提交时会运行空白字符/EOF/YAML/TOML/合并冲突/大文件检查、
ruff check --fix 和 mypy src;完整的 pytest 测试套件仅在
git push 时的 pre-push 阶段运行(与 CI 保持一致)。使用
poetry run pre-commit run --all-files 手动运行 commit 阶段,使用
poetry run pre-commit run --hook-stage pre-push --all-files 运行 pre-push 阶段。
已知限制
- OSM 标签的完整性因地区而异;地表/通行权限元数据经常缺失,并会 表示为不确定性,而非视作有利条件。
- 路由引擎(ORS、Valhalla、BRouter)将自行车类别映射到各自配置文件的方式
不同;
config.py中的映射是近似值,尤其是碎石路骑行。 - 不同提供商的海拔数据(爬升/下降)准确度各异,且不一定始终可用。
- 此服务生成的路线均不构成安全保证。说明会使用谨慎措辞(“与现有地图元数据 更为吻合”),而非“安全路线”之类的说法。
- BRouter 和 Valhalla 已完成端到端接入,但仅支持可自托管的部署
(
ROUTING_PROVIDER=brouter/valhalla/all; BRouter 通过 compose 配置文件接入,详见 docker/brouter/README.md),而 openrouteservice 仍是默认引擎。 - Pelias 地理编码选项需要在
<ORS_BASE_URL>/pelias/v1提供 Pelias API: 公共服务api.openrouteservice.org和标准的可自托管 ORS 均不提供此 API, 且该适配器仅针对模拟对象进行过测试(参见 docs/geocoding.md)。 如需在本地使用地理编码器,请使用可自托管的 Nominatim。
仓库结构
src/bike_routing_agent/
├── api.py FastAPI app (POST /v1/route/plan)
├── config.py Settings + provider profile mapping
├── models.py Pydantic v2 domain models
├── state.py LangGraph RouteAgentState
├── graph.py LangGraph wiring
├── errors.py Structured provider/geocoding errors
├── providers/ GeocodeProvider / RoutingProvider adapters
│ (ors_client.py: full ORS client -- directions, export,
│ isochrones, matrix, snap, POIs, Vroom, elevation,
│ Pelias geocoding, health; ors.py: the RoutingProvider;
│ geocoder.py: Nominatim; pelias.py: Pelias on
│ self-hosted ORS)
├── nodes/ One module per graph node
├── scoring/ Deterministic route scoring
├── exporters/ GeoJSON / GPX export
├── frontend/ Static web UI served at /
└── cli/ bike-router command line (route/serve/docker/config/providers)
docker/ Dockerfile + compose.yaml
tests/
├── fixtures/ Sample provider responses
├── nodes/ One test module per graph node
├── providers/ Adapter unit tests (mocked HTTP)
├── graph/ Graph branch tests
├── exporters/ Export format tests
└── live/ Tests marked @pytest.mark.live
docs/ Documentation suite (see docs/README.md)
许可证
MIT,详见 LICENSE。
第三方许可证
本项目基于 BRouter(MIT)和 OpenStreetMap 数据(ODbL)构建,并在 THIRD_PARTY_LICENSES.md 中致谢,同时附有完整的 BRouter 许可证文本。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。