微调语言模型识别收据图片并保存至JSON/XML

点击下方卡片,关注“小白玩转Python”公众号

动机

将收据图像转换为JSON或XML对象的动机在于以结构化和组织良好的方式更容易存储、分析和操作数据。JSON(JavaScript对象表示)和XML(可扩展标记语言)都是轻量级的数据交换格式,易于人类阅读和编写,也易于机器解析和生成。通过将收据图像转换为JSON或XML对象,数据可以轻松存储在数据库中或通过互联网传输,使其更易于访问和用于各种应用程序。

ce8a2ff45141906c3e9edecaa3b7e8d5.jpeg

收据图像示例

此外,使用编程语言和工具可以轻松处理和分析JSON和XML对象,从而更容易提取见解并基于数据做出决策。总体而言,将收据图像转换为JSON或XML对象有助于简化数据管理和分析,使其更加高效和有效。

{
    'receipt': {
        'store': 'The Lone Pine',
        'address': '43 Manchester Road',
        'city': 'Brisbane',
        'country': 'Australia',
        'phone': '617-3236-6207',
        'invoice': 'Invoice 08000008',
        'date': '09/04/08',
        'table': 'Table',
        'items': [
            {'name': 'Carlsberg Bottle', 'price': '16.00', 'quantity': '2'},
            {'name': 'Heineken Draft Standard.', 'price': '15.20', 'quantity': '1'},
            {'name': 'Heineken Draft Half Liter.', 'price': '15.20', 'quantity': '1'},
            {'name': 'Carlsberg Bucket (5 bottles).', 'price': '80.00', 'quantity': '1'},
            {'name': 'Grilled Chicken Breast.', 'price': '74.00', 'quantity': '1'},
            {'name': 'Sirloin Steak', 'price': '96.00', 'quantity': '1'},
            {'name': 'Coke', 'price': '3.50', 'quantity': '1'},
            {'name': 'Ice Cream', 'price': '18.00', 'quantity': '5'}
        ],
        'subtotal': '327.30',
        'tax': '16.36',
        'service_charge': '32.73',
        'total': '400.00'
    }
}

尽管OCR引擎在今天的任务中表现出色,但仍然需要高质量的图像才能准确识别文本。如果图像模糊、失真或光照不足,OCR引擎可能无法准确识别文本。

目标

研究并比较微调的LLM(语言模型)用于进行图像到结构化数据转换的用例。如果这比编写解析算法更好,因为LLM能够生成与给定输入文本相似的文本。这使它们在图像到文本转换、文本到文本转换和机器翻译等任务中非常有用。

  • 实验-1:图像 → OCR引擎 → 文本框 → LLM → JSON对象

  • 实验-2:图像 → LLM → XML或JSON对象

设置

  • 我的微调模型已发布在Huggingface上,可以直接进行下载并进行此实验:

    • OCR-to-Json: https://huggingface.co/mychen76/mistral7b_ocr_to_json_v1(使用最新的mistralai-7b作为基础)

    • Image-to-Json_and_XML: https://huggingface.co/mychen76/invoice-and-receipts_donut_v1(使用donut作为基础模型)

  • 我的数据集: mychen76/invoices-and-receipts_ocr_v1

  • 硬件: Ryzen 5700g, 96GB内存, RTX 3090 24GB显存

实验结果

实验-1: 输入OCR结果到LLM然后输出JSON对象

>> 成功,收据图像转换为json格式 — 花费46秒

实验-2: 输入图像到LLM然后输出结构化数据XML/JSON

>> 成功,收据图像转换为xml/json格式 — 花费8.9秒

观察

结果显示量少即意味着更好。实验-2仅花费了8.9秒,而实验-1花费了46秒,两者都是从冷启动到任务完成的时间—就性能结果而言,LLM模型与无OCR清晰地展示了这更优雅的方法。在准确性方面,使用3个epoch微调的模型大约达到76%以上。通过进一步改进数据和模型训练,可以获得更好的结果。

工作原理是怎样的?

实验-1: 图像 → OCR引擎 → 文本框 → LLM → JSON对象

让我们深入细节,这里我们从互联网上随机抽取收据图片。

import urllib.request 
import numpy as np
from PIL import Image


# pull a random receipt image from internet
image_url='https://groups.google.com/group/jzebra-users/attach/d16dbba8a612edfa/Bill%20Image_Receipt.png?part=0.1'
local_image_id='bill_image_receipt.png'
urllib.request.urlretrieve(image_url,local_image_id) 
receipt_image = Image.open(local_image_id)
receipt_image_array = np.array(receipt_image.convert('RGB'))

