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

370 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Обновленная версия, Не проверена
- **Платформа:** 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
```
Используйте код с осторожностью.
3. Перезапустите 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
```
Используйте код с осторожностью.
4. **Работа:** Модель готова к эксплуатации без интернета по команде `ollama run atm_expert`.
---