Как я могу индексировать таблицы вместе с текстами, присутствующими в 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"
}]
Это файловая структура после запуска кода:
Я надеюсь, что это помогает.