Files
obsidian/🤖ЛОКАЛЬНЫЙ ИИ-ЭКСПЕРТ ПО БАНКОМАТНОМУ ПО.md

15 KiB
Raw Permalink Blame History

Обновленная версия, Не проверена

  • Платформа: Windows 10/11 + WSL2 (Ubuntu 22.04 / 24.04)
  • Железо: NVIDIA RTX 3060 Ti (8 ГБ VRAM)
  • Базовая модель: Meta Llama 3.1 8B
  • Рабочая директория: C:\ST\aandc\ (в WSL2: /mnt/c/ST/aandc/)

ЧАСТЬ 1. Развертывание среды и проброс GPU в WSL2

1.1. Базовая установка подсистемы

Откройте PowerShell от имени Администратора на Windows:

powershell

wsl --install
wsl --set-default-version 2

Используйте код с осторожностью.

Перезагрузите ПК. В терминале Ubuntu задайте логин и пароль.

1.2. Выделение системных ресурсов (Защита от Out Of Memory)

  1. В Windows нажмите Win + R, введите %USERPROFILE% и нажмите Enter.
  2. Создайте файл .wslconfig и вставьте параметры:

ini

[wsl2]
memory=16GB
swap=8GB
localhostForwarding=true

Используйте код с осторожностью.

  1. Перезапустите WSL в PowerShell: wsl --shutdown

1.3. Инсталляция NVIDIA Container Toolkit (Проброс графического ядра)

Запустите терминал Ubuntu в WSL2:

bash

sudo apt-get update && sudo apt-get install -y ca-certificates curl gnupg2

# Скачивание официального GPG-ключа
curl -fsSL https://github.io | sudo gpg --dearmor --yes -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

# Добавление официального репозитория пакетов
curl -s -L https://github.io | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit

Используйте код с осторожностью.

Проверить сопряжение: команда nvidia-smi должна вывести таблицу с вашей RTX 3060 Ti.


ЧАСТЬ 2. Установка Ollama и Локальный Запуск

2.1. Установка движка и скачивание модели (в терминале WSL2)

bash

curl -fsSL https://ollama.com | sh
ollama pull llama3.1

Используйте код с осторожностью.

2.2. Фоновый запуск сервера Ollama в WSL2

bash

ollama serve > /dev/null 2>&1 &

Используйте код с осторожностью.

(Нажмите Enter, если терминал временно застынет. Проверить доступность: ollama list).


ЧАСТЬ 3. Автоматизированная генерация ShareGPT-датасета

3.1. Подготовка папок и Python

В Windows скопируйте все 71 технический PDF-мануал в папку C:\ST\aandc\manuals\.
В терминале WSL2 установите библиотеки (обход защиты PEP 668):

bash

pip3 install pypdf requests --break-system-packages

Используйте код с осторожностью.

3.2. Создание интеллектуального генератора generate_qa.py

Создайте файл /mnt/c/ST/aandc/generate_qa.py:

python

import os, re, json, pypdf, requests

MODEL_NAME = "llama3.1:latest"
OLLAMA_URL = "http://localhost:11434/api/generate"
MANUALS_DIR = "/mnt/c/ST/aandc/manuals"
OUTPUT_FILE = "/mnt/c/ST/aandc/aandc_dataset.jsonl"
WINDOW_SIZE = 3

SYSTEM_PROMPT = (
    "Вы — опытный technical writer и эксперт по банкоматному ПО.\n"
    "Изучите предоставленный текст. Создайте от 2 до 4 высококачественных пар 'Вопрос-Ответ'.\n"
    "Ответы должны быть глубокими, технически точными, без упоминания номеров страниц.\n"
    "Формат ответа строго JSON: [{\"conversations\": [{\"from\": \"human\", \"value\": \"Вопрос\"}, {\"from\": \"gpt\", \"value\": \"Ответ\"}]}]"
)

def clean_text(text):
    text = re.sub(r'Page \d+ of \d+', '', text, flags=re.IGNORECASE)
    text = re.sub(r'^\d+\s*$', '', text, flags=re.MULTILINE)
    return re.sub(r'\n+', '\n', text).strip()

