Recentemente, em um projeto de TI nativo, encontramos um desafio significativo: o cliente precisava implantar um serviço de IA capaz de interpretar imagens de documentos em servidores com sistema operacional nacional Kylin e CPU Hygon. Embora a necessidade parecesse simples, sua execução trouxe inúmeras dificuldades.
A exigência do cliente era clara: possuíam uma grande quantidade de relatórios PDF, demonstrações financeiras e documentos digitalizados, necessitando que a IA extraísse automaticamente textos, tabelas e até respondesse perguntas sobre o conteúdo dos documentos. Embora existissem diversos modelos de compreensão documental no mercado, muitos exigiam hardware avançado (especialmente GPUs) ou eram incompatíveis com ambientes nativos, apresentando falhas na instalação de dependências e na execução.
Testamos diversas soluções, mas muitas eram lentas demais com CPUs Hygon durante a inferência, ou possuíam arquiteturas incompatíveis com a versão mais antiga da biblioteca glibc do sistema Kylin. Ao ponto de quase desistir, descobrimos o projeto MinerU, um modelo otimizado de 1.2B parâmetros para cenários documentais, que prometia alta performance mesmo em CPUs.
Contudo, o desafio permanecia: as diretrizes oficiais de implantação visavam arquiteturas x86. Como adaptá-lo ao ambiente Hygon e Kylin? Este artigo compartilha nossa experiência prática.
- Vantagens do Modelo MinerU
2.1 Por que escolher um modelo de 1.2B?
Em um cenário dominado por modelos de dezenas ou centenas de bilhões de parâmetros, a escolha por um modelo menor apresenta justificativas práticas:
Custo de implantação: Modelos grandes requerem GPUs, mas muitos ambientes nativos dispõem apenas de CPUs. O MinerU-1.2B, otimizado para CPU, processa uma página A4 em 1-2 segundos, viável para operações reais.
Precisão direcionada: Diferente de modelos gerais, o MinerU foi treinado especificamente para compreensão documental. Sua acurácia em tabelas, fórmulas e layouts complexos supera a de modelos generalistas.
Consumo de recursos: O modelo ocupa apenas centenas de MB em disco e pouca memória, ideal para servidores com recursos limitados.
2.2 Funcionalidades do Modelo
O MinerU funciona como um "tradutor de documentos", capaz de extrair e compreender conteúdo a partir de imagens:
- Extração de texto: Preserva a estrutura original dos parágrafos.
- Reconhecimento de tabelas: Identifica bordas e relações entre células.
- Resumo de conteúdo: Fornece sínteses textuais sob consulta.
- Diálogo por perguntas: Localiza informações específicas no documento.
- Análise de layout: Distingue títulos, corpo de texto e legendas.
O modelo demonstra suporte robusto a documentos em chinês, incluindo textos verticais, em caracteres tradicionais e digitalizações com selos.
- Prática de Adaptação ao Ambiente Nativo
3.1 Preparação do Ambiente e Verificação de Dependências
A adaptação começa com o diagnóstico do ambiente. No Kylin OS, encontramos problemas típicos:
- Conflitos de glibc: Evitamos atualizar a biblioteca do sistema, optando por soluções com menor exigência de versão.
- Diferenças no conjunto de instruções: Durante a compilação, removemos flags de otimização específicas para CPUs Hygon.
- Falta de bibliotecas: Recorremos a compilação manual ou alternativas quando pacotes ausentes.
Nossa lista de verificação inicial:
# Verificação do sistema
uname -a
cat /etc/os-release
lscpu | grep -i "model name"
# Verificação de bibliotecas
ldd --version
python3 --version
pip3 --version
# Teste de conectividade
curl -I https://pypi.org
3.2 Guia de Implantação por Etapas
3.2.1 Configuração do Ambiente Base
Recomendamos criar um ambiente Python isolado com Miniconda:
# Download e instalação do Miniconda
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda3
/opt/miniconda3/bin/conda init
# Criação de ambiente dedicado
conda create -n mineru_env python=3.9 -y
conda activate mineru_env
3.2.2 Instalação de Dependências
Instale os pacotes necessários com fontes aceleradas:
pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install torch==1.13.1 torchvision==0.14.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
# Se falhar, tente a versão CPU
pip install torch==1.13.1+cpu torchvision==0.14.1+cpu -f https://download.pytorch.org/whl/torch_stable.html
pip install transformers==4.35.0
pip install Pillow opencv-python-headless
Em caso de erros, considere reduzir versões ou compilar a partir do código-fonte.
3.2.3 Download e Configuração do Modelo
Método 1: Download direto (com boa conectividade)
from transformers import AutoModel, AutoTokenizer
model_name = "OpenDataLab/MinerU2.5-2509-1.2B"
model = AutoModel.from_pretrained(model_name, trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
Método 2: Implantação offline
# Em máquina com internet
python -c "
from transformers import AutoModel, AutoTokenizer
model_name = 'OpenDataLab/MinerU2.5-2509-1.2B'
save_dir = './local_mineru'
model = AutoModel.from_pretrained(model_name, trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
model.save_pretrained(save_dir)
tokenizer.save_pretrained(save_dir)
"
tar -czf mineru_offline.tar.gz local_mineru/
No servidor nativo, carregue a partir do caminho local:
model = AutoModel.from_pretrained("./local_mineru", trust_remote_code=True)
tokenizer = AutoTokenizer.from_pretrained("./local_mineru", trust_remote_code=True)
3.3 Integração com Serviço Web
Implementamos um serviço Flask simples para acesso via navegador:
from flask import Flask, request, jsonify
from PIL import Image
import io
import torch
app = Flask(__name__)
loaded_model = None
loaded_tokenizer = None
def init_model():
global loaded_model, loaded_tokenizer
if loaded_model is None:
from transformers import AutoModel, AutoTokenizer
loaded_model = AutoModel.from_pretrained("./local_mineru", trust_remote_code=True)
loaded_tokenizer = AutoTokenizer.from_pretrained("./local_mineru", trust_remote_code=True)
loaded_model.eval()
@app.route('/process', methods=['POST'])
def handle_request():
init_model()
img_file = request.files.get('doc_image')
query = request.form.get('query', 'Extract text content')
if not img_file:
return jsonify({"status": "error", "message": "No image provided"}), 400
try:
image_data = Image.open(io.BytesIO(img_file.read())).convert('RGB')
inputs = loaded_tokenizer(images=image_data, text=query, return_tensors="pt")
with torch.no_grad():
output_tokens = loaded_model.generate(**inputs, max_length=512)
response_text = loaded_tokenizer.decode(output_tokens[0], skip_special_tokens=True)
return jsonify({"status": "success", "query": query, "result": response_text})
except Exception as ex:
return jsonify({"status": "error", "message": str(ex)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
- Otimização de Desempenho e Implantação em Produção
4.1 Técnicas de Otimização para CPU
Para melhorar a performance em CPUs Hygon:
1. Configuração de threads
import os
os.environ['OMP_NUM_THREADS'] = '4'
os.environ['MKL_NUM_THREADS'] = '4'
import torch
torch.set_num_threads(4)
2. Processamento em lote
def process_batch(images_list, queries_list):
inputs = loaded_tokenizer(
images=images_list,
text=queries_list,
padding=True,
return_tensors="pt"
)
with torch.no_grad():
outputs = loaded_model.generate(**inputs, max_length=512)
return [loaded_tokenizer.decode(o, skip_special_tokens=True) for o in outputs]
3. Quantização do modelo
import torch.quantization
quantized_model = torch.quantization.quantize_dynamic(
loaded_model,
{torch.nn.Linear},
dtype=torch.qint8
)
4.2 Recomendações para Ambiente de Produção
1. Containerização com Docker
FROM kylin:v10
RUN apt-get update && apt-get install -y python3 python3-pip libglib2.0-0
COPY ./local_mineru /app/model
COPY ./service.py /app/
WORKDIR /app
RUN pip3 install flask torch transformers Pillow
EXPOSE 8080
CMD ["python3", "service.py"]
2. Monitoramento e logs
import logging
logging.basicConfig(
filename='mineru_service.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
@app.before_request
def log_request():
logging.info(f"Request received: {request.method} {request.path}")
- Casos de Uso Práticos
5.1 Análise de Demonstrações Financeiras
Para extração automatizada de dados de relatórios em PDF:
- Converter PDFs para imagens.
- Consultar o serviço com perguntas como: "Qual a receita operacional?"
- Exportar os dados esrtuturados para planilhas.
Resultados: redução do tempo de processamento de 15-20 minutos para 1-2 minutos por relatório, com acurácia superior a 99% na extração numérica.
5.2 Revisão de Contratos
Identificação automatizada de cláusulas-chave mediante perguntas como: "Quais são as condições de pagamento?"
5.3 Sistema de Perguntas e Respostas sobre Documentação Técnica
Busca semântica em documentos digitalizados, permitindo consultas como: "Qual o procedimento de reinicialização do servidor?"
- Solução de Problemas Comuns
6.1 Vazamentos de Memória
O uso de blocos with para manipulação de imagens evita acúmulo de memória:
def safe_image_load(file_bytes):
with Image.open(io.BytesIO(file_bytes)) as img:
return img.convert('RGB').copy()
6.2 Gargalos de Concorrência
Implementação de pool de threads e timeout:
from concurrent.futures import ThreadPoolExecutor, TimeoutError
executor = ThreadPoolExecutor(max_workers=2)
@app.route('/async_process', methods=['POST'])
def async_handle():
future = executor.submit(process_single, request.files['image'], request.form['query'])
try:
result = future.result(timeout=30)
return jsonify(result)
except TimeoutError:
future.cancel()
return jsonify({"error": "Timeout"}), 504
6.3 Baixa Acurácia em Documenots de Qualidade Inferior
Pré-processamento com OpenCV para correção de iluminação e alinhamento:
import cv2
import numpy as np
def enhance_document_image(image):
arr = np.array(image)
gray = cv2.cvtColor(arr, cv2.COLOR_RGB2GRAY)
enhanced = cv2.equalizeHist(gray)
return Image.fromarray(enhanced)
- Conclusões e Recomendações
Esta experiência demonstra que modelos menores e especializados são viáveis em ambientes nativos, desde que se atente à otimização de CPU e à compatibilidade de dependências.
Recomendações para projetos semelhantes:
- Validar a viabilidade com um protótipo mínimo no ambiente-alvo.
- Manter alternativas com versões anteriores de bibliotecas.
- Investir em pré-processamento de dados de entrada.
- Implementar monitoramento robusto desde o início.
- Acompanhar atualizações do projeto MinerU para possíveis melhorias.
A implantação em ecossistemas nativos apresenta desafios únicos, mas com planejamento adequado, pode-se alcançar resultados funcionais e eficientes.