Skip to content

Commit dea4f84

Browse files
add usage into invoice sample
1 parent 12b3511 commit dea4f84

3 files changed

Lines changed: 110 additions & 7 deletions

File tree

sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample03_AnalyzeInvoice.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717
import com.azure.ai.contentunderstanding.models.DocumentSource;
1818
import com.azure.ai.contentunderstanding.models.AnalysisContent;
1919
import com.azure.ai.contentunderstanding.models.ContentObjectField;
20+
import com.azure.ai.contentunderstanding.models.UsageDetails;
2021
import com.azure.core.credential.AzureKeyCredential;
2122
import com.azure.core.util.polling.SyncPoller;
2223
import com.azure.identity.DefaultAzureCredentialBuilder;
2324

2425
import java.util.Arrays;
2526
import java.util.List;
27+
import java.util.Map;
2628

2729
/**
2830
* Sample demonstrating how to analyze invoices using Content Understanding service.
@@ -67,6 +69,43 @@ public static void main(String[] args) {
6769
AnalysisResult result = operation.getFinalResult();
6870
// END:ContentUnderstandingAnalyzeInvoice
6971

72+
// BEGIN:ContentUnderstandingAnalyzeInvoiceUsage
73+
// Access usage details from the operation status (available after polling completes).
74+
// Usage reports resource consumption for billing estimation:
75+
//
76+
// - documentPagesStandard/Basic/Minimal: Pages processed at each extraction tier.
77+
// Standard = layout + OCR (scanned docs), Basic = OCR only, Minimal = digital formats
78+
// (DOCX, XLSX, HTML, TXT) that need no OCR. Charged per 1,000 pages.
79+
//
80+
// - contextualizationTokens: Fixed-rate tokens charged by Content Understanding for
81+
// preparing context, generating confidence scores, source grounding, and formatting
82+
// output. Typically 1,000 tokens per page. Charged separately from LLM tokens.
83+
//
84+
// - tokens: Map of "{model}-input" / "{model}-output" token counts consumed by your
85+
// Foundry model deployment (e.g. "gpt-4.1-input", "gpt-4.1-output"). These are
86+
// billed on your Foundry deployment, not on Content Understanding.
87+
//
88+
// For full pricing details, see:
89+
// https://learn.microsoft.com/azure/ai-services/content-understanding/pricing-explainer
90+
UsageDetails usage = operation.waitForCompletion().getValue().getUsage();
91+
if (usage != null) {
92+
System.out.println("\nUsage Details:");
93+
if (usage.getDocumentPagesStandard() != null) {
94+
System.out.println(" Document pages (standard): " + usage.getDocumentPagesStandard());
95+
}
96+
if (usage.getContextualizationTokens() != null) {
97+
System.out.println(" Contextualization tokens: " + usage.getContextualizationTokens());
98+
}
99+
Map<String, Integer> tokens = usage.getTokens();
100+
if (tokens != null && !tokens.isEmpty()) {
101+
System.out.println(" Model tokens:");
102+
for (Map.Entry<String, Integer> entry : tokens.entrySet()) {
103+
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
104+
}
105+
}
106+
}
107+
// END:ContentUnderstandingAnalyzeInvoiceUsage
108+
70109
System.out.println("Analysis operation completed");
71110
System.out.println("Analysis result contains " + result.getContents().size() + " content(s)");
72111

sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample03_AnalyzeInvoiceAsyncTest.java

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.azure.ai.contentunderstanding.models.AnalysisContent;
1515
import com.azure.ai.contentunderstanding.models.ContentObjectField;
1616
import com.azure.ai.contentunderstanding.models.DocumentSource;
17+
import com.azure.ai.contentunderstanding.models.UsageDetails;
1718
import com.azure.core.util.polling.PollerFlux;
1819
import org.junit.jupiter.api.Test;
1920
import reactor.core.publisher.Mono;
@@ -25,6 +26,7 @@
2526

2627
import java.util.Arrays;
2728
import java.util.List;
29+
import java.util.Map;
2830

2931
/**
3032
* Async sample demonstrating how to analyze invoices using Content Understanding service.
@@ -51,16 +53,16 @@ public void testAnalyzeInvoiceAsync() {
5153
PollerFlux<ContentAnalyzerAnalyzeOperationStatus, AnalysisResult> operation
5254
= contentUnderstandingAsyncClient.beginAnalyze("prebuilt-invoice", Arrays.asList(input));
5355

54-
// Use reactive pattern: chain operations using flatMap
56+
// Wait for the operation to complete and get the operation status
5557
// In a real application, you would use subscribe() instead of block()
56-
AnalysisResult result = operation.last().flatMap(pollResponse -> {
57-
if (pollResponse.getStatus().isComplete()) {
58-
return pollResponse.getFinalResult();
59-
} else {
60-
return Mono.error(
61-
new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus()));
58+
ContentAnalyzerAnalyzeOperationStatus operationStatus = operation.last().map(pollResponse -> {
59+
if (!pollResponse.getStatus().isComplete()) {
60+
throw new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus());
6261
}
62+
return pollResponse.getValue();
6363
}).block(); // block() is used here for testing; in production, use subscribe()
64+
65+
AnalysisResult result = operationStatus.getResult();
6466
// END:ContentUnderstandingAnalyzeInvoiceAsync
6567

6668
// BEGIN:Assertion_ContentUnderstandingAnalyzeInvoiceAsync
@@ -74,6 +76,36 @@ public void testAnalyzeInvoiceAsync() {
7476
System.out.println("Analysis result contains " + result.getContents().size() + " content(s)");
7577
// END:Assertion_ContentUnderstandingAnalyzeInvoiceAsync
7678

79+
// BEGIN:ContentUnderstandingAnalyzeInvoiceUsageAsync
80+
// Get usage details from the operation status
81+
UsageDetails usage = operationStatus.getUsage();
82+
if (usage != null) {
83+
System.out.println("\nUsage Details:");
84+
if (usage.getDocumentPagesStandard() != null) {
85+
System.out.println(" Document pages (standard): " + usage.getDocumentPagesStandard());
86+
}
87+
if (usage.getContextualizationTokens() != null) {
88+
System.out.println(" Contextualization tokens: " + usage.getContextualizationTokens());
89+
}
90+
Map<String, Integer> tokens = usage.getTokens();
91+
if (tokens != null && !tokens.isEmpty()) {
92+
System.out.println(" Model tokens:");
93+
for (Map.Entry<String, Integer> entry : tokens.entrySet()) {
94+
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
95+
}
96+
}
97+
}
98+
// END:ContentUnderstandingAnalyzeInvoiceUsageAsync
99+
100+
// BEGIN:Assertion_ContentUnderstandingAnalyzeInvoiceUsageAsync
101+
assertNotNull(usage, "Usage details should not be null");
102+
assertNotNull(usage.getDocumentPagesStandard(), "Document pages (standard) should not be null");
103+
assertTrue(usage.getDocumentPagesStandard() > 0, "Document pages (standard) should be positive");
104+
assertNotNull(usage.getTokens(), "Tokens should not be null");
105+
assertTrue(!usage.getTokens().isEmpty(), "Tokens should not be empty");
106+
System.out.println("Usage details validated successfully");
107+
// END:Assertion_ContentUnderstandingAnalyzeInvoiceUsageAsync
108+
77109
// BEGIN:ContentUnderstandingExtractInvoiceFieldsAsync
78110
// Get the document content (invoices are documents)
79111
AnalysisContent firstContent = result.getContents().get(0);

sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample03_AnalyzeInvoiceTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.azure.ai.contentunderstanding.models.AnalysisContent;
1616
import com.azure.ai.contentunderstanding.models.ContentObjectField;
1717
import com.azure.ai.contentunderstanding.models.DocumentSource;
18+
import com.azure.ai.contentunderstanding.models.UsageDetails;
1819
import com.azure.core.util.polling.SyncPoller;
1920
import org.junit.jupiter.api.Test;
2021

@@ -25,6 +26,7 @@
2526

2627
import java.util.Arrays;
2728
import java.util.List;
29+
import java.util.Map;
2830

2931
/**
3032
* Sample demonstrating how to analyze invoices using Content Understanding service.
@@ -67,6 +69,36 @@ public void testAnalyzeInvoice() {
6769
System.out.println("Analysis result contains " + result.getContents().size() + " content(s)");
6870
// END:Assertion_ContentUnderstandingAnalyzeInvoice
6971

72+
// BEGIN:ContentUnderstandingAnalyzeInvoiceUsage
73+
// Get usage details from the operation status
74+
UsageDetails usage = operation.waitForCompletion().getValue().getUsage();
75+
if (usage != null) {
76+
System.out.println("\nUsage Details:");
77+
if (usage.getDocumentPagesStandard() != null) {
78+
System.out.println(" Document pages (standard): " + usage.getDocumentPagesStandard());
79+
}
80+
if (usage.getContextualizationTokens() != null) {
81+
System.out.println(" Contextualization tokens: " + usage.getContextualizationTokens());
82+
}
83+
Map<String, Integer> tokens = usage.getTokens();
84+
if (tokens != null && !tokens.isEmpty()) {
85+
System.out.println(" Model tokens:");
86+
for (Map.Entry<String, Integer> entry : tokens.entrySet()) {
87+
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
88+
}
89+
}
90+
}
91+
// END:ContentUnderstandingAnalyzeInvoiceUsage
92+
93+
// BEGIN:Assertion_ContentUnderstandingAnalyzeInvoiceUsage
94+
assertNotNull(usage, "Usage details should not be null");
95+
assertNotNull(usage.getDocumentPagesStandard(), "Document pages (standard) should not be null");
96+
assertTrue(usage.getDocumentPagesStandard() > 0, "Document pages (standard) should be positive");
97+
assertNotNull(usage.getTokens(), "Tokens should not be null");
98+
assertTrue(!usage.getTokens().isEmpty(), "Tokens should not be empty");
99+
System.out.println("Usage details validated successfully");
100+
// END:Assertion_ContentUnderstandingAnalyzeInvoiceUsage
101+
70102
// BEGIN:ContentUnderstandingExtractInvoiceFields
71103
// Get the document content (invoices are documents)
72104
AnalysisContent firstContent = result.getContents().get(0);

0 commit comments

Comments
 (0)