在这种情况下,将图像输入到OCR引擎(PaddleOCR)中:

from paddleocr import PaddleOCR, draw_ocr
from ast import literal_eval
import json


paddleocr = PaddleOCR(lang="en",ocr_version="PP-OCRv4",show_log = False,use_gpu=True)


def paddle_scan(paddleocr,img_path_or_nparray):
    result = paddleocr.ocr(img_path_or_nparray,cls=True)
    result = result[0]
    boxes = [line[0] for line in result]       #boundign box 
    txts = [line[1][0] for line in result]     #raw text
    scores = [line[1][1] for line in result]   # scores
    return  txts, result


# perform ocr scan
receipt_texts, receipt_boxes = paddle_scan(paddleocr,receipt_image_array)
print(50*"--","\ntext only:\n",receipt_texts)
print(50*"--","\nocr boxes:\n",receipt_boxes)

这里我们从互联网上随机选择一张收据图像:

[
    [[[188.0, 54.0], [453.0, 54.0], [453.0, 85.0], [188.0, 85.0]], ('The Lone Pine', 0.9998093247413635)],
    [[[194.0, 96.0], [449.0, 98.0], [449.0, 122.0], [194.0, 120.0]], ('43 Manchester Road', 0.9989086985588074)],
    [[[228.0, 127.0], [416.0, 130.0], [416.0, 154.0], [228.0, 151.0]], ('12480 Brisbane', 0.9684376120567322)],
    [[[267.0, 162.0], [375.0, 162.0], [375.0, 186.0], [267.0, 186.0]], ('Australia', 0.9997145533561707)],
    [[[234.0, 193.0], [409.0, 193.0], [409.0, 216.0], [234.0, 216.0]], ('617-3236-6207', 0.9996872544288635)],
    [[[46.0, 255.0], [308.0, 255.0], [308.0, 278.0], [46.0, 278.0]], ('Invoice 08000008', 0.9919947385787964)],
    [[[466.0, 255.0], [598.0, 255.0], [598.0, 278.0], [466.0, 278.0]], ('09/04/08', 0.9994759559631348)],
    [[[42.0, 283.0], [132.0, 283.0], [132.0, 311.0], [42.0, 311.0]], ('Table', 0.996922492980957)],
    [[[174.0, 283.0], [214.0, 283.0], [214.0, 311.0], [174.0, 311.0]], ('25', 0.999789297580719)],
    [[[514.0, 284.0], [601.0, 284.0], [601.0, 311.0], [514.0, 311.0]], ('12:45', 0.9964934587478638)],
    [[[67.0, 346.0], [291.0, 349.0], [291.0, 376.0], [67.0, 374.0]], ('2 Carlsberg Bottle', 0.9987956285476685)],
    [[[515.0, 346.0], [599.0, 346.0], [599.0, 372.0], [515.0, 372.0]], ('16.00', 0.999927818775177)],
    [
        [[69.0, 385.0], [395.0, 387.0], [395.0, 411.0], [69.0, 409.0]],
        ('3 Heineken Draft Standard.', 0.9832844138145447)
    ],
    [[[515.0, 384.0], [599.0, 384.0], [599.0, 409.0], [515.0, 409.0]], ('24.60', 0.9998160600662231)],
    [
        [[71.0, 423.0], [391.0, 423.0], [391.0, 446.0], [71.0, 446.0]],
        ('1 Heineken Draft Half Liter.', 0.9641053080558777)
    ],
    [[[515.0, 421.0], [601.0, 421.0], [601.0, 450.0], [515.0, 450.0]], ('15.20', 0.9998877644538879)],
    [
        [[69.0, 460.0], [430.0, 461.0], [430.0, 485.0], [69.0, 484.0]],
        ('2 Carlsberg Bucket (5 bottles).', 0.9744488596916199)
    ],
    [[[515.0, 461.0], [599.0, 461.0], [599.0, 486.0], [515.0, 486.0]], ('80.00', 0.9999421834945679)],
    [
        [[69.0, 498.0], [367.0, 500.0], [367.0, 524.0], [69.0, 522.0]],
        ('4 Grilled Chicken Breast.', 0.9772973656654358)
    ],
    [[[515.0, 499.0], [599.0, 499.0], [599.0, 524.0], [515.0, 524.0]], ('74.00', 0.9999668002128601)],
    [[[68.0, 534.0], [250.0, 537.0], [250.0, 562.0], [68.0, 560.0]], ('3 Sirloin Steak', 0.9997310638427734)],
    [[[515.0, 537.0], [599.0, 537.0], [599.0, 561.0], [515.0, 561.0]], ('96.00', 0.9999544024467468)],
    [[[67.0, 571.0], [162.0, 574.0], [161.0, 601.0], [67.0, 598.0]], ('1 Coke', 0.9997828006744385)],
    [[[530.0, 572.0], [602.0, 572.0], [602.0, 601.0], [530.0, 601.0]], ('3.50', 0.9999454617500305)],
    [[[69.0, 609.0], [219.0, 613.0], [218.0, 638.0], [68.0, 634.0]], ('5 Ice Cream', 0.9914573431015015)],
    [[[516.0, 611.0], [599.0, 611.0], [599.0, 637.0], [516.0, 637.0]], ('18.00', 0.9999335408210754)],
    [[[154.0, 664.0], [288.0, 664.0], [288.0, 688.0], [154.0, 688.0]], ('Subtotal', 0.9990756511688232)],
    [[[499.0, 664.0], [599.0, 664.0], [599.0, 688.0], [499.0, 688.0]], ('327.30', 0.9999766945838928)],
    [
        [[155.0, 701.0], [397.0, 701.0], [397.0, 724.0], [155.0, 724.0]],
        ('Sales/Gov Tax - 5%', 0.9551984071731567)
    ],
    [[[514.0, 697.0], [601.0, 697.0], [601.0, 724.0], [514.0, 724.0]], ('16.36', 0.9998232126235962)],
    [
        [[155.0, 733.0], [419.0, 733.0], [419.0, 757.0], [155.0, 757.0]],
        ('Service Charge - 10%', 0.9921121597290039)
    ],
    [[[512.0, 728.0], [601.0, 731.0], [600.0, 759.0], [511.0, 757.0]], ('32.73', 0.9999620318412781)],
    [[[154.0, 775.0], [335.0, 775.0], [335.0, 799.0], [154.0, 799.0]], ('GRAND TOTAL', 0.9899778962135315)],
    [[[499.0, 778.0], [599.0, 778.0], [599.0, 802.0], [499.0, 802.0]], ('376.40', 0.9999797940254211)],
    [[[39.0, 831.0], [223.0, 831.0], [223.0, 859.0], [39.0, 859.0]], ('Thank you and', 0.9922560453414917)],
    [[[336.0, 831.0], [407.0, 831.0], [407.0, 860.0], [336.0, 860.0]], ('Cash', 0.9998618364334106)],
    [[[499.0, 831.0], [601.0, 831.0], [601.0, 859.0], [499.0, 859.0]], ('400.00', 0.9998553395271301)],
    [[[38.0, 866.0], [220.0, 862.0], [220.0, 891.0], [38.0, 895.0]], ('see you again!', 0.9798097014427185)],
    [[[336.0, 864.0], [438.0, 869.0], [437.0, 898.0], [335.0, 894.0]], ('Change', 0.9998979568481445)],
    [[[515.0, 867.0], [599.0, 867.0], [599.0, 892.0], [515.0, 892.0]], ('23.60', 0.9999335408210754)],
    [[[37.0, 901.0], [108.0, 901.0], [108.0, 930.0], [37.0, 930.0]], ('John', 0.9990780353546143)],
    [
        [[73.0, 962.0], [569.0, 965.0], [569.0, 991.0], [73.0, 989.0]],
        ('Bring this bill back within the next 10 days', 0.9880536794662476)
    ],
    [
        [[50.0, 1000.0], [591.0, 1000.0], [591.0, 1023.0], [50.0, 1023.0]],
        ("and get 15% discount on that day's food bill..", 0.9851430654525757)
    ]
]

