pragmatiq
<p align="center">
<img src="https://raw.githubusercontent.com/dynamiq-ai/pragmatiq/main/docs/assets/pragmatiq-social.png" alt="pragmatiq: open-source banking financial model stack" width="780">
</p>
<p align="center">
<a href="https://pypi.org/project/pragmatiq/"><img alt="PyPI" src="https://img.shields.io/pypi/v/pragmatiq?include_prereleases&label=PyPI&color=0e8a8a"></a>
<a href="https://pragmatiq.getdynamiq.ai"><img alt="Docs" src="https://img.shields.io/badge/docs-pragmatiq.getdynamiq.ai-0e8a8a.svg"></a>
<a href="https://github.com/dynamiq-ai/pragmatiq/actions/workflows/ci.yml"><img alt="CI: GitHub Actions" src="https://img.shields.io/badge/ci-GitHub%20Actions-2088ff.svg"></a>
<a href="https://github.com/dynamiq-ai/pragmatiq/blob/main/LICENSE"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
<img alt="Python 3.11+" src="https://img.shields.io/badge/python-3.11%2B-3776AB.svg">
<img alt="Status: stable" src="https://img.shields.io/badge/status-stable-10b981.svg">
</p>
pragmatiq는 Ostroukhov 등이 발표한 PRAGMA 논문(arXiv:2604.08649)에서 설명된 아이디어를 개발자 친화적으로 구현한 것입니다. 이 도구는 타임스탬프가 찍힌 키-값 이벤트로 구성된 사용자 기록을 임베딩으로 변환하며, 이를 다운스트림 팀들이 프롭(probes), LoRA 파인튜닝, 그래프 기반 AML 실험 및 서비스에 사용할 수 있도록 합니다.
이 저장소에는 전체 스택이 포함되어 있습니다: 결정론적 합성 뱅킹 데이터 생성기, 토크나이저, 패딩 없는 PyTorch 모델, 학습 파이프라인, 배치 임베딩, ONNX/Triton 서빙, 노트북 및 Streamlit 데모입니다. 이 시스템은 GPU 우선(GPU-first)이며 CPU에서도 완벽하게 작동합니다(CPU-complete): 사용 가능한 CUDA 장치가 있으면 모든 명령어가 해당 장치에서 실행되고 (추론 시 bf16, 학습 시 bf16-mixed, 설치된 경우 flash-attn의 varlen 커널 사용), 그렇지 않으면 CPU에서 fp32로 동일한 코드를 실행합니다. 속도는 느리지만 결과 계약(result contract)은 절대 달라지지 않습니다.
pragmatiq는 PRAGMA 논문(arXiv 2604.08649)에서 영감을 받은 독립적인 구현체입니다.
Revolut과 관련이 있거나 이를 보증하는 것은 아닙니다.
목차
왜 이것이 존재하는가
PRAGMA 논문(arXiv:2604.08649)은 이종(heterogeneous) 뱅킹 행동에 대한 실용적인 파운데이션 모델 레시피를 설명합니다. 여기에는 거래(transactions), 앱 세션(app sessions), 거래(trades), 통신(communications), 프로필(profiles), 그리고 전송 관계(transfer relationships)가 포함됩니다. 이 논문은 참고 코드를 제공하지 않습니다.
pragmatiq는 연구원, ML 엔지니어 및 데이터 과학자가 실행하고, 검사하고, 적응시키고, 벤치마킹할 수 있는 오픈 구현체를 제공합니다. 목표는 PRAGMA보다 새로운 것을 주장하는 것이 아닙니다. 목표는 구현 경로를 구체화하는 것입니다.
빠른 시작
요구 사항
pip install
`train` extra는 Lightning을 포함하며, 이 라이브러리는 사전 학습(`pretraining`) (따라서 `quickstart`)에 사용됩니다. 단순히 `pip install pragmatiq`를 실행하면 이미 훈련된 모델을 이용한 임베딩을 위한 간소화된 추론(inference) 코어만 설치됩니다. `pragmatiq info`는 버전, 감지된 장치(`cuda`가 보이면, 아니면 `cpu`), flash-attn 사용 가능 여부, 그리고 어떤 extras가 설치되었는지 출력하며, `pragmatiq --version`은 패키지 버전을 출력합니다.
또는 레포지토리를 클론하여 개발 목적으로 사용할 수 있습니다:
```bash
git clone https://github.com/dynamiq-ai/pragmatiq.git && cd pragmatiq
pip install -e ".[dev,full]"
quickstart는 pragmatiq info가 보고하는 장치에서 합성 파이프라인을 처음부터 끝까지 실행합니다:
- 합성 사용자 및 이벤트 히스토리 생성,
- 키-값-시간 토크나이저(key-value-time tokenizer) 적합화(fit),
- 나노 마스크드 언어 모델(nano masked-language model) 사전 학습,
- 사용자 임베딩 수행,
- 원시 카운트 기준선(raw-count baseline)에 대한 그래디언트 부스팅 신용 위험 프로브 실행.
빠른 경로(--n-users 2000 --max-steps 80)는 노트북에서 시도하기 적절한 첫 번째 실행이며, 기본값은 하드웨어 테이블에 기록된 시간을 측정하는 기준(reference) 실행입니다.
단순히 pip install pragmatiq를 설치하면 간소화된 추론 코어만 얻게 됩니다. 즉, 검증(validating), 토크나이징(tokenizing), 훈련된 모델을 이용한 임베딩, 그래디언트 부스팅 프로브, 그리고 LoRA 파인튜닝 모두 추가 라이브러리 없이 작동합니다. 훈련에는 .[train]가 필요하며, 사전 학습은 Lightning에서 실행됩니다. 다른 extras는 특정 기능을 위한 도구들을 추가합니다: 슬림 ONNX/Triton 내보내기 및 서빙을 위한 .[serve] (Lightning / torch-geometric / transformers 제외), GraphSAGE 전이 그래프 제거(ablation)를 위한 .[aml] (torch-geometric), 고정된 Nemotron 텍스트 인코더를 위한 .[text], Weights & Biases 및 TensorBoard 미러링을 위한 .[tracking], 합성 현실성 보고서(synthetic realism report)를 위한 .[data] (matplotlib), Streamlit 데모를 위한 .[demo], 그리고 이 모든 것을 포함하는 .[full]입니다.
동일한 워크플로우는 Python에서도 사용할 수 있습니다:
from pragmatiq import api
result = api.quickstart(n_users=2000, max_steps=80)
...
CLI는 의도적으로 간결합니다. 명령어들은 인수를 파싱한 다음, pragmatiq/api.py의 공개 함수를 호출하므로, 노트북 환경과 프로덕션 호출자 모두 동일한 라이브러리 인터페이스를 사용합니다.
포함 내용
| 영역 | pragmatiq가 제공하는 것 |
|---|
| 합성 데이터 | 결정론적 시드(deterministic seeds), 인과 레이블, 사기/부도/AML 시나리오 및 현실성 검사를 갖춘 에이전트 기반 뱅킹 시뮬레이터. |
| ... | {} |
아키텍처
<p align="center">
<img src="https://raw.githubusercontent.com/dynamiq-ai/pragmatiq/main/docs/assets/architecture.png" alt="pragmatiq architecture: raw or synthetic banking data is validated, run through the key-value-time tokenizer into token-budget batches (parquet shards + LMDB index), then profile, event, and history encoders produce user embeddings; the event encoder also feeds the MLM pretraining head, and user embeddings feed probe / LoRA / AML GNN / serving." width="900">
</p>
<!-- Diagram source: docs/assets/architecture.mmd (render with @mermaid-js/mermaid-cli). -->
전반적으로 pragmatiq는 PRAGMA 레시피를 따릅니다:
- 키(Key)와 값(Value) 임베딩은 하나의 테이블을 공유하며, 이는 연결된 MLM 로짓(tied MLM logits)에도 재사용됩니다.
- 연속 시간 위치(Continuous time positions)는 논문의
8 * ln(1 + delta_t / 8) 변환을 사용합니다.
- 이벤트(Events)는 독립적으로 인코딩된 다음, 양방향 히스토리 인코더에서 프로필 정보와 결합됩니다.
- 마스킹(Masking)은 토큰, 전체 이벤트, 키 수준의 마스크를 결합하며,
[UNK] 대체 값은 MLM 손실(MLM loss)에서 제외됩니다.
- 체크포인트에는 모델, 옵티마이저, 스케줄러, 샘플러 위치, RNG 상태, 토크나이저 해시 및 해결된 설정(resolved config)이 포함됩니다.
- 레지스트리(Registries)를 통해 사용자는 라이브러리를 포크(forking)하지 않고도 헤드(heads), 마스커(maskers), 값 인코더(value encoders)를 사용자 정의할 수 있습니다.
인코더, 시간적 인코딩 및 목적 함수에 대한 교육 수준의 상세 설명은 docs/architecture.md를 참조하고, 목적 함수와 제한 사항에 대한 작성 내용은 MODEL_CARD.md를 참고하십시오.
논문 충실도(Paper fidelity)
PRAGMA 논문 이후에 이어지는 내용과 pragmatiq가 추가하는 부분:
| 구성 요소 | 논문에 포함됨 | pragmatiq |
|---|
Key–value–time 토큰화, 8·ln(1+Δt/8) 시간 변환, 연속 로그-초에 대한 TimeRoPE | ✓ | faithful |
| ... | | |
Repository map
pragmatiq/
├── pragmatiq/ # 라이브러리 — 모든 로직이 여기에 존재합니다
│ ├── api.py # 공개 함수: synthesize / tokenize / pretrain / ... (api.__all__)
...
tests/ 디렉터리는 살아있는 문서 역할을 겸합니다. 예를 들어,
tests/test_tokenizer.py는 토크나이저 계약(contract)을 엔드투엔드로 보여주며, tests/test_training.py는 비트 단위 정확도의 체크포인트 재개를 시연합니다.
Workflows (작업 흐름)
빠른 시작(quickstart)이 가장 좋은 첫 실행 방법입니다. 각 단계를 명시적으로 구동하고 싶을 때 아래 명령어를 사용하세요.
1. 데이터 생성 및 토큰화
pragmatiq synth generate --out data/synth --config configs/data/synthetic.yaml
pragmatiq tokenize data/synth --out data/tokenized --n-workers 8
생성기(generator)는 --n-users, --seed, 그리고 --n-workers를 받습니다. 동일한 시드(seed)는 어떤 워커 수에서도 바이트 단위로 동일한 출력을 생성합니다. 은행이 공유할 수 있는 집계 통계량(raw data 없음)에 맞게 생성기 사전 분포(generator priors)를 조정하려면 pragmatiq synth calibrate --stats configs/data/aggregates.example.yaml을 사용하세요.
2. 사전 학습 및 임베딩
pragmatiq pretrain data/tokenized --name demo --model-size small --config configs/pretrain.yaml
pragmatiq embed data/tokenized --run runs/demo --out embeddings.parquet
언제든지 실행을 검사하고 비교할 수 있습니다:
pragmatiq runs list
pragmatiq runs compare demo other-run
3. 작업 신호 평가
probe는 가장 빠른 검사 방식입니다 (고정된 임베딩 위에 적용되는 그래디언트 부스팅 헤드). 레이블이 지정된 태스크에 대한 지도 학습 어댑터 훈련을 원할 때는 파인튜닝(fine-tuning)을 사용하세요. GPU 환경에서는 파인튜너가 장치 메모리에서 토큰 예산을 할당하고 에포크별 epoch_stats (배치, 토큰, 초, 토큰/초)를 보고하여 느린 에포크가 숨겨지지 않고 눈에 보이게 합니다.
pragmatiq probe data/tokenized --run runs/demo --label data/synth/labels/default_12m.parquet
pragmatiq finetune data/tokenized --run runs/demo --label data/synth/labels/default_12m.parquet \
--config configs/finetune/credit.yaml
프로브 헤드(probe head)는 기본적으로 그래디언트 부스팅(gradient boosting) 방식입니다 (HistGradientBoostingClassifier; --probe-model logistic 또는 lightgbm을 사용하면 변경 가능). 이는 선형 헤드보다 학습된 임베딩의 비선형 구조를 더 잘 포착합니다. ROC-AUC와 PR-AUC가 모두 보고되는데, PR-AUC는 낮은 유병률(low-prevalence) 위험 태스크에서 신뢰할 수 있는 지표입니다. 그리고 **원시 카운트 기준선(raw-count baseline)**은 동일한 분류기를 사용하므로, 그 차이는 모델 계열이 아닌 표현력(representation)을 반영합니다. 기본 합성 부크(synthetic book)에서는 pragmatiq probe가 이 기준선을 능가합니다. 레이블 테이블에 eval_ts 열이 포함된 경우, 임베딩을 생성하기 전에 기록은 해당 시점까지 잘립니다 — 이는 probe와 기준선 모두에 적용되어 지표들이 사후 예측(hindcasts)이 아닌 예측치(forecasts)가 되도록 합니다.
임베딩의 가치는 신용(credit)에만 국한되지 않습니다. 다중 태스크 프로브 벤치마크(scripts/benchmarks/multitask_probe.py)는 모든 사용자 수준 태스크를 동일한 원시 카운트 기준선과 비교하여 검사합니다. 아래 표는 해당 스크립트의 --write 플래그에 의해 작성되었으며, 출처 기록(provenance stamp)을 포함하고 있어 더 큰 규모의 결과를 대체할 경우 거부됩니다.
이벤트 수준의 fraud/recurring (거래/시리즈 수준) 및 comm_uplift (처리 효과 태스크 — pragmatiq uplift 참조)는 이 사용자 임베딩 프로브가 아닌 자체 경로를 통해 평가됩니다.
<!-- MULTITASK_PROBE_RESULTS -->
이벤트 노후화 (Event staleness)
실제 운영 환경(production)에서는 이벤트 피드에 지연이 발생합니다. 즉, 9시에 점수를 매긴 임베딩은 그보다 훨씬 이전에 도착을 멈춘 이벤트들로 구축된 것입니다. 논문에서는 가장 최근의 기록 창(window)이 누락되었을 때도 태스크 메트릭이 거의 변하지 않음을 확인했습니다 (§3.4.2). pragmatiq probe --staleness-window 6h (또는 api.probe(..., staleness_window="6h"))는 프로브와 베이스라인 모두에 대해 모든 사용자의 평가 지점 직전의 마지막 6시간을 누락시키며, scripts/benchmarks/staleness_probe.py가 0 / 1h / 6h / 1d / 3d를 순회하며 --write 옵션으로 아래 표에 작성합니다.
<!-- STALENESS_PROBE_RESULTS -->
| task | stale window | probe ROC-AUC | Δ vs fresh | probe PR-AUC | Δ vs fresh | baseline ROC-AUC |
|---|
| default_12m | 0 | 0.710 | +0.000 | 0.131 | +0.000 | 0.487 |
| ... | | | | | | |
| <sub>provenance: n_users=50000, model=small, steps=2000, seed=0, commit=fd60311</sub> | | | | | | |
자체 데이터 사용하기 (Using your own data)