В настройках индексатора я вижу следующее:
При наведении на него я прочитал следующее:
True означает, что исходные данные файла получены из источника данных вашего BLOB-объекта. сохраняется. Это позволяет передать исходный файл пользовательскому навыку, или навыку «Извлечение документов».
Как прочитать исходный PDF-файл в связанном источнике данных большого двоичного объекта в пользовательском WebApiSkill?
file_data_base64 = value.get('data', {}).get('file_data', '')
...
Я включил Allow Skillset to read file data
в индексаторе. Моя полная установка:
inputs=[
InputFieldMappingEntry(name = "file_data", source = "/document/file_data")
],
import azure.functions as func
import datetime
import json
import logging
import base64
import fitz
from io import BytesIO
app = func.FunctionApp()
logging.basicConfig(level=logging.INFO)
@app.route(route = "CustomSplitSkill", auth_level=func.AuthLevel.FUNCTION)
def CustomSplitSkill(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
try:
req_body = req.get_json()
logging.info('Request body parsed successfully.')
except ValueError:
logging.error(f"Invalid input: {e}")
return func.HttpResponse("Invalid input", status_code=400)
# 'values' expected top-level key in the request body
response_body = {"values": []}
for value in req_body.get('values', []):
recordId = value.get('recordId')
file_data_base64 = value.get('data', {}).get('file_data', '').get('data', '')
if not file_data_base64:
logging.error("No file_data found in the request.")
return func.HttpResponse("Invalid input: No file_data found", status_code=400)
try:
file_data = base64.b64decode(file_data_base64)
try:
pdf_document = fitz.open(stream=BytesIO(file_data), filetype='pdf')
except fitz.FileDataError as e:
logging.error(f"Failed to open PDF document: {e}")
return func.HttpResponse("Failed to open PDF document", status_code=400)
except Exception as e:
logging.error(f"An unexpected error occurred while opening the PDF document: {e}")
return func.HttpResponse("An unexpected error occurred", status_code=500)
if pdf_document.page_count == 0:
logging.error("No pages found in the PDF document.")
return func.HttpResponse("Invalid PDF: No pages found", status_code=400)
extracted_text = ""
for page_num in range(pdf_document.page_count):
page = pdf_document.load_page(page_num)
extracted_text += page.get_text()
combined_list = [{'textItems': ['text1', 'text2'], 'numberItems': [0, 1]}] # i deleted the chunking and associated page extraction for simplicity
response_record = {
"recordId": recordId,
"data": {
"subdata": combined_list
}
}
response_body['values'].append(response_record)
except Exception as e:
logging.error(f"Error processing file_data: {e}")
return func.HttpResponse("Error processing file_data", status_code=500)
logging.info('Function executed successfully.')
return func.HttpResponse(json.dumps(response_body), mimetype = "application/json")
Ошибка:
Message:
Could not execute skill because the Web Api request failed.
Details:
Web Api response status: 'NotFound', Web Api response details: ''
Учитывая, что у меня есть проекции, я не могу правильно отладить это, поскольку отладка проекций не поддерживается. Похоже, что при ведении журнала не регистрируется конкретная ошибка, несмотря на обработку ошибок и проверки.
Извините, детали добавлены
Ваш веб-API не возвращает ответ, пожалуйста, проверьте его.
Это связано с тем, как считываются данные. Это тоже часть вопроса. Я сгенерировал и закодировал PDF-файл, который является частью моей команды curl для тестирования сценария. Всё работает, pdf читается правильно. Но это не работает в конвейере
Пожалуйста, добавьте полный код вашего навыка веб-API.
Код навыка обновлен.
Можете ли вы проверить журналы функции. Потому что ваша функция возвращается пустой.
В функции Azure на вкладке «Вызовы» вы можете увидеть количество ошибок, где вы найдете журналы и подробную информацию.
Спасибо. Последний совет по отладке оказался очень полезным. Ошибка там явно проявилась. Я слишком долго смотрел не в то место (поток журнала)...
Согласно этой документации, когда вы включаете параметр allowSkillsetToReadFileData
в индексаторе,
вы получите данные файла по пути /document/file_data
в контексте документа.
То же самое передается вашему пользовательскому набору навыков веб-API inputs
.
"inputs": [
{
"name": "file_data",
"source": "/document/file_data"
}
]
и доступ к нему осуществляется в функции, как показано ниже.
file_data = value.get('data', {}).get('file_data', '')
Благодарю за ваш ответ. Выглядит многообещающе!
Я только что попробовал, но что-то не получается...
Рад, что вы обнаружили ошибку и исправили код.
Спасибо за поддержку. Странно, что в Интернете нет примеров извлечения страниц. Для меня было несложно использовать для этого программу чтения PDF-файлов на Python, но я понятия не имею, что делают другие xD
Входные данные для вашего WebApiSkill в вашем наборе навыков должны быть установлены на:
"inputs": [
{
"name": "file_data",
"source": "/document/file_data"
}
]
Включите «Разрешить набору навыков читать данные файла» в индексаторе:
indexing_parameters_configuration = IndexingParametersConfiguration(
allow_skillset_to_read_file_data=True
)
# otherwise: HTTP response error: () Configuration property 'queryTimeout' is not supported for the data source of type 'azureblob'.
indexing_parameters_configuration.query_timeout = None
indexer = SearchIndexer(
name=indexer_name,
description = "Chunks, pages and embeddings",
skillset_name=skillset_name,
target_index_name=target_index_name,
data_source_name=data_source_name,
parameters = {"configuration": indexing_parameters_configuration}
)
Входные данные file_data
закодированы в формате Base64, поэтому сначала их необходимо декодировать, а затем открыть как байтовый поток с помощью программы чтения PDF по вашему выбору:
import re
import azure.functions as func
import datetime
import json
import logging
import base64
import fitz
from io import BytesIO
app = func.FunctionApp()
logging.basicConfig(level=logging.INFO)
@app.route(route = "CustomSplitSkill", auth_level=func.AuthLevel.FUNCTION)
def CustomSplitSkill(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
try:
req_body = req.get_json()
logging.info('Request body parsed successfully.')
except ValueError:
logging.error(f"Invalid input: {e}")
return func.HttpResponse("Invalid input", status_code=400)
# 'values' expected top-level key in the request body
response_body = {"values": []}
for value in req_body.get('values', []):
recordId = value.get('recordId')
file_data_base64 = value.get('data', {}).get('file_data', '').get('data', '')
if not file_data_base64:
logging.error("No file_data found in the request.")
return func.HttpResponse("Invalid input: No file_data found", status_code=400)
try:
file_data = base64.b64decode(file_data_base64)
try:
pdf_document = fitz.open(stream=BytesIO(file_data), filetype='pdf')
except fitz.FileDataError as e:
logging.error(f"Failed to open PDF document: {e}")
return func.HttpResponse("Failed to open PDF document", status_code=400)
except Exception as e:
logging.error(f"An unexpected error occurred while opening the PDF document: {e}")
return func.HttpResponse("An unexpected error occurred", status_code=500)
if pdf_document.page_count == 0:
logging.error("No pages found in the PDF document.")
return func.HttpResponse("Invalid PDF: No pages found", status_code=400)
combined_list = [{'textItems': ['text1', 'text2'], 'numberItems': [0, 1]}] # I deleted the chunking and associated page extraction in order to reduce the amount of code
response_record = {
"recordId": recordId,
"data": {
"subdata": combined_list
}
}
response_body['values'].append(response_record)
except Exception as e:
logging.error(f"Error processing file_data: {e}")
return func.HttpResponse("Error processing file_data", status_code=500)
logging.info('Function executed successfully.')
return func.HttpResponse(json.dumps(response_body), mimetype = "application/json")
только эта ошибка? просмотрите журналы индексатора и подробную информацию о точной причине сбоя