Как я могу индексировать таблицы вместе с текстами, присутствующими в PDF-файле, с помощью Llammaindex и LangChain? (я использую ключ Openai)

      def ask(file):
    print(" Loading...")
    PDFReader = download_loader("PDFReader")
    loader = PDFReader()
    documents = loader.load_data(file=Path(file))
    print("Path: ", Path(file))

    # Check if the index file exists
    if os.path.exists(INDEX_FILE):
        # Load the index from the file
        logger.info("found index.json in the directory")
        index = GPTSimpleVectorIndex.load_from_disk(INDEX_FILE)
    else:
        logger.info("didnt find index.json in the directory")
        llm_predictor = LLMPredictor(llm=OpenAI(temperature=0, model_name="text-davinci-003"))

        service_context = ServiceContext.from_defaults(llm_predictor=llm_predictor, chunk_size_limit=1024)
        index = GPTSimpleVectorIndex.from_documents(documents, service_context=service_context)

        # Save the index to the file
        index.save_to_disk(INDEX_FILE)

Выше приведен фрагмент кода для создания индекса для PDF-файла. Я использовал PDFReader от llamahub для извлечения текста из PDF-файла. Бот хорошо отвечает, когда его спрашивают о тексте. Но это не удается, когда я спрашиваю значение из таблицы, представленной в PDF-файле.

Я пробовал использовать разные текстовые модели open-ai. Лучшим из них является text-davinci-003. Бот не может мне ответить по поводу значений, представленных в таблицах в формате pdf. Это связано с тем, что pdfReader просто преобразует содержимое PDF в текст (он не предпринимает никаких специальных действий для преобразования содержимого таблицы). Я хочу знать, как я могу успешно индексировать текст и таблицы в PDF-файле, используя langchain и llamaindex.

1 ответ

