亚马逊AWS官方博客

Amazon Bedrock 大语言模型加速 OCR 场景精准提取

1. 背景介绍

光学字符识别(OCR)技术在识别印刷体或手写体文字方面已经取得了显著的进展,但仍然存在一些常见问题和挑战。以下是一些常见的 OCR 技术问题:

  • (一)文字质量: OCR 系统对文字质量要求较高,如果文本模糊、扭曲、模糊不清或遭受损坏,识别准确率可能会降低。
  • (二)手写体识别: 手写体文字识别是一个更具挑战性的任务,因为手写文字的风格和形状变化较大,而且可能存在连接、断开、变形等问题。
  • (三)文档类型多样性: 处理不同类型的文档(如表格、报告、手写笔记等)需要 OCR 系统具备适应性,这可能需要更复杂的模型和处理流程。
  • (四)上下文理解: 对于某些应用,理解文本的上下文是必要的,但传统的 OCR 技术可能缺乏这种上下文感知能力。

: 上述图片均来源于互联网

OCR 技术是人们日常使用最多的 AI 场景,但处理以上问题仍遇到了很大的挑战。本文的目的是帮助大家通过亚马逊云科技 OCR 以及生成式 AI(Gen-AI)产品加速关键内容提取与整理。

2. 亚马逊云科技 OCR 相关产品/解决方案

(1)Amazon Textract 是一种机器学习(ML)服务,可自动从任意文档或图像中提取文本、手写和数据。使用 Amazon Textract 的 AnalyzeDocument API 可提供表格功能,提供从任何文档中自动提取表格结构的功能。

(2)Amazon Rekognition 是一项功能强大的图像和视频分析服务,可提取图像中的信息并提供深入洞察。其中的图像文本识别功能专门用于处理真实世界的图像,而不仅仅是文档图像。它支持大多数拉丁语书写体文本以及数字,并且可以识别嵌入在各种布局中、采用不同字体和样式、在不同方向上作为横幅和海报覆盖在背景对象上的文本。

(3)AWS AI Solution Kit 提供一系列开箱即用的云上 AI 功能,例如:多语种高阶文字识别(OCR)、通用自然语言理解(NLU)、通用物体识别、图像超分、图片相似度、人像分割等。 特别是 AWS AI Solution Kit 增强了对于简体中文语言识别能力。

通过使用亚马逊云科技提供的这三款 OCR 产品/解决方案,可以有效解决文字质量低、手写体识别等问题。尤其是 Amazon Textract 能够处理多种文件格式,包括 JPG、PNG、PDF 等,并且能够处理扫描文档和手机拍摄的图片。除了提取文档中的内容(包括表格和表单字段等结构化数据),Amazon Textract 还可以在满足个人隐私信息(PII)保护的前提下,分析发票、收据或身份证中的相关数据。

在进行 OCR 内容提取时,文件内容格式不固定且需要上下文语义理解,仅使用 OCR 无法完全解决这个问题。在这种情况下,引入大语言模型可以很好地帮助我们克服这些局限性,并加速文本内容的精确提取。本文将介绍一套完整的解决方案,深入探讨如何结合 OCR 产品和大语言模型,以提高文本内容提取的准确性和效率。

3. 基于 Bedrock 进行 OCR 关键信息提取方案

3.1 Amazon Bedrock 介绍

Amazon Bedrock 服务于 2023 年 9 月 28 日正式可用,这是使用基础模型构建和扩展生成性人工智能应用程序的最简单方法。Amazon Bedrock 是一项完全托管的服务,提供来自 AI21 Labs、Anthropic、Cohere、Meta、Stability AI 和 Amazon 等领先提供商的高性能基础模型,以及客户构建生成式 AI 应用程序所需的一套广泛功能,简化开发,同时维护隐私和安全。

  • 在 Bedrock 上,用户可以享受可扩展、可靠且安全的亚马逊云科技托管服务,无需管理基础设施。
  • 用户可以访问从文本到图像的一系列强大的基础模型,包括一会我会使用到的新发布的 Amazon Titan 基础模型。用户可以轻松找到适合自身业务的模型,快速上手。
  • 用户可以在确保数据安全和隐私保护的前提下,使用自有数据基于基础模型进行定制。Bedrock 最重要的能力之一是极其容易定制模型。客户只需向 Bedrock 展示 Amazon S3 中的几个标注好的数据示例,Bedrock 就可以针对特定任务微调模型,最少仅需 20 个示例即可,而无需标注大量数据。
  • 没有任何用户数据被用于训练底层模型。所有数据都进行了加密,且不会离开用户的虚拟私有网络(VPC),因此用户完全可以确信获得数据安全和隐私保护。

3.2 Claude 模型介绍与使用申请

通过 Bedrock 您可以快速访问 Claude API。Claude V2 具有更好的性能和更长的回复时间。用户可以在每个提示中输入多达 100K,这意味着 Claude 可以处理数百页的技术文档甚至一本书。更重要的是,Claude 在交流中表现出色,能够清晰地解释其思路,几乎不会产生有害的输出,并且具有超强的记忆力。