现在,我们已经有了文本框,让我们加载一个可以接受输入并将其转换为 JSON 对象的微调模型。

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig




bnb_config = BitsAndBytesConfig(
    llm_int8_enable_fp32_cpu_offload=True,
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
)




device_map = {
    "transformer.word_embeddings": 0,
    "transformer.word_embeddings_layernorm": 0,
    "lm_head": 0,
    "transformer.h": 0,
    "transformer.ln_f": 0,
    "model.embed_tokens": 0,
    "model.layers": 0,
    "model.norm": 0
}
device = "cuda" if torch.cuda.is_available() else "cpu"




model_id = "mychen76/mistral7b_ocr_to_json_v1"
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    trust_remote_code=True,
    torch_dtype=torch.float16,
    quantization_config=bnb_config,
    device_map=device_map
)




tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)

然后通过构造一个提示符来运行推理:

prompt=f"""### Instruction:
You are POS receipt data expert, parse, detect, recognize and convert following receipt OCR image result into structure receipt data object. 
Don't make up value not in the Input. Output must be a well-formed JSON object.```json


### Input:
{receipt_boxes}


### Output:
"""


with torch.inference_mode():
    inputs = tokenizer(prompt,return_tensors="pt",truncation=True).to(device)
    outputs = model.generate(**inputs, max_new_tokens=512) ##use_cache=True, do_sample=True,temperature=0.1, top_p=0.95
    result_text = tokenizer.batch_decode(outputs)[0]
    print(result_text)

