MinerU: Implantação de Modelo de Linguagem de Código Aberto em Ambientes de TI Nativos (Kylin OS + CPU Hygon)

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.

  1. 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.

  1. 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)
  1. 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}")
  1. Casos de Uso Práticos

5.1 Análise de Demonstrações Financeiras

Para extração automatizada de dados de relatórios em PDF:

  1. Converter PDFs para imagens.
  2. Consultar o serviço com perguntas como: "Qual a receita operacional?"
  3. 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?"

  1. 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)
  1. 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:

  1. Validar a viabilidade com um protótipo mínimo no ambiente-alvo.
  2. Manter alternativas com versões anteriores de bibliotecas.
  3. Investir em pré-processamento de dados de entrada.
  4. Implementar monitoramento robusto desde o início.
  5. 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.

Tags: MinerU KylinOS HygonCPU documentunderstanding CPUinference

Publicado em 5-30 04:04 por Thomas