# 产品方案（v2）

> 修订日期：2026-09-15。本版在 v1 基础上结合阶段 1 实施结果修订，主要补充：实施现状与技术债清单、字段级数据模型、路由与 partial 约定、多语种与 SEO 规范、后台与权限设计、统计口径、部署运维方案，并更新分阶段路线图。

## 1. 产品定位

- 打造一个类似 Hugging Face 与 Ollama 的混合 AI 社区和模型库下载站。
- 以**简体中文优先**为核心原则，同时支持英文等多语种内容与界面切换。
- 兼顾模型发现、模型下载、部署指引、社区讨论与 SEO 获客。

## 2. 目标用户

1. 需要快速发现中文友好模型的开发者与研究者。
2. 需要下载模型并在本地或私有环境运行的个人和团队。
3. 需要围绕模型进行教程、评测、部署经验交流的社区用户。

## 3. 核心价值

- **中文优先**：模型标签、分类、榜单、部署指南优先覆盖简体中文语境。
- **发现 + 部署一体化**：既能像 Hugging Face 一样浏览与筛选模型，也能像 Ollama 一样提供本地运行说明。
- **SEO 友好**：采用后端渲染模板输出内容，提升搜索引擎收录效率。
- **渐进增强**：在 SSR 基础上通过 htmx 提供局部刷新、筛选和互动能力；核心内容在禁用 JavaScript 时仍可完整访问。

## 4. 实施现状与技术债（截至 2026-09-15）

### 4.1 已完成（阶段 1：MVP 骨架）

- FastAPI + Jinja2 + Bootstrap 5 + htmx 最小可运行骨架。
- 首页（站点定位、精选模型）、模型列表页（语言/标签筛选，SSR + htmx 局部刷新）、模型详情页（基础信息、适用场景、部署命令、下载入口）。
- 多语种框架：简体中文（默认）/ English，通过 `?lang=` 查询参数切换，文案集中在后端字典中管理。
- SEO 基础：`robots.txt`、`sitemap.xml`、canonical、hreflang（含 x-default）。

### 4.2 已知问题与技术债（按优先级）

1. ~~数据层缺失~~（已于 2026-09-15 解决）：SQLAlchemy 2.0 + Alembic 已接入，模型数据迁移至 PostgreSQL，由 `app/repository.py` 仓储层提供访问。
2. **单体文件膨胀**：`app/main.py` 约 320 行，双语文案大字典内联其中，需拆分为独立 i18n 模块；路由需按 pages / partials / system 拆分。
3. ~~语言切换丢参~~（已修复）：切换链接经 `switch_lang_url` 助手保留全部查询参数。
4. ~~无品牌化错误页~~（已修复）：`app/errors.py` 统一注册 404/500 等品牌化错误页。
5. ~~无搜索~~（已修复）：列表页已支持关键词搜索（名称/提供方/中英文简介模糊匹配）与五个筛选维度（语言、标签、分类、参数规模、许可证）。
6. ~~工程化缺口~~（已解决）：pytest 基线（83 例）、ruff、Alembic 迁移均已就绪。
7. ~~环境差距~~（已解决）：已通过 uv 安装独立 Python 3.12.12，依赖与应用运行验证通过。

## 5. MVP 范围

### 5.1 用户可见功能

- 首页：站点定位、热门/精选模型、分类导航、最新讨论。
- 模型列表页：支持分类、标签、语言、参数规模、许可证筛选，关键词搜索，分页。
- 模型详情页：模型简介、标签、下载链接、部署命令、适用场景、讨论入口。
- 下载页/部署页：针对本地推理工具（如 Ollama）提供示例命令与环境说明。
- 社区基础能力：模型评论、点赞/收藏预留位，首期可先只做只读展示。
- 多语种：默认简体中文，可切换英文，URL/参数层面可表达语言选择。

### 5.2 管理与运营

- 模型录入与编辑后台。
- 模型标签与分类管理。
- 热门榜单与精选推荐位配置。

## 6. 信息架构与路由设计

### 6.1 页面路由（SSR，进入 sitemap）

| 路由 | 说明 | 状态 |
| --- | --- | --- |
| `/` | 首页 | 已实现 |
| `/models` | 模型列表（筛选/搜索/分页） | 已实现（分页/搜索待做） |
| `/models/{slug}` | 模型详情 | 已实现 |
| `/categories/{slug}` | 分类聚合 | 规划中 |
| `/tags/{slug}` | 标签聚合 | 规划中 |
| `/guides`、`/guides/{slug}` | 教程/部署指南 | 规划中 |
| `/search` | 全站搜索 | 规划中 |
| `/discussions` | 社区讨论 | 预留（阶段 3） |

### 6.2 htmx partial 路由约定

- 统一挂在 `/partials/*` 前缀下，只返回 HTML 片段，不渲染整页布局。
- partial 响应一律不加 canonical/hreflang，并通过 `X-Robots-Tag: noindex` 阻止收录。
- 现有：`/partials/featured-models`、`/partials/model-cards`。
- 后续新增：分页、搜索建议、评论列表、收藏按钮等。

