VOIDER commited on
Commit
591e59b
·
verified ·
1 Parent(s): 0a29690

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +133 -0
  2. requirements.txt +5 -0
app.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from llama_cpp import Llama
3
+ from huggingface_hub import hf_hub_download
4
+ import base64
5
+ import io
6
+ import re
7
+
8
+ # Настройки модели
9
+ REPO_ID = "mradermacher/VisualQuality-R1-7B-GGUF"
10
+ # Ищем файл с квантованием Q8 (наилучшее качество для CPU)
11
+ MODEL_FILENAME = "VisualQuality-R1-7B.Q8_0.gguf"
12
+
13
+ # Глобальная переменная для модели
14
+ llm = None
15
+
16
+ def load_model():
17
+ global llm
18
+ if llm is None:
19
+ print(f"Загрузка модели {MODEL_FILENAME}...")
20
+ try:
21
+ model_path = hf_hub_download(
22
+ repo_id=REPO_ID,
23
+ filename=MODEL_FILENAME
24
+ )
25
+ # n_ctx=8192 важно для обработки изображений (визуальные токены занимают место)
26
+ llm = Llama(
27
+ model_path=model_path,
28
+ n_ctx=8192, # Контекстное окно
29
+ n_gpu_layers=0, # 0 для CPU (бесплатный Space)
30
+ verbose=True,
31
+ chat_format="chatml-function-calling" # Обычно Qwen совместим с chatml
32
+ )
33
+ print("Модель успешно загружена!")
34
+ except Exception as e:
35
+ print(f"Ошибка загрузки: {e}")
36
+ raise e
37
+ return llm
38
+
39
+ def image_to_base64(image):
40
+ buffered = io.BytesIO()
41
+ image.save(buffered, format="JPEG")
42
+ return base64.b64encode(buffered.getvalue()).decode('utf-8')
43
+
44
+ def evaluate_image(image, progress=gr.Progress()):
45
+ if image is None:
46
+ return "Пожалуйста, загрузите изображение.", ""
47
+
48
+ # Инициализация модели (если еще не загружена)
49
+ model = load_model()
50
+
51
+ # Системный промпт из официального репозитория VisualQuality-R1
52
+ system_prompt = "You are doing the image quality assessment task."
53
+
54
+ # Формируем сообщение пользователя по шаблону авторов
55
+ # Модель обучена выдавать <answer>score</answer>
56
+ user_prompt_text = (
57
+ "What is your overall rating on the quality of this picture? "
58
+ "The rating should be a float between 1 and 5, rounded to two decimal places, "
59
+ "with 1 representing very poor quality and 5 representing excellent quality. "
60
+ "Please only output the final answer with only one score in <answer> </answer> tags."
61
+ )
62
+
63
+ # Конвертация изображения для Llama-cpp
64
+ base64_image = image_to_base64(image)
65
+ image_url = f"data:image/jpeg;base64,{base64_image}"
66
+
67
+ messages = [
68
+ {"role": "system", "content": system_prompt},
69
+ {
70
+ "role": "user",
71
+ "content": [
72
+ {"type": "image_url", "image_url": {"url": image_url}},
73
+ {"type": "text", "text": user_prompt_text}
74
+ ]
75
+ }
76
+ ]
77
+
78
+ # Стриминг генерации
79
+ full_response = ""
80
+ print("Начало генерации...")
81
+
82
+ stream = model.create_chat_completion(
83
+ messages=messages,
84
+ max_tokens=1024,
85
+ temperature=0.6, # Немного вариативности для рассуждений
86
+ stream=True
87
+ )
88
+
89
+ for chunk in stream:
90
+ if "choices" in chunk:
91
+ delta = chunk["choices"][0]["delta"]
92
+ if "content" in delta and delta["content"]:
93
+ content = delta["content"]
94
+ full_response += content
95
+ # Возвращаем накопленный текст для стриминга в UI
96
+ yield full_response, "Вычисляется..."
97
+
98
+ # Парсинг итоговой оценки
99
+ # Ищем текст внутри тегов <answer>...</answer>
100
+ score_match = re.search(r'<answer>\s*([\d\.]+)\s*</answer>', full_response)
101
+ final_score = "Не найдено"
102
+
103
+ if score_match:
104
+ final_score = score_match.group(1)
105
+
106
+ yield full_response, final_score
107
+
108
+ # Интерфейс Gradio
109
+ with gr.Blocks(title="VisualQuality-R1 (Q8 GGUF)") as demo:
110
+ gr.Markdown("# 👁️ VisualQuality-R1 (7B Q8)")
111
+ gr.Markdown(
112
+ "Оценка качества изображений с использованием рассуждений (Chain of Thought). "
113
+ "Запущено на CPU (бесплатный Space), поэтому генерация может занять время."
114
+ )
115
+
116
+ with gr.Row():
117
+ with gr.Column():
118
+ input_img = gr.Image(type="pil", label="Загрузите изображение")
119
+ run_btn = gr.Button("Оценить качество", variant="primary")
120
+
121
+ with gr.Column():
122
+ output_score = gr.Label(label="Итоговая оценка (для лидерборда)")
123
+ output_text = gr.Textbox(label="Ход мыслей (CoT) и полный ответ", lines=15, show_copy_button=True)
124
+
125
+ run_btn.click(
126
+ fn=evaluate_image,
127
+ inputs=[input_img],
128
+ outputs=[output_text, output_score]
129
+ )
130
+
131
+ # Запуск при старте контейнера, чтобы модель скачалась сразу
132
+ if __name__ == "__main__":
133
+ demo.queue().launch()
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ huggingface_hub>=0.20.0
3
+ llama-cpp-python>=0.3.2
4
+ Pillow
5
+ numpy