Flashcards 是一个基于 AI 的记忆卡片学习系统。用户输入要学习的主题后,后端调用模型生成由浅入深的 4 选项选择题;用户完成答题后,可以继续追问、要求解释,再进入下一题。
当前仓库已经进入前后端一起推进的阶段。目标是把 Django、Django Ninja、PostgreSQL、Docker Compose、Vue、Pinia 和 Markdown 协议串成一个能继续扩展的学习系统骨架。
本地开发默认地址:
- 前端:
http://localhost:4387 - 后端 API:
http://localhost:8765/api/sessions - 页面右上角:
flashcards v0.1.3
如果你通过 Docker Compose 启动项目,优先从前端地址进入,再由前端代理访问后端 /api。
- 复制环境变量模板:
cp .env.example .env-
按需修改
.env中的数据库、Ollama 和端口配置。 -
启动开发环境:
docker compose up --build -d- 打开前端页面:
http://localhost:4387
- 查看服务状态:
docker compose ps- 前端:Vue 3、Pinia、Vue Router、Vite、splitpanes、markdown-it
- 后端:Django 5、Django Ninja
- 数据库:PostgreSQL 16
- 编排:Docker Compose
- AI 接口:Ollama client 封装
- Token 计数:
tiktokencl100k_base - 测试:Django TestCase
Flashcards/
├── .docker/
│ └── postgres/
├── backend/
│ ├── manage.py
│ ├── requirements/
│ ├── config/
│ └── apps/
│ └── cards/
├── frontend/
│ ├── package.json
│ ├── src/
│ └── Dockerfile
├── docs/
│ └── prd/
├── .env
├── .env.example
├── .gitignore
├── docker-compose.yml
└── README.md
后端已经落地:
- Django 项目骨架
cardsapp- Django ORM 模型
- Django Ninja API 路由
- Markdown 固定协议解析
- 会话创建、历史列表、pin、delete
- 消息发送与继续出题
- 答题提交
- 会话 summary 生成
- 上下文构造与 token 计数
- Ollama client 封装
- Docker Compose / PostgreSQL 持久化配置
- 后端测试文件
前端已经落地:
- Vue 3 + Pinia + Vue Router 骨架
- ChatGPT 风格的双栏学习界面
- 右上角版本号和 Ollama health 指示灯
- 左侧历史记录区
- 右侧聊天 / 题目 / 输入区
- Markdown 渲染
- 题目作答交互
- ghost draft 灰字提示,支持直接发送或点击编辑
- 可拖拽布局
- 基于
/api的前后端对接
联调已经验证:
docker compose up --build -d可以成功启动postgres健康检查通过backend在8765正常响应frontend在4387正常响应- 前端代理访问
/api/sessions已返回 JSON
根目录使用两个文件:
.env:本地开发真实配置.env.example:示例模板
主要变量:
DJANGO_SECRET_KEYDJANGO_DEBUGDJANGO_ALLOWED_HOSTSDJANGO_PORTFRONTEND_PORTPOSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORDPOSTGRES_HOSTPOSTGRES_PORTOLLAMA_BASE_URLOLLAMA_MODELOLLAMA_USE_STUBOLLAMA_TIMEOUTOLLAMA_NUM_CTXAPP_LOG_DIR
Django 后端默认使用:
8765
这样可以避开本机常见已占用端口,例如 8000 和 8080。
前端默认使用:
4387
这个端口也刻意避开了常见开发端口,减少与其他项目冲突。
PostgreSQL 数据目录挂载到:
.docker/postgres
这样删除容器后,本地开发数据仍可保留。
当前 docker-compose.yml 编排三个服务:
postgresbackendfrontend
容器启动职责:
postgres提供数据库backend等数据库健康后执行 migrate 并启动 Djangofrontend启动 Vite 开发服务器,并通过代理访问后端/api
后端会把调试日志写到:
.docker/logs
启动命令:
docker compose up --build -d查看状态:
docker compose ps停止服务:
docker compose down当前 API 基于 /api:
GET /api/health/ollamaPOST /api/sessionsGET /api/sessionsGET /api/sessions/{session_id}PATCH /api/sessions/{session_id}DELETE /api/sessions/{session_id}POST /api/sessions/{session_id}/messagesPOST /api/sessions/{session_id}/cards/{card_id}/answerPOST /api/sessions/{session_id}/summary
接口契约见:
后端要求模型输出固定 Markdown,不使用 JSON 作为主协议。当前支持:
# 记忆卡片# 学习解释# 会话摘要
后端再根据固定标题解析结构化字段。
这样做是为了避免长文本、多段解释、代码块场景下 JSON 容易崩溃的问题。
当前后端已经接上真实 Ollama 请求路径,同时保留 stub 回退。
行为规则:
- 当
OLLAMA_USE_STUB=1时,后端直接走 stub,适合离线开发或前端联调 - 当
OLLAMA_USE_STUB=0时,后端会请求OLLAMA_BASE_URL/api/generate - 如果真实请求失败,当前实现仍会回退到 stub,避免整条学习链路直接报废
- 解释型追问接口支持流式渲染,失败时会在前端显示重试状态
- 右上角 health 指示灯会通过
GET /api/health/ollama判断模型是否可达、目标模型是否存在
当前默认模型名:
gpt-oss:120b
主程序上下文设计保持:
128k
当前后端使用:
tiktokencl100k_baseOLLAMA_NUM_CTX=131072
上下文构造目标不是根据你机器当前临时开了多少上下文去降级产品设计,而是始终按主设计保留:
- 最大上下文:
128000 - 裁剪前保留阈值:
100000
即使你本机当前 Ollama 实例暂时只开 64k,主程序设计仍然保持 128k。
真实 Ollama 与解析失败调试信息会写入:
.docker/logs
当前包含:
ollama/记录 health 检查、真实 generate 请求和 fallback 情况parser/记录 Markdown 解析失败时的原始返回、错误原因和关联日志路径
当前已经写入这些测试文件:
backend/apps/cards/tests/test_markdown_parser.pybackend/apps/cards/tests/test_context_builder.pybackend/apps/cards/tests/test_api.pybackend/apps/cards/tests/test_services.pybackend/apps/cards/tests/test_prompt_builder.py
后端测试已经用 python manage.py test 实际跑过一遍并通过。
前端构建也已经验证通过:
cd frontend
npm run build下面这些截图都来自当前仓库的 demo/ 目录。
这版实现是第一阶段全栈骨架,不是最终版。
当前还没做:
- 用户鉴权
- 生产部署
换句话说,现在是“全栈骨架 + Docker 联调 + Ollama 接线 + 前后端主流程”已经完成,但还没有进入生产化阶段。
当前项目按这些原则实现:
- ORM 优先
- 业务逻辑集中到 service 层
- Markdown 解析集中封装
- 不自己造轮子
- DRY / SOLID
后续建议顺序:
- 提交这次 Ollama 接线改动
- 在合适时机把
OLLAMA_USE_STUB=0,做一次真实模型联调验证 - 补前端测试和构建校验
- 优化会话详情里答题记录的持久化展示
- 再考虑生产部署和鉴权













