Views
No views yet
Looking for GGUF quantizations for llama.cpp, LM Studio, or other GGUF-compatible runtimesCheck : 👉Qwen3-VL-8B-Contracts-OCR-GGUF
Image(page_i)
Image(page_i+1)
Target JSONPage1 + Page2 -> JSON
Page2 + Page3 -> JSON
Page3 + Page4 -> JSON
...| Parameter | Value |
|---|---|
| LoRA Rank | 16 |
| LoRA Alpha | 32 |
| Dropout | 0 |
| Epochs | 4 |
| Learning Rate | 2e-4 |
| Optimizer | AdamW 8-bit |
| Scheduler | Cosine |
| Warmup Ratio | 0.05 |
| Effective Batch Size | 8 |
| Max Sequence Length | 4096 |
1{
2 "company_name": "",
3 "company_address": "",
4 "company_type": "",
5 "law_reference": {
6 "law_number": "",
7 "law_year": ""
8 },
9 "company_capital": "",
10 "commercial_register_number": "",
11 "approval_date": "",
12 "real_estate_registry_minutes_number": "",
13 "company_duration": "",
14 "company_activity": "",
15 "articles": [
16 {
17 "id": "",
18 "value": ""
19 }
20 ,...
21 ]
22}1import gc
2import json
3import torch
4from unsloth import FastVisionModel
5from qwen_vl_utils import process_vision_info
6from PIL import Image
7
8model, tokenizer = FastVisionModel.from_pretrained(
9 "a-mo-yehia/contract_OCR_model",
10 load_in_4bit=False,
11)
12
13FastVisionModel.for_inference(model)
14
15img1 = Image.open("page1.jpg").convert("RGB")
16img2 = Image.open("page2.jpg").convert("RGB")
17
18SYSTEM_PROMPT = """\
19أنت نظام استخراج بيانات من عقود تأسيس شركات مصرية مسحوبة ضوئياً.
20
21الوثيقة أمامك هي صفحتان من عقد تأسيس شركة مصرية مكتوبة بالعربية.
22
23─── بنية المستند ───
24- يبدأ العقد بديباجة (تمهيد) تذكر القانون المنظِّم للشركة.
25- تأتي بعدها مواد مرقّمة (مادة ١، مادة ٢، ...) تحتوي على كل التفاصيل.
26- اسم الشركة ونوعها: عادةً في المواد الأولى (١–٣).
27- غرض الشركة ونشاطها: في مادة الغرض (المادة ٣ أو ٤ غالباً).
28- العنوان: في المادة التي تذكر "المركز الرئيسي".
29- رأس المال وتوزيعه بين الشركاء: في مادة واحدة تحتوي عادةً على جدول.
30- مدة الشركة: في المادة التي تذكر السنوات أو الأجل.
31- رقم القانون: في التمهيد أو أوائل المواد، صيغته "القانون رقم XXX لسنة XXXX".
32
33─── قواعد الاستخراج ───
34- انسخ كل نص عربي حرفياً كما يظهر في الصورة — لا تصحّح ولا تُعيد صياغة.
35- إذا كانت مادة ممتدة وانتهت الصفحة قبل اكتمالها: "partial": true.
36- إذا لم يوجد حقل في الصفحتين: اتركه سلسلة فارغة "".
37- إذا لم تكن هناك مواد في الصفحتين: أرجع "articles": [].
38- إذا احتوت الوثيقة على أي جداول، **يجب** استخراجها كاملة وتنسيقها حصرياً بصيغة Markdown (MD).
39- يمنع منعاً باتاً تجاهل أي بيانات مجدولة أو دمجها كنص عادي.
40- أرجع JSON صحيح فقط — بدون markdown، بدون شرح، بدون مفاتيح إضافية.\
41"""
42
43
44def run_inference(img1: Image.Image, img2: Image.Image, file_id: str, page_start: int) -> str:
45 gc.collect()
46 torch.cuda.empty_cache()
47
48 messages = [
49 {"role": "system", "content": SYSTEM_PROMPT},
50 {"role": "user", "content": [
51 {"type": "image", "image": img1},
52 {"type": "image", "image": img2},
53 {"type": "text", "text": (
54 f"استخرج جميع البيانات من الصفحتين "
55 f"من عقد {file_id} وأرجعها كـ JSON كامل."
56 )},
57 ]},
58 ]
59
60 input_text = tokenizer.apply_chat_template(messages, add_generation_prompt=True)
61 image_inputs, _ = process_vision_info(messages)
62
63 inputs = tokenizer(
64 image_inputs,
65 input_text,
66 add_special_tokens=False,
67 return_tensors="pt",
68 ).to("cuda")
69
70 with torch.no_grad():
71 out = model.generate(
72 **inputs,
73 max_new_tokens=4096,
74 use_cache=True,
75 do_sample=False,
76 repetition_penalty=1.1,
77 )
78
79 generated = tokenizer.decode(
80 out[0, inputs["input_ids"].shape[-1]:],
81 skip_special_tokens=True,
82 ).strip()
83
84 return generated
85
86raw_output = run_inference(img1, img2, FILE_ID, PAGE_START)
87
88print("\n=== Raw Output ===")
89print(raw_output)