def extract_pdf_chunks(pdf_path, window_size=3):
    try:
        with open(pdf_path, 'rb') as f:
            reader = pypdf.PdfReader(f)
            for i in range(0, len(reader.pages), window_size):
                chunk_text = "".join([reader.pages[j].extract_text() or "" for j in range(i, min(i + window_size, len(reader.pages)))])
                cleaned = clean_text(chunk_text)
                if len(cleaned) > 100: yield cleaned
    except Exception as e: print(f"Ошибка чтения {os.path.basename(pdf_path)}: {e}")

def ask_ollama(context):
    payload = {"model": MODEL_NAME, "prompt": f"ДОКУМЕНТАЦИЯ:\n{context}\n\nСгенерируй JSON.", "system": SYSTEM_PROMPT, "stream": False, "format": "json"}
    try:
        response = requests.post(OLLAMA_URL, json=payload)
        if response.status_code == 200: return response.json().get("response", "")
    except: pass
    return None

def main():
    pdf_files = [f for f in os.listdir(MANUALS_DIR) if f.lower().endswith('.pdf')]
    print(f"Найдено файлов: {len(pdf_files)}. Старт генерации...")
    
    with open(OUTPUT_FILE, 'w', encoding='utf-8') as outfile:
        for idx, pdf_name in enumerate(pdf_files, 1):
            print(f"[{idx}/{len(pdf_files)}] Обработка: {pdf_name}")
            for chunk in extract_pdf_chunks(os.path.join(MANUALS_DIR, pdf_name), WINDOW_SIZE):
                raw_json = ask_ollama(chunk)
                if not raw_json: continue
                try:
                    data = json.loads(raw_json)
                    # Всеядный парсер: обрабатывает и массивы, и прямые словари
                    items = data if isinstance(data, list) else [data] if isinstance(data, dict) and "conversations" in data else data.values() if isinstance(data, dict) else []
                    for item in items:
                        if isinstance(item, dict) and "conversations" in item:
                            outfile.write(json.dumps(item, ensure_ascii=False) + "\n")
                            outfile.flush()
                except: continue
    print("Датасет успешно сохранен!")

if __name__ == "__main__": main()

Используйте код с осторожностью.

Запуск: python3 /mnt/c/ST/aandc/generate_qa.py. Сформируется чистый файл aandc_dataset.jsonl на 756 диалогов.


ЧАСТЬ 4. Индустриальный Fine-Tuning на 8 ГБ VRAM

Для обхода аппаратных ограничений памяти Triton-ядер мы используем чистый, надежный стек Hugging Face (peft + bitsandbytes + transformers) в режиме 4-битного квантования.

4.1. Установка стабильного окружения

bash

pip install torch torchvision torchaudio --index-url https://pytorch.org --break-system-packages
pip install transformers datasets peft bitsandbytes trl --break-system-packages

Используйте код с осторожностью.

4.2. Развертывание «железного» скрипта обучения train.py

Создайте файл /mnt/c/ST/aandc/train.py (выполняется прямо сейчас):

python

import os, json, torch
from datasets import Dataset
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments, Trainer, DataCollatorForLanguageModeling
from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training

MODEL_NAME = "unsloth/llama-3.1-8b-Instruct-bnb-4bit"
max_seq_length = 512  # Идеальный размер контекста для защиты 8 ГБ VRAM от пиков
DATASET_PATH = "/mnt/c/ST/aandc/aandc_dataset.jsonl"

torch.cuda.empty_cache()

print("--- 1. Конфигурация 4-бит NF4 ---")
bnb_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.float16, bnb_4bit_use_double_quant=True)

print("--- 2. Загрузка модели через HF ---")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
tokenizer.pad_token = tokenizer.eos_token
model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, quantization_config=bnb_config, device_map="auto")
model = prepare_model_for_kbit_training(model)

print("--- 3. Настройка LoRA параметров ---")
peft_config = LoraConfig(r=16, lora_alpha=16, target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], lora_dropout=0.05, bias="none", task_type="CAUSAL_LM")
model = get_peft_model(model, peft_config)

print("--- 4. Валидация и Токенизация датасета ---")
valid_dialogues = []
with open(DATASET_PATH, "r", encoding="utf-8") as f:
    for line in f:
        if not line.strip(): continue
        try:
            item = json.loads(line)
            if "conversations" in item and isinstance(item["conversations"], list):
                valid_dialogues.append({"conversations": item["conversations"]})
        except: continue

dataset = Dataset.from_list(valid_dialogues)

def tokenize_prompts_func(examples):
    tokenized_inputs = {"input_ids": [], "attention_mask": []}
    for con in examples["conversations"]:
        mapped = [{"role": "user" if m["from"] == "human" else "assistant", "content": m["value"]} for m in con]
        text = tokenizer.apply_chat_template(mapped, tokenize=False, add_generation_prompt=False)
        tokenized = tokenizer(text, truncation=True, max_length=max_seq_length, padding=False)
        tokenized_inputs["input_ids"].append(tokenized["input_ids"])
        tokenized_inputs["attention_mask"].append(tokenized["attention_mask"])
    return tokenized_inputs

dataset = dataset.map(tokenize_prompts_func, batched=True, remove_columns=["conversations"])

print("--- 5. Запуск неубиваемого Trainer ---")
trainer = Trainer(
    model=model, train_dataset=dataset,
    data_collator=DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False),
    args=TrainingArguments(
        per_device_train_batch_size=1, gradient_accumulation_steps=8,
        warmup_steps=5, max_steps=60, learning_rate=2e-4, fp16=True, logging_steps=1,
        optim="adamw_8bit", weight_decay=0.01, lr_scheduler_type="linear",
        seed=3407, output_dir="outputs", remove_unused_columns=False
    ),
)
trainer.train()
print("--- ТРЕНИРОВКА УСПЕШНО ЗАВЕРШЕНА ---")

model.save_pretrained("/mnt/c/ST/aandc/aandc_lora_model")
tokenizer.save_pretrained("/mnt/c/ST/aandc/aandc_lora_model")
print("Адаптеры сохранены!")

Используйте код с осторожностью.

Запуск: выгрузите Ollama (pkill -f ollama) для очистки VRAM и введите python3 /mnt/c/ST/aandc/train.py.


ЧАСТЬ 5. Экспорт адаптеров и Сборка модели для Ollama

После завершения обучения у вас есть базовая модель и папка обученных LoRA-адаптеров aandc_lora_model. Переведём их в единый формат .gguf.

5.1. Скачивание утилиты конвертации llama.cpp

bash

cd /mnt/c/ST/aandc/
git clone https://github.com
pip3 install -r llama.cpp/requirements.txt --break-system-packages

Используйте код с осторожностью.

5.2. Слияние и Квантование (Merge & Quantize)

Мы берем обученные веса LoRA и упаковываем их в единый 4-битный файл, который мгновенно зачитает любая система:

bash

# Конвертируем веса адаптеров LoRA в формат GGUF
python3 llama.cpp/convert_hf_to_gguf.py /mnt/c/ST/aandc/aandc_lora_model/ --outfile atm_expert_q4.gguf

Используйте код с осторожностью.

5.3. Настройка Modelfile

Создайте текстовый файл /mnt/c/ST/aandc/Modelfile:

dockerfile

FROM ./atm_expert_q4.gguf

TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|>

{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>

{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>

{{ .Response }}<|eot_id|>"""

SYSTEM "Вы — специализированный локальный ИИ-эксперт по банкоматному ПО. Вы отвечаете строго на основе технической документации, без «каши», четко, структурированно, используя инженерные термины."

Используйте код с осторожностью.

5.4. Регистрация Эксперта

bash

# Поднимаем сервер заново
ollama serve > /dev/null 2>&1 &

# Регистрируем финальную модель
ollama create atm_expert -f /mnt/c/ST/aandc/Modelfile

Используйте код с осторожностью.

Проверка работоспособности: ollama run atm_expert.


ЧАСТЬ 6. Автономный перенос модели на другой ПК

Благодаря архитектуре .gguf, готовый эксперт полностью автономен и не требует CUDA, Python или Linux на целевом ПК.

  1. Копирование: Заберите с флешки два файла: atm_expert_q4.gguf и Modelfile.
  2. Установка Ollama: На целевом ПК (Windows, Mac или Linux) поставьте чистую Ollama с официального сайта ollama.com.
  3. Импорт: Положите файлы в любую папку (например, C:\ATM_AI\), откройте командную строку Windows (cmd/PowerShell) в этой папке и выполните:

bash

cd C:\ATM_AI\
ollama create atm_expert -f Modelfile

Используйте код с осторожностью.

  1. Работа: Модель готова к эксплуатации без интернета по команде ollama run atm_expert.