Views
No views yet


| Model Configuration | Evaluation Type | Mean Absolute Error (MAE) | Mean Absolute Percentage Error (MAPE) | Key Advantage |
|---|---|---|---|---|
| Qwen2.5-VL Fine-Tuned (Direct) | Native Inference | 0.718 g | 37.16% | Best Performance (No external DB queries required) |
| Qwen2.5-VL Fine-Tuned (RAG) | With Visual Anchors | 1.005 g | 45.06% | High consistency but slightly higher variance |
| Gemini 3.1 Flash (RAG Avg) | Center-of-Range RAG | 0.969 g | 46.32% | Requires expensive embedding & Pinecone query |
| Gemini 3.1 Flash (RAG Max) | Production RAG (Max) | 1.062 g | 51.42% | High bias towards upper-limit estimations |
| Qwen2.5-VL Base (Un-tuned) | Native Prompting | > 3.500 g | > 150.0% | Hallucinates abstract volumes; no density cohesion |
[!IMPORTANT] Key Finding: Fine-tuning the vision-language model directly on gold jewelry weights resulted in a 25.9% reduction in Mean Absolute Error (MAE) compared to the production-grade Gemini 3.1 Flash RAG system, while completely eliminating the need for vector database queries and CLIP embedding overhead during inference.
1import torch
2from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
3from peft import PeftModel
4
5# Base model and adapter paths
6base_model_name = "Qwen/Qwen2.5-VL-3B-Instruct"
7adapter_model_path = "princetunes/gold-weight-prediction-qwen2.5-vl"
8
9# 1. Load the processor and base model
10processor = AutoProcessor.from_pretrained(base_model_name)
11model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
12 base_model_name,
13 torch_dtype=torch.bfloat16,
14 device_map="auto"
15)
16
17# 2. Attach the fine-tuned LoRA adapters
18model = PeftModel.from_pretrained(model, adapter_model_path)1from PIL import Image
2import requests
3
4def predict_gold_weight(image_path, purity="18K", ring_size=6.0):
5 image = Image.open(image_path).convert("RGB")
6
7 # Prompt format used during fine-tuning
8 prompt = f"Analyze this jewelry ring design. Predict its 18K gold weight in grams for ring size {ring_size}."
9
10 # Prepare inputs using the standard Qwen2.5-VL format
11 messages = [
12 {
13 "role": "user",
14 "content": [
15 {"type": "image", "image": image},
16 {"type": "text", "text": prompt}
17 ]
18 }
19 ]
20
21 text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
22 image_inputs, video_inputs = processor.image_processor(images=image, videos=None, return_tensors="pt")
23
24 inputs = processor(
25 text=[text],
26 images=image,
27 padding=True,
28 return_tensors="pt"
29 ).to(model.device)
30
31 # Generate weight prediction
32 with torch.no_grad():
33 generated_ids = model.generate(**inputs, max_new_tokens=32)
34 generated_ids_trimmed = [
35 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
36 ]
37 output_text = processor.batch_decode(
38 generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
39 )[0]
40
41 return output_text
42
43# Example execution
44print(predict_gold_weight("ring_image.jpg", purity="18K", ring_size=7.0))r = 16, Alpha lora_alpha = 32, Target Modules: Causal LM projections)