Bangun sistem RAG multimodal yang didukung AI dengan Docling dan Granite

Penyusun

BJ Hargrave

Open Source Developer, STSM

Erika Russi

Data Scientist

IBM

Dalam tutorial ini, Anda akan menggunakan Docling dari IBM dan IBM Granite vision sumber terbuka, penanaman berbasis teks, dan model generative AI untuk membuat sistem RAG. Model-model ini tersedia melalui berbagai kerangka kerja sumber terbuka. Dalam tutorial ini, kita akan menggunakan Replicate untuk menghubungkan ke visi IBM Granite dan model AI generatif serta HuggingFace untuk terhubung ke model penanaman.

Generasi dengan dukungan pengambilan data multimodal

Generasi dengan dukungan pengambilan data (RAG) adalah teknik yang digunakan dengan model bahasa besar (LLM) untuk menghubungkan model dengan basis pengetahuan informasi di luar data yang telah dilatih LLM tanpa harus melakukan penyempurnaan. RAG tradisional terbatas pada contoh penggunaan berbasis teks seperti ringkasan teks dan chatbot.

Multimodal RAG dapat menggunakan multimodal LLM (MLLM) untuk memproses informasi dari berbagai jenis data untuk dimasukkan sebagai bagian dari basis pengetahuan eksternal yang digunakan dalam RAG. Data multimodal dapat mencakup teks, gambar, audio, video atau bentuk lainnya. LLM multimodal populer termasuk Gemini Google, Meta Llama 3.2 dan GPT-4 dan GPT-4o OpenAI.

Untuk resep ini, Anda akan menggunakan model IBM Granite yang mampu memproses modalitas yang berbeda. Anda akan membuat sistem AI untuk menjawab pertanyaan pengguna real-time dari data tidak terstruktur dalam PDF.

Ikhtisar tutorial

Selamat datang di tutorial Granite. Dalam tutorial ini, Anda akan belajar cara memanfaatkan kekuatan alat-alat canggih untuk membangun pipeline RAG multimodal yang didukung oleh AI. Tutorial ini akan memandu Anda melalui proses berikut:

  • Prapemrosesan dokumen: Pelajari cara menangani dokumen dari berbagai sumber, mengurai dan mengubahnya menjadi format yang dapat digunakan, dan menyimpannya dalam basis data vektor dengan menggunakan Docling. Anda akan menggunakan Granite MLLM untuk menghasilkan deskripsi gambar dalam dokumen.
  • RAG: Memahami cara menghubungkan LLM seperti Granite dengan basis pengetahuan eksternal untuk meningkatkan respons kueri dan menghasilkan insight yang berharga.
  • LangChain untuk Integrasi alur kerja: Temukan cara menggunakan LangChain untuk merampingkan dan mengorkestrasi alur kerja pemrosesan dan pengambilan dokumen, memungkinkan interaksi yang mulus antara berbagai komponen sistem.

Tutorial ini menggunakan tiga teknologi mutakhir:

  1. Docling: Toolkit sumber terbuka yang digunakan untuk mengurai dan mengonversi dokumen.
  2. Granite: LLM canggih yang menyediakan kemampuan bahasa alami yang kuat dan model bahasa visi yang menyediakan gambar ke teks.
  3. LangChain: Kerangka kerja andal yang digunakan untuk membangun aplikasi yang didukung oleh model bahasa, yang dirancang untuk menyederhanakan alur kerja yang kompleks dan mengintegrasikan alat bantu eksternal dengan lancar.

Pada akhir tutorial ini, Anda akan mencapai hal berikut:

  • Dapatkan kecakapan dalam pra-pemrosesan dokumen, pemotongan, dan pemahaman gambar.
  • Mengintegrasikan basis data vektor untuk meningkatkan kemampuan pengambilan.
  • Gunakan RAG untuk melakukan pengambilan data yang efisien dan akurat untuk aplikasi dunia nyata.

Tutorial ini dirancang untuk pengembang, peneliti, dan penggemar AI yang ingin meningkatkan pengetahuan mereka tentang manajemen dokumen dan teknik pemrosesan bahasa alami (NLP) tingkat lanjut. Tutorial ini juga dapat ditemukan di Granite Snack Cookbook GitHub milik Komunitas IBM Granite dalam bentuk Jupyter Notebook.

Prasyarat

  • Keakraban dengan pemrograman Python.
  • Pemahaman dasar LLM, konsep NLP dan visi komputer.

Langkah-langkah

Langkah 1: Instal dependensi

! echo "::group::Install Dependencies"
%pip install uv
! uv pip install git+https://github.com/ibm-granite-community/utils.git \
    transformers \
    pillow \
    langchain_classic \
    langchain_core \
    langchain_huggingface sentence_transformers \
    langchain_milvus 'pymilvus[milvus_lite]' \
    docling \
    'langchain_replicate @ git+https://github.com/ibm-granite-community/langchain-replicate.git'
