Tech Blog

RTX 2070ノートだけで個人RAGをファインチューニングした話

LLM Fine-tuning QLoRA GPU AI RAG

RTX 2070ノートだけで個人RAGをファインチューニングした話

なぜローカルで完結させたかったか

my-rag-brainには個人の思考ログ、仕事の判断記録、気づいたことなどが全部入っている。これをクラウドのAPIに流すことに抵抗があった。

ローカルで動かしたかった。


Tiny-Criticとは何か

RAGシステムがChromaDBから取得したチャンクは、必ずしもクエリと関連しているとは限らない。距離が近くても、内容がズレていることがある。

Tiny-Criticは、取得済みのチャンクをもう一度「クエリと関係があるか/ないか」で二値判定する小さなモデルだ。無関係なチャンクを除去して、LLMに渡すコンテキストを絞り込む。


訓練データの作り方

手元のRAGログ(クエリとヒットチャンクのペア)から、ラベル付きデータを生成した。

# 2114件のペアを均衡化して 1036件(yes/no = 50:50)に
positives = [(q, chunk, 1) for q, chunk in relevant_pairs]
negatives = [(q, chunk, 0) for q, chunk in irrelevant_pairs]
balanced = positives[:518] + negatives[:518]

訓練データが偏っていると片側に収束する。均衡化は必須だった。


QLoRAで4bit量子化訓練

Qwen2.5-3B-Instructを4bit量子化してLoRAアダプタをかける構成にした。RTX 2070 Max-Qのメモリ(8GB)でも動く。

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16,
)
model = AutoModelForSequenceClassification.from_pretrained(
    "Qwen/Qwen2.5-3B-Instruct",
    quantization_config=bnb_config,
    num_labels=2,
)
model = get_peft_model(model, LoraConfig(
    r=8, lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05,
    bias="none",
))

結果

項目
訓練データ2114件 → 均衡化 1036件
訓練時間約1時間53分(RTX 2070 Max-Q)
最終loss1.454
token accuracy約76%(ピーク 約81%)

76%というのは完璧ではない。しかし「無関係なチャンクが混入しやすい」という問題に対して、コスト0で動くフィルタとして十分に機能している。


クラウドを使わなかった理由

訓練も推論も手元のGPUで完結している。個人ログはどこにも出ていかない。

これはセキュリティの話というより、自分のデータが自分の管理下にあるという感覚の問題だ。RAGシステムに何を入れるかの判断が、外部サービスの利用規約に縛られない。


関連する記事

気軽にメッセージください

仕事の依頼、案件紹介、ご感想・ご質問なんでもお待ちしております。 高い志をもった同士の皆様と繋がることを切に願っております。 これからも人生を掛けたチャレンジを続けていきます。 何卒よろしくお願い致します。