### 6.3 系统与后台路由

- 系统：`/healthz`、`/robots.txt`、`/sitemap.xml`（已实现）。
- 后台（阶段 2 起，需登录）：`/admin/login`、`/admin`（仪表盘）、`/admin/models`（列表）、`/admin/models/new`、`/admin/models/{id}/edit`、分类与标签管理、推荐位配置。
- 文档直达：`/产品方案.md`、`/TODO.md`（开发期保留，上线后可下线）。

## 7. 技术方案

### 7.1 后端

- **Python 3.12**（pyproject 限定 `>=3.12,<3.13`）。
- **FastAPI**：路由、表单处理与页面渲染入口。
- **Jinja2**：纯后端渲染模板，保证首屏内容可抓取。
- **SQLAlchemy 2.0**（选定 ORM）：类型友好、生态成熟，符合"稳定 LTS 组件"原则；配合 **Alembic** 做迁移。
- **PostgreSQL 16**：模型、用户、评论、分类、标签等主数据存储；初期搜索为应用层模糊匹配（名称/提供方/中英文简介），后续按需升级 `pg_trgm` 与中文分词扩展。
- **psycopg 3**：数据库驱动；连接串使用 `postgresql+psycopg://` 方言前缀。
- **Redis**：当前不启用；在缓存、异步任务、限流场景保留接入可能，`settings.redis_url` 与 `/healthz` 探测已预留。

### 7.2 前端

- **Bootstrap 5**：统一响应式 UI 与组件体系（当前经 CDN 引入，上线前评估本地托管）。
- **htmx**：筛选、分页、局部刷新、轻交互；所有交互必须保证无 JS 降级可用。

### 7.3 工程化

- **pytest + httpx**：路由冒烟、筛选逻辑、i18n 回退、sitemap 生成等基线测试。
- **ruff**：lint 与代码格式化统一约定。
- **argon2-cffi**：后台账号密码哈希；会话采用签名 Cookie（itsdangerous）。

## 8. 数据模型设计（字段级）

### 8.1 核心实体

> 实现说明：多语字段在实现层采用 SQLAlchemy 可移植 JSON 类型——PostgreSQL 下为 `jsonb`，测试环境（SQLite）下为 `json`；主键为自增整数。

**models（模型主表）**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| id | int PK, 自增 | |
| slug | varchar, unique | URL 用，如 `qwen3-32b` |
| name | varchar | 显示名 |
| provider | varchar | 提供方，如 Qwen / Meta |
| parameter_size | varchar | 原文，如 `32B`、`567M` |
| parameter_class | varchar | 筛选口径：`lt1b` / `1b-7b` / `8b-15b` / `16b-33b` / `34b-70b` / `gt70b` |
| license | varchar | 许可证名 |
| license_url | varchar, nullable | |
| source_url | varchar, nullable | 上游来源（HF/Ollama 等） |
| languages | jsonb | 语言代码数组，如 `["zh", "en", "multi"]` |
| headline | jsonb | `{zh-Hans, en}` 一句话简介 |
| summary | jsonb | `{zh-Hans, en}` 摘要 |
| description | jsonb, nullable | `{zh-Hans, en}` 长文（Markdown） |
| use_cases | jsonb | `{zh-Hans: [], en: []}` |
| deployment_command | text, nullable | 如 `ollama run qwen3:32b` |
| status | varchar | `draft` / `published` / `archived` |
| featured | boolean | 首页推荐位 |
| published_at | timestamptz, nullable | |
| created_by | FK → users, nullable | |
| created_at / updated_at | timestamptz | |

索引：`(status, featured)`、`(parameter_class)`、`published_at`。

**model_versions（模型版本与文件）**

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| id | int PK, 自增 | |
| model_id | FK → models | |
| version_tag | varchar | 如 `v1`、`qwen3-32b-q4_k_m` |
| format | varchar | `gguf` / `safetensors` / `onnx` / `awq` 等 |
| quantization | varchar, nullable | 如 `Q4_K_M` |
| file_size_bytes | bigint, nullable | |
| checksum_sha256 | varchar, nullable | |
| download_url | varchar | |
| is_default | boolean | 详情页默认下载项 |
| created_at | timestamptz | |

**categories（分类，支持二级预留）**：id、slug unique、name jsonb、description jsonb nullable、parent_id FK nullable、sort_order int。
**tags（标签）**：id、slug unique、name jsonb、kind varchar（`capability`/`scene`/`format`，便于分组展示）。
**model_categories**、**model_tags**：关联表，联合主键。

**guides（教程/部署指南）**：id、slug unique、title jsonb、content jsonb（Markdown）、status、author_id FK → users nullable、related_model_id FK → models nullable、created_at、updated_at。

**users（用户）**：id、username unique、email unique nullable、password_hash、role（`admin`/`editor`/`member`）、is_active、created_at。

**comments（评论）**：id、model_id FK nullable（初期仅模型）、guide_id FK nullable（后续）、user_id FK、parent_id FK nullable（楼中楼预留）、content text、status（`visible`/`hidden`/`deleted`）、created_at。索引：`(model_id, status, created_at)`。