然后获取输出:

{
    'receipt': {
        'store': 'The Lone Pine',
        'address': '43 Manchester Road',
        'city': 'Brisbane',
        'country': 'Australia',
        'phone': '617-3236-6207',
        'invoice': 'Invoice 08000008',
        'date': '09/04/08',
        'table': 'Table',
        'items': [
            {'name': 'Carlsberg Bottle', 'price': '16.00', 'quantity': '2'},
            {'name': 'Heineken Draft Standard.', 'price': '15.20', 'quantity': '1'},
            {'name': 'Heineken Draft Half Liter.', 'price': '15.20', 'quantity': '1'},
            {'name': 'Carlsberg Bucket (5 bottles).', 'price': '80.00', 'quantity': '1'},
            {'name': 'Grilled Chicken Breast.', 'price': '74.00', 'quantity': '1'},
            {'name': 'Sirloin Steak', 'price': '96.00', 'quantity': '1'},
            {'name': 'Coke', 'price': '3.50', 'quantity': '1'},
            {'name': 'Ice Cream', 'price': '18.00', 'quantity': '5'}
        ],
        'subtotal': '327.30',
        'tax': '16.36',
        'service_charge': '32.73',
        'total': '400.00'
    }
}

到目前为止,LLM 的结果看起来不错,是一个格式良好的 JSON 对象。

实验-2:图像 → LLM → XML 或 JSON 对象

让我们深入细节,这次转换更简化,只需输入一张图像。首先获取一些测试数据 — 示例 invoice.png:

from datasets import load_dataset




dataset_id = "mychen76/invoices-and-receipts_ocr_v1"
dataset = load_dataset(dataset_id)




def display_record(record):
    image1 = record['image']
    print("image size:", image1.size)
    display(image1.resize((800, 600)))
    return image1




input_image = display_record(dataset['test'][1])

b0755a1d3f4cfae220ebaf0fa2b00658.jpeg接下来,加载模型和处理器:

import torch
from transformers import DonutProcessor, VisionEncoderDecoderModel


model_id="mychen76/invoice-and-receipts_donut_v1"
def load_model(model_id=model_id):
    processor = DonutProcessor.from_pretrained(model_id)
    model = VisionEncoderDecoderModel.from_pretrained(model_id)
    return processor, model


processor, model = load_model(model_id)

XML输出

def generateTextInImage(processor,model,input_image,task_prompt="<s_receipt>"):
    pixel_values = processor(input_image, return_tensors="pt").pixel_values
    print ("input pixel_values: ",pixel_values.shape)
    task_prompt = "<s_receipt>"
    decoder_input_ids = processor.tokenizer(task_prompt, add_special_tokens=False, return_tensors="pt")["input_ids"]
    device = "cuda" if torch.cuda.is_available() else "cpu"
    model.to(device)
    outputs = model.generate(pixel_values.to(device),
                               decoder_input_ids=decoder_input_ids.to(device),
                               max_length=model.decoder.config.max_position_embeddings,
                               early_stopping=True,
                               pad_token_id=processor.tokenizer.pad_token_id,
                               eos_token_id=processor.tokenizer.eos_token_id,
                               use_cache=True,
                               num_beams=1,
                               bad_words_ids=[[processor.tokenizer.unk_token_id]],
                               return_dict_in_generate=True,
                               output_scores=True,)
    return outputs


def generateOutputXML(processor,model, input_image, task_start="<s_receipt>",task_end="</s_receipt>"):
    import re
    outputs=generateTextInImage(processor,model,input_image,task_prompt=task_start)
    sequence = processor.batch_decode(outputs.sequences)[0]
    sequence = sequence.replace(processor.tokenizer.eos_token, "").replace(processor.tokenizer.pad_token, "")
    sequence = re.sub(r"<.*?>", "", sequence, count=1).strip()  # remove first task start token
    return sequence


