Ад файнцюнінгу да дакладнасці: як істотна скараціць галюцынацыі
Файнцюнінг разам з RAG супраць галюцынацый: чаму аднаго файнцюнінгу мала, архітэктура з Ollama і наколькі вырасла дакладнасць.
Крыніцы: From Fine-Tuning to Precision: Significantly Reducing Hallucinations in Your RAG Pipeline
У гэтым карыце парадоксальная дорага ад сыр'ёў да рабочай сістэмы для: «Ад тонкай наладкі да точнасці: значныя зменшэння галюцынацый у вашай паіплайне RAG». Акцэнт ставяцца на практычныя крокі, чыстае перакананне і код, які можна проста дадзіць у рэпозытарый без неабяснення меты.
1. Введэнне
У стадзіі 1 «Введэнне» неабяжна з'явіць вхідныя даны, адпаведальнага за крок і крытэрыя завершэння прычым перамене коду. Аперацыйныя працавнікі павінны магчымае перазапускаць крок з вядомай точкі контролю, не спрабоўваючы з'ясаваць схованы стан. Спрыятлівае ставленне да гэтай стадзіі як да кантракту межа вхіднымі данымі і перакананымі выходамі. Назваць всі элементы, з'явіць крытэрыя успеху і не падтрымваць тыхню частковую адработку. Паказаць тыя часткі тэксту, якія фактычна ляглі в основу адпаведнай адказы. Без цых цітатаў аперацыйныя працавнікі не зможуць адразліць галюцынацыю ад працявання індэксу.
You: What was the revenue from contracts with customers in 2024?
Assistant: The revenue was €179,058,000. ← Wrong! Correct answer is €159,088,000.
2. Чаму тонкая наладка?
Для этапы тонкай наладкі «2 Why» неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтыяры завершэння пры зміне коду. Аперацыйныя працавнікі павінны магчымае перазапускаць крок з вядомай точкі контролю, не прабуючы спадарожваць схованы стан. Запісвайце час выканання і кост токеноў або запытаў праза функцыйнае рэзультат. Відкрытыя даны пра косцы запобегаюць неспакоўным рахункам, калі працэс пераходзіць з дэмовай асяроддзя ў спакульную. Указвайце тыя часткі тэксту, якія фактычна ляглі в основу адпаведнай адказы. Без цых цітатаў аперацыйныя працавнікі не зможуць адразніць галюцынацыю ад прасоў у індэксаванні.
Рашэнне: тонкая наладкі з MLX
Для тонкай наладкі «Рашэння» паэтапам неабяжна ўзначыць вхідныя даны, адпаведальнага за кожны крок і крытэрыя завершэння пры зміне коду. Аператары должны магчыма ўвайсці крок з вядомага пункта контролю, не спрабоўваючы з’ясаваць схованы стан. Конфігурацыю трэба залічыць параду ад коду прыкладнення. Файлы сераўіса, хранільнікі секрэтных дадзеных і флагі функцыйяў должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць, не чытаяўшы весь ланцуг задач. Паказваць трэба тыя часткі тэксту, якія фактычна лежалі в основе адпаведнай адказу. Без цых цітатаў аператары не можаць розразліць галюцынацію ад прычыны, зв’язанай з недастаткам індэксацыі.
3. Дыяграма архітэктуры
Для этапы 3 «Архітэктурныя дыяграмы» неабходна прадзеўжэнне вхідных дадзеных, выявленне адпаведнага адпаведальнага за шаг і вызначэнне крэтарыяў завершэння працы перад зменым коду. Аперацыйныя працавнікі павінны магчымае запускаць шаг з вядомай точкі контролю, не падозрываючы прыхованы стан сістэмы. Неабходна аддзеўжэнне інструкцый як па шляху успеху, так і па шляху вярнення да нормальнага стану. Практыка павтарэння спроб, людзкія перакрыцця і обработка некорэктных паведамленняў ёсць часткай продукту, а не элементамі, якія дадаюцца пазней.
┌─────────────────────────────────────────────────────────────────────────────┐
│ PART 3: FINE-TUNING WORKFLOW (M1) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Dataset 2. MLX Fine-Tuning │
│ ┌──────────────────┐ ┌────────────────────────────────────────────┐ │
│ │ Chart Images │─────▶│ Base Model (Qwen2-VL-2B) │ │
│ │ Q&A Pairs │ │ + LoRA Adapters (mlx_vlm.lora) │ │
│ │ (train.jsonl) │ │ + Unified Memory Training on Apple Silicon│ │
│ └──────────────────┘ └────────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ Fine-Tuned LoRA Adapters │ │
│ │ (./fine_tuned_adapters/) │ │
│ └────────────────┬─────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ 3. Merge & Export to GGUF │ │
│ │ (mlx_vlm.fuse + convert_hf_to_gguf.py) │ │
│ └────────────────┬─────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ 4. Deploy with Ollama │ │
│ │ ollama create my-chart-model │ │
│ │ (text.gguf + mmproj.gguf) │ │
│ └────────────────┬─────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ 5. Update rag_engine.py │ │
│ │ │ │
│ │ VISION_MODEL = "my-chart-model" # ← Change ONE line │ │
│ │ TEXT_MODEL = "llama3.2:3b" # Unchanged │ │
│ │ │ │
│ │ ✔ Existing app.py (from Part 2) automatically uses the new model! │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
4. Падготовка набора дадзеных
Для 4-го этапа «Падрэблікаванне набора даных» неабяжна прадзефінаваць вхідныя даны, адпраўніка крока і крэтыяры завершэння пры змены коду. Аперацыйныя працавнікі павінны магчымае перзапускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест амаль неконтрольваных скрыптав. Калі крок не выйшае, прычына неудачы павінна вказываць на адзін конкрэтны аспект, а не на заплутаны ланцоўкі задач. Наводзіце тыя часткі тэксту, якія фактычна лежаць у падставе адпаведнай адказы. Без ціх цытатаў аперацыйныя працавнікі не зможуць адразніць галюцынацыю ад працягу праз прашчэпы ў індэксаванні. Для 4-го этапа «Падрэблікаванне набора даных» неабяжна прадзефінаваць вхідныя даны, адпраўніка крока і крэтыяры завершэння пры змены коду. Аперацыйныя працавнікі павінны магчымае перзапускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Запісвайце час выканання і кост токенаў або запытаў разам з функцыйнаімі рэзультатамі. Відразлівасць костаў з самага пачатку запобегае неспакойным рахункам, калі працэс пераходзіць з дэмавай версіі ў спяльную срэду.
Model sees: (Chart image)
Model reads: (Question)
Model learns: (Correct answer)
Ўраганы дасэткі
Калі працуеце з юраганамі дасэткі, спачатку запісайце умовы: неабяжлівыя даныя, сігнал успеху і тое, што выканаецца у разы частковага нявезення. Такі спіс дапамагае заліцьваць пазнейшыя змены ў кодзе. Зберагаюце настройкі праза код аплікацыі. Файлы сяродавішча, хранільнікі секрэтных дадзеных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаюць пераглядаць іх без неабяжлівага чытання всей структуры. Перад налашоўкай запытанняяў пераканаеццаеся ў рэкалі на фіксаванай групе запытанняяў. Частае змена запытанняяў рэдка калі вядомае слабую сістэму пошуку.
Падготовка дадзеных па шагам
Калі вы працуеце над этапам падготовкі даных па кроках, спачатку запісайце умовы контракту: неабяжлівыя даны, сігнал успеху і тое, што выканаецца у разе частковага невыпалення. Такі спіс контроля дапамагае заліцьварыць пазнейшыя змены ў кодзе. Документавайце як шлях успеху, так і шлях вярнення да стану нормы. Перапрыбуткі, людзкія перакрыцця і апрацоўка некорэктных паведамленняў ёсць часткай продукту, а не пазнейшым дапрацоўкам. Перад налаштаваннем запітаў пераканайцеся ў рэверыі на фіксаванай сэтке запітаў. Частыя змены запітоў рэдка калі вядуць да павышэння якосці выкарыстоўвання даных.
Step 1: Create Raw Dataset → chart_dataset/raw_train.jsonl
Step 2: Convert to MLX Format → chart_dataset/train.jsonl
Step 3: Verify Dataset → Check that train.jsonl exists
Шаг 1: Створыце необработаны набір даных
Калі працуеце над Крокам 1 «Стварыць стэйдж», спачатку запісайце умовы вікорыткі: неабяжлівыя даныя, сігнал успеху і тое, што выканаецца у разы частковага нявыпалення. Такі спіс пераканальвае залічваць пазнейшыя змены ў кодзе адпаведна. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок нявыпанаецца, прычына нявыпалення павінна вказваць на адзін конкрэтны аспект, а не на заплутаны ланцюг задач. Перад налаштаваннем запітоў пераканайцеся ў рэзультатах адпаведна да фіксованага набора запытанняў. Рэдкая змена запытоў выправляе слабкія аспекты адзысквання інформацыі. Калі працуеце над Крокам 1 «Стварыць стэйдж», спачатку запісайце умовы вікорыткі: неабяжлівыя даныя, сігнал успеху і тое, што выканаецца у разы частковага нявыпалення. Такі спіс пераканальвае залічваць пазнейшыя змены ў кодзе адпаведна. Запісвайце час выканення і кост токенаў або запытаў разам з функцыйнаімі рэзультатамі. Відразлівасць костаў з самага пачатку запобегае неспакойным рахункам, калі праця пераходзіць з дэмавайнага рэжыма ў спяльныя асяроддзя.
# download_chartqa.py
from datasets import load_dataset
import json
import os
os.makedirs("chart_dataset", exist_ok=True)
# Download ChartQA dataset
dataset = load_dataset("ahmed-masry/ChartQA", split="train")
# Convert to flat format with standard keys
converted = []
for item in dataset:
converted.append({
"image": item["imgname"], # Path to chart image
"question": item["query"],
"answer": item["label"]
})
# Save as raw dataset
with open("chart_dataset/raw_train.jsonl", "w") as f:
for entry in converted:
f.write(json.dumps(entry) + "\n")
print(f"✅ Converted {len(converted)} ChartQA samples to chart_dataset/raw_train.jsonl")
README.md: 100%|█████████████████████████████████████████████| 2.12k/2.12k [00:00<00:00, 3.72MB/s]
Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
data/train-00000-of-00003.parquet: downloading bytes: ████████████████████████| 213MB, 17.3MB/s
......
Generating test split: 100%|████████████████████████| 2500/2500 [00:00<00:00, 20517.87 examples/s]
✅ Converted 28299 ChartQA samples to raw_train.jsonl
Варыянт B: Створэнне сінтэтычных дадзейнаў
Этап стварэння сінтэтычных дадзейнаў у варыянце B работае наякша, калі яго расследжваць як мерыемую паверхню. Зафіксавайце адна ідэальная транскрыпцыю, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расшырваць масштабы. Зберагаюце настройкі паза кодам прыемліка. Файлы сяродавішча, хранільнікі секрэтных дадзейнаў і флагі функцый должны знаходзіцца ў аднам месцы, куды аператары можаць адбавляць контроль без неабяжнага чытання всіх дадзейнаў. Раздзеляйце правілы часткавання дадзейнаў ад правілаў ўзяць іх. Змена аднаго з яных не должна вымагаць перапісву другога, калі зменяюцца паказнікі якосці.
# generate_synthetic_data.py
import json
import matplotlib.pyplot as plt
import numpy as np
import os
os.makedirs("chart_dataset/images", exist_ok=True)
dataset = []
for i in range(100):
categories = ['Q1', 'Q2', 'Q3', 'Q4']
values = np.random.randint(100, 500, 4)
plt.figure()
plt.bar(categories, values)
plt.title(f"Quarterly Revenue {i}")
plt.savefig(f"chart_dataset/images/chart_{i:03d}.png")
plt.close()
dataset.append({
"image": f"images/chart_{i:03d}.png",
"question": "Which quarter had the highest revenue?",
"answer": f"Q{np.argmax(values) + 1} with ${max(values)} million"
})
with open("chart_dataset/raw_train.jsonl", "w") as f:
for entry in dataset:
f.write(json.dumps(entry) + "\n")
print("✅ Generated 100 synthetic samples in chart_dataset/raw_train.jsonl")
Крок 2: Канвертаванне у фармат MLX
Этап 2 – пераклад у стадыю – найэфектывней працуе, калі яго расследжваюць як вімерную плошчу. Зафіксавайце адна ідэальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расшырваць масштабы. Дакументавайце як успішны, так і вярнучыся шляхы. Перапрыбуткі, людзкія контраліны і обработка некорэктных паведамленняў ёсць часткай продукту, а не пасляднім дапрацоўкам. Раздзеліце політыку частакавання дадзеных ад політыкі ўзяць іх. Змена адной не должна прымусіваць перапісванне другой, калі зменяюцыся паказнікі якосці.
# convert_to_mlx_format.py
import json
import os
def convert_raw_to_mlx_format(data_dir="chart_dataset"):
"""
Convert raw dataset to MLX format.
Input: chart_dataset/raw_train.jsonl
Output: chart_dataset/train.jsonl (MLX-compatible)
"""
raw_file = os.path.join(data_dir, "raw_train.jsonl")
out_file = os.path.join(data_dir, "train.jsonl")
if not os.path.exists(raw_file):
print(f"❌ {raw_file} not found. Run download_chartqa.py or generate_synthetic_data.py first.")
return None
dataset = []
with open(raw_file, "r") as f:
for line in f:
item = json.loads(line)
# Build full image path
img_str = item["image"]
image_path = img_str if img_str.startswith(data_dir) else os.path.join(data_dir, img_str)
dataset.append({
"images": [image_path], # MUST be a list
"messages": [
{"role": "user", "content": item["question"]},
{"role": "assistant", "content": item["answer"]}
]
})
with open(out_file, "w") as f:
for entry in dataset:
f.write(json.dumps(entry) + "\n")
print(f"✅ Converted {len(dataset)} samples to {out_file}")
return dataset
if __name__ == "__main__":
convert_raw_to_mlx_format()
python convert_to_mlx_format.py
Этап 3: Пераканацца ў наборэ дадзеных
Шаг 3: Перакантролюванне працэй эфектываў, калі яго расследжаюць як вімерную паверхню. Запісаўце адна «золатая» транскрыпцыю, адын прыклад неудачы і прыметку па абратанні зялёных настройкаў пры расшырэнні масштаба. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі шаг не выйшаў, прычына неудачы павінна вказываць на адную адпаведальнасць, а не на заплутаны ланцоўкі задач. Раздзеляйце правілы частакавання дадзеных і правілы ўтрыманні іх. Змена адных не павінна вымагаць перапісву іншых, калі зменяюцыся паказатэлі якасці.
ls -la chart_dataset/
chart_dataset/
├── raw_train.jsonl # Raw Q&A pairs (flat keys)
├── train.jsonl # MLX-formatted (overwritten by prepare_mlx_dataset)
└── images/ # Chart images
📌 Important: Before running the fine-tuning command, ensure train.jsonl exists in your dataset directory.
If you see a FileNotFoundError, you haven't run the conversion step yet.
5. Тонкая наладка з MLX
Этап 5 «Тонкая наладка з дапамогай MLX» працюе найкрашча, калі яго розглядаць як вімерную паверхню. Зафіксавце адны ідэальны прыклад, адну справу з бягам і запіс пра вярнэнне да пачатковага стану, перш чым расшырваць масштабы. Разглядзіце гэты этап як кантракт межа вхіднымі данымі і паверынутымі выходнымі рэзультатамі. Даце назвы артыфактам, задаце крытэрыі успеху і не прабуйце прыймаць часткова завершаную працу без паведамлення. Раздзеліце правілы частковай апрацоўкі даных ад правіл яўлення інформацыі. Змена адных не должна вымагаць перапісву іншых, калі зменяюцца паказнікі якосці.
Прыямыя прычынкі
Этап пярэдушных абавязкаў работае наякрацей, калі яго спрыяваць як мерыемую плошчу. Зафіксавайце адны ідэальны прымер, адзін кейс неудачы і запіс пра абвяртанне перад расшырэнням масштаба. Запісвайце часы выканання і косты токеноў або запытаў па боку функцыйнаых рэзультатаў. Відразлівасць костаў з самага пачатку запобегае неспакойным рахункам, калі працэс пераходзіць з дэмаверсіі ў спяльныя асяроддзя. Раздзеліце політыку часткавага обрабоцкі і політыку выкарыстоўвання дадзеных. Змена адной з іх не павінна вымагаць перапісвання другой, калі зменяюцца паказнікі якосці.
# For fine-tuning vision models
pip install mlx-vlm
# For merging adapters (needed after training)
pip install mlx-lm
Адрабоўка параметраў
Этап тонкай наладкі працюе найэфектывней, калі яго розглядаць як вімерную паверхню. Зафіксавце адны ідэальны прыклад працы, адну справу з бягам і прыметкі па поверненню да пачатковага стану пры розшырэнні масштаба. Зберагачце настройкі пазырочна ад коду прыемліка. Файлы сераўіснага сераўісу, хранілішчы секрэтных даных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаць адбавляць аўдыт без неабяжнага чытання всіх дадзеных. Раздзеляйце правілы часткавага апрацоўкі дадзеных ад правіл абрання дадзеных. Змена ў одных не должна вымагаць перапісву іншых, калі зменяюцца паказнікі якосці.
python -m mlx_vlm.lora \
--model Qwen/Qwen2-VL-2B-Instruct \
--dataset ./chart_dataset/train.jsonl \
--iters 1000 \
--batch-size 1 \
--lora-rank 8 \
--gradient-accumulation-steps 4 \
--max-seq-length 512
Розумеўце выходныя даны трэніравання
Этап выхадзення рэзультаата трэнінгу разумеўнага адпаведання працюе найкрашча, калі яго спрыяваць як мерыемую паверхню. Запісаце адна ідэальная транскрыпцыя, адзін прыклад неудачы і прыметку па адвярненню перад расшырэнням масштаба. Дакументавайце як успішны, так і вярнучыся шляхы. Перапрыбуткі, людзкія контралі і обработка некорэктных паведамленняў ёсць часткай продукту, а не пасляднім дапрацоўкам. Раздзеліце політыку частакавання ад політыкі выкарыстоўвання. Змена адной не должна прымусіць перапісваў другойя, калі зменяюцыся паказнікі якосці.
INFO:__main__:Loading model from Qwen/Qwen2-VL-2B-Instruct
Fetching 11 files: 100%|████████████████████████████████████████| 11/11 [00:00<00:00, 1465.47it/s]
Download complete: : | 0.00B
Reconstruction complete: | | 0.00B / 0.00B
INFO:__main__:Loading dataset from ./chart_dataset/train.jsonl
INFO:__main__:Setting up LoRA
#trainable params: 9.232384 M || all params: 2208.9856 M || trainable%: 0.418%
INFO:__main__:Setting up optimizer
INFO:__main__:Training model (sft)
Starting training..., iterations: 1000
No validation dataset provided — training will run without validation.
......
Iter 120: Train loss 7.77592850, Learning Rate 2.000e-05,
It/sec 0.242, Tokens/sec 103.862, Trained Tokens 51480, Peak mem 8.069 GB
.....
Saved final adapter weights to adapters.safetensors.
INFO:__main__:Training completed! Model saved to adapters.safetensors
6. Рашэнне проблем
Этап адміністрування проблем карэйша, якга можна вымерыць. Зберагачыце адны ідэальны прыклад, адну справу з бягам і запіс пра вярнэнне да пачатковага стану, перш чым расшырваць масштабы. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, прычына бягу должна вказываць на адну конкрэтную адпаведнасць, а не на заплутаны ланцюг задач. Раздзеляйце правілы фрагментавання і правілы запошуку. Змена адных не должна вымагаць перапісву іншых, калі зменяюцца паказатэлі якосці.
Памылка: няма датасэту
Этап памылкі «Няма датасэту» карэйша, якга можна вымерыць. Зберагачыце адны ідэальны прыклад, адну справу з бягам і запіс пра вярнэнне да пачатковага стану, перш чым расшырваць масштабы.
FileNotFoundError: Couldn't find any data file at .../chart_dataset/train.jsonl
python convert_to_mlx_format.py
Памылка: не хватка памяці (OOM)
RuntimeError: [METAL] Command buffer execution failed: Insufficient Memory
python -m mlx_vlm.lora \
--model Qwen/Qwen2-VL-2B-Instruct \
--dataset ./chart_dataset/train.jsonl \
--iters 1000 \
--batch-size 1 \ # ← Reduced from 4 to 1
--lora-rank 4 \ # ← Reduced from 8 to 4
--gradient-accumulation-steps 8 \ # ← Added
--max-seq-length 256 # ← Added
Памылка: шлях адаптэра не знайдзены
FileNotFoundError: The adapter path does not exist: fine_tuned_adapters
ls -la adapters.safetensors adapter_config.json
python -m mlx_lm fuse \
--model Qwen/Qwen2-VL-2B-Instruct \
--adapter-path . \
--save-path ./fine_tuned_model_merged
Памылка: непূরны кэш
IncompleteSnapshotError: The cached snapshot for 'Qwen/Qwen2-VL-2B-Instruct' is incomplete
rm -rf ~/.cache/huggingface/hub/models--Qwen--Qwen2-VL-2B-Instruct
7. Скількі часу займе навчання?
Total Time (seconds) = Total Iterations ÷ It/sec
Total Time (minutes) = Total Time (seconds) ÷ 60
1000 ÷ 0.242 = 4,132 seconds
4,132 ÷ 60 = ~69 minutes
8. Адаптаванне адаптэраў LoRA
python -m mlx_lm fuse \
--model Qwen/Qwen2-VL-2B-Instruct \
--adapter-path . \
--save-path ./fine_tuned_model_merged
9. Экспорт у фармат GGUF для Ollama
Крок 1: Экспорт MLX у фармат Hugging Face
#!/usr/bin/env python3
import mlx_lm
from mlx_lm import load, save
model, tokenizer, config = load("./fine_tuned_model_merged")
save(model, tokenizer, config, "./hf_export")
print("✅ Exported to ./hf_export")
python export_to_hf.py
Крок 2: Канвертаванне у GGUF
# Clone llama.cpp (if not already done)
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
# Convert text model
python convert_hf_to_gguf.py ../hf_export \
--outfile chart_model-text.gguf \
--outtype f16
Крок 3: Канвертаванне праектара візуальных дадзеных
python convert_hf_to_gguf.py ../hf_export \
--outfile chart_model-mmproj.gguf \
--outtype f16 \
--mmproj
ls ~/.cache/huggingface/hub/models--Qwen--Qwen2-VL-2B-Instruct/snapshots/
# sample output . You'll see a hash directory (e.g., 895c3a49...)
# 895c3a49bc3fa70a340399125c650a463535e71c
cd llama.cpp
# replace <hash> with the output above (e.g., 895c3a49...)
python convert_hf_to_gguf.py ~/.cache/huggingface/hub/models--Qwen--Qwen2-VL-2B-Instruct/snapshots/<hash>/ \
--outfile base-mmproj.gguf \
--outtype f16 \
--mmproj
10. Размешчэнне з адказам Ollama
FROM ./chart_model-text.gguf
FROM ./chart_model-mmproj.gguf
PARAMETER temperature 0.2
Стварэнне мадэлі
ollama create my-chart-model -f Modelfile
Перакананне ў правільнасці мадэлі
ollama list
# output :
# NAME ID SIZE MODIFIED
# my-chart-model:latest b3fd6d8fd742 4.4 GB 7 hours ago
# qwen2.5vl:3b fb90415cde1e 3.2 GB 9 days ago
# llama3.2:3b a80c4f17acd5 2.0 GB 10 days ago
# llama3:latest 365c0bd3c000 4.7 GB 3 months ago
# You should see my-chart-model in the list.
Тэставанне мадэлі
ollama run my-chart-model "What is 2+2?"
11. Інтэграцыя ў вашу існуючую прыкладку RAG
# In rag_engine.py (from Parts 1 & 2)
# Before:
VISION_MODEL = "qwen2.5vl:3b"
# After:
VISION_MODEL = "my-chart-model" # Your fine-tuned model
TEXT_MODEL = "llama3.2:3b" # Unchanged
python app.py
12. Ацэнка: базовая мадэль проты налаштаванай
Порэвнянне
13. Вывык
Заўтрак цэлага коду
git clone https://github.com/froilan-sia/m1_multimodal_rag.git
cd m1_multimodal_rag