多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Floci 中 Amazon Textract 服务的模拟实现:JSON 1.1 桩响应、异步任务生命周期与 AI_MOCK_CONFIG 定制

Floci 中 Amazon Textract 服务的模拟实现:JSON 1.1 桩响应、异步任务生命周期与 AI_MOCK_CONFIG 定制 Floci 中 Amazon Textract 服务的模拟实现JSON 1.1 桩响应、异步任务生命周期与 AI_MOCK_CONFIG 定制【免费下载链接】flociLight, fluffy, and always free - The AWS Local Emulator alternative项目地址: https://gitcode.com/gh_mirrors/fl/floci本篇技术指南聚焦 FlociAWS 本地模拟器中 Textract 服务文档 所定义的实现Floci 以「dummy response stub」方式模拟 Amazon Textract 的 JSON 1.1 API不执行真实 OCR但返回与 AWS 线协议完全一致的数据形状使 AWS SDK 与 CLI 客户端可以无错误地消费响应。读完本文你将掌握 Textract 六个支持操作的调用方式、三块Block桩层级结构的字段构成、异步任务「即刻 SUCCEEDED」的生命周期机制以及如何通过AI_MOCK_CONFIG为不同 S3 对象定制检测结果。Textract 模拟的协议基线Textract 在 Floci 中走 AWS JSON 1.1 协议与 AWS 官方行为一致协议类型JSON 1.1请求头X-Amz-Target: Textract.Action同时请求体使用Content-Type: application/x-amz-json-1.1入口所有 action 统一路由到POST /由 TextractJsonHandler 根据X-Amz-Target头完成动作分发见handle()的switch分支TextractJsonHandler.java#L29-L47核心定位是「响应形状兼容优先」模拟器不解析文档内容但保证响应 JSON 的结构与 AWS Textract 契约一致因此 boto3、AWS CLI、Java SDK 等客户端反序列化时不会报错。Document与DocumentLocation输入无论是Bytes还是S3Object引用均被接受但不解析唯一的例外是S3Object会被提取为 mock 查询键详见下文「Mock Responses」。支持的操作一览Operation说明DetectDocumentText返回桩 PAGE LINE WORD 三块结构AnalyzeDocument返回桩 blocksFeatureTypes参数被接受但忽略StartDocumentTextDetection返回JobId任务立即置为 SUCCEEDEDGetDocumentTextDetection对已知JobId返回SUCCEEDED 桩 blocksStartDocumentAnalysis返回JobId任务立即置为 SUCCEEDEDGetDocumentAnalysis对已知JobId返回SUCCEEDED 桩 blocks从源码看六个动作在 TextractJsonHandler.java#L31-L46 中被逐一映射到 TextractService 对应方法任何未列出的 action如Textract.DetectSentiment会返回 HTTP 400 与UnknownOperationException错误体这一行为在 TextractIntegrationTest.java#L193-L204 中有集成测试覆盖。同步操作的行为差异DetectDocumentText响应含DocumentMetadata.Pages恒为 1、Blocks3 块桩、DetectDocumentTextModelVersion固定1.0。AnalyzeDocument与前者共享同一buildStubBlocks()桩数据但返回字段为AnalyzeDocumentModelVersion。FeatureTypes如TABLES、FORMS会被解析但直接忽略对应测试 TextractIntegrationTest.java#L223-L235 验证了「空请求体也可成功」。模型版本常量MODEL_VERSION 1.0定义于 TextractService.java#L33。桩 Block 层级结构每次响应默认返回 3 个Block对象构成 PAGE → LINE → WORD 的父子链严格对齐 AWS Textract 的 API_Block 形状BlockTypeTextRelationshipsPAGE无CHILD→ LINE 的IdLINEFlociCHILD→ WORD 的IdWORDFloci无每个 Block 均包含IdUUID 字符串每次调用随机生成Confidence固定99.9Page固定1GeometryBoundingBoxWidth/Height/Left/Top 4 点PolygonPAGE 块的BoundingBox为整页0,0,1.0,1.0LINE/WORD 块为0.1,0.1,0.15,0.05。Geometry由公共工具 AwsGeometry.buildGeometry() 统一构建Relationships由buildRelationships(CHILD, childId)生成TextractService.java#L155-L203。测试对形状兼容性做了逐字段断言TextractIntegrationTest.java#L55-L72 校验每个 Block 的Id、Confidence、BoundingBox四要素与 4 点Polygon均非空Blocks.Page恒为 1L266-L277WORD 块的Text为FlociL238-L249。异步任务生命周期Start*/Get*四件套用于模拟异步工作流其实现位于 TextractService.java#L81-L130StartDocumentTextDetection/StartDocumentAnalysis生成UUID.randomUUID()作为JobId以「jobId → 任务类型」的键值对写入内存中的ConcurrentHashMap任务类型分别为TEXT_DETECTION/DOCUMENT_ANALYSIS立即返回JobId——任务无需等待天然处于已完成状态。GetDocumentTextDetection/GetDocumentAnalysis校验JobId后返回JobStatus: SUCCEEDED并附带DocumentMetadata、桩Blocks与对应模型版本字段。成功返回后该JobId会从内存表中移除避免无界增长TextractService.java#L99-L100。requireKnownJob()TextractService.java#L132-L145定义了错误语义JobId缺失或空白 → HTTP 400ValidationExceptionJobId is required.未知JobId→ HTTP 400InvalidJobIdException类型错配把StartDocumentTextDetection的JobId交给GetDocumentAnalysis或反之→ HTTP 400InvalidJobIdExceptionJob was not started by the correct operation.上述三类错误路径及「JobId 唯一性」「正确模型版本」均有测试覆盖TextractIntegrationTest.java#L116-L141、L169-L191、L308-L331。注意Job 表纯内存存储模拟器重启即丢失JobId不会跨重启持久化GetDocumentTextDetection/GetDocumentAnalysis的NextToken分页同样不在支持范围内。配置项变量默认值说明FLOCI_SERVICES_TEXTRACT_ENABLEDtrue启用或禁用 Textract 服务AI_MOCK_CONFIG未设置共享 mock 响应配置文件路径详见「Mock Responses」开关对应的底层配置接口是 EmulatorConfig.TextractServiceConfig其enabled()字段带WithDefault(true)注解环境变量形式即为FLOCI_SERVICES_TEXTRACT_ENABLED。与之并列的comprehend()、rekognition()、translate()也使用同样的开关模式EmulatorConfig.java#L733-L738因为这四个「固定桩 AI 服务」共享同一套 mock 加载机制。默认配置可见 src/main/resources/application.yml测试配置见 src/test/resources/application.yml。Mock Responses按 S3 对象定制检测结果默认情况下DetectDocumentText与AnalyzeDocument对所有调用返回相同的桩Block列表。当应用逻辑需要真正读取「识别出的文本」例如断言发票金额、表单字段可设置AI_MOCK_CONFIG指向一个 JSON 文件该文件由 Textract、Comprehend、Rekognition、Translate 四个服务共享{ textract: { my-bucket/invoice.pdf: { DetectDocumentText: { DocumentMetadata: { Pages: 1 }, Blocks: [{ BlockType: LINE, Id: line-1, Confidence: 99.5, Text: Invoice Total: $42.00 }], DetectDocumentTextModelVersion: 1.0 } } } }配置文件的顶层结构为{服务键: {查询键: {Action: 完整响应体}}}服务键textract另有comprehend、rekognition、translate查询键Bucket/Name由请求中Document.S3Object的Bucket与Name拼接而成ActionDetectDocumentText或AnalyzeDocument值为希望原样返回的完整 JSON 响应。查询键的提取逻辑位于 TextractJsonHandler.extractS3Key()仅当Document.S3Object同时包含非空的Bucket、Name文本字段时才返回Bucket/Name键否则返回null。因此使用Bytes承载的Document没有 S3 键mock 不生效永远回落到默认桩mock 仅对S3Object形式的请求生效。回退与容错规则由 AiMockConfigLoader 保证「永不抛异常」见其lookup()与load()实现 AiMockConfigLoader.java#L61-L121AI_MOCK_CONFIG未设置、文件缺失/不可读、JSON 非法或文件中没有匹配条目 → 全部回落到默认桩响应配置文件按修改时间mtime缓存文件内容变化后自动重新读取无需重启模拟器即可热更新 mock异步Start*/Get*流程不支持 mockmock 键需要随 JobId 持久化不在范围内。仓库自带的测试夹具 src/test/resources/fixtures/ai-mock-config.json 演示了四个服务共用一个文件的完整形态TextractIntegrationTest.java#L40-L53 验证了匹配mock-bucket/invoice.pdf时返回定制BlocksInvoice Total: $42.00。实操示例AWS CLIexport AWS_ENDPOINT_URLhttp://localhost:4566 export AWS_DEFAULT_REGIONus-east-1 export AWS_ACCESS_KEY_IDtest export AWS_SECRET_ACCESS_KEYtest # DetectDocumentText aws textract detect-document-text \ --document {S3Object:{Bucket:my-bucket,Name:test.pdf}} # AnalyzeDocument aws textract analyze-document \ --document {S3Object:{Bucket:my-bucket,Name:test.pdf}} \ --feature-types TABLES FORMS # Async: start poll JOB_ID$(aws textract start-document-text-detection \ --document-location {S3Object:{Bucket:my-bucket,Name:test.pdf}} \ --query JobId --output text) aws textract get-document-text-detection --job-id $JOB_IDPython boto3import boto3 client boto3.client(textract, endpoint_urlhttp://localhost:4566) # Sync resp client.detect_document_text( Document{S3Object: {Bucket: my-bucket, Name: test.pdf}} ) for block in resp[Blocks]: print(block[BlockType], block.get(Text, )) # Async job client.start_document_text_detection( DocumentLocation{S3Object: {Bucket: my-bucket, Name: test.pdf}} ) result client.get_document_text_detection(JobIdjob[JobId]) print(result[JobStatus]) # SUCCEEDEDAWS_ENDPOINT_URLhttp://localhost:4566指向 Floci 默认监听端口SDK 客户端经由标准 SigV4 签名访问即可得到桩响应集成测试中使用的授权头形如AWS4-HMAC-SHA256 CredentialAKID/.../textract/aws4_requestTextractIntegrationTest.java#L21-L22说明签名校验与区域无关us-east-1等任意区域均可通过。Out of Scope明确不模拟的能力为保持行为可预期以下能力明确不在模拟范围内docs/services/textract.md「Out of Scope」一节真实 OCR 或文档分析永远返回固定桩 Block 列表AnalyzeExpense、AnalyzeID、AnalyzeLendingDocument等专项分析操作Adapter 管理 APIGetAdapterVersion、CreateAdapter、ListAdaptersGetDocumentTextDetection/GetDocumentAnalysis的NextToken分页跨重启的任务持久化。如果应用代码依赖上述任一能力建议在真实 AWS 或具备相应能力的替代环境中验证Floci 的 Textract 桩仅用于打通端到端调用链路与基础数据流。小结Floci 对 Textract 的模拟遵循「形状兼容、行为最小」的设计协议头、Block 层级、几何结构、模型版本字段均与 AWS 契约对齐六个核心操作可用 CLI/SDK 直接调用AI_MOCK_CONFIG提供按Bucket/Name粒度热更新的响应定制让开发者在没有真实 OCR 的前提下依然能驱动依赖文本结果的应用逻辑。相关代码入口为 TextractJsonHandler 与 TextractService完整行为契约可参照 TextractIntegrationTest共享 mock 机制同样服务于 Comprehend 文档、Rekognition 文档 与 Translate 文档四个服务的配置方式完全一致。【免费下载链接】flociLight, fluffy, and always free - The AWS Local Emulator alternative项目地址: https://gitcode.com/gh_mirrors/fl/floci创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表