Я понимаю, что вы ищете открытый исходный код, но я решил поделиться этим с вами, используя Adobe API; Вы можете использовать бесплатную пробную версию здесь: Adobe API Developer . Функция Python ниже (убедитесь, что вы получили «private.Key» от Adobe API ( ). Вы получите его после нажатия при запуске пробной версии внутри заархивированной папки, которая будет загружена на ваш компьютер.

      from adobe.pdfservices.operation.auth.credentials import Credentials
from adobe.pdfservices.operation.exception.exceptions import ServiceApiException, ServiceUsageException, SdkException
from adobe.pdfservices.operation.pdfops.options.extractpdf.extract_pdf_options import ExtractPDFOptions
from adobe.pdfservices.operation.pdfops.options.extractpdf.extract_renditions_element_type import \
    ExtractRenditionsElementType
from adobe.pdfservices.operation.pdfops.options.extractpdf.extract_element_type import ExtractElementType
from adobe.pdfservices.operation.execution_context import ExecutionContext
from adobe.pdfservices.operation.io.file_ref import FileRef
from adobe.pdfservices.operation.pdfops.extract_pdf_operation import ExtractPDFOperation
import logging
import os
import re
import zipfile
import json
import glob
import pandas as pd

def adobeAPI(base_path, file_path):
    # Your code for the AdobeAPI function
    logging.basicConfig(level=os.environ.get("LOGLEVEL", "INFO"))

    try:

        # Initial setup, create credentials instance.
        credentials = Credentials.service_account_credentials_builder() \
            .from_file("/path/to/pdfservices-api-credentials.json") \
            .build()

        # Create an ExecutionContext using credentials and create a new operation instance.
        execution_context = ExecutionContext.create(credentials)
        extract_pdf_operation = ExtractPDFOperation.create_new()

        # Set operation input from a source file.
        source = FileRef.create_from_local_file(file_path)
        extract_pdf_operation.set_input(source)

        # Build ExtractPDF options and set them into the operation
        extract_pdf_options: ExtractPDFOptions = ExtractPDFOptions.builder() \
            .with_elements_to_extract([ExtractElementType.TEXT, ExtractElementType.TABLES]) \
            .with_elements_to_extract_renditions([ExtractRenditionsElementType.TABLES,
                                                  ExtractRenditionsElementType.FIGURES]) \
            .build()
        extract_pdf_operation.set_options(extract_pdf_options)

        # Execute the operation.
        result: FileRef = extract_pdf_operation.execute(execution_context)

        # set a path for the zipped file
        outputzip = os.path.join(base_path, "output", str(
            get_filename(file_path)+".zip"))

        # set a path for the extracted zipped file
        outputzipextract = os.path.join(
            base_path, "output", str(get_filename(file_path)))

        # Save the result to the specified location.
        result.save_as(outputzip)
    except (ServiceApiException, ServiceUsageException, SdkException):
        logging.exception("Exception encountered while executing operation")

    # Open the ZIP file
    with zipfile.ZipFile(outputzip, 'r') as zip_ref:
        # Extract all the contents of the ZIP file to the current working directory
        zip_ref.extractall(path=outputzipextract)

    # Opening JSON file
    with open(os.path.join(outputzipextract, "structuredData.json")) as json_file:
        data = json.load(json_file)



    # get the list of .xlsx files
    List_xlsx_files = []
    xlsx_files = glob.glob(os.path.join(
        outputzipextract, "tables", "*.xlsx"))
    for file in xlsx_files:
        List_xlsx_files.append(file)


    list_of_values = list(range(len(data['elements'])-1))


    filename = get_filename(file_path)
    with open(os.path.join(outputzipextract, str(filename + '.txt')), "w", encoding='utf-8') as file:

        concatenated_string = ""

        for sec_index in list_of_values:

            pattern_figure = r"Figure$"
            match_figure = re.search(
                pattern_figure, data['elements'][int(sec_index)]['Path'])

            pattern_table_all = r"\/Table(?:\[\d+\])?$"
            match_table_all = re.search(
                pattern_table_all, data['elements'][int(sec_index)]['Path'])

            pattern_table_part = r"/Table(?:\[\d+\])?/"
            match_table_part = re.search(
                pattern_table_part, data['elements'][int(sec_index)]['Path'])

            if match_figure or match_table_part:
                continue

            elif match_table_all:

                xlsx_file = List_xlsx_files[0]
                match = re.search(r'(?<=\\)[^\\]*$', xlsx_file)
                xlsx_file = match.group(0)
                dfs_fixed_dict = get_dict_xlsx(outputzipextract, xlsx_file)
                json_string = json.dumps(dfs_fixed_dict)
                concatenated_string = concatenated_string + "\n" + json_string

                List_xlsx_files.pop(0)  # removing the used xlsx file

            elif 'Text' in data['elements'][int(sec_index)]:
                concatenated_string = concatenated_string + \
                    "\n" + data['elements'][int(sec_index)]['Text']

            else:
                continue


        file.write(concatenated_string)


    localfile = os.path.join(outputzipextract, str(filename + '.txt'))

    return localfile


############################ < Function to get filename out of path>##################


def get_filename(file_path):
    pattern = r'[/\\]([^/\\]+)\.pdf$'
    match = re.search(pattern, file_path)
    if match:
        return match.group(1)
    else:
        return None

############################ </ Function to get filename out of path>##################



#################### < Function to get a dictionary of Excel files>##################

def get_dict_xlsx(outputzipextract, xlsx_file):

    dfs = pd.read_excel(os.path.join(
        outputzipextract, "tables", xlsx_file), sheet_name='Sheet1', engine='openpyxl')

    # Convert the DataFrame to a dictionary
    data_dict = dfs.to_dict(orient='records')


    cleaned_data_dict = [
        {re.sub(r'_x[0-9a-fA-F]{4}_', '', k).strip()
                : re.sub(r'_x[0-9a-fA-F]{4}_', '', v).strip() for k, v in item.items()}
        for item in data_dict
    ]

    return cleaned_data_dict

#################### </Function to get a dictionary of Excel files>##################

Это файловая структура перед запуском кода:

После запуска у вас появится папка «Выход», в которой вы сможете найти текстовую версию вашего PDF-файла. Вы заметите формат таблиц json, когда откроете текстовый файл. GPT может читать json и учитывать его, когда пытается ответить на ваш вопрос. В моем PDF-файле есть таблица:

Ваш txt-файл содержит следующий формат json:

      [{
    "No.": "1",
    "Equipment": "Pump",
    "Plant": "A1",
    "Tag": "P-1"
}, {
    "No.": "2",
    "Equipment": "Tank",
    "Plant": "A2",
    "Tag": "T-1"
}, {
    "No.": "3",
    "Equipment": "Heat Exchanger",
    "Plant": "A3",
    "Tag": "HE-1"
}, {
    "No.": "4",
    "Equipment": "Vessel",
    "Plant": "A4",
    "Tag": "V-1"
}]

Это файловая структура после запуска кода:

Я надеюсь, что это помогает.

Другие вопросы по тегам