在编码、数学和推理方面,最新的模型在法学考试的多项选择部分得分为 76.5%,而 Claude1.3 的得分为 73.0%。与申请研究生院的大学生相比,Claude2 在 GRE 阅读和写作考试中超过了 90% 的排名,并且在定量推理方面与中位数申请者成绩相当。

当您首次登陆 Bedrock 时,需要通过左下角模型列表(Model Access)中选择,请求访问在 Bedrock 中使用的模型。比如 Anthropic Claude 模型能首先需要提交一些使用详细信息,然后才能获得访问权限。请注意,只有具有所需 IAM 权限的用户才能管理此帐户的模型访问权限。

3.3 实现方案架构

4. 操作配置

4.1 Amazon Lambda 配置说明

进入到 Lambda 控制台,按照以下配置创建一个新的函数。

  • 函数名称:填写你的函数名称,如 bedrock_demo
  • 运行时:选择 Python 3.10
  • 架构:选择 x86_64
  • 权限:创建具有基本 Lambda 权限的新角色
  • 点击创建函数

创建完 Lambda 函数之后,修改 Lambda 函数配置,方便我们后续进行测试。

  • 首先修改 Lambda 函数的超时时间,设置为 1 分钟
  • 创建名为 bedrock 的策略,策略配置如下
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",	
                "Action": "bedrock:*",
                "Resource": "*"
            }
        ]
    }
    
  • Lambda 函数的角色权限,点击该角色,并将以下 2 个策略(AmazonS3FullAccess,AmazonTextractFullAccess),以及刚创建的 bedrock 策略附加到该角色上

由于 Amazon Bedrock 需要特定版本的 Boto3 SDK,因此需要进行下载安装,并通过 Layer 的方式上传到 Lambda 中。

  • 以下脚本会下载 boto3 最新版本,re-zip 并将其上传到 S3 存储桶当中,上传完之后进行删除
  • 需要将 BUCKET_NAME 替换为你的 S3 存储桶,该存储桶与你的 Lambda 函数在同个区域
  • 另外需要修改.sh 文件的权限
    chmod +x ./NAME.sh
    #! /bin/sh
    bucket='s3://BUCKET_NAME/'
    python -m pip install boto3 --target ./pythonzip -r lambda_layer.zip ./python
    aws s3 cp ./lambda_layer.zip $bucket
    rm -r ./pythonrm ./lambda_layer.zip
    

在 Lambda 创建 Layer 层,并将存储在 S3 存储桶的 zip 文件上传

  • BUCKET_NAME 替换为存储 zip 文件的存储桶
  • 点击创建
  • 为你的 Lambda 函数添加刚才创建的 Layer 层

4.2 Amazon API Gateway 配置说明

进入到 API Gateway 控制台,按照以下配置创建一个新的函数。

  • 创建 REST API
  • API 详细信息:选择新建 API
  • API 名称:填写你的 API 名称,如 my_api
  • 点击创建 API

创建完 API 之后,点击创建方法,方便我们后续进行测试。

在以下创建方法的界面中进行配置。

  • 方法类型:选择 POST 类型
  • 集成类型:选择 Lambda 函数
  • Lambda 函数:选择在 1 部分创建的 Lambda 函数
  • 点击创建方法

在该 POST 方法中,在集成请求将 Lambda 代理集成开启

在 API 设置将二进制媒体类型添加 image/jpg 以及 image/jpeg

在创建的 API 界面,点击部署 API,选择一个新阶段,并添加阶段名称

在阶段选择你创建的阶段,并复制调用 URL,后续使用该 URL 进行测试

4.3 Amazon Lambda 代码实现

将以下代码复制到 Lambda 函数中,并点击 Deploy 进行部署。

import boto3
import base64
import json

