-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcustom_schema.rb
More file actions
54 lines (43 loc) · 2.31 KB
/
Copy pathcustom_schema.rb
File metadata and controls
54 lines (43 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# frozen_string_literal: true
# Custom fields on top of a preset, fields injected into every line-item row, and saving
# the combination so later calls are one argument.
#
# ruby examples/custom_schema.rb invoice.pdf
require "vision_api"
path = ARGV[0] || "invoice.pdf"
vision = VisionAPI.new
schema = {
# Plain form: the string is the description. Descriptions are the prompt — the more
# precisely you say what you want, the better the extraction.
"machine_serial" => 'Serial number of the machine being invoiced, without the "SN:" prefix',
# Typed form. Numbers come back as JSON numbers, dates as ISO YYYY-MM-DD.
"total_net" => { "type" => "number", "description" => "Total before tax" },
"is_paid" => { "type" => "boolean", "description" => "Whether the invoice is marked PAID" },
"reference_numbers" => { "type" => "array", "description" => "All reference numbers", "items" => "string" },
# "line_item" is reserved: these become extra columns on every row of the preset's
# line-item array. Only meaningful with a preset that has line items; with a bare custom
# schema there is nothing to inject into.
"line_item" => { "lot_number" => "The lot number printed on this line, if present" }
}
res = vision.analyze(file: path, preset: "invoice", schema: schema)
result = res["result"]
puts "serial: #{VisionAPI::Result.value(result, 'machine_serial')}"
puts "net total: #{VisionAPI::Result.value(result, 'total_net')}"
puts "paid: #{VisionAPI::Result.value(result, 'is_paid')}"
VisionAPI::Result.rows(result, "line_item").each do |row|
line = VisionAPI::Result.unwrap(row)
puts " #{line['quantity'] || '?'} × #{line['description'] || '(no description)'} " \
"= #{line['amount'] || '?'} [lot #{line['lot_number'] || '—'}]"
end
# Save it, and the next call is schema_name: "our-invoices". The definition is compiled
# before it is stored, so an invalid schema fails here rather than on the first extraction
# that uses it.
begin
vision.create_schema("our-invoices", preset: "invoice", schema: schema)
puts %(\nsaved as "our-invoices")
rescue VisionAPI::ConflictError
vision.update_schema("our-invoices", preset: "invoice", schema: schema)
puts %(\nupdated "our-invoices")
end
again = vision.analyze(file: path, schema_name: "our-invoices")
puts "same fields via the saved schema: #{again['result'].size}"