前置条件
uv
Python 包与环境管理工具,每个后端服务都是独立的 uv 项目。
Python 3.11
后端运行时(由 uv 按服务管理)。
Flutter
客户端运行时,参考官方 quick install。
ffmpeg
视频 / 音频转写前先提取音轨;只处理文字文章时不需要。
1. 获取代码并安装依赖
RakullApp 现在是单一大仓库(monorepo):全部源码(rakull_server、rakullapp_core、docs 等)都直接在仓库里,不再使用子模块。普通 clone 即可拿到所有代码。
uv sync / uv run 会安装完整运行时;Agent Server 默认包含 OpenAI 与 Azure Speech SDK,无需额外 extra。转写还需要系统安装 ffmpeg:
各微服务仍保留独立的 remote 仓库(
RakullServer、RakullAgentServer 等),但它们现在是下游镜像:只在主仓 PR 合并后由同步脚本自动更新,日常开发不要直接克隆或修改它们。详见仓库模型。2. 一键启动所有后端
- 先准备本地 PostgreSQL,再初始化持库服务(幂等):
scripts/init_all_dbs.sh会自动调用scripts/setup_postgres.sh(前置条件是本机有 Homebrew,本地开发不用 Docker),由它基于postgresql@18完成安装 / initdb / 启动,创建rakull角色和rakull_data、rakull_collection两个库;随后data_server在这两个物理隔离的库上幂等建 schema——rakull_data放文章 / 句子 / 媒体 / 反馈 / 每周推荐等内容,rakull_collection专放收藏域,两库同进程持有但不跨库 JOIN。user_manager不受影响,仍建自己的 SQLite 认证库;管理员账号照旧直接写入user_manager的库。 - 用同一个
JWT_SECRET启动六个服务,使签发的 token 在各服务间通用。 - 自动注入服务间地址(
DATA_SERVER_URL等)与同一个CONTROLLER_ASSERTION_SECRET(study/collection 调 data_server 的内部服务断言密钥)。 - 按
Ctrl-C时优雅停止全部服务(每个服务独立进程组,不留孤儿进程)。
| 服务 | 端口 | 角色 |
|---|---|---|
user_manager | 8010 | 鉴权 / 管理(面向客户端) |
agent_server | 8011 | AI 计算(内部) |
immersive_study_server | 8012 | 控制器 / App Server(面向客户端) |
collection_server | 8013 | 收藏薄网关(面向客户端,无状态) |
data_server | 8014 | 持久化 / Model(内部) |
manager_server | 8015 | Admin Server:管理后台 + 数据采集(面向管理端) |
手动安装 PostgreSQL(通常可跳过)
本地开发统一使用本机原生 PostgreSQL(Homebrew,不用 Docker)。正常情况下run_all_servers.sh 会通过 scripts/setup_postgres.sh 自动完成安装 / initdb / 启动 / 建角色建库,你什么都不用装。想单独准备或排查时,可以手动执行:
rakull / 密码 rakull、库 rakull_data 与 rakull_collection、连接串 postgresql://rakull:rakull@localhost:5432/...、主版本 PG_MAJOR=18。可用环境变量覆盖:PG_HOST / PG_PORT / PG_ROLE / PG_PASSWORD / PG_SUPERUSER / PG_MAJOR;业务侧用 DATA_DATABASE_URL / COLLECTION_DATABASE_URL 覆盖连接串。注意 user_manager 不使用 PostgreSQL,它仍维护自己的 SQLite 认证库 local_auth.db。
从 PostgreSQL 16 升级到 18(一次性)
PostgreSQL 18 无法直接读取 16 的 data directory。setup_postgres.sh 发现端口仍被旧主版本集群占用时会直接报错退出,不会静默写旧库。先停掉后端服务(bash scripts/stop_all_servers.sh),再按本地数据是否需要保留二选一:
A. 本地数据可丢弃——schema 会在下次 run_all_servers.sh 时自动重建:
pg_upgrade 原地升级整个集群(含 rakull_data / rakull_collection):
bash scripts/run_all_servers.sh 即可;确认无误前不要删除旧 data directory($(brew --prefix)/var/postgresql@16)。仍需临时跑旧版本时,PG_MAJOR=16 bash scripts/setup_postgres.sh 即可。
从旧版 SQLite 迁移历史数据(一次性)
PostgreSQL 改造后运行时不再读取任何 SQLite 文件。如果你是从旧版升级、本地还留着历史数据,旧文件位于data_server 的服务根目录(rakull_server/data_server/data.db 与 collection.db,不是 data/ 子目录)。按下面步骤一次性搬入 PostgreSQL:
OVERRIDING SYSTEM VALUE 写入并在结尾把序列重置到 max(id);加载期间临时摘除外键、禁用用户触发器,结束后全部恢复;每个库在单事务内完成,任何一行失败都整体回滚。--replace 会先 TRUNCATE 目标表再重灌——首次 bootstrap 已写入情景 / 旅程种子行,因此本地迁移基本都要带它(种子行也包含在旧 SQLite 中)。
更老的仓库(收藏曾独立存放):在收藏域并入 data_server 之前,收藏住在另一个文件 rakull_server/collection_server/collection.db,与 data_server/collection.db 是两套独立数据、各自有一套 id。追加 --legacy-collection-sqlite 即可把它按并集合并进来(脚本会自动重排主键、把卡片指向新的收藏夹 id,两账号数据互不冲突):
bash scripts/run_all_servers.sh 启动,登录客户端确认文章与收藏可见,即可删除或归档旧 .db 文件。迁移脚本是一次性切换工具,不是长期兼容层;全新环境没有历史数据,直接跳过本小节。登录账号始终在 user_manager 的 SQLite 中,不参与本次迁移。
3. 在管理后台配置 AI、语音、COS 与用户
六个服务启动后,打开管理后台并以默认管理员admin / admin123 登录:
- AI APIs → Models:添加 OpenAI-compatible Endpoint 与 API Key,并创建至少一个 Model Binding。首个可用模型会自动成为默认模型;CallPlan 仅用于指定不同模型之间的默认与 Fallback。Endpoint 连接测试使用当前未保存表单;保存会先实测连接,只有成功才写入。
- AI APIs → Speech & automation:配置 Whisper Key / Base URL / Model、Azure TTS Key / Region / Voice,运行真实测试,并设置文章自动 TTS 开关。Whisper 测试音频上限为 5 MB;Azure 测试会合成固定日文短句,可能产生少量费用。
- COS storage:配置 COS 凭证、Bucket 与 Region,执行 Bucket、PUT、HEAD、GET、LIST、DELETE 六步探测,再管理 Rakull 对象。
- Users / Requests:管理账号并审批待注册用户。
config.local.yaml > config.yaml > 默认值。
管理账号与用户审批
管理员账号在初始化时直接写入数据库(user_manager 的 app/db/seed.py,幂等),默认 admin / admin123,可用环境变量 ROOT_ADMIN_USERNAME / ROOT_ADMIN_PASSWORD 覆盖。不再有“第一个注册用户自动成为 root”的行为 —— 所有注册都会进入待审批队列,由管理员批准。schema 里预置了三个邀请码:zy、wai、zx。
用管理员账号登录拿到 token:
token,可直接用于后续请求:
4. 运行 Flutter 客户端
在rakullapp_core/ 目录下,通过 --dart-define 把三个面向客户端的服务地址传进去:
客户端只直连这三个服务,永远不会直接访问内部的
agent_server / data_server。可选:把管理后台打包为 App
也可以把控制台打包成桌面 / 移动端 App:rakull_manager 是一个只做 WebView 的 Flutter 壳,指向上面的控制台地址。
下一步
架构总览
理解 MVC 分层与服务职责。
贡献流程
创建分支、测试并通过 PR 提交改动。