def lambda_handler(event, context):

    #获取api请求的图片并将图片存储到s3桶中
    s3_client = boto3.client('s3')
    content_type = event['headers']['content-type']
    object_key = 'images/uploaded-image.jpg'
    
    #填写自己桶的名称
    bucket = 'BUCKET_NAME'
    
    image_data=base64.b64decode(event['body'])
    s3_client.put_object(Bucket=bucket, Key=object_key, Body=image_data, ContentType=content_type)

    #调用detect_document_text分析图片,并提取文本
    textract_client = boto3.client('textract')
    response = textract_client.detect_document_text(
        Document={'S3Object': {'Bucket': bucket, 'Name': object_key}})

    #Get the text blocks
    blocks=response['Blocks']
    #print(blocks)
    
    columns = []
    lines = []
    for item in response["Blocks"]:
          if item["BlockType"] == "LINE":
            column_found=False
            for index, column in enumerate(columns):
                bbox_left = item["Geometry"]["BoundingBox"]["Left"]
                bbox_right = item["Geometry"]["BoundingBox"]["Left"] + item["Geometry"]["BoundingBox"]["Width"]
                bbox_centre = item["Geometry"]["BoundingBox"]["Left"] + item["Geometry"]["BoundingBox"]["Width"]/2
                column_centre = column['left'] + column['right']/2
    
                if (bbox_centre > column['left'] and bbox_centre < column['right']) or (column_centre > bbox_left and column_centre < bbox_right):
                    #Bbox appears inside the column
                    lines.append([index, item["Text"]])
                    column_found=True
                    break
            if not column_found:
                columns.append({'left':item["Geometry"]["BoundingBox"]["Left"], 'right':item["Geometry"]["BoundingBox"]["Left"] + item["Geometry"]["BoundingBox"]["Width"]})
                lines.append([len(columns)-1, item["Text"]])
    
    lines.sort(key=lambda x: x[0])
    
    result_string = ""
    
    for line in lines:
        result_string += line[1] + '\n'
    
    #print(result_string)
    
    #将图片中的文本信息作为prompt的一部份来调用bedrock claude模型
    bedrock = boto3.client(service_name='bedrock', region_name='us-west-2',endpoint_url='https://bedrock-runtime.us-west-2.amazonaws.com')
    modelId = 'anthropic.claude-v2' 
    accept = 'application/json'
    contentType = 'application/json'

    prompt = """Human: I need to provide eye data to help me customize my glasses
    
    Steps:
    1. As common sense, please refer to the theoretical value to judge Sphere: -10.0 ~ +10.0,Cylinder: 0.0 ~ -5.0,Axis: 0 ~ 180, ADD: 0.0 ~ +3.0.
    2. When "SPH" appears in the corresponding cell. Or "Plano", the result can directly output "N/A".(When the confidence is greater than 0.92, the output is carried out, otherwise the corresponding key output "N/A")
    3. Please output the JSON results strictly according to the 〈Template〉 format.
    4. Don't reply outside the {text}.
    <Template> = {
      "od_sph": " ", 
      "os_sph": " ", 
      "od_cyl": " ", 
      "os_cyl": " ", 
      "od_axis": " ",
      "os_axis": " ",
      "od_add": " ", 
      "os_add": " ", 
    }
    <text>
    %s
    </text>
    
    Assistant:"""%(result_string)

    #print(prompt) 
        
    body = json.dumps({ "prompt":prompt,
                       "max_tokens_to_sample": 300,
                       "temperature": 0.1,
                       "top_k": 250,
                       "top_p": 1,
                       "stop_sequences": []
                      }) 
    response = bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)
    response_body = json.loads(response.get('body').read())
    
    #print(response_body.get("completion"))
    
    return {
        'statusCode': 200,
        'body': json.dumps(response_body.get("completion"))
    }

4.4 结果验证

如下图验光处方单由于格式不统一或医生笔记难以识读,提取关键参数具有一定难度。为快速获取处方参数,采用大模型 Claude 对包含内容注释的问题文本进行语义理解,提取出球面度数(SPH)、柱面度数(CYL)、散光轴位(AXIS)和近视加力(ADD),并将缺失参数填充为“N/A”,最后转换为结构化的 JSON 格式数据,以便后续应用。此方案既可处理非结构化文本,又可实现参数提取和结构化,可有效提升处方信息的采集效率。

通过 API 的调用 URL 进行测试,类似 https://xxx.us-west-2.amazonaws.com/test 的请求,根据 API Gateway Endpoint 地址执行以下命令并返回输出结果。

curl -X POST https://xxx.us-west-2.amazonaws.com/test -H 'Content-Type: image/jpeg' --data-binary @image.jpg
{
"od_sph": "-2.50",
"os_sph": "-3.00",
"od_cyl": "-0.75",
"os_cyl": "-1.00",
"od_axis": "173",
"os_axis": "004",
"od_add": "N/A",
"os_add": "N/A"
}

5. 总结

本文介绍了一套完整的解决方案,旨在有效解决文字质量低、手写体识别、文档类型多样性以及上下文理解等问题。我们利用 Amazon API Gateway +Lambda +S3 +Textract+ Bedrock 构建了一个无服务器应用,无需进行运维管理。在无固定模板的样例中,相比传统的 OCR 正则匹配方法可以极大地提升准确率。优势在于它的灵活性和可扩展性,开发者无需依赖固定的模板,可以适应各种文档类型和样式。而且根据需要轻松地调整和改进模型,以进一步提高准确率和性能。

希望本文对您有所帮助,如果您有任何疑问或需要进一步的信息,请随时联系我们!

本篇作者

于涛

亚马逊云科技解决方案架构师,负责亚马逊云科技云计算方案咨询和设计。目前主要专注在现代化应用改造和机器学习领域的技术研究和实践。加入 AWS 之前曾服务于大型运营商及 IT 解决方案供应商,积累了丰富的跨境电商/快消行业项目经验。

杨树铭

亚马逊云科技解决方案架构师,负责亚马逊云科技云计算方案咨询和设计。他与客户合作构建各类创新解决方案,帮助客户解决业务问题并快速使用 AWS 服务。热衷于游戏/大数据领域,熟悉 EMR、Kinesis、Athena、Glue 等服务与方案设计。

赵克鸣

亚马逊云科技解决方案架构师,负责云计算解决方案的咨询和设计。热爱 AI/ML 领域的技术研究,并通过可实施的解决方案,帮助客户取得业务价值。