13.08.2026 налажена работа с ИИ. Подготовка к разбивке файлов agent и db_tools

This commit is contained in:
2026-08-13 14:21:43 +03:00
parent a622fd98d2
commit fc1a608a5f
13 changed files with 3628 additions and 210 deletions
+50 -23
View File
@@ -1,37 +1,53 @@
import io
import base64
import os
import subprocess
import logging
import pandas as pd
from PIL import Image
logger = logging.getLogger("FILE_PARSER")
def extract_text_from_file(file_bytes: bytes, filename: str) -> str:
"""Извлекает текст из изображений (OCR), PDF, таблиц и текстовых файлов."""
def extract_text_from_file(file_bytes: bytes, filename: str) -> dict:
ext = os.path.splitext(filename)[1].lower()
# Создаем временный файл во избежание проблем с памятью
temp_filepath = f"/tmp/upload_{os.getpid()}_{filename}"
with open(temp_filepath, "wb") as f:
f.write(file_bytes)
try:
# 1. ИЗОБРАЖЕНИЯ (OCR через системный /usr/bin/tesseract)
# 1. ИЗОБРАЖЕНИЯ (.png, .jpg, .jpeg, .bmp, .webp) -> Кодируем в Base64 для Vision LLM
if ext in ['.png', '.jpg', '.jpeg', '.bmp', '.webp']:
cmd = ['tesseract', temp_filepath, 'stdout', '-l', 'rus+eng']
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
text = res.stdout.strip()
return text if text else "[OCR: На изображении не удалось распознать текст]"
b64_str = base64.b64encode(file_bytes).decode('utf-8')
return {
"text": f"[ПРИКРЕПЛЕНО ИЗОБРАЖЕНИЕ: {filename}]",
"image_b64": b64_str
}
# 2. PDF ДОКУМЕНТЫ (через системный /usr/bin/pdftotext из poppler-utils)
# 2. PDF ДОКУМЕНТЫ (Конвертируем 1-ю страницу в картинку для Vision LLM)
elif ext == '.pdf':
cmd = ['pdftotext', temp_filepath, '-']
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
text = res.stdout.strip()
return text if text else "[PDF: Текстовый слой не найден. Возможно, скан без OCR]"
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
pdf_text = res.stdout.strip()
# 3. ЭЛЕКТРОННЫЕ ТАБЛИЦЫ (XLSX, CSV через Pandas)
img_prefix = f"/tmp/pdf_preview_{os.getpid()}"
subprocess.run(['pdftoppm', '-png', '-r', '200', '-f', '1', '-l', '1', temp_filepath, img_prefix], check=True)
page_png = f"{img_prefix}-1.png"
b64_str = None
if os.path.exists(page_png):
with open(page_png, "rb") as pf:
b64_str = base64.b64encode(pf.read()).decode('utf-8')
os.remove(page_png)
context_text = f"[ПРИКРЕПЛЕН ДОКУМЕНТ PDF: {filename}]"
if pdf_text:
context_text += f"\n\n[ЭЛЕКТРОННЫЙ ТЕКСТОВЫЙ СЛОЙ PDF]:\n{pdf_text}"
return {
"text": context_text,
"image_b64": b64_str
}
# 3. ЭЛЕКТРОННЫЕ ТАБЛИЦЫ (.xlsx, .xls, .csv)
elif ext in ['.xlsx', '.xls', '.csv']:
if ext == '.csv':
df = pd.read_csv(temp_filepath)
@@ -39,23 +55,34 @@ def extract_text_from_file(file_bytes: bytes, filename: str) -> str:
df = pd.read_excel(temp_filepath)
total_rows = len(df)
df_preview = df.head(100) # Показываем первые 100 строк
df_preview = df.head(100)
table_str = df_preview.to_string(index=False)
note = f"\n(Показано первых 100 строк из {total_rows})" if total_rows > 100 else ""
return f"[СОДЕРЖИМОЕ ТАБЛИЦЫ {filename}]:\n{table_str}{note}"
return {
"text": f"[СОДЕРЖИМОЕ ТАБЛИЦЫ {filename}]:\n{table_str}{note}",
"image_b64": None
}
# 4. ТЕКСТОВЫЕ ФАЙЛЫ (TXT, LOG, JSON)
# 4. ТЕКСТОВЫЕ ФАЙЛЫ
elif ext in ['.txt', '.log', '.json', '.xml', '.md']:
with open(temp_filepath, 'r', encoding='utf-8', errors='replace') as tf:
return tf.read().strip()
return {
"text": tf.read().strip(),
"image_b64": None
}
else:
return f"[ОШИБКА: Формат {ext} не поддерживается для анализа]"
return {
"text": f"[ОШИБКА: Формат {ext} не поддерживается]",
"image_b64": None
}
except Exception as e:
logger.error(f"Ошибка при анализе файла {filename}: {e}")
return f"[ОШИБКА ОБРАБОТКИ ФАЙЛА: {str(e)}]"
return {
"text": f"[ОШИБКА ОБРАБОТКИ ФАЙЛА: {str(e)}]",
"image_b64": None
}
finally:
if os.path.exists(temp_filepath):
os.remove(temp_filepath)