-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDetectThenAnalyze.java
More file actions
77 lines (66 loc) · 3.33 KB
/
Copy pathDetectThenAnalyze.java
File metadata and controls
77 lines (66 loc) · 3.33 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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
* Routing a mixed inbox.
*
* The pattern is detect (1 credit per 10 calls, amortised) → analyze with the chosen preset
* (normal price). Worth it when the *type* is the decision: you can refuse to spend 40
* credits on a 40-page PDF that turns out to be a scanned fax cover sheet.
*
* If you just want the data and don't care which preset produced it, skip this and pass
* preset("auto") — classification bundled into an extraction is free.
*
* java -cp target/visionapi-java-1.0.0.jar examples/DetectThenAnalyze.java ./inbox
*/
import io.visionapi.AnalyzeRequest;
import io.visionapi.AnalyzeResponse;
import io.visionapi.DetectRequest;
import io.visionapi.DetectResponse;
import io.visionapi.VisionApi;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Stream;
public class DetectThenAnalyze {
// What we are willing to spend extraction credits on, and what to do otherwise.
private static final Set<String> HANDLED = Set.of("invoice", "receipt", "purchase_order", "packing_slip");
private static final List<String> SUPPORTED = List.of(".pdf", ".png", ".jpg", ".jpeg", ".webp", ".tif", ".tiff");
public static void main(String[] args) throws IOException {
Path inbox = Path.of(args.length > 0 ? args[0] : "./inbox");
VisionApi vision = VisionApi.create();
try (Stream<Path> files = Files.list(inbox)) {
files.filter(DetectThenAnalyze::isSupported).sorted().forEach(path -> {
DetectResponse guess = vision.detect(DetectRequest.builder().file(path).build());
// A fallback means nothing matched confidently and the generic preset was
// substituted. That is "shape unknown", not a match — check what was rejected.
if (guess.isFallback()) {
String closest = guess.detections().isEmpty()
? ""
: " (closest: " + guess.detections().get(0).preset()
+ " — " + guess.detections().get(0).reason() + ")";
System.out.println(path.getFileName() + ": unrecognised" + closest);
return;
}
if (!HANDLED.contains(guess.recommended())) {
System.out.println(path.getFileName() + ": " + guess.recommended()
+ " — not a type we process, skipping");
return;
}
// recommended() is exactly what preset("auto") would have run, so it is safe
// to commit to it.
AnalyzeResponse res = vision.analyze(AnalyzeRequest.builder()
.file(path)
.preset(guess.recommended())
.build());
System.out.printf("%s: %s → %d credit(s) %s%n",
path.getFileName(), guess.recommended(), res.creditsUsed(), res.result().unwrap(true));
});
}
System.out.println("\n" + vision.credits().balance() + " credits remaining");
}
private static boolean isSupported(Path path) {
String name = path.getFileName().toString().toLowerCase(Locale.ROOT);
return SUPPORTED.stream().anyMatch(name::endsWith);
}
}