language, license, base_model, tags, datasets, pipeline_tag
language license base_model tags datasets pipeline_tag
vi
en
apache-2.0 Qwen/Qwen3-4B-Instruct-2507
qwen3
accounting
vietnamese
kế-toán
thông-tư-133
fine-tuned
cot
chain-of-thought
custom-tt133
text-generation

AAI Accountant — TT133 v1.1

AI tư vấn kế toán chuyên biệt cho Thông tư 133/2016/TT-BTC (Chế độ kế toán doanh nghiệp nhỏ và vừa Việt Nam)

Phiên bản 1.1 (Cải tiến: tăng độ chính xác câu trả lời, giảm halluciation)

Thông tin mô hình

Thuộc tính Giá trị
Base model Qwen/Qwen3-4B-Instruct-2507
Fine-tune method LoRA FP16 (rank=32, RSLoRA)
Dataset 1484 samples từ TT133 + Phụ lục biểu mẫu + Nghiệp vụ
Language Tiếng Việt (kế toán)
Context length 4096 tokens
Format ChatML + <think>...</think> CoT

Khả năng

  • Hướng dẫn định khoản kế toán theo TT133 (Nợ/Có, TK XXX)
  • Giải thích điều khoản — trả lời câu hỏi về 91 Điều của TT133
  • Biểu mẫu BCTC — hướng dẫn điền B01-DNN, B02-DNN, B09-DNN...
  • Danh mục tài khoản — tra cứu mã TK, phân loại, bút toán điển hình
  • Chain-of-Thought — suy luận từng bước rõ ràng trước khi trả lời

Dataset breakdown

Loại nội dung Samples %
Văn bản (Điều khoản chung) 267 18%
Nguyên tắc kế toán 249 17%
Biểu mẫu (Phụ lục) 358 24%
Ví dụ 72 5%
Định khoản Nợ/Có 447 30%
Phụ lục chung 91 6%

Cách dùng

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_id = 'steve-nguyen/aai-accountant-tt133-v1.1'
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
    model_id, torch_dtype=torch.float16, device_map='auto'
)
# System prompt
SYSTEM_STRICT = '''Bạn là AI kế toán chuyên biệt theo Thông tư 133/2016/TT-BTC.
QUY TẮC BẮT BUỘC:
1. Chỉ nhắc các TK có thật trong TT133 (TK 111911, theo danh mục TT133)
2. Khi hỏi về B01-DNN/B02-DNN, trả lời đúng mapping: Mã số → TK nguồn
3. Nếu không chắc chắn 100%, nói rõ: "Cần kiểm tra lại với văn bản TT133"
4. Không liệt kê TK theo pattern số tăng dần nếu không chắc
Nguyên tắc: Chính xác > Đầy đủ. Thà ít mà đúng hơn nhiều mà sai.'''

def ask(question, max_new_tokens=1024):
    messages = [
        {'role': 'system', 'content': SYSTEM_STRICT},
        {'role': 'user',   'content': question},
    ]
    chat_text = tokenizer.apply_chat_template(
        messages, tokenize=False, add_generation_prompt=True,
        enable_thinking=True,
    )
    encoded = tokenizer(chat_text, return_tensors='pt').to('cuda')
    prompt_len = encoded['input_ids'].shape[1]

    with torch.no_grad():
        outputs = model.generate(
            **encoded,
            max_new_tokens       = max_new_tokens,
            do_sample            = True,
            temperature          = 0.1,
            top_p                = 0.9,
            repetition_penalty   = 1.05,
            eos_token_id         = tokenizer.eos_token_id,
            pad_token_id         = tokenizer.eos_token_id,
        )

    text = tokenizer.decode(outputs[0][prompt_len:], skip_special_tokens=True)

    import re
    text = re.sub(r'<think>.*?</think>', '', text, flags=re.DOTALL).strip()
    return text

    try:
        chat_text = tokenizer.apply_chat_template(
            messages,
            tokenize=False,
            add_generation_prompt=True,
            enable_thinking=False,
        )
    except TypeError:
        chat_text = tokenizer.apply_chat_template(
            messages, tokenize=False, add_generation_prompt=True,
        )

    encoded = tokenizer(
        chat_text, return_tensors='pt', return_attention_mask=True,
    ).to('cuda')

    input_ids      = encoded['input_ids']
    attention_mask = encoded['attention_mask']
    prompt_len     = input_ids.shape[1]

    with torch.no_grad():
        outputs = model.generate(
            input_ids            = input_ids,
            attention_mask       = attention_mask,
            max_new_tokens       = max_new_tokens,
            do_sample            = False,
            temperature          = 1.0,
            repetition_penalty   = 1.1,
            no_repeat_ngram_size = 5,
            eos_token_id         = tokenizer.eos_token_id,
            pad_token_id         = tokenizer.eos_token_id,
            use_cache            = True,
        )

    generated = outputs[0][prompt_len:]
    text = tokenizer.decode(generated, skip_special_tokens=True)

    import re
    text = re.sub(r'<think>.*?</think>', '', text, flags=re.DOTALL).strip()
    return text

print('✅ ask() sẵn sàng — inference mode ON')
print('   enable_thinking=False | do_sample=False (greedy decoding)')

#Đặt câu hỏi
q1 = 'Công ty ABC mua hàng hóa giá 100 triệu đồng, chưa trả tiền người bán. Hãy định khoản nghiệp vụ này theo TT133.'
print('='*60)
print('❓', q1)
print('='*60)
print(ask(q1))

Lưu ý

  • Mô hình được tối ưu cho Thông tư 133 (Doanh nghiệp Vừa và Nhỏ).
  • Một số trường hợp Mô hình trả lời không đúng yêu cầu, chỉ cần điều chình System prompt (SYSTEM_STRICT).
  • Luôn kiểm tra lại bút toán với kế toán viên — AI có thể mắc lỗi trong các trường hợp phức tạp.
  • Không áp dụng cho mục đích pháp lý mà không có xác nhận chuyên môn.

License

Apache 2.0 — kế thừa từ Qwen3-4B-Instruct.

Góp ý

Mọi ý kiến đóng góp xin gởi vào email: anh.nd@outlook.com

Description
Model synced from source: steve-nguyen/aai-accountant-tt133-v1.1
Readme 32 KiB
Languages
Jinja 100%