Uzun Metni İşleme

Dosyalarla çalışırken, örneğin PDF'lerle, dil modelinizin bağlam penceresini aşan metinlerle karşılaşmanız muhtemeldir. Bu metni işlemek için şu stratejilere başvurabilirsiniz:

  1. LLM Değiştirme Daha geniş bir bağlam penceresini destekleyen başka bir LLM seçin.
  2. Brute Force Belgeyi parçalara ayırın ve her parçadan içerik çıkarın.
  3. RAG Belgeyi parçalara ayırın, parçaları indeksleyin ve "ilgili" görünen parçalardan yalnızca içerik çıkarın.

Unutmayın ki bu stratejilerin farklı avantaj ve dezavantajları vardır ve en iyi stratejinin muhtemelen tasarladığınız uygulamaya bağlı olduğunu unutmayın!

Kurulum

Örnek verilere ihtiyacımız var! Wikipedia'dan arabalar hakkında bir makaleyi indirip LangChain Document olarak yükleyelim.

import re

import requests
from langchain_community.document_loaders import BSHTMLLoader

response = requests.get("https://en.wikipedia.org/wiki/Car")
with open("car.html", "w", encoding="utf-8") as f:
    f.write(response.text)
loader = BSHTMLLoader("car.html")
document = loader.load()[0]
document.page_content = re.sub("\n\n+", "\n", document.page_content)
print(len(document.page_content))
78967

Şema Tanımlama

Burada, metinden ana gelişmeleri çıkarmak için şema tanımlayacağız.

from typing import List, Optional

from langchain.chains import create_structured_output_runnable
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI


class KeyDevelopment(BaseModel):
    """Arabaların tarihindeki bir gelişme hakkında bilgi."""

    year: int = Field(
        ..., description="Önemli bir tarihî gelişmenin yaşandığı yıl."
    )
    description: str = Field(
        ..., description="Bu yılda ne oldu? Gelişme neydi?"
    )
    evidence: str = Field(
        ...,
        description="Yıldan ve açıklamadan alıntılanan aynı şekildeki cümle(ler).",
    )


class ExtractionData(BaseModel):
    """Arabaların tarihindeki önemli gelişmeler hakkında çıkarılan bilgiler."""

    key_developments: List[KeyDevelopment]


prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "Metindeki önemli tarihî gelişmeleri belirlemede uzman birisiniz. Yalnızca önemli tarihî gelişmeleri çıkarın. Metinde önemli bilgi bulunamazsa hiçbir şey çıkarmayın.",
        ),
        ("human", "{text}"),
    ]
)


llm = ChatOpenAI(
    model="gpt-4-0125-preview",
    temperature=0,
)

