Jellyfish Backend
基于 FastAPI + LangChain/LangGraph + SQLAlchemy 的后端 API,使用 uv 管理依赖。
技术栈
- FastAPI:Web 框架
- LangChain / LangGraph:链与工作流编排,
PromptTemplate管理提示词 - SQLAlchemy:异步 ORM,默认 SQLite(可换 PostgreSQL 等)
- uv:包管理与虚拟环境
目录结构
backend/
├── pyproject.toml # 项目与依赖(uv)
├── .python-version # Python 版本
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置(pydantic-settings)
│ ├── dependencies.py # 依赖注入(如 get_db)
│ ├── api/
│ │ └── v1/
│ │ ├── __init__.py # 路由聚合
│ │ └── routes/ # 各模块路由
│ ├── core/
│ │ └── db.py # SQLAlchemy 引擎与 Base
│ ├── models/ # ORM 模型
│ ├── schemas/ # Pydantic 请求/响应
│ ├── services/ # 业务逻辑
│ └── chains/ # LangChain PromptTemplate、LangGraph
├── tests/
├── .env.example
└── README.md
当前分层约定
目前后端已经按“路由层瘦身,业务逻辑下沉”的方向整理过一轮,建议后续继续遵循下面这套分工:
app/api/v1/routes/- 负责收参、依赖注入、调用 service、包装响应
app/services/common/- 负责通用校验、通用 CRUD、公共错误文案
app/services/studio/- 负责项目、章节、分镜、文件、图片任务等 Studio 主业务
app/services/llm/- 负责 Provider / Model / Settings 管理逻辑
app/services/film/- 负责视频生成、分镜帧提示词任务等编排逻辑
推荐遵循的判断标准:
- 留在 route 的
- 参数解析
Depends- 调 service
- 返回
ApiResponse
- 放到 service 的
- 跨实体校验
- 默认值策略
- 文件/存储交互
- 任务编排
- AI 工作流调用
响应与错误约定
当前接口已经统一使用 ApiResponse 响应壳,后续新增接口也建议保持一致:
- 创建成功:
created_response(...) - 普通成功:
success_response(...) - 空响应成功:
empty_response() - 分页成功:
paginated_response(...)
错误风格也已开始统一,优先复用:
entity_not_found(...)entity_already_exists(...)required_field(...)invalid_choice(...)not_belong_to(...)
快速开始
1. 安装 uv(若未安装)
curl -LsSf https://astral.sh/uv/install.sh | sh
2. 进入 backend 并安装依赖
cd backend
uv sync
3. 配置环境
cp .env.example .env
# 按需编辑 .env
4. 初始化数据库(可选,MySQL/PostgreSQL 等)
如果你使用的是 SQLite 默认配置(DATABASE_URL=sqlite+aiosqlite:///./jellyfish.db),可以跳过本节,首次访问时会自动创建文件。
若切换到 MySQL / PostgreSQL 等外部数据库,建议先手动初始化表结构:
-
在
.env中配置数据库连接(示例):# SQLite(默认) # DATABASE_URL=sqlite+aiosqlite:///./jellyfish.db # MySQL(使用 aiomysql 驱动) # DATABASE_URL=mysql+aiomysql://user:pass@localhost:3306/jellyfish # PostgreSQL # DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/jellyfish -
运行初始化脚本(使用 uv):
cd backend uv sync # 确保依赖已安装 uv run python init_db.py
该脚本会导入所有 ORM 模型并调用 Base.metadata.create_all(),在目标数据库中创建所需的 27 张业务表。
5. 启动服务
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
- API 文档:http://localhost:8000/docs
- 健康检查:http://localhost:8000/health
- API v1 示例:http://localhost:8000/api/v1/example/prompt
- 影视技能(确认路由):http://localhost:8000/api/v1/film (GET);实体/分镜抽取见下方,需 POST 且路径带 /api/v1 前缀。
影视技能 API(需配置 OPENAI_API_KEY)
| 方法 | 完整路径 | 说明 |
|---|---|---|
| GET | /api/v1/film |
返回端点说明,用于确认路由已注册 |
| POST | /api/v1/film/extract/entities |
人物/地点/道具抽取 |
| POST | /api/v1/film/extract/shotlist |
分镜/镜头表抽取 |
未配置 OPENAI_API_KEY 时上述 POST 返回 503。
常用命令
| 命令 | 说明 |
|---|---|
uv sync |
安装/同步依赖 |
uv sync --group dev |
同步依赖并包含开发组(pytest、pylint 等) |
uv add <pkg> |
添加依赖 |
uv run uvicorn app.main:app --reload |
开发运行 |
uv run pytest |
运行测试 |
uv run pytest tests/... -q |
运行定向测试 |
uv run pylint app |
对 app 包运行 Pylint(需已 uv sync --group dev) |
python -m py_compile <paths> |
快速做语法检查 |
代码检查(Pylint)
与常见开源 Python 项目一致,Pylint 选项集中在 pyproject.toml 的 [tool.pylint.*](行宽、Python 版本、jobs=1 等;并对 SQLAlchemy / 文档串等噪声规则做了合理关闭)。
cd backend
uv sync --group dev
uv run pylint app
- Pylint:未使用导入、风格问题、部分可维护性告警等。
- BasedPyright:类型检查配置在同文件
[tool.basedpyright],供 IDE 或本机已安装的basedpyrightCLI 使用;与 Pylint 互补(类型 vs 风格/模式)。 - CI:变更
backend/**的 PR(及启用 Merge queue 时的合并组)会运行仓库根目录下的.github/workflows/backend-pylint.yml。若要将 Pylint 作为合并前置,请在 GitHub 分支保护 / Rules 中把对应状态检查(一般为 Backend Pylint / pylint)设为必需,详见该 workflow 文件头注释。
测试
推荐入口
现在无论你在仓库根目录还是 backend/ 目录运行,pytest 都已经做了统一配置。
在 backend/ 目录:
cd backend
uv run pytest -q
在仓库根目录:
uv run pytest backend/tests -q
常用定向测试
运行 service 层测试:
cd backend
uv run pytest \
tests/test_common_services.py \
tests/test_llm_manage.py \
tests/test_shot_character_links.py \
tests/test_script_division.py \
tests/test_studio_files_service.py \
tests/test_generated_video_service.py \
tests/test_shot_frame_prompt_tasks_service.py \
tests/test_image_task_services.py \
-q
运行 API 响应壳测试:
cd backend
uv run pytest \
tests/test_api_response_envelopes.py \
tests/test_llm_api_responses.py \
tests/test_studio_prompts_categories.py \
tests/test_studio_api_responses.py \
tests/test_shot_subresource_api_responses.py \
tests/test_files_api_responses.py \
tests/test_task_status_api_responses.py \
tests/test_shot_character_links_api_responses.py \
tests/test_image_tasks_api_responses.py \
tests/test_generated_video_api_responses.py \
tests/test_tasks_images_api_responses.py \
-q
当前测试重点
当前测试主要覆盖三类目标:
- 公共层
- 通用校验、通用 CRUD、公共错误文案
- service 层
studio、llm、film的关键业务服务
- API 层
- 创建/删除/异常时的
ApiResponse外层结构
- 创建/删除/异常时的
如果只是快速验证本轮改动,建议优先:
cd backend
uv run pytest tests/test_common_services.py tests/test_studio_api_responses.py -q
语法级快速检查
在做较大重构但暂时不想跑全量测试时,可以先做一轮语法检查:
cd backend
python -m py_compile $(rg --files app tests)
说明
- 根目录
pytest.ini已补齐,避免从仓库根目录执行时异步测试被误跳过 - 异步测试统一使用
@pytest.mark.asyncio - 真实 LLM 联调前,请先执行
uv sync --group dev
扩展说明
- 数据库:在
app/models/下新增模型并继承Base,在app/core/db.py中可调用init_db()建表。 - 提示词:在
app/chains/prompts.py中增加PromptTemplate。 - 工作流:在
app/chains/graphs.py中定义StateGraph并compile(),在路由中ainvoke调用。