## generate xml
xml=generateOutputXML(processor,model,input_image)
print(xml)
<s_header>
    <s_invoice_no> 13194726</s_invoice_no>
    <s_invoice_date> 05/29/2021</s_invoice_date>
    <s_seller> Hopkins and 
    Sons 62283 Flores Tunnel North Luis, IA 69983</s_seller>
    <s_client> Sims PLC USS Kramer FPO AA 
    81651</s_client>
    <s_seller_tax_id> 952-73-7223</s_seller_tax_id>
    <s_client_tax_id> 
    995-88-9495</s_client_tax_id>
    <s_iban> GB31LZX520242755934691</s_iban>
</s_header>
<s_items>
    <s_item_desc> Beach Lunch 
    Lounge Striped Shirt Dress Large Navy Blue White Long Sleeve Casual</s_item_desc>
    <s_item_qty> 
    1,00</s_item_qty>
    <s_item_net_price> 16,99</s_item_net_price>
    <s_item_net_worth> 16,99</s_item_net_worth>
    <s_item_vat>
    10%</s_item_vat>
    <s_item_gross_worth> 18,69</s_item_gross_worth>
    <sep/>
    <s_item_desc> Jams World Hawaiian 0 Dress 
    Rayon SZ.L</s_item_desc>
    <s_item_qty> 5,00</s_item_qty>
    <s_item_net_price> 65,00</s_item_net_price>
    <s_item_net_worth>
    325,00</s_item_net_worth>
    <s_item_vat> 10%</s_item_vat>
    <s_item_gross_worth> 
    357,50</s_item_gross_worth>
    <sep/>
    <s_item_desc> LuLaRoe Nicole Dress Size Large 26</s_item_desc>
    <s_item_qty> 
    2,00</s_item_qty>
    <s_item_net_price> 1,99</s_item_net_price>
    <s_item_net_worth> 3,98</s_item_net_worth>
    <s_item_vat> 
    10%</s_item_vat>
    <s_item_gross_worth> 4,38</s_item_gross_worth>
    <sep/>
    <s_item_desc> phynny Was Medium Linen Wrap 
    Dress Dessert Rose Embroidered Bohemian</s_item_desc>
    <s_item_qty> 2,00</s_item_qty>
    <s_item_net_price> 
    89,99</s_item_net_price>
    <s_item_net_worth> 179,98</s_item_net_worth>
    <s_item_vat> 
    10%</s_item_vat>
    <s_item_gross_worth> 197,98</s_item_gross_worth>
    <sep/>
    <s_item_desc> Eileen Fisher Women's Long 
    Sleeve Fleece Lined Front Pockets Dress XS Gray</s_item_desc>
    <s_item_qty> 2,00</s_item_qty>
    <s_item_net_price> 
    15,99</s_item_net_price>
    <s_item_net_worth> 31,98</s_item_net_worth>
    <s_item_vat> 
    10%</s_item_vat>
    <s_item_gross_worth> 35,18</s_item_gross_worth>
    <sep/>
    <s_item_desc> Hanna Anderson Women's L Large 
    Coral Short Sleeve Casual Fall Tee Shirt Dress</s_item_desc>
    <s_item_qty> 1,00</s_item_qty>
    <s_item_net_price> 
    24,00</s_item_net_price>
    <s_item_net_worth> 24,00</s_item_net_worth>
    <s_item_vat> 
    10%</s_item_vat>
    <s_item_gross_worth> 26,40</s_item_gross_worth>
</s_items>
<s_summary>
    <s_total_net_worth> 
    $581,93</s_total_net_worth>
    <s_total_vat> $58,19</s_total_vat>
    <s_total_gross_worth> $ 
    640,12</s_total_gross_worth>
</s_summary>

以及 JSON 格式:

