Em sistemas de inteligência artificial multimodal, como o MiniCPM-o-4.5-nvidia-FlagOS, a visualização detalhada de imagens é crucial para uma análise eficiente. Limitações na interface padrão, como imagens pequenas ou fixas, podem prejudicar a interação do usuário. Este guia demosntra como integrar uma funcionalidade de zoom em imagens utilizando Gradio Blocks, aprimorando significativamente a experiência do usuário.
Motivação para Adicionar Zoom em Imagens
Em cenários onde o usuário precisa examinar detalhes específicos em uma imagem enviada, como texto pequeno ou elementos gráficos complexos, a capacidade de ampliar e navegar na imagem torna-se essencial. Com uma interface baseada em Gradio Blockss, é possível incorporar componentes interativos que permitem zoom, arastar e visualização em tela cheia, tornando a análise de imagens mais intuitiva e eficaz.
Reestruturação da Interface com Gradio Blocks
O ponto de partida é substituir o uso simplificado de gr.ChatInterface por uma estrutura modular com gr.Blocks. Isso oferece controle total sobre o layout e a adição de componentes personalizados. A seguir, um exemplo de como configurar a interface básica:
import gradio as gr
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
# Carregamento do modelo e tokenizador
model_path = "/root/ai-models/FlagRelease/MiniCPM-o-4___5-nvidia-FlagOS"
ai_model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.bfloat16, device_map="auto", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
def process_multimodal_input(user_query, conversation_history, uploaded_image):
"""Processa a entrada do usuário e gera uma resposta."""
if uploaded_image is None:
input_tokens = tokenizer(user_query, return_tensors="pt").to(ai_model.device)
else:
# Lógica multimodal específica do modelo (exemplo simplificado)
input_tokens = tokenizer(f"[Imagem processada] {user_query}", return_tensors="pt").to(ai_model.device)
with torch.no_grad():
generated_output = ai_model.generate(**input_tokens, max_new_tokens=512)
response = tokenizer.decode(generated_output[0], skip_special_tokens=True)
conversation_history.append((user_query, response))
return "", conversation_history, None
with gr.Blocks(title="Assistente Multimodal MiniCPM-o", theme=gr.themes.Soft()) as demo:
gr.Markdown("# Assistente de IA com Visualização de Imagens Aprimorada")
with gr.Row():
with gr.Column(scale=2):
chat_display = gr.Chatbot(height=400, label="Histórico da Conversa")
input_query = gr.Textbox(label="Digite sua pergunta", placeholder="Faça uma pergunta sobre a imagem...")
with gr.Row():
send_button = gr.Button("Enviar", variant="primary")
clear_button = gr.Button("Limpar Conversa")
with gr.Column(scale=1):
image_upload = gr.Image(type="pil", label="Carregar Imagem", height=200, elem_id="input_image")
zoom_preview = gr.HTML(label="Visualização com Zoom", elem_id="zoom_container")
gr.Markdown("*Use o scroll do mouse para zoom e arraste para navegar.*")
send_button.click(process_multimodal_input, inputs=[input_query, chat_display, image_upload], outputs=[input_query, chat_display, zoom_preview])
clear_button.click(lambda: ([], None, ""), outputs=[chat_display, image_upload, zoom_preview])
Integrando Componente de Zoom com Viewer.js
Para habilitar o zoom interativo, utilizamos a biblioteca JavaScript Viewer.js através de um componente gr.HTML. A imagem carregada é convertida para Base64 e incorporada em HTML, permitindo que o Viewer.js forneça funcionalidades avançadas de visualização. Ajuste a função de processamento para atualizar a visualização:
import io
import base64
def update_zoom_view(image):
if image is None:
return gr.HTML.update(value="<div style='padding:40px; text-align:center;'>Nenhuma imagem carregada</div>")
# Converter imagem para Base64
buffered = io.BytesIO()
image.save(buffered, format="PNG")
encoded_image = base64.b64encode(buffered.getvalue()).decode()
image_data_uri = f"data:image/png;base64,{encoded_image}"
# Gerar HTML com Viewer.js
html_content = f"""
<div id="zoom_view">
<img src="{image_data_uri}" style="max-width:100%; cursor:zoom-in;" alt="Imagem para zoom">
</div>
<script>
function initViewer() {{
const imgElement = document.querySelector('#zoom_view img');
if (imgElement && typeof Viewer !== 'undefined') {{
if (window.viewerInstance) window.viewerInstance.destroy();
window.viewerInstance = new Viewer(imgElement, {{
toolbar: {{
zoomIn: true,
zoomOut: true,
reset: true
}},
navbar: false
}});
}}
}}
setTimeout(initViewer, 100);
</script>
"""
return html_content
# Atualizar eventos para incluir zoom
image_upload.change(update_zoom_view, inputs=image_upload, outputs=zoom_preview)
send_button.click(lambda q, h, i: (process_multimodal_input(q, h, i)[0], process_multimodal_input(q, h, i)[1], update_zoom_view(i)), inputs=[input_query, chat_display, image_upload], outputs=[input_query, chat_display, zoom_preview])
Otimizações e Considerações
Para melhorar o desempenho, considere armazenar imagens em cache ou usar caminhos temporários em vez de codificação Base64 recorrente. Além disso, gerencie instâncias do Viewer.js para evitar conflitos em atualizações dinâmicas. Certifique-se de adaptar a lógica de processamento do modelo de acordo com a API específica do MiniCPM-o, integrando corretamente os recursos multimodais.
Esta abordagem pode ser estendida para outras aplicações baseadas em Gradio que necessitam de visualização detalhada de imagens, proporcionando uma interface mais interativa e profissional.