技术分享

告别杂乱无章的文本输出:利用 Prism Schema 实现结构化数据提取

作者头像 人称外号大脸猫
157 阅读
告别杂乱无章的文本输出:利用 Prism Schema 实现结构化数据提取

🔥 为什么需要结构化识别?

传统 AI 文本识别面临一个普遍痛点:输出的信息往往是自由文本格式,需要额外的解析工作才能转为可用数据。

传统方式示例:

“公司名称是XX科技,信用代码是91110108MA01XX,成立于2020年...”

开发人员需要编写复杂的正则表达式或文本解析逻辑,这一过程容易出错且效率低下。

Prism Schema 带来的革新: 通过定义数据结构模板,AI 能够直接返回标准化的 JSON 数据:

{
  "company_name": "XX科技有限公司",
  "credit_code": "91110108MA01XX",
  "established_date": "2020-01-01"
}

核心价值:

  • 零解析成本:无需编写和维护复杂的文本解析逻辑
  • 高准确性:结构化输出大幅降低字段提取错误率
  • 开发效率:直接获得可用数据,减少80%的数据处理代码

🎯 核心技术:Prism Schema 深度解析

什么是 Schema?

Schema 即 数据结构定义模板,用于明确告知 AI 模型应返回的数据格式、字段类型、验证规则等。

基础 Schema 类型

Prism 提供了完整的数据类型支持:

use Prism\Prism\Schema\{
    ObjectSchema, StringSchema, 
    ArraySchema, NumberSchema, 
    BooleanSchema, EnumSchema
};

示例:用户信息 Schema 定义

// 定义用户个人信息 Schema
$userSchema = new ObjectSchema(
    name: 'user',
    description: '用户个人信息',
    properties: [
        new StringSchema('name', '姓名', required: true),
        new StringSchema('id_card', '身份证号', pattern: '/^\d{17}[\dX]$/'),
        new NumberSchema('age', '年龄', minimum: 0, maximum: 150),
        new ArraySchema(
            name: 'hobbies',
            description: '爱好列表',
            items: new StringSchema('hobby', '爱好名称')
        )
    ],
    requiredFields: ['name', 'id_card']
);

💼 实战应用:营业执照结构化识别系统

第一步:设计营业执照 Schema

我们创建一个完整的营业执照数据结构定义:

<?php
// app/Schemas/BusinessLicenseSchema.php

namespace App\Schemas;

use Prism\Prism\Schema\{
    ObjectSchema, StringSchema, 
    NumberSchema, ArraySchema,
    EnumSchema
};

class BusinessLicenseSchema
{
    /**
     * 获取完整营业执照 Schema
     */
    public static function getSchema()
    {
        return new ObjectSchema(
            name: 'business_license',
            description: '中国营业执照结构化信息',
            properties: [
                // 基础信息
                new StringSchema(
                    name: 'company_name', 
                    description: '公司全称',
                    minLength: 2,
                    maxLength: 200,
                    required: true
                ),
                
                new StringSchema(
                    name: 'credit_code',
                    description: '统一社会信用代码',
                    pattern: '/^[A-Z0-9]{18}$/',
                    required: true
                ),
                
                // 更多字段定义...
            ],
            requiredFields: ['company_name', 'credit_code', 'established_date']
        );
    }
    
    /**
     * 获取简化版 Schema(用于快速验证)
     */
    public static function getSimpleSchema()
    {
        return new ObjectSchema(
            name: 'simple_business_license',
            description: '营业执照基础信息',
            properties: [
                new StringSchema('company_name', '公司名称', required: true),
                new StringSchema('credit_code', '统一社会信用代码', required: true),
                // 简化字段集...
            ]
        );
    }
}

第二步:集成到识别服务

创建识别服务,整合 Schema 与 AI 模型调用:

<?php
// app/Services/StructuredLicenseOCRService.php

namespace App\Services;

use Prism\Prism;
use Prism\Media\Image;
use App\Schemas\BusinessLicenseSchema;

class StructuredLicenseOCRService
{
    private $retryCount = 0;
    private $maxRetries = 2;
    
    /**
     * 主识别方法:使用 Schema 进行结构化识别
     */
    public function recognizeWithSchema($imagePath, $useComplexSchema = true)
    {
        try {
            // 根据需求选择 Schema 复杂度
            $schema = $useComplexSchema 
                ? BusinessLicenseSchema::getSchema()
                : BusinessLicenseSchema::getSimpleSchema();
            
            // 构建 AI 请求(核心:withSchema 方法)
            $response = Prism::text()
                ->using('openai', 'gpt-4-vision-preview')
                ->withSchema($schema)  // 指定数据结构模板
                ->withPrompt(
                    '请从这张营业执照图片中提取信息,严格按照要求的Schema格式返回数据。' .
                    '特别注意:统一社会信用代码必须是18位,日期格式为YYYY-MM-DD。' .
                    '如果图片中某些信息缺失,请对应字段返回null。'
                )
                ->withImages([Image::fromLocalPath($imagePath)])
                ->asStructured();  // 请求结构化输出
            
            // 验证和清理返回数据
            return $this->validateAndClean($response->data);
            
        } catch (\Exception $e) {
            // 智能重试逻辑
            return $this->handleRecognitionError($e, $imagePath);
        }
    }
    