{
    'header': {
        'invoice_no': '13194726',
        'invoice_date': '05/29/2021',
        'seller': 'Hopkins and Sons 62283 Flores Tunnel North Luis, IA 69983',
        'client': 'Sims PLC USS Kramer FPO AA 81651',
        'seller_tax_id': '952-73-7223',
        'client_tax_id': '995-88-9495',
        'iban': 'GB31LZX520242755934691'
    },
    'items': [
        {
            'item_desc': 'Beach Lunch Lounge Striped Shirt Dress Large Navy Blue White Long Sleeve Casual',
            'item_qty': '1,00',
            'item_net_price': '16,99',
            'item_net_worth': '16,99',
            'item_vat': '10%',
            'item_gross_worth': '18,69'
        },
        {
            'item_desc': 'Jams World Hawaiian 0 Dress Rayon SZ.L',
            'item_qty': '5,00',
            'item_net_price': '65,00',
            'item_net_worth': '325,00',
            'item_vat': '10%',
            'item_gross_worth': '357,50'
        },
        {
            'item_desc': 'LuLaRoe Nicole Dress Size Large 26',
            'item_qty': '2,00',
            'item_net_price': '1,99',
            'item_net_worth': '3,98',
            'item_vat': '10%',
            'item_gross_worth': '4,38'
        },
        {
            'item_desc': 'phynny Was Medium Linen Wrap Dress Dessert Rose Embroidered Bohemian',
            'item_qty': '2,00',
            'item_net_price': '89,99',
            'item_net_worth': '179,98',
            'item_vat': '10%',
            'item_gross_worth': '197,98'
        },
        {
            'item_desc': "Eileen Fisher Women's Long Sleeve Fleece Lined Front Pockets Dress XS Gray",
            'item_qty': '2,00',
            'item_net_price': '15,99',
            'item_net_worth': '31,98',
            'item_vat': '10%',
            'item_gross_worth': '35,18'
        },
        {
            'item_desc': "Hanna Anderson Women's L Large Coral Short Sleeve Casual Fall Tee Shirt Dress",
            'item_qty': '1,00',
            'item_net_price': '24,00',
            'item_net_worth': '24,00',
            'item_vat': '10%',
            'item_gross_worth': '26,40'
        }
    ],
    'summary': {'total_net_worth': '$581,93', 'total_vat': '$58,19', 'total_gross_worth': '$ 640,12'}
}


{
    'header': {
        'invoice_no': '13194726',
        'invoice_date': '05/29/2021',
        'seller': 'Hopkins and Sons 62283 Flores Tunnel North Luis, IA 69983',
        'client': 'Sims PLC USS Kramer FPO AA 81651',
        'seller_tax_id': '952-73-7223',
        'client_tax_id': '995-88-9495',
        'iban': 'GB31LZX520242755934691'
    },
    'items': [
        {
            'item_desc': 'Beach Lunch Lounge Striped Shirt Dress Large Navy Blue White Long Sleeve Casual',
            'item_qty': '1,00',
            'item_net_price': '16,99',
            'item_net_worth': '16,99',
            'item_vat': '10%',
            'item_gross_worth': '18,69'
        },
        {
            'item_desc': 'Jams World Hawaiian 0 Dress Rayon SZ.L',
            'item_qty': '5,00',
            'item_net_price': '65,00',
            'item_net_worth': '325,00',
            'item_vat': '10%',
            'item_gross_worth': '357,50'
        },
        {
            'item_desc': 'LuLaRoe Nicole Dress Size Large 26',
            'item_qty': '2,00',
            'item_net_price': '1,99',
            'item_net_worth': '3,98',
            'item_vat': '10%',
            'item_gross_worth': '4,38'
        },
        {
            'item_desc': 'phynny Was Medium Linen Wrap Dress Dessert Rose Embroidered Bohemian',
            'item_qty': '2,00',
            'item_net_price': '89,99',
            'item_net_worth': '179,98',
            'item_vat': '10%',
            'item_gross_worth': '197,98'
        },
        {
            'item_desc': "Eileen Fisher Women's Long Sleeve Fleece Lined Front Pockets Dress XS Gray",
            'item_qty': '2,00',
            'item_net_price': '15,99',
            'item_net_worth': '31,98',
            'item_vat': '10%',
            'item_gross_worth': '35,18'
        },
        {
            'item_desc': "Hanna Anderson Women's L Large Coral Short Sleeve Casual Fall Tee Shirt Dress",
            'item_qty': '1,00',
            'item_net_price': '24,00',
            'item_net_worth': '24,00',
            'item_vat': '10%',
            'item_gross_worth': '26,40'
        }
    ],
    'summary': {'total_net_worth': '$581,93', 'total_vat': '$58,19', 'total_gross_worth': '$ 640,12'}
}

·  END  ·

HAPPY LIFE

bb0034a5ab679cd90603c091d8acff4b.png

本文仅供学习交流使用,如有侵权请联系作者删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值