amlAnti-money-laundering review
Applies an institution's monitoring policy to a customer's last 30 days - clear, investigate, escalate or block.
Data: Synthetic institutions, customers and transactions; code fixes every label and GLM 5.3 writes some texts; laundering-pattern rows from IBM AMLworld.
Licence, in plain words
The adapter: Apache-2.0. Every data source has an open licence or was made for this adapter.
Every data source and its licenceTrained on Jeff v1.3. Adapters are tied to the exact base they were trained on. What changed in v1.3
Use it when
- You have a written transaction-monitoring policy (warning signs, thresholds, high-risk and blocked countries and parties) and want each customer review sorted first.
- You want the policy's own answer with a calibrated probability, so analysts start with the unsure cases.
Not a good fit when
- You want the model to find laundering your policy does not describe. It applies the rules you give it; on raw transactions without a written policy (IBM's AMLworld cross-test) it scores 60.0%, below the base alone.
- You need a final decision without a person. Reports to the authorities have legal consequences.
- Your activity summaries look very different from the training format. Test on your own data first.
Request format
The state is an object with these fields, in this order. Only activity changes from request to request, so it comes last and the rest can be prepared in advance.
| State field | Changes per request | What goes in it |
|---|---|---|
institution | No | The institution, its customer groups, and its monitoring policy - warning signs, thresholds, high-risk and blocked countries and parties, and what each action means. |
customer | No | The customer profile: segment, occupation or business, expected incoming money, senders, recipients and countries, own accounts, documented events. |
activity | Yes | The customer's payments over the review period, with a short summary of the totals the policy uses. |
| Question | Type | What it decides |
|---|---|---|
suspicious | Choice | Whether the activity is suspicious under the policy. Options: |
action | Choice | Which action the policy requires. Options: |
- Ask one question per request; each was trained with its own fixed instructions.
- Keep the institution and the customer profile the same across reviews, and put the activity last, so the unchanging part can be prepared in advance.
- The request format may still change before release.
General rules for every request are in the request format guide.
Example
The same request three ways. It assumes a Jeff server on your machine with this adapter loaded (see Install).
from jeff import Client
from jeff.client import choice_question
jeff = Client("http://localhost:8765", model="aml")
state = {
"institution": "Meridian Crypto Exchange is a crypto exchange based in Italy. It serves these customer groups: private crypto investor, business accepting crypto payments. Clear means the review is closed with a short note; investigate means an analyst opens a case and reviews the customer's documents; escalate means the case goes to the money-laundering reporting officer, who decides on a report to the authorities; block means the payment is stopped and the account frozen until compliance decides.\n\nMonitoring rules (all amounts in euro):\nEach review covers one customer's last 30 days. Transfers between the customer's own accounts and wallets (listed in the customer profile) are ignored by every rule.\nWarning signs:\nW1 Structuring: 3 or more deposits made with cash vouchers bought at partner kiosks each from 2,400.00 up to just under the reporting threshold of 3,000.00.\nW2 Rapid pass-through: the incoming money totals at least 1,000.00 and at least 90% of it is sent out again (by any payment or cash withdrawal) within 72 hours of arriving.\nW3 Many senders: money comes from more different senders than the customer profile expects per month.\nW4 Many recipients: money goes to more different recipients than the customer profile expects per month.\nW8 High-risk country: a payment to or from a country on the high-risk list that the customer profile does not list as an expected country.\nHigh-risk countries: Algeria, Bulgaria, Cameroon, Lebanon, Mali, Nigeria, Philippines, South Sudan, Venezuela.\nBlocked countries: Belarus, North Korea, Syria.\nBlocked parties: Field Summit EOOD (Bulgaria); Ember Nova Company (Bolivia); Coral Alder Ltd (Malta).\nActions (exactly one applies):\nblock: any payment to or from a blocked country or a blocked party, whatever else the activity shows.\nescalate: two or more different warning signs, or W2 (Rapid pass-through) even on its own.\ninvestigate: exactly one warning sign, other than W2.\nclear: no warning sign and no blocked country or party.",
"customer": "Customer: Kenji Okafor (individual), customer since November 2019.\nSegment: private crypto investor. Occupation or business: shop owner investing in crypto.\nExpected incoming: about 620.00 a month.\nExpected senders: up to 8 different senders a month. Expected recipients: up to 6 different recipients a month.\nExpected countries: Italy, Lebanon.\nOwn accounts and wallets: bank account ending 5014 at another bank; own hardware wallet 0xb84f...182c.",
"activity": "Review period: 1 June 2026 to 30 June 2026 (30 days). Amounts in euro.\nPayments:\n01 Jun 09:12 received 46.76 by crypto deposit from wallet 0x576b...5f0d at FalconCoin (Italy)\n10 Jun 17:34 sent 376.32 by crypto withdrawal to wallet 0x3292...217b (private wallet, owner and country unknown)\n14 Jun 14:23 received 478.54 by crypto deposit from wallet 0x576b...5f0d at FalconCoin (Italy)\nSummary (transfers between own accounts left out):\n- incoming: 2 payments, total 525.30, from 1 different senders\n- outgoing: 1 payments, total 376.32, to 1 different recipients\n- share of incoming money sent out again within 72 hours: 0%\n- counterparty countries: Italy",
}
answers = jeff.ask(state, {
"action": choice_question(
{
"block": "Block: at least one payment goes to or comes from a blocked country or a blocked party, whatever else.",
"investigate": "Investigate: exactly one warning sign applies, and the policy does not say to escalate that one alone.",
"escalate": "Escalate: two or more different warning signs apply, or a sign that the policy says to escalate alone.",
"clear": "Clear: no warning sign applies at all, and no payment involves a blocked country or any blocked party.",
},
"A compliance analyst at the institution described above reviews this customer's last 30 days of activity. Which action does the institution's monitoring policy require?",
),
})
print("action", answers.choice("action").key)import { Client, choiceQuestion } from '@jeff/client';
const jeff = new Client({ url: 'http://localhost:8765', model: 'aml' });
const state = {
institution: 'Meridian Crypto Exchange is a crypto exchange based in Italy. It serves these customer groups: private crypto investor, business accepting crypto payments. Clear means the review is closed with a short note; investigate means an analyst opens a case and reviews the customer\'s documents; escalate means the case goes to the money-laundering reporting officer, who decides on a report to the authorities; block means the payment is stopped and the account frozen until compliance decides.\n\nMonitoring rules (all amounts in euro):\nEach review covers one customer\'s last 30 days. Transfers between the customer\'s own accounts and wallets (listed in the customer profile) are ignored by every rule.\nWarning signs:\nW1 Structuring: 3 or more deposits made with cash vouchers bought at partner kiosks each from 2,400.00 up to just under the reporting threshold of 3,000.00.\nW2 Rapid pass-through: the incoming money totals at least 1,000.00 and at least 90% of it is sent out again (by any payment or cash withdrawal) within 72 hours of arriving.\nW3 Many senders: money comes from more different senders than the customer profile expects per month.\nW4 Many recipients: money goes to more different recipients than the customer profile expects per month.\nW8 High-risk country: a payment to or from a country on the high-risk list that the customer profile does not list as an expected country.\nHigh-risk countries: Algeria, Bulgaria, Cameroon, Lebanon, Mali, Nigeria, Philippines, South Sudan, Venezuela.\nBlocked countries: Belarus, North Korea, Syria.\nBlocked parties: Field Summit EOOD (Bulgaria); Ember Nova Company (Bolivia); Coral Alder Ltd (Malta).\nActions (exactly one applies):\nblock: any payment to or from a blocked country or a blocked party, whatever else the activity shows.\nescalate: two or more different warning signs, or W2 (Rapid pass-through) even on its own.\ninvestigate: exactly one warning sign, other than W2.\nclear: no warning sign and no blocked country or party.',
customer: 'Customer: Kenji Okafor (individual), customer since November 2019.\nSegment: private crypto investor. Occupation or business: shop owner investing in crypto.\nExpected incoming: about 620.00 a month.\nExpected senders: up to 8 different senders a month. Expected recipients: up to 6 different recipients a month.\nExpected countries: Italy, Lebanon.\nOwn accounts and wallets: bank account ending 5014 at another bank; own hardware wallet 0xb84f...182c.',
activity: 'Review period: 1 June 2026 to 30 June 2026 (30 days). Amounts in euro.\nPayments:\n01 Jun 09:12 received 46.76 by crypto deposit from wallet 0x576b...5f0d at FalconCoin (Italy)\n10 Jun 17:34 sent 376.32 by crypto withdrawal to wallet 0x3292...217b (private wallet, owner and country unknown)\n14 Jun 14:23 received 478.54 by crypto deposit from wallet 0x576b...5f0d at FalconCoin (Italy)\nSummary (transfers between own accounts left out):\n- incoming: 2 payments, total 525.30, from 1 different senders\n- outgoing: 1 payments, total 376.32, to 1 different recipients\n- share of incoming money sent out again within 72 hours: 0%\n- counterparty countries: Italy',
};
const answers = await jeff.ask(state, {
action: choiceQuestion(
{
block: 'Block: at least one payment goes to or comes from a blocked country or a blocked party, whatever else.',
investigate: 'Investigate: exactly one warning sign applies, and the policy does not say to escalate that one alone.',
escalate: 'Escalate: two or more different warning signs apply, or a sign that the policy says to escalate alone.',
clear: 'Clear: no warning sign applies at all, and no payment involves a blocked country or any blocked party.',
},
'A compliance analyst at the institution described above reviews this customer\'s last 30 days of activity. Which action does the institution\'s monitoring policy require?',
),
});
console.log('action', answers.action.key);curl -s http://localhost:8765/v1/systemone \
-H 'content-type: application/json' \
-d '{
"model": "aml",
"state": {
"institution": "Meridian Crypto Exchange is a crypto exchange based in Italy. It serves these customer groups: private crypto investor, business accepting crypto payments. Clear means the review is closed with a short note; investigate means an analyst opens a case and reviews the customer'\''s documents; escalate means the case goes to the money-laundering reporting officer, who decides on a report to the authorities; block means the payment is stopped and the account frozen until compliance decides.\n\nMonitoring rules (all amounts in euro):\nEach review covers one customer'\''s last 30 days. Transfers between the customer'\''s own accounts and wallets (listed in the customer profile) are ignored by every rule.\nWarning signs:\nW1 Structuring: 3 or more deposits made with cash vouchers bought at partner kiosks each from 2,400.00 up to just under the reporting threshold of 3,000.00.\nW2 Rapid pass-through: the incoming money totals at least 1,000.00 and at least 90% of it is sent out again (by any payment or cash withdrawal) within 72 hours of arriving.\nW3 Many senders: money comes from more different senders than the customer profile expects per month.\nW4 Many recipients: money goes to more different recipients than the customer profile expects per month.\nW8 High-risk country: a payment to or from a country on the high-risk list that the customer profile does not list as an expected country.\nHigh-risk countries: Algeria, Bulgaria, Cameroon, Lebanon, Mali, Nigeria, Philippines, South Sudan, Venezuela.\nBlocked countries: Belarus, North Korea, Syria.\nBlocked parties: Field Summit EOOD (Bulgaria); Ember Nova Company (Bolivia); Coral Alder Ltd (Malta).\nActions (exactly one applies):\nblock: any payment to or from a blocked country or a blocked party, whatever else the activity shows.\nescalate: two or more different warning signs, or W2 (Rapid pass-through) even on its own.\ninvestigate: exactly one warning sign, other than W2.\nclear: no warning sign and no blocked country or party.",
"customer": "Customer: Kenji Okafor (individual), customer since November 2019.\nSegment: private crypto investor. Occupation or business: shop owner investing in crypto.\nExpected incoming: about 620.00 a month.\nExpected senders: up to 8 different senders a month. Expected recipients: up to 6 different recipients a month.\nExpected countries: Italy, Lebanon.\nOwn accounts and wallets: bank account ending 5014 at another bank; own hardware wallet 0xb84f...182c.",
"activity": "Review period: 1 June 2026 to 30 June 2026 (30 days). Amounts in euro.\nPayments:\n01 Jun 09:12 received 46.76 by crypto deposit from wallet 0x576b...5f0d at FalconCoin (Italy)\n10 Jun 17:34 sent 376.32 by crypto withdrawal to wallet 0x3292...217b (private wallet, owner and country unknown)\n14 Jun 14:23 received 478.54 by crypto deposit from wallet 0x576b...5f0d at FalconCoin (Italy)\nSummary (transfers between own accounts left out):\n- incoming: 2 payments, total 525.30, from 1 different senders\n- outgoing: 1 payments, total 376.32, to 1 different recipients\n- share of incoming money sent out again within 72 hours: 0%\n- counterparty countries: Italy"
},
"questions": {
"action": {
"type": "choice",
"instructions": "A compliance analyst at the institution described above reviews this customer'\''s last 30 days of activity. Which action does the institution'\''s monitoring policy require?",
"criteria": {
"block": "Block: at least one payment goes to or comes from a blocked country or a blocked party, whatever else.",
"investigate": "Investigate: exactly one warning sign applies, and the policy does not say to escalate that one alone.",
"escalate": "Escalate: two or more different warning signs apply, or a sign that the policy says to escalate alone.",
"clear": "Clear: no warning sign applies at all, and no payment involves a blocked country or any blocked party."
}
}
}
}'A real response from this adapter appears here when it is released.
Results
On this adapter's held-out test sets, never trained on, scored three ways on the same rows: the untrained model Jeff is built from, the Jeff v1.3 base alone, and the base with this adapter. Questions have 2 to 8 options. As of 2026-10-05. All adapters
| Test set | Test rows | Qwen3.5-0.8B untrained | Jeff base v1.3 alone | Jeff base v1.3 + adapter |
|---|---|---|---|---|
test | 5,120 | 36.0% · 0.022 | 40.5% · 0.103 | 95.0% · 0.012 |
test-amlworld-v1 | 4,500 | 48.9% · 0.023 | 64.3% · 0.044 | 60.0% · 0.244 |
test5,120 test rows- Qwen3.5-0.8B untrained
- 36.0% · 0.022
- Jeff base v1.3 alone
- 40.5% · 0.103
- Jeff base v1.3 + adapter
- 95.0% · 0.012
test-amlworld-v14,500 test rows- Qwen3.5-0.8B untrained
- 48.9% · 0.023
- Jeff base v1.3 alone
- 64.3% · 0.044
- Jeff base v1.3 + adapter
- 60.0% · 0.244
Each cell: accuracy · calibration error (ECE; lower is better, 0 is perfect).
By group (test set test)
| Group | Rows | Qwen3.5-0.8B untrained | Jeff base v1.3 alone | Jeff base v1.3 + adapter |
|---|---|---|---|---|
| question: action | 2,386 | 27.3% | 22.4% | 94.1% |
| question: pattern | 348 | 13.8% | 17.8% | 99.7% |
| question: suspicious | 2,386 | 47.9% | 62.0% | 95.3% |
By group (test set test-amlworld-v1)
| Group | Rows | Qwen3.5-0.8B untrained | Jeff base v1.3 alone | Jeff base v1.3 + adapter |
|---|---|---|---|---|
| question: amlworld_window | 4,500 | 48.9% | 64.3% | 60.0% |
With llama.cpp
The same test, through llama.cpp: the base GGUF plus this adapter's LoRA GGUF, with the temperature refitted for each format. Running Jeff with llama.cpp
| Test set | Full precision | Q8_0 | Q4_K_M |
|---|---|---|---|
test | 95.0% · 0.012 | 95.0% · 0.012 | 94.6% · 0.015 |
test-amlworld-v1 | 60.0% · 0.244 | 59.8% · 0.246 | 60.7% · 0.221 |
Source: results/sources/v1.3/new-adapters.table.json
Model card
aml: how it was made
How it was made
In short: Synthetic institutions, customers and transactions; code fixes every label and GLM 5.3 writes some texts; laundering-pattern rows from IBM AMLworld.
- Test set: Whole simulated institutions are held out: the test's 117 families (institutions, and for the pattern question traced laundering attempts) never appear in training, so its policies and customers are new to the adapter. 5,120 test rows: 2,386 per policy question (suspicious, action) and 348 pattern rows.
- Training data: not published.
- Training data: 40,054 rows (version 2 of the data, built 2026-10-04); development 1,064, calibration 1,136 and test 5,120 rows.
- Training mixed in a replay sample of the Jeff base model's own training data: 4,005 rows, about 10% on top of the adapter's 40,054 (a precaution; its effect has not been measured).
- What it is not: it follows the institution's written policy, not a general laundering detector. On an out-of-distribution cross-test (4,500 windows from IBM's AMLworld simulation, asking only whether any transaction is part of laundering, with no written policy to apply) the adapter scores 60.0% (ECE 0.244), below the base alone at 64.3%. That test is shown for information; it is not what the adapter was trained to do.
- Every label is computed by code - the scenario sets the action first, then the written policy's rules are re-applied to the transactions shown, and the build stops if the two disagree. GLM never sets a label.
- A second question, which laundering pattern a traced set of transfers forms (fan-out, fan-in, cycle and others), uses rows built from IBM's synthetic AMLworld data.
Data and licence
Adapter: Apache-2.0
- Synthetic institutions, customers and transactionsReleased with the adapter under Apache-2.0Generated by GLM 5.3 (own hardware), for some texts; everything else by codeSimulated by code with fixed seeds; all names are invented. Some policy introductions, customer profiles and activity texts are written or reworded by GLM 5.3 and checked by code.
- IBM Transactions for Anti Money Laundering (AMLworld), laundering-pattern rowsCommunity Data License Agreement - Sharing - Version 1.0 (CDLA-Sharing-1.0); shared data, including modified data, must keep the same termsNot generated by a modelAltman et al., "Realistic Synthetic Financial Transactions for Anti-Money Laundering Models", NeurIPS 2023 Datasets and Benchmarks. Fully synthetic; no real people or accounts.
Check it yourself
Changelog
- 1.3.0 · 2026-10-03First release, trained on Jeff v1.3 with the live-last prompt layout (run 0.8b-aml-v2-20261004-0713, data version 2).
Comments
Comments open when JeffHub launches. They will live in the registry repository's GitHub Discussions, one thread per adapter; you sign in with GitHub, and JeffHub stores no accounts.
