# 拍照解题功能设计文档 **文档版本**: v1.0 **创建日期**: 2025-01-29 **设计者**: Backend Team **状态**: 设计阶段 --- ## 一、功能概述 ### 1.1 核心能力 拍照解题功能基于阿里云百炼 EduTutor 服务,提供两大核心能力: - **试卷切题(Cut Questions)**: 上传试卷图片,自动识别并切分题目,返回结构化信息 - **解题辅导(Answer)**: 上传题目图片,获取详细的解题思路和答案 ### 1.2 业务价值 - 提升学习效率:快速获取题目解析,节省查找时间 - 智能化教学:提供结构化的解题思路,培养解题能力 - 试卷数字化:自动切分试卷,便于题库管理和批量处理 --- ## 二、功能架构 ### 2.1 系统架构 ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Frontend │ │ Backend │ │ 百炼 EduTutor │ │ │ │ │ │ │ │ 图片上传 │───▶│ 图片处理 │───▶│ Cut API │ │ 题目展示 │ │ 请求转发 │ │ Answer API │ │ 答案渲染 │◀───│ 结果解析 │◀───│ (SSE 流式) │ │ │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ ▼ │ ┌─────────────────┐ │ │ PostgreSQL │ └─────────────▶│ │ (可选) │ 题目记录 │ │ 解答历史 │ └─────────────────┘ ``` ### 2.2 数据流向 **试卷切题流程**: 1. 用户上传试卷图片 → 前端 2. 图片上传至 OSS → 后端 3. 调用 Cut API → 百炼服务 4. 返回题目列表(含坐标、结构化信息、子图链接)→ 后端 5. 解析并展示题目 → 前端 **解题辅导流程**: 1. 用户选择题目/上传图片 → 前端 2. 调用 Answer API(SSE 流式)→ 后端 3. 流式返回解题过程 → 百炼服务 4. 实时渲染解答内容 → 前端 --- ## 三、核心接口设计 ### 3.1 试卷切题接口 **端点**: `POST /api/edu/cut-questions` **请求参数**: ```json { "image_url": "https://oss.example.com/paper.png", "options": { "struct": true, // 是否返回结构化信息 "extract_images": true // 是否返回子题图片链接 } } ``` **响应结构**: ```json { "success": true, "data": { "questions": [ { "index": 0, "type": "填空题", "stem": { "text": "若 a + b = -1, ab = 4, 则...", "pos_list": [[21, 4, 364, 4, 364, 78, 21, 78]] }, "options": [], "answer": [{"text": "-17"}], "merged_image": "https://oss.../question_0.png", "sub_images": ["https://oss.../sub_0_0.png"] } ] }, "input_tokens": 80, "output_tokens": 38 } ``` ### 3.2 解题辅导接口 **端点**: `POST /api/edu/answer` (SSE 流式) **请求参数**: ```json { "image_url": "https://oss.example.com/question.png", "parameters": { "grade": 6, // 年级(0-17, 99=其他) "stage": "小学", // 学段 "subject": "数学" // 学科 } } ``` **SSE 流式响应**: ``` data: {"type": "start", "content": "### 【考点分析】:\n"} data: {"type": "chunk", "content": "本题涉及代数表达式..."} data: {"type": "chunk", "content": "### 【方法点拨】:\n"} data: {"type": "finish", "finish_reason": "stop", "tokens": {"input": 654, "output": 457}} ``` --- ## 四、数据模型设计 ### 4.1 题目记录表 (question_records) | 字段 | 类型 | 说明 | |------|------|------| | id | UUID | 主键 | | user_id | UUID | 用户ID(外键) | | image_url | TEXT | 原始图片链接 | | question_type | VARCHAR(20) | 题目类型 | | stem_text | TEXT | 题干文本 | | answer_text | TEXT | 答案文本 | | structured_data | JSONB | 完整结构化数据 | | created_at | TIMESTAMP | 创建时间 | ### 4.2 解答历史表 (answer_history) | 字段 | 类型 | 说明 | |------|------|------| | id | UUID | 主键 | | question_id | UUID | 题目ID(外键) | | user_id | UUID | 用户ID(外键) | | answer_content | TEXT | 解答内容(Markdown) | | grade | INTEGER | 年级 | | subject | VARCHAR(50) | 学科 | | input_tokens | INTEGER | 输入Token数 | | output_tokens | INTEGER | 输出Token数 | | created_at | TIMESTAMP | 创建时间 | --- ## 五、技术实现要点 ### 5.1 图片处理 **上传策略**: - 前端直传 OSS(推荐):减轻后端压力,提升上传速度 - 后端中转:适用于需要图片预处理的场景 **图片要求**: - 格式:JPG、PNG - 分辨率:建议 1080p 以上 - 大小限制:< 10MB - 必须是公网可访问的 URL ### 5.2 SSE 流式处理 **后端实现**: ```python async def answer_stream(image_url: str, params: dict): client = create_edututor_client() request = build_answer_request(image_url, params) async for chunk in client.answer_sse_async(request): yield format_sse_event(chunk) ``` **前端实现**: ```javascript const eventSource = new EventSource('/api/edu/answer'); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); appendAnswer(data.content); }; ``` ### 5.3 错误处理 **常见错误场景**: - 图片无法访问:返回 400,提示图片链接无效 - API 调用超时:设置 100s 超时,超时后返回 504 - 识别失败:返回 422,提示图片质量不佳或题目不清晰 - 配额不足:返回 429,提示今日调用次数已达上限 ## 六、性能与成本 ### 6.1 性能指标 | 指标 | 目标值 | |------|--------| | 切题响应时间 | < 5s(单页试卷) | | 解题首字响应 | < 2s | | 解题完整响应 | < 15s | | 并发支持 | 100 QPS | ### 6.2 成本控制 **优化策略**: - 缓存相同题目的解答结果 - 对重复图片进行去重识别 - 用户侧限流:每用户每天最多 50 次调用 --- ## 七、安全与合规 ### 7.1 数据安全 - 图片链接有效期:7 天(百炼返回的临时链接) - 敏感信息过滤:检测并脱敏个人信息(姓名、学号等) - 访问控制:仅用户本人可查看历史记录 --- ## 八、用户体验设计 ### 8.1 交互流程 **试卷切题**: 1. 点击"上传试卷"按钮 2. 选择图片(支持拖拽) 3. 显示上传进度 4. 展示切分后的题目列表(卡片式布局) 5. 点击题目卡片查看详情 **解题辅导**: 1. 选择题目或上传单题图片 2. 选择年级、学科(可选) 3. 点击"开始解题" 4. 流式展示解题过程(打字机效果) 5. 支持复制、收藏、分享 ### 8.2 UI 组件 - **上传组件**: 拖拽上传 + 点击上传,显示预览和进度 - **题目卡片**: 显示题号、类型、题干预览、缩略图 - **解答面板**: Markdown 渲染,支持数学公式(LaTeX) - **历史记录**: 时间线展示,支持搜索和筛选 --- ## 九、开发计划 ### 9.2 技术依赖 **后端**: - `alibabacloud-edututor20250707`: 百炼 SDK - `alibabacloud-credentials`: 凭证管理 - `oss2`: 阿里云 OSS SDK(图片上传) **前端**: - `react-markdown`: Markdown 渲染 - `katex`: 数学公式渲染 - `react-dropzone`: 文件上传组件 --- ## 十、测试策略 ### 10.1 单元测试 - 图片上传逻辑 - API 请求构造和响应解析 - SSE 流式数据处理 - 数据库 CRUD 操作 ### 10.2 集成测试 - 完整的切题流程 - 完整的解题流程 - 错误场景处理 - 并发请求测试 ### 10.3 用户测试 - 不同类型试卷的识别准确率 - 不同学科题目的解答质量 - 流式输出的流畅度 - 移动端适配效果 --- ## 十一、后续优化方向 ### 11.1 功能增强 - 支持手写题目识别 - 支持拍照后本地裁剪和标注 - 支持多题批量解答 - 支持解答过程的语音播报 ### 11.2 智能化升级 - 根据用户历史推荐相似题目 - 智能识别薄弱知识点 - 生成个性化练习题 - 错题本自动整理 ### 11.3 社区化 - 用户可分享优质解答 - 支持题目讨论和评论 - 教师可创建题目集合 - 学生可组队刷题 --- ## 十二、风险与应对 | 风险 | 影响 | 应对措施 | |------|------|----------| | API 调用超限 | 服务不可用 | 实现本地缓存 + 用户限流 | | 识别准确率低 | 用户体验差 | 提供手动编辑入口 + 反馈机制 | | 图片加载慢 | 响应时间长 | CDN 加速 + 图片压缩 | | 成本超预算 | 运营压力 | 实施分级收费策略 | --- ## 附录 ### A. 相关文档 - [拍照解题 Answer API](../Outside/bailian/拍照解题answerapi.md) - [拍照搜题 Cut API](../Outside/bailian/拍照搜题cutapi.md) - [拍照搜题集成文档](../Outside/bailian/拍照搜题.md) - [模型价格](../Outside/bailian/模型价格.md) ### B. 环境变量配置 ```bash # 阿里云凭证 ALIBABA_CLOUD_ACCESS_KEY_ID=your_access_key_id ALIBABA_CLOUD_ACCESS_KEY_SECRET=your_access_key_secret # 百炼 Workspace ID BAILIAN_WORKSPACE_ID=llm-uflun9q7q59osmbb # OSS 配置(图片上传) OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com OSS_BUCKET=your-bucket-name OSS_ACCESS_KEY_ID=your_oss_ak OSS_ACCESS_KEY_SECRET=your_oss_sk ``` ### C. API 调用示例 **切题示例**: ```bash curl -X POST "http://localhost:8000/api/edu/cut-questions" \ -H "Content-Type: application/json" \ -d '{ "image_url": "https://example.com/paper.png", "options": {"struct": true, "extract_images": true} }' ``` **解题示例**: ```bash curl -N "http://localhost:8000/api/edu/answer" \ -H "Content-Type: application/json" \ -d '{ "image_url": "https://example.com/question.png", "parameters": {"grade": 6, "subject": "数学"} }' ``` --- **文档结束**