    /**
     * 数据验证与增强处理
     */
    private function validateAndClean($data)
    {
        // 1. 必填字段校验
        $required = ['company_name', 'credit_code'];
        foreach ($required as $field) {
            if (empty($data[$field])) {
                $data['validation_warnings'][] = "缺失必填字段: {$field}";
            }
        }
        
        // 2. 格式验证
        if (isset($data['credit_code']) && !preg_match('/^[A-Z0-9]{18}$/', $data['credit_code'])) {
            $data['validation_warnings'][] = '统一社会信用代码格式不正确';
        }
        
        // 3. 添加处理元数据
        $data['_meta'] = [
            'extracted_at' => now()->toIso8601String(),
            'schema_version' => '1.0',
            'confidence_score' => $this->calculateConfidence($data)
        ];
        
        return $data;
    }
}

第三步:创建 API 接口

提供 RESTful API 供前端或第三方系统调用:

<?php
// app/Http/Controllers/LicenseController.php

namespace App\Http\Controllers;

use App\Services\StructuredLicenseOCRService;
use Illuminate\Http\Request;

class LicenseController extends Controller
{
    protected $ocrService;
    
    public function __construct()
    {
        $this->ocrService = new StructuredLicenseOCRService();
    }
    
    /**
     * 营业执照识别 API
     * POST /api/license/recognize
     */
    public function recognize(Request $request)
    {
        $validated = $request->validate([
            'image' => 'required|file|image|max:10240',
            'schema_type' => 'sometimes|in:simple,complex'
        ]);
        
        try {
            $path = $request->file('image')->store('temp', 'public');
            $fullPath = storage_path('app/public/' . $path);
            
            $useComplexSchema = $request->get('schema_type', 'complex') === 'complex';
            $result = $this->ocrService->recognizeWithSchema($fullPath, $useComplexSchema);
            
            // 清理临时文件
            unlink($fullPath);
            
            return response()->json([
                'success' => true,
                'data' => $result,
                'processing_time_ms' => $result['_meta']['processing_time_ms'] ?? 0
            ]);
            
        } catch (\Exception $e) {
            return response()->json([
                'error' => '识别失败',
                'message' => $e->getMessage()
            ], 500);
        }
    }
}

🚀 高级功能:智能校验与数据增强

为确保数据质量,我们可以在 Schema 识别基础上增加智能校验层:

<?php
// app/Services/LicenseValidator.php

namespace App\Services;

class LicenseValidator
{
    /**
     * 营业执照数据智能校验
     */
    public function validateLicense($licenseData)
    {
        $errors = [];
        $warnings = [];
        
        // 1. 统一社会信用代码校验(国家标准算法)
        if (isset($licenseData['credit_code'])) {
            if (!$this->validateCreditCode($licenseData['credit_code'])) {
                $errors[] = '统一社会信用代码校验失败';
            }
        }
        
        // 2. 成立日期逻辑校验
        if (isset($licenseData['established_date'])) {
            $established = \Carbon\Carbon::parse($licenseData['established_date']);
            if ($established->isFuture()) {
                $errors[] = '成立日期不能是未来日期';
            }
        }
        
        // 3. 与工商数据库对比(可选增强)
        if (isset($licenseData['credit_code']) && $this->hasOfficialAccess()) {
            $officialData = $this->queryOfficialDatabase($licenseData['credit_code']);
            $comparison = $this->compareWithOfficial($licenseData, $officialData);
            if ($comparison['has_discrepancy']) {
                $warnings[] = '部分信息与官方登记存在差异';
            }
        }
        
        return [
            'is_valid' => empty($errors),
            'errors' => $errors,
            'warnings' => $warnings,
            'validation_score' => $this->calculateValidationScore($errors, $warnings)
        ];
    }
}

📊 实施效果与优势总结

通过集成 Prism Schema,我们实现了以下显著改进:

性能提升

1 ** 开发效率** 2 识别准确率 3 ** 处理速度** 4 ** 维护成本**

核心优势

  1. 标准化输出:消除数据格式不一致问题
  2. 零解析代码:无需编写和维护复杂的文本解析逻辑
  3. 易于集成:结构化 JSON 可直接对接业务系统
  4. 灵活扩展:通过修改 Schema 即可适应新需求
  5. 质量可控:内置验证规则确保数据质量

适用场景

  • 证件、执照、票据等标准化文档识别
  • 合同关键信息提取
  • 报告结构化数据抽取
  • 多源数据归一化处理
  • 实时数据流结构化处理

🎯 最佳实践建议

  1. 渐进式 Schema 设计:从简单 Schema 开始,逐步增加复杂度
  2. 版本管理:对 Schema 进行版本控制,便于回溯和更新
  3. 测试用例:为每个 Schema 编写对应的测试用例
  4. 监控告警:监控识别成功率,设置自动告警机制
  5. 降级策略:准备传统 OCR 降级方案,确保系统可用性

Prism Schema 通过将数据结构定义前置,从根本上改变了 AI 识别输出的处理范式。它不仅大幅提升了开发效率和识别准确率,更重要的是提供了一种可维护、可扩展的数据提取解决方案。随着业务需求的变化,仅需调整 Schema 定义即可适应新的数据结构,真正实现了"一次定义,到处使用"的开发体验。

结构化输出正在成为 AI 应用的标配功能,提前掌握 Schema 驱动开发模式,将在未来的 AI 集成项目中占据显著优势。