拍照搜题.md 9.8 KB

阿里云百炼 - 拍照搜题 API 集成文档

概述

阿里云百炼提供拍照搜题能力,支持:

  • 解题辅导:上传题目图片,获取解题思路和答案
  • 试卷切题:上传试卷图片,自动识别并切分题目

环境配置

必需环境变量

# 阿里云凭证(推荐使用 RAM 用户 AK,不要使用主账号)
ALIBABA_CLOUD_ACCESS_KEY_ID=LTAI5tHETpDzVUPDfPLRn7Pk
ALIBABA_CLOUD_ACCESS_KEY_SECRET= 从users表中获取

# 百炼 Workspace ID
BAILIAN_WORKSPACE_ID=llm-uflun9q7q59osmbb

依赖安装

pip install alibabacloud-edututor20250707
pip install alibabacloud-credentials
pip install alibabacloud-tea-openapi
pip install alibabacloud-tea-util

安全警告

⚠️ 不要使用阿里云主账号 AK

  • 主账号拥有全部权限,AK 泄露风险极高
  • 推荐使用最小化授权的 RAM 用户 AK
  • 通过环境变量管理凭证,不要硬编码

完整代码实现

客户端初始化

import os
import asyncio
import json
from typing import List

from alibabacloud_edututor20250707.client import Client as edututor20250707_client
from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_edututor20250707 import models as edututor20250707_models
from alibabacloud_tea_util import models as util_models


class EduTutorSample:
    """百炼 Workspace ID(从环境变量读取)"""
    workspace_id = os.getenv("BAILIAN_WORKSPACE_ID")
    
    def __init__(self):
        pass

    @staticmethod
    def create_client() -> edututor20250707_client:
        """
        创建 EduTutor 客户端
        使用默认凭据链(自动从环境变量读取 AK/SK)
        
        Returns:
            edututor20250707_client: 初始化的客户端实例
        """
        credential = CredentialClient()
        config = open_api_models.Config(credential=credential)
        config.endpoint = 'edututor.cn-hangzhou.aliyuncs.com'
        return edututor20250707_client(config)

功能 1:解题辅导(Answer)

上传题目图片,获取 AI 解题思路和答案。支持同步和异步两种调用方式。

同步调用

    @staticmethod
    def answer(image: str) -> None:
        """
        同步解题辅导接口(SSE 流式返回)
        
        Args:
            image: 题目图片 URL(需公网可访问)
        """
        client = EduTutorSample.create_client()
        
        # 构造消息内容(图片 + 文本提示)
        content = [
            {"image": image},
            {"type": "text", "text": "回答这个问题"}
        ]
        
        # 构造请求
        thread_messages = edututor20250707_models.AnswerSSERequestMessages(
            content=content,
            role='user'
        )
        
        request = edututor20250707_models.AnswerSSERequest(
            messages=[thread_messages],
            parameters=edututor20250707_models.AnswerSSERequestParameters(
                grade=0,          # 年级(0 表示不限)
                stage='other',    # 学段(other/小学/初中/高中)
                subject='other'   # 学科(other/数学/物理/化学等)
            ),
            workspace_id=EduTutorSample.workspace_id
        )
        
        # 设置超时时间(100 秒)
        runtime = util_models.RuntimeOptions(read_timeout=1000 * 100)
        headers = {}
        
        # SSE 流式接收
        sse_receiver = client.answer_ssewith_sse(request, headers, runtime)
        for response in sse_receiver:
            print(response.body)  # 处理每个流式响应块

异步调用

    @staticmethod
    async def answer_async(image: str) -> None:
        """
        异步解题辅导接口(SSE 流式返回)
        
        Args:
            image: 题目图片 URL(需公网可访问)
        """
        content = [
            {"image": image},
            {"type": "text", "text": "回答这个问题"}
        ]
        
        client = EduTutorSample.create_client()
        thread_messages = edututor20250707_models.AnswerSSERequestMessages(
            content=content,
            role='user'
        )
        
        request = edututor20250707_models.AnswerSSERequest(
            messages=[thread_messages],
            parameters=edututor20250707_models.AnswerSSERequestParameters(
                grade=0,
                stage='other',
                subject='other'
            ),
            workspace_id=EduTutorSample.workspace_id
        )
        
        runtime = util_models.RuntimeOptions(read_timeout=1000 * 100)
        headers = {}
        
        # 异步 SSE 流式接收
        sse_receiver = client.answer_ssewith_sse_async(request, headers, runtime)
        frame_count = 0
        
        async for res in sse_receiver:
            try:
                print(res.body)
                frame_count += 1
                print(f"已接收 {frame_count} 个数据块")
            except json.JSONDecodeError:
                print('------JSON 解析错误--------')
                print(res.get('headers'))
                print(res.get('event').data)
                print('------JSON 解析错误结束--------')
                continue
        
        print('------流式响应结束--------')

参数说明

参数 类型 必填 说明
image string 题目图片 URL(需公网可访问)
grade int 年级(0 表示不限)
stage string 学段:other/小学/初中/高中
subject string 学科:other/数学/物理/化学/英语
workspace_id string 百炼 Workspace ID

功能 2:试卷切题(Cut Questions)

上传试卷图片,自动识别并切分题目,支持 OCR 结构化和图片提取。

同步调用

    @staticmethod
    def cut(image: str) -> None:
        """
        同步试卷切题接口
        
        Args:
            image: 试卷图片 URL(需公网可访问)
        """
        client = EduTutorSample.create_client()
        
        # 配置切题参数
        params = edututor20250707_models.CutQuestionsRequestParameters(
            struct=True,          # 是否输出题目结构化(OCR)信息
            extract_images=True   # 是否返回题目图片链接
        )
        
        request = edututor20250707_models.CutQuestionsRequest(
            image=image,
            parameters=params,
            workspace_id=EduTutorSample.workspace_id
        )
        
        runtime = util_models.RuntimeOptions(read_timeout=1000 * 100)
        headers = {}
        
        response = client.cut_questions_with_options(request, headers, runtime)
        print(response.body)

异步调用

    @staticmethod
    async def cut_async(image: str) -> None:
        """
        异步试卷切题接口
        
        Args:
            image: 试卷图片 URL(需公网可访问)
        """
        client = EduTutorSample.create_client()
        
        params = edututor20250707_models.CutQuestionsRequestParameters(
            struct=True,
            extract_images=True
        )
        
        request = edututor20250707_models.CutQuestionsRequest(
            image=image,
            parameters=params,
            workspace_id=EduTutorSample.workspace_id
        )
        
        runtime = util_models.RuntimeOptions(read_timeout=1000 * 100)
        headers = {}
        
        response = await client.cut_questions_with_options_async(request, headers, runtime)
        print(response.body)

参数说明

参数 类型 必填 说明
image string 试卷图片 URL(需公网可访问)
struct bool 是否输出题目结构化(OCR)信息
extract_images bool 是否返回题目图片链接
workspace_id string 百炼 Workspace ID

使用示例

if __name__ == '__main__':
    # 示例图片 URL(需替换为实际可访问的图片链接)
    image = "https://example.com/question.png"
    
    # ==================== 试卷切题 ====================
    print("=== 同步切题 ===")
    EduTutorSample.cut(image=image)
    
    print("\n=== 异步切题 ===")
    asyncio.run(EduTutorSample.cut_async(image=image))
    
    # ==================== 解题辅导 ====================
    print("\n=== 同步解题 ===")
    EduTutorSample.answer(image=image)
    
    print("\n=== 异步解题 ===")
    asyncio.run(EduTutorSample.answer_async(image=image))

注意事项

图片要求

  • 图片必须是公网可访问的 URL
  • 支持格式:JPG、PNG
  • 建议分辨率:1080p 以上
  • 图片清晰度影响识别准确率

超时设置

  • 默认超时时间:100 秒(read_timeout=1000 * 100
  • 复杂试卷切题可能需要更长时间
  • 建议根据实际情况调整超时参数

错误处理

  • SSE 流式响应可能出现 JSON 解析错误,需要捕获 json.JSONDecodeError
  • 网络异常需要重试机制
  • 建议记录完整的请求和响应日志

待补充信息

如需以下信息,请联系相关人员:

  • API 调用频率限制(QPS)
  • 计费方式和价格(参考 模型价格.md
  • 响应数据结构详细说明
  • 错误码列表和处理建议
  • 图片上传到 OSS 的最佳实践
  • 生产环境配置建议(如负载均衡、重试策略)
  • 监控和日志方案

相关文档


文档版本:v1.0
最后更新:2025-01-29
维护者:Backend Team