### 8.2 扩展实体

- **collections（专题/榜单）**：id、slug unique、title jsonb、description jsonb、sort_order、status。
- **collection_items**：collection_id、model_id、position，联合主键。
- **favorites**：user_id、model_id、created_at，联合唯一。
- **download_events（下载统计）**：id、model_id FK、version_id FK nullable、source（`direct`/`ollama`/`hf`）、referer、ip_hash（哈希后存储，不存原始 IP）、user_agent、created_at。热门榜口径由此表聚合。

## 9. 多语种与 SEO 规范

- 语言切换使用 `?lang=` 查询参数（现状保留），默认 `zh-Hans`；服务端按参数 → Accept-Language → 默认值顺序确定语言。
- 每个页面输出 `canonical`（指向默认语言版本）、`hreflang`（各语言版本 + `x-default`）。
- 模板中所有用户可见文案必须走 i18n 字典，禁止硬编码中英文字符串；新增文案需双语同步录入。
- `sitemap.xml` 从数据库动态生成；模型数量超过 5 万时拆分为 sitemap index（静态页 / 模型页 / 指南页）。
- meta description 规则：首页用站点定位语；模型页优先取 headline，其次 summary 截断 150 字符。
- partial 片段响应加 `X-Robots-Tag: noindex`。
- 阶段 4 预留 OG/Twitter Card 等社交分享标签。

## 10. 后台与权限设计

- 角色：`admin`（全部权限）、`editor`（内容录入与编辑）、`member`（普通社区用户，阶段 3 启用注册）。
- 认证：最小 session 方案——argon2-cffi 校验密码，itsdangerous 签名 Cookie（有效期 7 天）维持会话；`SECRET_KEY` 经环境变量注入；后台路由统一经 `require_admin` 依赖鉴权，未登录重定向至 `/admin/login?next=…`。
- 后台界面首期仅简体中文。
- 表单安全：所有后台写操作校验 CSRF Token（签名生成，绑定用户）；登录接口速率限制（每 IP 5 分钟 5 次，进程内存实现，接入 Redis 后迁移）。
- 审计：后台对模型的创建/修改记录操作人（预留字段 `created_by`，阶段 3 完善审计日志）。

## 11. 统计口径与榜单

- 下载入口点击经服务端跳转（302）并写入 `download_events`。
- 热门榜口径：近 30 天 `download_events` 计数，按 `source` 加权（暂定 direct=1、ollama/hf=0.5，可调）。
- 榜单更新策略：初期实时聚合，性能不足时改为定时物化（Redis 接入后缓存）。

## 12. 部署与运维

- 进程：生产用 gunicorn + uvicorn worker（或等效方案），systemd 或容器编排托管。
- 配置：全部经环境变量注入（`.env` 本地开发，`.env.example` 已提供）；密钥不进仓库。
- 数据库：PostgreSQL 独立部署，每日 `pg_dump` 备份保留 14 天；迁移通过 Alembic 随发布执行。
- 前端资源：Bootstrap/htmx 当前经 CDN 引入，上线前评估改为本地托管 + 长缓存。
- 日志：uvicorn access log，后续视需要引入结构化日志。
- 监控：`/healthz` 已提供存活探测（含 Redis 开关状态），后续补充数据库连通性检查。

## 13. 非功能要求

- 默认界面与内容优先显示简体中文。
- 页面需要具备良好的移动端适配。
- 核心页面（首页、列表、详情）在禁用 JavaScript 时必须完整可读、可筛选、可翻页。
- 性能目标：首屏 SSR P95 < 300ms，htmx partial P95 < 150ms（单机、万级模型数据规模）。
- 安全：ORM 参数化查询防注入；Jinja 自动转义防 XSS；后台鉴权 + CSRF + 登录限流；统计表只存 IP 哈希。
- 保持架构简单，优先使用 Python 与现成稳定组件。

## 14. 分阶段路线图

### 阶段 1：MVP 骨架（已完成）

- 基础站点、首页、模型列表页、模型详情页模板。
- 多语种切换、SEO 基础、htmx 局部刷新。

### 阶段 2：数据层与内容管理（当前重点）

- 接入 SQLAlchemy 2.0 + Alembic + PostgreSQL，落地 §8.1 核心表。
- 仓储层替换硬编码数据；路由与 i18n 模块拆分。
- 列表分页、关键词搜索、筛选维度扩展；sitemap 动态化。
- 最小后台（认证 + 模型录入/编辑 + 分类标签管理）。
- 测试基线与 ruff；修复语言切换丢参、品牌化错误页等技术债。
- 统一开发环境到 Python 3.12。

### 阶段 3：社区与增长

- 评论、收藏、用户注册与主页。
- 下载统计、热门榜单、专题 collections、首页推荐位配置。
- guides 教程频道。

### 阶段 4：运营与性能（视情况启动）

- 视流量接入 Redis（缓存、限流、榜单物化）。
- 生产部署落地（进程管理、备份、监控告警）。
- 英文内容运营流程、社交分享与 OG 优化。
