Ngày 25 tháng 6 — Baidu đã phát hành mô hình OCR không giới hạn vào ngày 22 tháng 6, với tổng cộng 3 tỷ tham số, nhưng chỉ có 500 triệu tham số được kích hoạt trong quá trình suy luận. Mô hình này nhằm giải quyết vấn đề các mô hình OCR đầu cuối trở nên chậm hơn khi xử lý các tài liệu dài hơn.
Tính năng nổi bật nhất là, với độ dài ngữ cảnh tối đa tiêu chuẩn là 32K, mô hình OCR cho phép đọc toàn bộ một cuốn sách trong một lần duy nhất lần đầu tiên.
Lưu ý rằng đây không phải là xử lý từng trang một, không phải là chia nhỏ tác vụ bằng vòng lặp for, và không dựa vào bộ lập lịch bên ngoài để ghép nối các kết quả. Thay vào đó, đây là một suy luận tiến thẳng thực sự, trực tiếp hoàn thành việc phân tích cú pháp hàng chục trang tài liệu.
Điều ấn tượng hơn nữa là nó không chỉ đạt được điều này mà còn làm rất xuất sắc. Trên OmniDocBench v1.5, một tiêu chuẩn đánh giá phổ biến cho việc phân tích tài liệu, Unlimited OCR đã đạt được điểm số tiên tiến nhất (SOTA) là 93,23%, cao hơn DeepSeek OCR tới 6 điểm phần trăm.
Tại sao tất cả các người mẫu đều gặp phải hiện tượng “mất trí nhớ từng trang”?
Khi nói đến nhận dạng ký tự quang học (OCR), các mô hình OCR hiện tại vẫn còn khá tệ.
Họ chia một tác vụ dài, liên tục thành hàng chục tác vụ nhỏ không liên quan, sau đó dựa vào một bộ lập lịch bên ngoài để ghép nối các kết quả lại với nhau một cách khó khăn. Nó giống như chạy một vòng lặp for, xử lý một trang, xóa bộ nhớ, rồi bắt đầu trang tiếp theo từ đầu.
Nó hoạt động được, nhưng về cơ bản chỉ là một biện pháp tạm thời trong kỹ thuật, và vẫn còn rất xa so với trí tuệ thực sự.
Lý do là vì khi đầu ra càng dài, bộ nhớ đệm KV theo cơ chế chú ý tiêu chuẩn càng tăng theo cấp số nhân — bộ nhớ không thể đáp ứng kịp, và tốc độ càng ngày càng chậm lại.
Đây là vấn đề chính khiến tất cả các mô hình phải xử lý từng trang một và thường xuyên “quên” mất thông tin.
Nhưng con người chưa bao giờ sao chép sách theo cách này.
Chúng ta duy trì trạng thái nhận thức liên tục — mắt chúng ta tập trung vào ba điểm: cuốn sách gốc, đoạn văn ngắn vừa viết xong và từ tiếp theo sắp viết.
Những bài viết trước đây dần phai mờ trong trí nhớ tôi, trong khi bối cảnh gần đây được sử dụng để theo dõi tiến trình hiện tại.
Khả năng này có một cái tên tuyệt vời: “quên nhẹ nhàng”.
Chính khả năng “quên đi những gì nên quên” này cho phép con người chịu đựng được những nhiệm vụ cực kỳ dài với mức độ tải nhận thức rất thấp. Ví dụ, sao chép một cuốn sách, dịch hàng trăm trang, hoặc liên tục chép lại âm thanh trong nhiều giờ liền.
Điều Baidu muốn làm là tích hợp mô hình chú ý của con người, đó là “nhìn thấy toàn bộ văn bản gốc nhưng chỉ nhớ vài dòng gần nhất”, vào mô hình của mình, để OCR có thể loại bỏ hiện tượng mất bộ nhớ.
Hôm nay, tôi sẽ thử nghiệm Unlimited OCR với bốn bài toán chính: Nhận dạng công thức, Nhận dạng bảng, Sắp xếp thứ tự đọc và Văn bản viết tay.
Chúng ta hãy bắt đầu với Nhận dạng Công thức. Tôi đã tải lên một hình ảnh chứa các công thức toán học phức tạp. Như bạn có thể thấy, mô hình xử lý chúng cực kỳ tốt — diễn giải chính xác các chỉ số trên, chỉ số dưới, và thậm chí cả những biểu thức rất dài và phức tạp.
Tiếp theo là nhận dạng bảng. Đây là một vấn đề nổi tiếng khó khăn, và có rất nhiều loại bảng, đôi khi có đường viền, đôi khi không, chứa vô số con số mà các mô hình rất dễ hiểu sai. Tôi đã sử dụng Unlimited OCR trên một số ví dụ về bảng và thấy độ chính xác của nó thực sự ấn tượng.
Một thách thức lớn khác là hiểu cấu trúc và thứ tự đọc của tài liệu. Trong các tài liệu hiện đại, nội dung không chỉ phức tạp hơn mà còn có bố cục rất đa dạng. Hãy nghĩ đến các thiết kế nhiều cột, văn bản và hình ảnh hỗn hợp, các nếp gấp, in màu, các bản quét nghiêng và các chú thích viết tay — tất cả đều làm phức tạp quá trình nhận dạng ký tự quang học (OCR). Thứ tự đọc chính xác không phải lúc nào cũng đơn giản là từ trên xuống dưới, từ trái sang phải.
Báo cáo kỹ thuật của Unlimited OCR chứng minh cách mô hình có thể hiểu được những cấu trúc phức tạp này, gần giống như con người. Cho dù đó là một bài báo học thuật, một tờ báo nhiều cột hay một báo cáo kỹ thuật, nó đều phân tích bố cục một cách thông minh và khôi phục lại thứ tự đọc phù hợp với trực giác của con người.
Cuối cùng, trong quá trình thử nghiệm, Unlimited OCR gặp khó khăn với nội dung viết tay. Mặc dù quá trình trích xuất diễn ra nhanh chóng, độ chính xác lại thấp hơn đáng kể so với dự kiến. Đối với các ghi chú viết tay chứa nhiều yếu tố hỗn hợp như văn bản, số, đoạn văn, hình ảnh và bố cục nhiều cột, mô hình thường bỏ sót nội dung, tạo ra văn bản không chính xác và gặp khó khăn trong việc bảo toàn cấu trúc ban đầu.
Do đó, kết quả đầu ra đòi hỏi phải chỉnh sửa thủ công đáng kể và không đủ tin cậy đối với các tài liệu viết tay phức tạp.
Điều gì làm nên sự độc đáo của Unlimited OCR?
Để hiểu tại sao mô hình này đáng chú ý, chúng ta cần xem xét quy trình điển hình của một hệ thống tài liệu dựa trên trí tuệ nhân tạo.
Một tập tin PDF được gửi đến, công cụ OCR xử lý từng trang một, bước xử lý thứ hai sẽ tái tạo các trang thành một văn bản duy nhất, và văn bản đó được lập chỉ mục vào cơ sở dữ liệu vector ở trạng thái mà RAG có thể sử dụng.
Mỗi giai đoạn đều làm tăng thêm sự chậm trễ và các điểm dễ xảy ra lỗi: bảng biểu bị chia làm hai trang, thiếu tiêu đề, thứ tự đọc không chính xác.
Cách tiếp cận của Unlimited-OCR thay đổi góc nhìn. Mô hình duy trì toàn bộ tài liệu như một ngữ cảnh, nhưng trong quá trình tạo văn bản, nó chỉ di chuyển một cửa sổ trượt của văn bản đã được tạo ra.
Đây là điểm khác biệt then chốt. Trong các bộ giải mã thông thường, bộ nhớ làm việc tăng tuyến tính với mỗi token đầu ra, điều này trở thành nút thắt cổ chai đối với các tài liệu rất dài.
Bằng cách giữ cho cửa sổ văn bản được tạo ra không đổi, việc phân tích các tài liệu dài trở thành một quá trình đọc liên tục từ đầu đến cuối, thay vì một quá trình tái tạo.
Đối với những người xây dựng quy trình xử lý tài liệu, kết quả rất rõ ràng: ít công đoạn tiền xử lý hơn, ít mã ghép nối hơn và văn bản được tái tạo nhất quán hơn được chuyển đến RAG.
So sánh OCR không giới hạn và OCR DeepSeek
Khi đến giai đoạn này, chúng tôi đã xem xét lại DeepSeek OCR và nhận thấy rằng cả hai dường như đang tập trung vào hai khía cạnh khác nhau của cùng một lộ trình kỹ thuật.
DeepSeek OCR giải quyết vấn đề phía đầu vào — làm thế nào để nén các tài liệu độ phân giải cao thành càng ít mã thông báo hình ảnh càng tốt. Unlimited OCR giải quyết vấn đề phía đầu ra — làm thế nào để ngăn chặn mô hình bị quá tải bởi bộ nhớ đệm cặp khóa-giá trị ngày càng mở rộng trong quá trình tạo ra dữ liệu lâu dài.
Một quá trình diễn ra ở khâu mã hóa, và quá trình kia diễn ra ở khâu giải mã. Xét riêng lẻ, cả hai đều hợp lệ, nhưng khi xem xét cùng nhau, chúng lại có mối liên hệ mật thiết đáng ngạc nhiên.
Điều thú vị hơn nữa là báo cáo kỹ thuật của Unlimited OCR đề cập đến DeepSeek OCR khá thường xuyên, tới 40 lần. Ở nhiều chỗ, nó không giống như một bài so sánh đối thủ cạnh tranh thông thường, mà giống như đang tiếp tục mạch suy nghĩ và phát triển nó hơn nữa.
Còn về lý do tại sao nó lại mang đến cho mọi người cảm giác này, chúng tôi có một phỏng đoán táo bạo.
Hãy bắt đầu lập trình nào!
Bây giờ chúng ta hãy cùng khám phá từng bước và tìm ra câu trả lời cho việc tạo ra một ứng dụng suy luận mạnh mẽ. Chúng ta sẽ cài đặt các thư viện hỗ trợ mô hình. Để làm điều này, chúng ta sẽ thực hiện lệnh `pip install`.
pip install torch torchvision transformers pillow einops addict easydict pymupdf psutil langchain langchain-community langchain-openai faiss-gpu sentence-transformers openai
Bước tiếp theo là bước thông thường: Chúng ta sẽ nhập các thư viện cần thiết, tầm quan trọng của việc này sẽ trở nên rõ ràng khi chúng ta tiến hành một số cấu hình cơ bản.
Unlimited-OCR: chuyển đổi tài liệu và hình ảnh thành dữ liệu có cấu trúc, thân thiện với AI (như JSON và Markdown) với độ chính xác hàng đầu trong ngành — hỗ trợ các ứng dụng AI.
import os
import torch
import tempfile
import fitz # PyMuPDF
from transformers import AutoModel, AutoTokenizer
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
from langchain.docstore.document import Document
Vì vậy, tôi đã xây dựng hệ thống SimpleRAG này, kết hợp Unlimited-OCR để trích xuất văn bản với OpenAI để tạo truy vấn. Hãy để tôi giới thiệu cho bạn những gì tôi đã phát triển ở đây.
Trong giai đoạn khởi tạo, tôi thiết lập các thành phần cốt lõi — tôi sử dụng embedding BGE của HuggingFace cho biểu diễn vector và GPT-4o làm mô hình trò chuyện với nhiệt độ bằng không để đảm bảo phản hồi nhất quán. Tôi khởi tạo các vị trí giữ chỗ cho kho lưu trữ vector và chuỗi hỏi đáp mà chúng ta sẽ xây dựng sau này.
Sau đó, tôi bắt đầu tải mô hình Unlimited-OCR và bộ mã hóa từ HuggingFace vào bộ nhớ GPU.
Khi tôi gọi điện extract_text_from_images(), tôi cung cấp một danh sách các tệp hình ảnh hoặc PDF. Hệ thống sẽ xử lý từng tệp một.
Nếu tệp là PDF, trước tiên tôi chuyển đổi từng trang thành hình ảnh (PNG) và lưu chúng vào một thư mục tạm thời. Sau đó, tôi gửi tất cả các trang đến Unlimited-OCR để nó có thể đọc văn bản từ toàn bộ tài liệu.
Nếu tệp tin đã là hình ảnh, tôi sẽ gửi trực tiếp đến Unlimited-OCR. Chế độ này hoạt động tốt với các tài liệu có bố cục phức tạp, bảng biểu và biểu mẫu.
Sau khi quá trình nhận dạng ký tự quang học (OCR) hoàn tất, mô hình sẽ lưu văn bản đã trích xuất vào các tệp văn bản hoặc markdown tạm thời. Sau đó, tôi đọc các tệp này và kết hợp tất cả văn bản thành một chuỗi dài duy nhất.
Cuối cùng, tôi lưu văn bản dưới dạng Tài liệu LangChain và lưu đường dẫn tệp gốc làm siêu dữ liệu. Điều này giúp tôi biết văn bản đó đến từ tài liệu nào khi tôi tìm kiếm hoặc đặt câu hỏi sau này.
class SimpleRAG :
def __init__ ( self ):
self.embeddings = HuggingFaceEmbeddings(model_name= “BAAI/bge-small-en-v1.5” )
self.llm = ChatOpenAI(model= “gpt-4o” , temperature= 0 )
self.vectorstore = None
self.qa_chain = None
model_name = “baidu/Unlimited-OCR”
self.tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code= True )
self.model = AutoModel.from_pretrained(
model_name,
trust_remote_code= True ,
use_safetensors= True ,
torch_dtype=torch.bfloat16,
). eval ().cuda()
def _pdf_to_images ( self, pdf_path, dpi= 300 ):
doc = fitz. open (pdf_path)
tmp_dir = tempfile.mkdtemp(prefix= “pdf_ocr_” )
mat = fitz.Matrix(dpi / 72 , dpi / 72 )
paths = []
for i, page in enumerate (doc):
out = os.path.join(tmp_dir, f”page_ {i+ 1 :04d} .png” )
page.get_pixmap(matrix=mat).save(out)
paths.append(out)
doc.close()
return paths
def _read_output_text ( self, output_path ):
“””Đọc tất cả các tệp .md hoặc .txt được ghi bởi save_results=True.”””
texts = []
for fname in sorted (os.listdir(output_path)):
if fname.endswith(( “.md” , “.txt” )):
with open (os.path.join(output_path, fname), “r” , encoding= “utf-8” ) as f:
texts.append(f.read())
return “\n\n” .join(texts)
def extract_text_from_images ( self, image_paths: list ):
docs = []
for path in image_paths:
is_pdf = path.lower().endswith( “.pdf” )
tmp_out = tempfile.mkdtemp(prefix= “ocr_out_” )
if is_pdf:
pages = self._pdf_to_images(path)
self.model.infer_multi(
self.tokenizer,
prompt= “<image>Phân tích nhiều trang.” ,
image_files=pages,
output_path=tmp_out,
image_size= 1024 ,
max_length= 32768 ,
no_repeat_ngram_size= 35 ,
ngram_window= 1024 ,
save_results= True ,
)
else :
self.model.infer(
self.tokenizer,
prompt= “<image>Phân tích tài liệu.” ,
image_file=path,
output_path=tmp_out,
base_size= 1024 ,
image_size= 640 ,
crop_mode= True ,
max_length= 32768 ,
no_repeat_ngram_size= 35 ,
ngram_window= 128 ,
save_results= True ,
)
text = self._read_output_text(tmp_out)
if not text.strip():
text = “Không tìm thấy văn bản”
docs.append(Document(page_content=text, metadata={ “source” : path}))
return docs
Trong build_indexquy trình này, tôi trích xuất văn bản từ tất cả các hình ảnh, chia tài liệu thành các đoạn 1000 ký tự với độ chồng lấp 200 ký tự bằng cách sử dụng Recursive Character TextSplitter, tạo một vectorstore FAISS với các embedding BGE, và thiết lập một chuỗi RetrievalQA sử dụng GPT-4o và truy xuất 3 đoạn có liên quan nhất cho mỗi truy vấn.
Vì querytôi vừa chuyển câu hỏi đến chuỗi xử lý yêu cầu (QA), chuỗi này sẽ xử lý việc truy xuất và tạo câu trả lời.
def build_index ( self, image_paths: list ):
docs = self.extract_text_from_images(image_paths)
text_splitter = RecursiveCharacterTextSplitter(chunk_size= 1000 , chunk_overlap= 200 )
splits = text_splitter.split_documents(docs)
self.vectorstore = FAISS.from_documents(splits, self.embeddings)
self.qa_chain = RetrievalQA.from_chain_type(
llm=self.llm,
retriever=self.vectorstore.as_retriever(search_kwargs={ “k” : 3 }),
)
def query ( self, question: str ):
return self.qa_chain.invoke(question)
# Cách sử dụng
rag = SimpleRAG()
rag.build_index([ “your_pic.jpg” ]) # cũng chấp nhận .pdf
answer = rag.query( “trích xuất toàn bộ bảng?” ) )
in (câu trả lời)
Phần kết luận :
Unlimited-OCR không phải là phần mềm OCR đầu tiên dựa trên mô hình ngôn ngữ hình ảnh, nhưng nó giải quyết đúng vấn đề theo đúng cách. Phân tích các tài liệu dài từ lâu đã là điểm yếu của quy trình RAG, và ý tưởng đọc tài liệu trong một quy trình duy nhất mà không cần chia nhỏ và ghép nối chúng lại với nhau đã loại bỏ một nguồn gây ra lỗi lặp đi lặp lại.
Sự kết hợp giữa giấy phép MIT, quy mô 3 tỷ tham số và các trọng số có thể tải xuống miễn phí khiến nó trở thành một lựa chọn khả thi cho bất kỳ ai xây dựng hệ thống tài liệu, từ các cá nhân làm việc tự do đến các công ty chuyên nghiệp.

Bài viết liên quan: