Haben Sie Lappen über PDFs, Dokumenten und Berichten durchgeführt? Viele wichtige Dokumente sind nicht nur einfacher Textual content. Denken Sie über Forschungsarbeiten, Finanzberichte oder Produkthandbücher nach. Sie enthalten oft eine Mischung aus Absätzen, Tabellen und anderen strukturierten Elementen. Dies schafft eine bedeutende Herausforderung für die serienmäßigen Abruf-Generationssysteme (RAGS-Augmented Era). Effektiver Lappen bei semi-strukturierten Daten erfordert mehr als nur eine grundlegende Textaufteilung. Dieser Leitfaden bietet eine praktische Lösung mit intelligenter unstrukturierter Datenanalyse und einer fortschrittlichen RAG-Technik, die als Multi-Vektor-Retriever bekannt ist, alle im Langchain-Rag-Framework.

Bedarf an Lappen auf halbstrukturierten Daten

Traditionell LAPPEN Pipelines stolpern oft mit diesen Dokumenten mit gemischten Instrengungen. Erstens kann ein einfacher Textsplitter eine Tabelle in zwei Hälften hacken und die wertvollen Daten in sich zerstören. Zweitens kann das Einbetten des rohen Textes einer großen Tabelle laute, ineffektive Vektoren für die semantische Suche erzeugen. Das Sprachmodell sieht möglicherweise nie den richtigen Kontext, um die Frage eines Benutzers zu beantworten.

Wir werden ein intelligentes System erstellen, das Textual content clever von Tabellen trennt und verschiedene Strategien zum Speichern und Abrufen von jeweils anwendet. Dieser Ansatz stellt sicher, dass unser Sprachmodell genaue Informationen erhält, die es benötigt, um genaue Antworten zu geben.

Die Lösung: ein intelligentere Ansatz zum Abrufen

Unsere Lösung wird mit zwei Schlüsselkomponenten die Kernherausforderungen direkt angepackt. Bei dieser Methode geht es darum, Daten auf eine Weise vorzubereiten und abzurufen, die ihre ursprüngliche Bedeutung und Struktur bewahrt.

  • Intelligente Daten Parsen: Wir verwenden die unstrukturierte Bibliothek, um das anfängliche schwere Anheben durchzuführen. Anstatt blind den Textual content zu spalten, unstrukturierte sie partition_pdf Funktionsanalysen das Format eines Dokuments. Es kann den Unterschied zwischen einem Absatz und einer Tabelle erkennen, die jedes Ingredient sauber extrahiert und seine Integrität bewahrt.
  • Der Multi-Vektor-Retriever: Dies ist der Kern unserer Fortgeschrittene Lappentechnik. Mit dem Multi-Vektor-Retriever können wir mehrere Darstellungen unserer Daten speichern. Zum Abrufen werden wir präzise Zusammenfassungen unserer Textbrocken und -Tische verwenden. Diese kleineren Zusammenfassungen sind für die Einbettung und Ähnlichkeitssuche viel besser. Zur Antwortgenerierung übergeben wir die vollständige, rohe Tabelle oder den Textanteil an das Sprachmodell. Dies gibt dem Modell den vollständigen Kontext, den es benötigt.

Der allgemeine Workflow sieht so aus:

Bauen der Lag -Pipeline

Gehen wir durch, wie Sie dieses System Schritt für Schritt aufbauen. Wir werden die verwenden Lama2 Forschungsarbeit Als Beispieldokument.

Schritt 1: Einrichten der Umgebung

Zuerst müssen wir die notwendigen installieren Python Pakete. Wir werden Langchain für das Kerngerüst verwenden, das für Parsen unstrukturiert ist, und Chroma für unseren Vektor Retailer.

! pip set up langchain langchain-chroma "unstructured(all-docs)" pydantic lxml langchainhub langchain_openai -q

Die PDF -Parsing von unstrukturiertem Unstrukturierter beruht auf einigen externen Instruments zur Verarbeitung und Optische Charaktererkennung (OCR). Wenn Sie sich auf einem Mac befinden, können Sie sie einfach mit Homebrew installieren.

!apt-get set up -y tesseract-ocr
!apt-get set up -y poppler-utils

Schritt 2: Datenbelastung und Parsen mit unstrukturierter Analyse

Unsere erste Aufgabe ist es, die PDF zu verarbeiten. Wir verwenden Partition_PDF von unstrukturiertem, was für diese Artwork von unstrukturierten Datenanalysen speziell erstellt wird. Wir konfigurieren es, um Tabellen zu identifizieren und den Textual content des Dokuments durch seine Titel und Untertitel zu unterteilen.

from typing import Any

from pydantic import BaseModel

from unstructured.partition.pdf import partition_pdf

# Get parts

raw_pdf_elements = partition_pdf(

   filename="/content material/LLaMA2.pdf",

   # Unstructured first finds embedded picture blocks

   extract_images_in_pdf=False,

   # Use structure mannequin (YOLOX) to get bounding bins (for tables) and discover titles

   # Titles are any sub-section of the doc

   infer_table_structure=True,

   # Publish processing to mixture textual content as soon as we now have the title

   chunking_strategy="by_title",

   # Chunking params to mixture textual content blocks

   # Try to create a brand new chunk 3800 chars

   # Try to hold chunks > 2000 chars

   max_characters=4000,

   new_after_n_chars=3800,

   combine_text_under_n_chars=2000,

   image_output_dir_path=path,

)

Nachdem wir den Partitioner ausgeführt haben, können wir sehen, welche Arten von Elementen es gefunden hat. Die Ausgabe zeigt zwei Haupttypen: CompositeElement Für unsere Textbrocken und Desk für die Tische.

# Create a dictionary to retailer counts of every kind

category_counts = {}

for ingredient in raw_pdf_elements:

   class = str(kind(ingredient))

   if class in category_counts:

       category_counts(class) += 1

   else:

       category_counts(class) = 1

# Unique_categories can have distinctive parts

unique_categories = set(category_counts.keys())

category_counts

Ausgabe:

Identifizierung des zusammengesetzten Elements und der Tabellenstücke

Wie Sie sehen können, hat unstrukturierte Arbeiten hervorragende Arbeit geleistet, um 2 verschiedene Tabellen und 85 Textbrocken zu identifizieren. Lassen Sie uns diese nun in verschiedene Pay attention trennen, um die Verarbeitung zu vereinfachen.

class Ingredient(BaseModel):

   kind: str

   textual content: Any

# Categorize by kind

categorized_elements = ()

for ingredient in raw_pdf_elements:

   if "unstructured.paperwork.parts.Desk" in str(kind(ingredient)):

       categorized_elements.append(Ingredient(kind="desk", textual content=str(ingredient)))

   elif "unstructured.paperwork.parts.CompositeElement" in str(kind(ingredient)):

       categorized_elements.append(Ingredient(kind="textual content", textual content=str(ingredient)))

# Tables

table_elements = (e for e in categorized_elements if e.kind == "desk")

print(len(table_elements))

# Textual content

text_elements = (e for e in categorized_elements if e.kind == "textual content")

print(len(text_elements))

Ausgabe:

Textelemente in der Ausgabe

Schritt 3: Zusammenfassungen zum besseren Abrufen erstellen

Große Tabellen und lange Textblöcke erzeugen keine sehr effektiven Einbettungen für die semantische Suche. Eine kurze Zusammenfassung ist jedoch perfekt. Dies ist die zentrale Idee, einen Multi-Vektor-Retriever zu verwenden. Wir werden ein einfaches erstellen Langchain Kette, um diese Zusammenfassungen zu erzeugen.

from langchain_core.output_parsers import StrOutputParser

from langchain_core.prompts import ChatPromptTemplate

from langchain_openai import ChatOpenAI

from getpass import getpass

OPENAI_KEY = getpass('Enter Open AI API Key: ')

LANGCHAIN_API_KEY = getpass('Enter Langchain API Key: ')

LANGCHAIN_TRACING_V2="true"

# Immediate

prompt_text = """You might be an assistant tasked with summarizing tables and textual content. Give a concise abstract of the desk or textual content. Desk or textual content chunk: {ingredient} """

immediate = ChatPromptTemplate.from_template(prompt_text)

# Abstract chain

mannequin = ChatOpenAI(temperature=0, mannequin="gpt-4.1-mini")

summarize_chain = {"ingredient": lambda x: x} | immediate | mannequin | StrOutputParser()

Jetzt wenden wir diese Kette auf unsere extrahierten Tabellen und Textbrocken an. Die Batch -Methode ermöglicht es uns, diese gleichzeitig zu verarbeiten, was die Dinge beschleunigt.

# Apply to tables

tables = (i.textual content for i in table_elements)

table_summaries = summarize_chain.batch(tables, {"max_concurrency": 5})

# Apply to texts

texts = (i.textual content for i in text_elements)

text_summaries = summarize_chain.batch(texts, {"max_concurrency": 5})

Schritt 4: Aufbau des Multi-Vektor-Retrievers

Mit unseren Zusammenfassungen ist es Zeit, den Retriever aufzubauen. Es verwendet zwei Speicherkomponenten:

  1. Eine Vektorstore (Chromadb) speichert das eingebettete Zusammenfassungen.
  2. Ein Docstore (ein einfacher In-Reminiscence-Retailer) hält die roh Tabelle und Textinhalt.

Der Retriever verwendet eindeutige IDs, um eine Verbindung zwischen einer Zusammenfassung im Vektor Retailer und seinem entsprechenden Rohdokument im DocStore zu erstellen.

import uuid

from langchain.retrievers.multi_vector import MultiVectorRetriever

from langchain.storage import InMemoryStore

from langchain_chroma import Chroma

from langchain_core.paperwork import Doc

from langchain_openai import OpenAIEmbeddings

# The vectorstore to make use of to index the kid chunks

vectorstore = Chroma(collection_name="summaries", embedding_function=OpenAIEmbeddings())

# The storage layer for the mother or father paperwork

