Add batch-llm module: 100,000 synthetic tickets classified by a ChatClient in a Spring Batch 6 chunk step with Resilience4j rate limiting and retry, skip-and-record for malformed JSON, restart after kill -9 in a second JVM, and a per-chunk cost ledger. The model is a deterministic simulated ChatModel; prices are configurable placeholders. No provider called.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017ic4b4VQVEJWetTT1dYzyJ
This commit is contained in:
2026-10-29 06:10:22 +00:00
co-authored by Claude Sonnet 5.5
parent aa8b1604ed
commit 6d792f00e0
48 changed files with 2093 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
# 3,000 tickets through the real job
job status COMPLETED
step: read=3000 write=2987 processSkip=13 commits=30 rollbacks=0
TICKET_RESULT rows 2987
SKIPPED_TICKET rows 13
classified + skipped 3000 (tickets: 3000)
Skipped tickets and why (first one of each kind):
ticket 46 category not in schema raw reply: {"category":"Account & Payments","priority":1,"confidence":0.74}
ticket 234 not JSON raw reply: Sure! Here is the classification you asked for: {"category":"BILLING","priority":4,"confidence":0.7}
ticket 491 missing field raw reply: {"category":"OTHER","priority":2}
First 3 ledger rows (one per committed chunk):
tickets written skipped attempts 429s 503s bad promptTok complTok cost
1-100 99 1 104 1 1 3 10831 1469 0.007619000
101-200 100 0 100 0 0 0 10574 1453 0.007466500
201-300 99 1 105 2 1 3 10736 1495 0.007610500
Ledger totals vs the provider's own meter (they must agree when nothing was lost):
ledger provider
calls received 3,104 3,104
429 rejections 39 39
503 rejections 14 14
billed calls 3,051 3,051
prompt tokens 324,790 324,790
completion tokens 44,107 44,107
Cost = prompt tokens x input price + completion tokens x output price, per million tokens.
table 'EXAMPLE-NOT-A-REAL-PRICE' (input 0.50, output 1.50): 0.228555500 <- the ledger's total
same tokens under table 'OTHER-EXAMPLE' (input 2.00, output 6.00): 0.914222000
Both tables are invented inputs. Tokens are the measurement; money is tokens x a table you supply.
Tokens spent on replies that were then skipped: bad replies billed = 64 of 3051 billed calls.