Gidi — GiaoDịch
Tiếng Việt · English
Đây là thử nghiệm của mình để xây dựng một classifier nhỏ.
Demo: https://gidi.8bu.dev. Model chạy hoàn toàn trong trình duyệt (onnxruntime-web, INT8).
Model: gidi-finance-v3, release 3.0.0.
Đây là model on-device nhỏ cho ghi chú tài chính cá nhân tiếng Việt ngắn như
mượn chú hai 5 xị.
Với mỗi ghi chú, hệ thống dự đoán:
type: loại giao dịch, thuộc một trong expense, income, borrow, lend, repayment_in, repayment_out, transfer, refund;target: span của đối tác, chẳng hạnchú hai, hoặcnull;value: span chứa số tiền theo cách người dùng viết, chẳng hạn5 xị, hoặcnull. Span là chuỗi con của ghi chú. Hệ thống không suy ra số từ span này.
gidi-finance-v3 gồm ba phần:
- Một encoder INT8 (4 lớp, 768 chiều, từ vựng đã cắt còn 8.338 token) trong một đồ thị ONNX.
Encoder dự đoán
typevàtarget. - Bước word snap: span
targetđược mở rộng ra ranh giới của cả từ. Ví dụpbanktrongrut tien vpbank 1trthànhvpbank. - Một parser theo luật (
gidi.value_parser, phiên bản1) lấyvaluetừ ghi chú gốc. Không có value head nơ-ron.config.jsonghi phiên bản parser; runtime từ chối nạp bundle nếu phiên bản parser không khớp.
Hệ thống chuẩn hóa ghi chú về NFC và cắt phần đưa vào encoder tại 32 token. Parser đọc toàn bộ ghi chú, kể cả phần sau điểm cắt.
Thay đổi so với gidi-finance-v2
- Quy tắc nợ. Ghi chú chỉ nói về một khoản nợ đang có (
còn nợ Hùng 300k,Hoa còn nợ mình 350k) nhậnborrow(mình nợ) hoặclend(người kia nợ mình). Trước đây loại này bị bỏ qua. Xemdocs/annotation-v3.md. - Quy tắc quà. Người nhận quà hoặc tiền mừng là đối tác, nên là
target(mừng cưới Hoa 1 triệucótargetlàHoa). Bộ test dùng quy tắc này. Dữ liệu huấn luyện của model này chưa áp dụng quy tắc quà, nên ghi chú về quà vẫn là điểm yếu (xem Giới hạn). - Số tiền theo luật.
valueđến từ parser theo luật, không còn từ value head dùng CRF. Parser có kết quả xác định và không có điểm tin cậy, nênvalue_confidencelànull. - Word snap bật mặc định (
target_snap: wordstrongconfig.json). - Nhỏ một nửa. Chỉ còn một encoder: bundle INT8 là 29,3 MB, v2 là 58,1 MB. Độ trễ p50 khoảng 1,4 ms (v2: 3,5 ms), CPU một luồng, Apple Silicon, batch 1.
Kết quả
Bộ test mới human-value-02: 200 ghi chú, 190 ghi chú được chấm. Nhãn do hai bộ gán nhãn LLM
độc lập tạo ra, rồi đối chiếu và phân xử. Đây là nhãn LLM, không phải nhãn người.
end-to-end là đúng cả type, target và value.
Cột v2 là bundle gidi-finance-v2 chạy nguyên trạng trên cùng 190 ghi chú.
human-value-02 (n = 190) |
gidi-finance-v3 |
gidi-finance-v2 |
|---|---|---|
type đúng |
92,11 % | 75,79 % |
target khớp chính xác |
85,26 % | 74,74 % |
value khớp chính xác |
100,00 % | 98,42 % |
| end-to-end | 78,95 % | 59,47 % |
Hai bộ cũ hơn, chỉ chấm type và target. type và target của v2 giống hệt encoder
gidi-finance-v1 INT8, nên cột v2 lấy từ encoder đó.
| bộ | type v3 |
type v2 |
target v3 |
target v2 |
|---|---|---|---|---|
| test đóng băng (n = 105) | 94,29 % | 94,29 % | 92,38 % | 88,57 % |
| probe-v1 (n = 81) | 82,72 % | 77,78 % | 85,19 % | 81,48 % |
Các số này đến từ một lần chấm, với seed 1 cố định trước khi huấn luyện, không chọn theo điểm. Với bộ nhỏ như vậy, chênh lệch vài điểm phần trăm chưa chắc có ý nghĩa.
Biến thể
| biến thể | archive | tệp model | kích thước | sha256 |
|---|---|---|---|---|
| int8 | gidi-finance-v3-3.0.0-int8.tar.gz |
model.int8.onnx |
28.7 MB | 61c17d27b92e1ac4ac1add0af73344cb1c68bdbbc19db58532ce6d38d9bb7315 |
| fp32 | gidi-finance-v3-3.0.0-fp32.tar.gz |
model.onnx |
114.0 MB | 1304c5986609a35305d5d81809cedb7145dc5a6e1b8e9718d33af1ea3f93fd85 |
Khuyến nghị dùng int8 để deploy. fp32 là bản export tham chiếu
để kiểm tra parity.
Bản fp32 chỉ có trên GitHub release, trong archive -fp32.
Cả hai archive đều là runtime bundle đầy đủ.
Mỗi bundle gồm model, config.json (label, giao diện ONNX, quy tắc value và target_snap),
tokenizer.json, tokenizer_config.json, vocab_map.json, LICENSE, README này và
release-manifest.json. Release liệt kê sha256 của mỗi tệp trong
manifest.json và checksums.txt.
Nếu repository chỉ lưu tệp INT8, có thể kiểm tra chúng bằng lệnh
sha256sum -c --ignore-missing checksums.txt.
Cách dùng
Yêu cầu: Python >=3.12, onnxruntime >=1.30.0, tokenizers
=0.23.2, numpy >=2.0, và package
gidi(gidi.inferencevàgidi.value_parser). Parser nằm trong packagegidi, không nằm trong tệp ONNX.
Giải nén archive. Sau đó nạp thư mục bằng GidiPredictor.
GidiPredictor đọc config.json và tự bật word snap và parser.
from pathlib import Path
from gidi.inference.predictor import GidiPredictor
# INT8 archive: the bundle contains model.int8.onnx, which is the default model file.
predictor = GidiPredictor.from_bundle("gidi-finance-v3-3.0.0-int8")
print(predictor.predict("mượn chú hai 5 xị").to_dict())
# FP32 archive: point to its model.onnx.
root = Path("gidi-finance-v3-3.0.0-fp32")
predictor = GidiPredictor.from_bundle(root, model_path=root / "model.onnx")
predict(...).to_dict() trả về các key sau:
| key | ý nghĩa |
|---|---|
type |
loại giao dịch |
type_confidence |
xác suất softmax của type |
target |
văn bản đối tác (sau word snap), hoặc null |
target_span |
offset [start, end] theo code point trong input, hoặc null |
target_confidence |
độ tin cậy của target span |
value_text |
văn bản số tiền (text[start:end] của input), hoặc null |
value_span |
offset [start, end] của value, hoặc null |
value_confidence |
luôn là null: parser theo luật không có điểm tin cậy |
truncated |
true nếu encoder cắt ghi chú tại giới hạn token |
model_version |
gidi-finance-v3 |
Khi tích hợp ONNX Runtime trực tiếp, graph nhận input_ids và attention_mask.
Graph trả về type_logits và tag_logits. Lấy argmax của tag_logits, giải mã span target,
rồi mở rộng ra ranh giới từ như target_snap trong config.json.
Graph không có value_logits: phần value cần parser gidi.value_parser (hoặc bản port
tương đương đúng phiên bản 1).
Giới hạn đã biết
- Đối tác (
target) đúng khoảng 85 %. Trênhuman-value-02, 25 ghi chú saitarget, 12 saitypevà 3 sai cả hai (40 ghi chú sai trong 190). Lỗitargetthường gặp là tên thương hiệu hoặc cửa hàng nhiều từ bị cắt (đi xem phim lotte cinema 130kcholotte,trả góp thế giới di động 1tr8chođộng) và đối tác bị bỏ sót (cf trung nguyen 45k). - Ghi chú về quà và lì xì. Model chưa học quy tắc quà. Ví dụ đã biết là sai:
lì xì bà ngoại 500k(choincome, đúng làexpense) vàquà tốt nghiệp em Khải 500k(chotốt, đúng làKhải). - Một số ghi chú nợ vẫn sai hướng, chẳng hạn
Hung no minh 2tr chua tra(chorepayment_in, đúng làlend) vànhớ đòi Trang 450k(choborrow, đúng làlend). - Bộ test dùng nhãn LLM.
human-value-02có 190 ghi chú chấm được, nhãn do hai bộ gán nhãn LLM độc lập tạo ra, rồi phân xử, không phải nhãn người. Nhãnvaluekhớp với parser trên cả 190 ghi chú, nên con số 100 % củavaluechưa chứng minh parser đúng trên ghi chú khác. Các số trên chỉ là ước lượng sơ bộ. - Điểm tin cậy của
typevàtargetchưa hiệu chỉnh. Hệ thống chưa có ngưỡng hay cơ chế từ chối. - Hệ thống không chuyển đổi NBSP và chữ số full-width trước encoder.
- Nếu
targetnằm sau điểm cắt 32 token, encoder không tìm thấy nó (truncatedlàtrue). Parser vẫn đọc toàn bộ ghi chú. - Hệ thống không extract hoặc normalize số tiền hay ngày tháng.
Không có class "out of scope".
Mỗi ghi chú nhận một
typetrong cáctypetrên.
Giấy phép
Apache License 2.0. Toàn văn nằm trong LICENSE.