retailer = InMemoryStore()

id_key = "doc_id"

# The retriever (empty to start out)

retriever = MultiVectorRetriever(

   vectorstore=vectorstore,

   docstore=retailer,

   id_key=id_key,

)

# Add texts

doc_ids = (str(uuid.uuid4()) for _ in texts)

summary_texts = (

   Doc(page_content=s, metadata={id_key: doc_ids(i)})

   for i, s in enumerate(text_summaries)

)

retriever.vectorstore.add_documents(summary_texts)

retriever.docstore.mset(record(zip(doc_ids, texts)))

# Add tables

table_ids = (str(uuid.uuid4()) for _ in tables)

summary_tables = (

   Doc(page_content=s, metadata={id_key: table_ids(i)})

   for i, s in enumerate(table_summaries)

)

retriever.vectorstore.add_documents(summary_tables)

retriever.docstore.mset(record(zip(table_ids, tables)))

Schritt 5: Lagkette laufen

Schließlich bauen wir die komplette Langchain -Lag -Pipeline. Die Kette wird eine Frage stellen, unseren Retriever verwenden, um die entsprechenden Zusammenfassungen abzurufen, die entsprechenden Rohdokumente zu ziehen und dann alles an das Sprachmodell weiterzugeben, um eine Antwort zu generieren.

from langchain_core.runnables import RunnablePassthrough

# Immediate template

template = """Reply the query primarily based solely on the next context, which may embrace textual content and tables:

{context}

Query: {query}

"""

immediate = ChatPromptTemplate.from_template(template)

# LLM

mannequin = ChatOpenAI(temperature=0, mannequin="gpt-4")

# RAG pipeline

chain = (

   {"context": retriever, "query": RunnablePassthrough()}

   | immediate

   | mannequin

   | StrOutputParser()

)

Let's check it with a selected query that may solely be answered by  a desk within the paper.

chain.invoke("What's the variety of coaching tokens for LLaMA2?")

Ausgabe:

Testen der Arbeit des Workflows

Das System funktioniert perfekt. Durch die Überprüfung des Prozesses können wir feststellen, dass der Retriever die Zusammenfassung von Tabelle 1 zuerst gefunden hat, in der die Modellparameter und Schulungsdaten erörtert werden. Dann holte es die vollständige rohe Tabelle aus dem DocStore und lieferte sie dem an die Llm. Dies gab dem Modell die genauen Daten, die zur korrekten Beantwortung der Frage erforderlich waren, und beweist die Leistung dieses Lappen beim semi-strukturierten Datenansatz.

Sie können auf den vollständigen Code auf dem zugreifen Colab Pocket book oder die Github -Repository.

Abschluss

Das Handeln von Dokumenten mit gemischten Textual content und Tabellen ist ein häufiges Drawback mit der realen Welt. Eine einfache Lag -Pipeline reicht in den meisten Fällen nicht aus. Durch die Kombination intelligenter unstrukturierter Daten, die mit dem Multi-Vektor-Retriever analysiert werden, erstellen wir ein viel robusteres und genauereres System. Diese Methode stellt sicher, dass die komplexe Struktur Ihrer Dokumente zu einer Stärke und nicht zu einer Schwäche wird. Es bietet dem Sprachmodell einen vollständigen Kontext auf leicht verständliche Weise, was zu besseren, zuverlässigeren Antworten führt.

Mehr lesen: Erstellen Sie eine Lag -Pipeline mit dem Lama -Index

Häufig gestellte Fragen

Q1. Kann diese Methode für andere Dateitypen wie DOCX oder HTML verwendet werden?

A. Ja, die unstrukturierte Bibliothek unterstützt eine Vielzahl von Dateitypen. Sie können einfach die Funktion partition_pdf mit der entsprechenden tauschen, z. B. partition_docx.

Q2. Ist eine Zusammenfassung die einzige Möglichkeit, den Multi-Vektor-Retriever zu verwenden?

A. Nein, Sie könnten hypothetische Fragen aus jedem Chunk erstellen oder einfach den rohen Textual content einbetten, wenn er klein genug ist. Eine Zusammenfassung ist oft die effektivste für komplexe Tabellen.

Q3. Warum nicht einfach die gesamte Tabelle als Textual content einbetten??

A. Große Tabellen können „verrauschte“ Einbettungen erzeugen, bei denen die Kernbedeutung in den Particulars verloren geht. Dies macht die semantische Suche weniger effektiv. Eine kurze Zusammenfassung erfasst die Essenz der Tabelle für ein besseres Abruf.

Harsh Mishra ist ein KI/ML -Ingenieur, der mehr Zeit damit verbringt, mit großen Sprachmodellen zu sprechen als mit tatsächlichen Menschen. Leidenschaft über Genai, NLP und Maschinen schlauer (damit sie ihn noch nicht ersetzen). Wenn er Fashions nicht optimiert, optimiert er wahrscheinlich seine Kaffeeaufnahme. 🚀☕

Melden Sie sich an, um weiter zu lesen und Experten-Kuratinhalte zu genießen.

Von admin

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert