内容
# 运行教练
一款由AI驱动的跑步教练,连接您的Strava账户,通过Telegram机器人或命令行界面提供基于数据的训练建议。由Claude(Anthropic)和Strava API提供支持。
## 功能
- 在提供建议之前,分析您的实际Strava训练历史
- 标记受伤风险模式(训练量激增、训练日过多、没有恢复)
- 建议具有特定目标的训练(配速、距离、休息间隔)
- 在对话中记住关于您的事实(目标、受伤历史、偏好)
- 在PostgreSQL中持久化对话历史和记忆(即使在机器人重启时)
- 通过Telegram机器人(托管)或命令行界面(本地)可用
## 架构
```
bot.py / cli.py ← 入口点
coach/agent.py ← CoachSession: Claude 代理 + MCP + 记忆(由 bot 使用)
coach/cli.py ← 命令行界面特定代理循环
coach/prompts.py ← 两个接口共用的系统提示
db.py ← PostgreSQL 连接池 + 历史/记忆 CRUD
strava_mcp/server.py ← MCP 服务器,暴露 Strava 工具(子进程)
strava_mcp/strava_client.py ← Strava API HTTP 客户端
config.py ← 凭证 + token 管理
auth.py ← 一次性 Strava OAuth 流程
```
Claude 通过 [模型上下文协议(MCP)](https://modelcontextprotocol.io) 调用 Strava 工具。MCP 服务器作为子进程运行,通过标准输入/输出进行通信。
对话历史和运动员记忆按聊天持久化存储在 PostgreSQL 中(当设置 `DATABASE_URL` 时),因此上下文在机器人重启和重新部署时仍然存在。如果未配置数据库,则默认为内存存储。
## 先决条件
- Python 3.11+
- 具有已记录活动的 [Strava 账户](https://www.strava.com)
- [Anthropic API 密钥](https://console.anthropic.com)
- Telegram 机器人令牌(适用于机器人;可选,仅限命令行界面)
- PostgreSQL 数据库(可选 - 用于持久聊天历史;Railway 上需要)
## 设置
### 1. 克隆并安装依赖项
```bash
git clone <仓库网址>
cd running-coach
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
```
### 2. 创建 Strava 应用
1. 前往 [strava.com/settings/api](https://www.strava.com/settings/api)
2. 创建新应用
3. 将 **授权回调域名** 设置为 `localhost`
4. 记录您的 **客户端 ID** 和 **客户端密钥**
### 3. 创建 Telegram 机器人(可选 - 仅限命令行界面时跳过)
1. 在 Telegram 上联系 [@BotFather](https://t.me/BotFather)
2. 发送 `/newbot` 并按照提示操作
3. 复制机器人令牌
4. 联系 [@userinfobot](https://t.me/userinfobot) 获取您的 Telegram 用户 ID
### 4. 配置环境变量
```bash
cp .env.example .env
```
编辑 `.env` 并填写所需值:
```env
ANTHROPIC_API_KEY="" # console.anthropic.com
STRAVA_CLIENT_ID="" # strava.com/settings/api
STRAVA_CLIENT_SECRET="" # strava.com/settings/api
TELEGRAM_BOT_TOKEN="" # from @BotFather
TELEGRAM_ALLOWED_USER_ID="" # from @userinfobot
```
`DATABASE_URL`、`STRAVA_ACCESS_TOKEN`、`STRAVA_REFRESH_TOKEN` 和 `STRAVA_TOKEN_EXPIRES_AT` 仅在 Railway 部署时需要 - 请参见下面的部署部分。
### 5. 与 Strava 认证
```bash
python auth.py
```
这将打开一个浏览器进行 OAuth 授权,并将令牌保存到 `.tokens.json`。
## 运行
### Telegram 机器人
```bash
python bot.py
```
在 Telegram 上给您的机器人发送消息。
| 命令 | 描述 |
|---|---|
| `/reset` | 清除对话历史并重新开始 |
| `/memory` | 查看机器人记住的关于您的信息 |
| `/clearmemory` | 删除所有存储的记忆事实 |
### 命令行界面
```bash
python cli.py
```
在提示符下输入您的问题。输入 `quit` 以退出。
## 部署到 Railway
### 1. 推送到 GitHub
```bash
git add .
git commit -m "初始提交"
git push
```
### 2. 创建 Railway 项目
1. 前往 [railway.app](https://railway.app) 并创建新项目
2. 连接您的 GitHub 仓库
3. Railway 将自动检测 Python 并安装 `requirements.txt`
### 3. 添加 PostgreSQL 数据库
在您的 Railway 项目中 → **新建** → **数据库** → **PostgreSQL**。Railway 将自动将 `DATABASE_URL` 注入您的服务中。机器人在启动时创建所需的表(`chat_history`、`user_memory`)。
或者,使用免费的外部 Postgres 提供商,如 [Neon](https://neon.tech) 并在 Railway 变量中手动设置 `DATABASE_URL`。
### 4. 在 Railway 中设置环境变量
在您的 Railway 服务中 → **变量**,添加 `.env` 中的所有内容以及您的 Strava 令牌(由于 `.tokens.json` 未被提交):
| 变量 | 获取位置 |
|---|---|
| `ANTHROPIC_API_KEY` | [console.anthropic.com](https://console.anthropic.com) |
| `STRAVA_CLIENT_ID` | [strava.com/settings/api](https://www.strava.com/settings/api) |
| `STRAVA_CLIENT_SECRET` | [strava.com/settings/api](https://www.strava.com/settings/api) |
| `TELEGRAM_BOT_TOKEN` | [@BotFather](https://t.me/BotFather) |
| `TELEGRAM_ALLOWED_USER_ID` | [@userinfobot](https://t.me/userinfobot) |
| `STRAVA_ACCESS_TOKEN` | 从本地 `.tokens.json` → `access_token` |
| `STRAVA_REFRESH_TOKEN` | 从本地 `.tokens.json` → `refresh_token` |
| `STRAVA_TOKEN_EXPIRES_AT` | 从本地 `.tokens.json` → `expires_at` |
首先在本地运行 `auth.py` 以生成 `.tokens.json`,然后复制上面的值。
### 5. 部署
Railway 在每次推送到连接的分支时自动部署。`Procfile` 告诉 Railway 以 `python bot.py` 作为工作进程运行。
## 项目结构
```
running-coach/
├── auth.py # 一次性 Strava OAuth 流程
├── cli.py # 命令行界面入口
├── bot.py # Telegram 机器人入口
├── config.py # 凭证 + token 管理
├── Procfile # Railway 启动命令
├── requirements.txt
├── .env.example # 环境变量模板
├── db.py # PostgreSQL 连接池 + 历史/记忆 CRUD
├── coach/
│ ├── agent.py # CoachSession: Claude 代理 + MCP + 记忆(由 bot 使用)
│ ├── cli.py # 命令行界面代理循环
│ └── prompts.py # 共享系统提示
└── strava_mcp/
├── server.py # MCP 服务器(Strava 工具)
└── strava_client.py # Strava API HTTP 客户端
```
## 可用的 Strava 工具
MCP 服务器向 Claude 公开以下工具:
| 工具 | 描述 |
|---|---|
| `get_current_timestamp` | 当前 Unix 时间戳 - 用于计算活动查询的日期范围 |
| `get_athlete` | 运动员资料(姓名、体重、FTP、测量偏好) |
| `get_athlete_stats` | 最近、今年和整个生命周期的跑步总数 |
| `get_athlete_zones` | 配置的心率和功率区 |
| `list_activities` | 按日期范围筛选的分页活动列表 |
| `get_activity` | 包括分段和最佳表现的完整活动详情 |
| `get_activity_laps` | 每圈分解(适用于间歇训练) |
| `get_activity_zones` | 活动的 心率和配速区分布 |
| `save_memory` | 在对话之间持久化关于运动员的重要事实 |