! echo "::endgroup::"

Langkah 2: Pilih model AI

Pencatatan

Untuk melihat beberapa informasi pencatatan, kita dapat mengonfigurasi level log INFO.

CATATAN: Anda dapat melewatkan menjalankan sel ini.

import logging

logging.basicConfig(level=logging.INFO)


Muat model Granite

Tentukan model penanaman yang akan digunakan untuk menghasilkan vektor penanaman teks. Di sini kita akan menggunakan salah satu model Granite Embeddings

Untuk menggunakan model penanaman yang berbeda, ganti sel kode ini dengan salah satu dari resep Model Penanaman ini.

from langchain_huggingface import HuggingFaceEmbeddings
from transformers import AutoTokenizer

embeddings_model_path = “ibm-granite/granite-embedding-30m-english”
embeddings_model = HuggingFaceEmbeddings(
    model_name=embeddings_model_path,
)
embeddings_tokenizer = AutoTokenizer.from_pretrained(embeddings_model_path)

 

Tentukan MLLM yang akan digunakan untuk pemahaman gambar. Kami akan menggunakan model visi Granite. 

from ibm_granite_community.notebook_utils import get_env_var
from langchain_community.llms import Replicate
from transformers import AutoProcessor

vision_model_path = “ibm-granite/granite-vision-3.2-2b”
vision_model = Replicate(
    model=vision_model_path,
    replicate_api_token=get_env_var(“REPLICATE_API_TOKEN”),
    model_kwargs={
        “max_tokens”: embeddings_tokenizer.max_len_single_sentence, # Set the maximum number of tokens to generate as output.
        “min_tokens”: 100, # Set the minimum number of tokens to generate as output.
    },
)
vision_processor = AutoProcessor.from_pretrained(vision_model_path)

 

Tentukan model bahasa yang akan digunakan untuk operasi pembuatan RAG.  Di sini kita menggunakan klien Replicate LangChain untuk menyambung ke model Granite dari ibm-granite org di Replicate.

Untuk menyiapkan Replicate, lihat Memulai dengan Replicate. Untuk menyambung ke model pada penyedia selain Replicate, gantikan sel kode ini dengan sel kode dari resep komponen LLM.

Untuk menghubungkan ke model pada penyedia selain Replicate, gantikan sel kode ini dengan sel kode dari resep komponen LLM.

from langchain_replicate import ChatReplicate

model_path = "ibm-granite/granite-4.0-h-small"
model = ChatReplicate(
    model=model_path,
    replicate_api_token=get_env_var("REPLICATE_API_TOKEN"),
    model_kwargs={
        "max_tokens": 1000, # Set the maximum number of tokens to generate as output.
        "min_tokens": 100, # Set the minimum number of tokens to generate as output.
    },
)

Langkah 3: Persiapkan dokumen untuk basis data vektor

Dalam contoh ini, dari sekumpulan dokumen sumber, kami menggunakan Docling untuk mengonversi dokumen menjadi teks dan gambar. Teks kemudian dibagi menjadi beberapa bagian. Gambar diproses oleh MLLM untuk menghasilkan ringkasan gambar.

Gunakan Docling untuk mengunduh dokumen dan mengonversi ke teks dan gambar

Docling akan mengunduh dokumen PDF dan memprosesnya sehingga kami dapat memperoleh teks dan gambar yang terkandung dalam dokumen. Dalam PDF, ada berbagai jenis data, termasuk teks, tabel, grafik, dan gambar.

from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.base_models import InputFormat
from docling.datamodel.pipeline_options import PdfPipelineOptions

pdf_pipeline_options = PdfPipelineOptions(
    do_ocr=False,
    generate_picture_images=True,
)
format_options = {
    InputFormat.PDF: PdfFormatOption(pipeline_options=pdf_pipeline_options),
}
converter = DocumentConverter(format_options=format_options)

sources = [
    “https://midwestfoodbank.org/images/AR_2020_WEB2.pdf”,
]
conversions = { source: converter.convert(source=source).document for source in sources }

 

Dengan dokumen yang diproses, kami kemudian memproses lebih lanjut elemen teks dalam dokumen. Kami membagi data tersebut menjadi ukuran yang sesuai untuk model penyematan yang kami gunakan. Daftar dokumen LangChain dibuat dari potongan teks.

from docling_core.transforms.chunker.hybrid_chunker import HybridChunker
from docling_core.types.doc.document import TableItem
from langchain_core.documents import Document

doc_id = 0
texts: list[Document] = []
for source, docling_document in conversions.items():
    for chunk in HybridChunker(tokenizer=embeddings_tokenizer).chunk(docling_document):
        items = chunk.meta.doc_items
        if len(items) == 1 and isinstance(items[0], TableItem):
            continue # we will process tables later
        refs = “ “.join(map(lambda item: item.get_ref().cref, items))
        print(refs)
        text = chunk.text
        document = Document(
            page_content=text,
            metadata={
                “doc_id”: (doc_id:=doc_id+1),
                “source”: source,
                “ref”: refs,
            },
        )
        texts.append(document)

print(f”{len(texts)} text document chunks created”)

 

Selanjutnya kami memproses tabel apa pun dalam dokumen. Kami mengonversi data tabel ke format markdown untuk diteruskan ke model bahasa. Daftar dokumen LangChain dibuat dari rendering markdown tabel.

from docling_core.types.doc.labels import DocItemLabel

doc_id = len(texts)
tables: list[Document] = []
for source, docling_document in conversions.items():
    for table in docling_document.tables:
        if table.label in [DocItemLabel.TABLE]:
            ref = table.get_ref().cref
            print(ref)
            text = table.export_to_markdown()
            document = Document(
                page_content=text,
                metadata={
                    “doc_id”: (doc_id:=doc_id+1),
                    “source”: source,
                    “ref”: ref
                },
            )
            tables.append(document)


print(f”{len(tables)} table documents created”)

 

Akhirnya, kami memproses semua gambar yang terdapat dalam dokumen. Di sini kita menggunakan model bahasa visi untuk memahami isi gambar. Dalam contoh ini, kami tertarik pada informasi tekstual apa pun dalam gambar. Anda mungkin ingin bereksperimen dengan teks prompt yang berbeda untuk melihat bagaimana itu dapat meningkatkan hasil.

CATATAN: Pemrosesan gambar dapat memakan waktu yang sangat lama tergantung pada jumlah gambar dan layanan yang menjalankan model bahasa visi.

import base64
import io
import PIL.Image
import PIL.ImageOps
from IPython.display import display

def encode_image(image: PIL.Image.Image, format: str = “png”) -> str:
    image = PIL.ImageOps.exif_transpose(image) or image
    image = image.convert(“RGB”)

    buffer = io.BytesIO()
    image.save(buffer, format)
    encoding = base64.b64encode(buffer.getvalue()).decode(“utf-8”)
    uri = f”data:image/{format};base64,{encoding}”
    return uri

# Feel free to experiment with this prompt
image_prompt = “If the image contains text, explain the text in the image.”
conversation = [
    {
        “role”: “user”,
        “content”: [
            {“type”: “image”},
            {“type”: “text”, “text”: image_prompt},
        ],        
    },
]
vision_prompt = vision_processor.apply_chat_template(
    conversation=conversation,
    add_generation_prompt=True,
)
pictures: list[Document] = []
doc_id = len(texts) + len(tables)
for source, docling_document in conversions.items():
    for picture in docling_document.pictures:
        ref = picture.get_ref().cref
        print(ref)
        image = picture.get_image(docling_document)
        if image:
            text = vision_model.invoke(vision_prompt, image=encode_image(image))
            document = Document(
                page_content=text,
                metadata={
                    “doc_id”: (doc_id:=doc_id+1),
                    “source”: source,
                    “ref”: ref,
                },
            )
            pictures.append(document)

print(f”{len(pictures)} image descriptions created”)

 

Kita kemudian dapat menampilkan dokumen LangChain yang dibuat dari dokumen input.

import itertools
from docling_core.types.doc.document import RefItem

# Print all created documents
for document in itertools.chain(texts, tables):
    print(f”Document ID: {document.metadata[‘doc_id’]}”)
    print(f”Source: {document.metadata[‘source’]}”)
    print(f”Content:\n{document.page_content}”)
    print(“=” * 80) # Separator for clarity

for document in pictures:
    print(f”Document ID: {document.metadata[‘doc_id’]}”)
    source = document.metadata[‘source’]
    print(f”Source: {source}”)
    print(f”Content:\n{document.page_content}”)
    docling_document = conversions[source]
    ref = document.metadata[‘ref’]
    picture = RefItem(cref=ref).resolve(docling_document)
    image = picture.get_image(docling_document)
    print(“Image:”)
    display(image)
    print(“=” * 80) # Separator for clarity

Isi basis data vektor

Dengan menggunakan model penanaman, kita memuat dokumen dari potongan teks dan menghasilkan teks gambar ke dalam basis data vektor. Pembuatan basis data vektor ini memungkinkan kita untuk dengan mudah melakukan pencarian kesamaan semantik di seluruh dokumen kita.

CATATAN: Populasi basis data vektor dapat memakan waktu tergantung pada model penanaman dan layanan Anda.

Pilih basis data vektor Anda

Tentukan basis data yang akan digunakan untuk menyimpan dan mengambil vektor penanaman.

Untuk terhubung ke basis data vektor selain Milvus, ganti sel kode ini dengan satu dari resep Penyimpanan Vektor ini.

import tempfile
from langchain_core.vectorstores import VectorStore
from langchain_milvus import Milvus

db_file = tempfile.NamedTemporaryFile(prefix=”vectorstore_”, suffix=”.db”, delete=False).name
print(f”The vector database will be saved to {db_file}”)

vector_db: VectorStore = Milvus(
    embedding_function=embeddings_model,
    connection_args={“uri”: db_file},
    auto_id=True,
    enable_dynamic_field=True,
    index_params={“index_type”: “AUTOINDEX”},
)

 

Kami sekarang menambahkan semua dokumen LangChain untuk teks, tabel, dan deskripsi gambar ke basis data vektor.

import itertools
documents = list(itertools.chain(texts, tables, pictures))
ids = vector_db.add_documents(documents)
print(f”{len(ids)} documents added to the vector database”)

Langkah 4: RAG dengan Granite

Sekarang setelah kita berhasil mengonversi dokumen kami dan memvektoriskannya, kita dapat menyiapkan pipeline RAG.

Ambil potongan yang relevan

Di sini kita menguji basis data vektor dengan mencari potongan dengan informasi yang relevan dengan kueri kita di ruang vektor. Kita menampilkan dokumen yang terkait dengan deskripsi gambar yang diambil.

Jangan ragu untuk mencoba pertanyaan yang berbeda.

query = "How much was spent on food distribution relative to the amount of food distributed?"
for doc in vector_db.as_retriever().invoke(query):
    print(doc)
    print("=" * 80) # Separator for clarity

 

Dokumen yang dikembalikan harus responsif terhadap kueri. Mari kita lanjutkan dan membangun pipeline RAG kita.


Buat pipeline RAG untuk Granite

Pertama kita membuat prompt bagi Granite untuk melakukan query RAG. Kami menggunakan template obrolan Granite dan menyediakan nilai placeholder yang akan diganti oleh pipeline RAG LangChain.

Selanjutnya, kita membangun pipeline RAG dengan menggunakan template prompt Granite yang dibuat sebelumnya.

from ibm_granite_community.langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_classic.chains.retrieval import create_retrieval_chain
from langchain_core.prompts import ChatPromptTemplate

# Create a Granite prompt for question-answering with the retrieved context
prompt_template = ChatPromptTemplate.from_template("{input}")

# Assemble the retrieval-augmented generation chain
combine_docs_chain = create_stuff_documents_chain(
    llm=model,
    prompt=prompt_template,
)
rag_chain = create_retrieval_chain(
    retriever=vector_db.as_retriever(),
    combine_docs_chain=combine_docs_chain,
)

Buat respons dengan pengambilan yang ditingkatkan untuk sebuah pertanyaan

Saluran ini menggunakan kueri untuk menemukan dokumen dari basis data vektor dan menggunakannya sebagai konteks untuk kueri.

from ibm_granite_community.notebook_utils import wrap_text

output = rag_chain.invoke({"input": query})

print(wrap_text(output['answer']))

Luar biasa! Kami telah membuat aplikasi AI yang berhasil memanfaatkan pengetahuan dari teks dan gambar dokumen sumber.

Langkah Berikutnya

  • Jelajahi alur kerja RAG tingkat lanjut untuk industri lain.
  • Bereksperimenlah dengan jenis dokumen lain dan kumpulan data yang lebih besar.
  • Optimalkan rekayasa prompt untuk respons Granite yang lebih baik.
Solusi terkait
IBM watsonx.ai

Latih, validasi, lakukan tuning, dan terapkan AI generatif, model dasar, dan kemampuan machine learning dengan IBM watsonx.ai, studio perusahaan generasi berikutnya untuk pembangun AI. Bangun aplikasi AI dalam waktu singkat, dengan sedikit data.

Temukan watsonx.ai
Solusi kecerdasan buatan (AI)

Gunakan AI di bisnis Anda dalam perpaduan antara keahlian AI terdepan di industri dari IBM dan portofolio solusi Anda.

Jelajahi solusi AI
Layanan AI

Temukan kembali alur kerja dan operasi yang penting dengan menambahkan AI untuk memaksimalkan pengalaman, pengambilan keputusan secara real-time, dan nilai bisnis.

Jelajahi layanan AI
Ambil langkah selanjutnya

Dapatkan akses satu atap ke kemampuan yang mencakup siklus hidup pengembangan AI. Hasilkan solusi AI yang kuat dengan antarmuka ramah pengguna, alur kerja yang efisien, serta akses ke API dan SDK berstandar industri.

Jelajahi watsonx.ai Pesan demo langsung