extractor = prompt | llm.with_structured_output(
    schema=ExtractionData,
    method="function_calling",
    include_raw=False,
)
/home/eugene/.pyenv/versions/3.11.2/envs/langchain_3_11/lib/python3.11/site-packages/langchain_core/_api/beta_decorator.py:86: LangChainBetaWarning: The function `with_structured_output` is in beta. It is actively being worked on, so the API may change.
  warn_beta(

Zorlama Yöntemi

Belgeleri LLM'lerin bağlam penceresine sığacak şekilde parçalara ayırın.

from langchain_text_splitters import TokenTextSplitter

text_splitter = TokenTextSplitter(
    chunk_size=2000,
    chunk_overlap=20,
)

texts = text_splitter.split_text(document.page_content)

.batch işlevselliğini kullanarak her parçada çıkarımı paralel olarak çalıştırın!

İpucu

Genellikle cinsinden batch()'i paralelleştirmek için kullanabilirsiniz. batch, iş yüklerinizi paralelleştirmenize yardımcı olmak için bir threadpool kullanır.

Modeliniz bir API aracılığıyla sunuluyorsa, bu çıkarma akışınızı muhtemelen hızlandıracaktır!

first_few = texts[:3]

extractions = extractor.batch(
    [{"text": text} for text in first_few],
    {"max_concurrency": 5},  # maksimum eş zamanlılık geçirerek paralelizasyonu sınırlayın!
)

Sonuçları Birleştir

Verileri parçalardan çıkardıktan sonra çıkarmaları birleştirmek isteyeceğiz.

ana_gelismeler = []

for cikarma in cikarmalar:
    ana_gelismeler.extend(cikarma.ana_gelismeler)

ana_gelismeler[:20]
[KeyDevelopment(year=1966, description="The Toyota Corolla began production, recognized as the world's best-selling automobile.", evidence="The Toyota Corolla has been in production since 1966 and is recognized as the world's best-selling automobile."),
 KeyDevelopment(year=1769, description='Nicolas-Joseph Cugnot built the first steam-powered road vehicle.', evidence='French inventor Nicolas-Joseph Cugnot built the first steam-powered road vehicle in 1769.'),
 KeyDevelopment(year=1808, description='François Isaac de Rivaz designed and constructed the first internal combustion-powered automobile.', evidence='French-born Swiss inventor François Isaac de Rivaz designed and constructed the first internal combustion-powered automobile in 1808.'),
 KeyDevelopment(year=1886, description='Carl Benz patented his Benz Patent-Motorwagen, inventing the modern car.', evidence='The modern car—a practical, marketable automobile for everyday use—was invented in 1886, when German inventor Carl Benz patented his Benz Patent-Motorwagen.'),
 KeyDevelopment(year=1908, description='The 1908 Model T, an affordable car for the masses, was manufactured by the Ford Motor Company.', evidence='One of the first cars affordable by the masses was the 1908 Model T, an American car manufactured by the Ford Motor Company.'),
 KeyDevelopment(year=1881, description='Gustave Trouvé demonstrated a three-wheeled car powered by electricity.', evidence='In November 1881, French inventor Gustave Trouvé demonstrated a three-wheeled car powered by electricity at the International Exposition of Electricity.'),
 KeyDevelopment(year=1888, description="Bertha Benz undertook the first road trip by car to prove the road-worthiness of her husband's invention.", evidence="In August 1888, Bertha Benz, the wife of Carl Benz, undertook the first road trip by car, to prove the road-worthiness of her husband's invention."),
 KeyDevelopment(year=1896, description='Benz designed and patented the first internal-combustion flat engine, called boxermotor.', evidence='In 1896, Benz designed and patented the first internal-combustion flat engine, called boxermotor.'),
 KeyDevelopment(year=1897, description='Nesselsdorfer Wagenbau produced the Präsident automobil, one of the first factory-made cars in the world.', evidence='The first motor car in central Europe and one of the first factory-made cars in the world, was produced by Czech company Nesselsdorfer Wagenbau (later renamed to Tatra) in 1897, the Präsident automobil.'),
 KeyDevelopment(year=1890, description='Daimler Motoren Gesellschaft (DMG) was founded by Daimler and Maybach in Cannstatt.', evidence='Daimler and Maybach founded Daimler Motoren Gesellschaft (DMG) in Cannstatt in 1890.'),
 KeyDevelopment(year=1902, description='A new model DMG car was produced and named Mercedes after the Maybach engine.', evidence='Two years later, in 1902, a new model DMG car was produced and the model was named Mercedes after the Maybach engine, which generated 35 hp.'),
 KeyDevelopment(year=1891, description='Auguste Doriot and Louis Rigoulot completed the longest trip by a petrol-driven vehicle using a Daimler powered Peugeot Type 3.', evidence='In 1891, Auguste Doriot and his Peugeot colleague Louis Rigoulot completed the longest trip by a petrol-driven vehicle when their self-designed and built Daimler powered Peugeot Type 3 completed 2,100 kilometres (1,300 mi) from Valentigney to Paris and Brest and back again.'),
 KeyDevelopment(year=1895, description='George Selden was granted a US patent for a two-stroke car engine.', evidence='After a delay of 16 years and a series of attachments to his application, on 5 November 1895, Selden was granted a US patent (U.S. patent 549,160) for a two-stroke car engine.'),
 KeyDevelopment(year=1893, description='The first running, petrol-driven American car was built and road-tested by the Duryea brothers.', evidence='In 1893, the first running, petrol-driven American car was built and road-tested by the Duryea brothers of Springfield, Massachusetts.'),
 KeyDevelopment(year=1897, description='Rudolf Diesel built the first diesel engine.', evidence='In 1897, he built the first diesel engine.'),
 KeyDevelopment(year=1901, description='Ransom Olds started large-scale, production-line manufacturing of affordable cars at his Oldsmobile factory.', evidence='Large-scale, production-line manufacturing of affordable cars was started by Ransom Olds in 1901 at his Oldsmobile factory in Lansing, Michigan.'),
 KeyDevelopment(year=1913, description="Henry Ford began the world's first moving assembly line for cars at the Highland Park Ford Plant.", evidence="This concept was greatly expanded by Henry Ford, beginning in 1913 with the world's first moving assembly line for cars at the Highland Park Ford Plant."),
 KeyDevelopment(year=1914, description="Ford's assembly line worker could buy a Model T with four months' pay.", evidence="In 1914, an assembly line worker could buy a Model T with four months' pay."),
 KeyDevelopment(year=1926, description='Fast-drying Duco lacquer was developed, allowing for a variety of car colors.', evidence='Only Japan black would dry fast enough, forcing the company to drop the variety of colours available before 1913, until fast-drying Duco lacquer was developed in 1926.')]

Merhaba! Size nasıl yardımcı olabilirim? Eğer çevrilmesi gereken bir metnin varsa, lütfen paylaşmaktan çekinmeyin.

RAG tabanlı yaklaşım

Başka bir basit fikir, metni parçalamak ancak her parçadan bilgi çıkarmak yerine sadece en ilgili parçalara odaklanmaktır.

dikkat

Hangi parçaların ilgili olduğunu belirlemek zor olabilir.

Örneğin, burada kullandığımız car makalesinde, makalenin çoğunluğu önemli gelişme bilgisi içeriyor. Dolayısıyla RAG kullanarak muhtemelen çok fazla ilgili bilgiyi atıyor olacağız.

Bu yaklaşımın işleyip işlemediğini kendi durumunuzda denemenizi ve belirlemenizi öneririz.

FAISS vektör deposuna dayanan basit bir örnek aşağıda yer almaktadır.

from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
from langchain_core.runnables import RunnableLambda
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter

texts = text_splitter.split_text(document.page_content)
vectorstore = FAISS.from_texts(texts, embedding=OpenAIEmbeddings())

retriever = vectorstore.as_retriever(
    search_kwargs={"k": 1}
)  # Yalnızca ilk belgeden çıkarılması

Bu durumda RAG çıkartıcısı yalnızca en üst belgeye bakmaktadır.

rag_extractor = {
    "text": retriever | (lambda docs: docs[0].page_content)  # en üst belgenin içeriğini al
} | extractor
results = rag_extractor.invoke("Otomobillerle ilişkilendirilen ana gelişmeler")
for key_development in results.key_developments:
    print(key_development)
year=1924 description="Almanya'nın ilk seri üretilen otomobili, Opel 4PS Laubfrosch, üretildi ve Opel'i pazarda %37.5 payla Almanya'nın önde gelen otomobil üreticisi haline getirdi." evidence="Almanya'nın ilk seri üretilen otomobili, Opel 4PS Laubfrosch (Ağaç Kurbağası), 1924 yılında Rüsselsheim'da üretildi ve kısa sürede Opel'i Almanya'nın önde gelen otomobil üreticisi haline getirdi, pazarın %37.5'ini oluşturdu."
year=1925 description='Morris, toplam Britanya otomobil üretiminin %41'ine sahip olarak pazarda domine etti.' evidence='1925 yılında, Morris toplam Britanya otomobil üretiminin %41'ine sahipti.'
year=1925 description='Citroën, Renault ve Peugeot, Fransa’da 550.000 otomobil üretti ve pazarda domine etti.' evidence="Citroën aynısını Fransa'da 1919'da yaptı; Renault'nun 10CV ve Peugeot'nun 5CV gibi diğer ucuz otomobillerle birlikte 1925 yılında 550.000 otomobil üretti."
year=2017 description='Benzinle çalışan otomobillerin üretimi en yüksek seviyeye ulaştı.' evidence='Benzinle çalışan otomobillerin üretimi 2017 yılında en yüksek seviyeye ulaştı.'

Sık Karşılaşılan Sorunlar

Farklı yöntemler maliyet, hız ve doğruluk açısından kendi artıları ve eksileri bulunmaktadır.

Bu sorunlara dikkat edin:

  • Metni parçalara ayırma, bilginin birden fazla parçaya dağılmış olması durumunda LLM’nin bilgi çıkaramamasına neden olabilir.
  • Büyük parça örtüşmesi aynı bilginin iki kez çıkartılmasına neden olabilir, bu nedenle çiftleşmeye hazırlıklı olun!
  • LLM’ler veri uydurabilir. Büyük bir metin boyunca tek bir gerçek üzerine arama yapılıyorsa ve zorlayıcı bir yaklaşım kullanılıyorsa daha fazla uydurulmuş veri elde edebilirsiniz.