TECHNICAL_NOTES.md 6.8 KB

百炼平台身份证识别技术实现说明

概述

本项目使用阿里云百炼平台的 qwen-vl 视觉模型实现身份证识别功能。相比之前的 LangChain4J 方案,直接使用百炼官方 SDK 可以获得更好的性能和更准确的识别结果。

核心实现

1. Maven 依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dashscope-sdk-java</artifactId>
    <version>2.16.3</version>
</dependency>

2. 配置文件

application.yml 中配置百炼平台 API Key:

bailian:
  api-key: YOUR_API_KEY_HERE  # 替换为你的百炼平台 API Key
  model: qwen-vl-max  # 可选:qwen-vl-max、qwen-vl-plus、qwen-vl-v1 等

3. 核心代码实现

IdCardRecognitionService.java

@Service
public class IdCardRecognitionService {

    @Value("${bailian.api-key}")
    private String apiKey;

    @Value("${bailian.model}")
    private String modelName;

    public IdCardRecognitionResult recognizeIdCard(MultipartFile file) {
        // 1. 文件验证
        // 2. 保存为临时文件
        // 3. 调用百炼 API
        // 4. 解析响应
        // 5. 清理临时文件
    }

    private IdCardRecognitionResult callDashScopeAPI(String imagePath) {
        // 创建多模态对话实例
        MultiModalConversation conversation = new MultiModalConversation();

        // 构建用户消息
        MultiModalMessage userMessage = MultiModalMessage.builder()
                .role(Role.USER.getValue())
                .content(Arrays.asList(
                    Collections.singletonMap("image", imagePath),
                    Collections.singletonMap("text", buildPrompt())
                ))
                .build();

        // 构建请求参数
        MultiModalConversationParam param = MultiModalConversationParam.builder()
                .apiKey(apiKey)
                .model(modelName)
                .messages(Arrays.asList(userMessage))
                .build();

        // 调用 API
        MultiModalConversationResult result = conversation.call(param);

        // 解析响应...
    }
}

技术要点

1. 图片处理

  • 前端上传的图片通过 MultipartFile 接收
  • 保存到系统临时目录(System.getProperty("java.io.tmpdir")
  • 使用 UUID 生成唯一文件名,避免冲突
  • 识别完成后自动清理临时文件

2. 百炼平台调用

使用官方 SDK 的 MultiModalConversation 类:

MultiModalConversation conversation = new MultiModalConversation();
MultiModalConversationResult result = conversation.call(param);

3. 提示词设计

优化的提示词可以显著提升识别准确率:

private String buildPrompt() {
    return """
        请仔细分析这张图片,并完成以下任务:

        1. 判断图片中是否为中华人民共和国居民身份证(正面)
        2. 如果是身份证,请提取其中的18位身份证号码
        3. 如果不是身份证或无法识别,请说明原因

        回答要求:
        - 如果是身份证且识别成功,请直接输出18位身份证号码
        - 如果不是身份证或识别失败,请说明原因

        注意事项:
        - 身份证号为18位,最后一位可能是X
        - 只输出身份证号码或失败原因,不要包含其他内容
        """;
}

4. 响应解析

多层解析策略确保高成功率:

  1. 直接提取:使用正则表达式直接匹配18位身份证号
  2. JSON 解析:如果模型返回 JSON 格式,提取其中的身份证号字段
  3. 失败判断:识别失败的关键词("不是身份证"、"无法识别"等)
  4. 格式验证:验证提取的身份证号格式是否正确(18位,前17位数字,最后一位数字或X)

与 LangChain4J 方案对比

特性 LangChain4J 方案 百炼 SDK 方案
依赖 LangChain4J + OpenAI 兼容层 官方 SDK
配置 需要 base-url、temperature 等 只需 API Key 和模型名
性能 通过兼容层调用 直接调用,性能更好
图片传递 Base64 编码 本地文件路径
准确率 较好 更好
错误处理 通用异常 专门的异常类型

支持的模型

百炼平台支持以下视觉模型:

  • qwen-vl-max:最强性能,推荐使用(默认)
  • qwen-vl-plus:性能均衡
  • qwen-vl-v1:经济实惠

可以在 application.yml 中切换模型:

bailian:
  model: qwen-vl-plus  # 切换到 plus 模型

常见问题

Q1: 临时文件存储在哪里?

临时文件存储在系统临时目录:

  • Windows: C:\Users\用户名\AppData\Local\Temp
  • Mac/Linux: /tmp

识别完成后会自动清理。

Q2: 为什么使用本地文件而不是 Base64?

百炼 SDK 的 MultiModalConversation 类原生支持本地文件路径,这样:

  • 避免了 Base64 编码/解码的性能开销
  • 减少了内存占用
  • SDK 内部会自动处理文件上传

Q3: 如何提高识别准确率?

  1. 图片质量:确保图片清晰、光线充足
  2. 提示词优化:根据实际需求调整提示词
  3. 模型选择:使用 qwen-vl-max 获得最佳效果
  4. 多次尝试:可以提供重试机制

Q4: API 调用失败怎么办?

代码中已经实现了完善的异常处理:

try {
    // 调用 API
} catch (NoApiKeyException e) {
    // API Key 未配置
} catch (ApiException e) {
    // API 调用失败
} catch (UploadFileException e) {
    // 图片上传失败
}

前端会显示友好的错误提示,并允许用户手动输入身份证号。

Q5: 如何查看调试日志?

application.yml 中已配置:

logging:
  level:
    com.medical.demo: DEBUG
    com.alibaba.dashscope: DEBUG

可以在控制台看到详细的调用日志,包括:

  • 图片临时文件路径
  • API 请求参数
  • 百炼平台响应内容
  • 解析过程和结果

性能优化建议

  1. 并发控制:如果有多人同时使用,考虑添加线程池限制并发请求数
  2. 缓存机制:对同一身份证号的多次识别请求可以缓存结果
  3. 图片压缩:在上传前对大图片进行压缩,减少传输时间
  4. 重试机制:网络波动时可以自动重试

扩展功能建议

  1. 身份证反面识别:识别有效期、签发机关等信息
  2. OCR 增强功能:识别姓名、性别、民族等信息并自动填充表单
  3. 人脸对比:验证持证人与身份证照片是否一致
  4. 批量识别:支持上传多张身份证图片进行批量处理

参考文档


技术支持:如有问题,请查看项目 README.md 或提 Issue