Seeking Help to Improve Summarization Script for Class Transcriptions and Resolve Error

I had an accident and became tetraplegic. Now, I use chat a lot, and currently, I am trying to create a script to summarize some of my classes based on transcriptions. Here is the code I am using:

python

Copiar código

import os
import openai
from PyPDF2 import PdfReader
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
import dotenv
from pathlib import Path
import logging
import re
from tqdm import tqdm
import time

# Configuração de logging
logging.basicConfig(filename='processamento_resumos.log', level=logging.DEBUG,
                    format='%(asctime)s:%(levelname)s:%(message)s')

# Carregar variáveis de ambiente
dotenv.load_dotenv()

# Configurar a chave da API da OpenAI de uma variável de ambiente
openai_api_key = os.getenv('OPENAI_API_KEY')
if openai_api_key is None:
    raise EnvironmentError("A chave da API da OpenAI não foi encontrada no ambiente.")
openai.api_key = openai_api_key

# Função para sanitizar nomes de arquivos
def sanitize_filename(filename):
    return re.sub(r'[<>:"/\\|?*]', '_', filename)

# Função para ler PDF e extrair texto
def read_pdf(file_path):
    try:
        reader = PdfReader(file_path)
        text = ''
        for page in reader.pages:
            text += page.extract_text() or ''
        return text
    except Exception as e:
        raise IOError(f"Erro ao ler o arquivo PDF: {e}")

# Função para dividir o texto em blocos por número de tokens
def split_text(text, max_tokens_per_block=1500):
    words = text.split()
    blocks = []
    current_block = []
    current_block_length = 0
    for word in words:
        current_block.append(word)
        current_block_length += len(word) + 1  # +1 for space
        if current_block_length > max_tokens_per_block:
            blocks.append(' '.join(current_block))
            current_block = []
            current_block_length = 0
    if current_block:
        blocks.append(' '.join(current_block))
    return blocks

# Função para resumir bloco de texto usando API OpenAI com retry
def summarize_block(block_text, retries=3):
    prompt = f"""Por favor, gere um resumo detalhado e informativo do seguinte texto, com foco nos pontos chave, conclusões e insights relevantes. O resumo deve ser abrangente, mas conciso, e deve capturar a essência do conteúdo de forma clara e organizada.

Formato do Resumo:

1. **Principais Tópicos**:
   - Descreva os principais tópicos abordados no texto.

2. **Conclusões e Insights**:
   - Destaque as principais conclusões e insights derivados do texto.

3. **Dados Numéricos**:
   - Mencione dados numéricos relevantes, como estatísticas, porcentagens, valores, etc.

4. **Perguntas Explorativas**:
   - Inclua perguntas que possam gerar discussões ou reflexões sobre o tema, incentivando o pensamento crítico e a análise do conteúdo.

Texto:

{block_text}

Observações:

- Ao inserir o texto, forneça o máximo de contexto possível sobre o tema e o propósito do resumo.
- Ajuste os parâmetros da API, como max_tokens e temperature, para obter resultados que atendam às suas necessidades.
- Se o texto for muito longo, considere dividi-lo em partes menores e resumir cada parte individualmente."""

    for attempt in range(retries):
        try:
            response = openai.Completion.create(
                model="gpt-3.5-turbo-instruct",
                prompt=prompt,
                max_tokens=1500,  # Ajustado para evitar ultrapassar o limite
                temperature=0.5,
            )
            return response.choices[0].text.strip()
        except Exception as e:
            logging.error(f"Tentativa {attempt + 1} falhou: {e}")
            if attempt < retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
            else:
                raise IOError(f"Erro ao resumir o texto com a OpenAI após {retries} tentativas: {e}")

# Função para compilar resumos dos blocos em um resumo final
def compile_summaries(summaries):
    final_summary = "Resumo Final\n\n"
    for i, summary in enumerate(summaries, start=1):
        final_summary += f"Bloco {i}:\n{summary}\n\n"
    return final_summary

# Função para escrever resumo final em um arquivo PDF
def write_summary_to_pdf(summary_text, output_path):
    try:
        c = canvas.Canvas(str(output_path), pagesize=letter)
        width, height = letter
        y = height - 50
        c.setFont('Helvetica-Bold', 16)
        c.drawString(50, y, "Resumo Final")
        y -= 30
        c.setFont('Helvetica', 12)
        lines = summary_text.split('\n')
        for line in lines:
            wrapped_lines = wrap_text(line, width - 100, c)
            for wrapped_line in wrapped_lines:
                if y < 50:
                    c.showPage()
                    y = height - 50
                    c.setFont('Helvetica', 12)
                c.drawString(50, y, wrapped_line)
                y -= 15
        c.save()
    except Exception as e:
        raise IOError(f"Erro ao escrever o arquivo PDF: {e}")

# Função para quebrar linhas de texto
def wrap_text(text, max_width, canvas):
    words = text.split()
    lines = []
    current_line = []
    for word in words:
        current_line.append(word)
        width = canvas.stringWidth(' '.join(current_line), 'Helvetica', 12)
        if width > max_width:
            lines.append(' '.join(current_line[:-1]))
            current_line = [word]
    lines.append(' '.join(current_line))
    return lines

# Função principal para processar arquivos PDF na pasta de entrada
def process_pdf_files(input_folder, output_folder, theme):
    input_folder = Path(input_folder)
    output_folder = Path(output_folder)
    if not input_folder.is_dir():
        raise NotADirectoryError(f"A pasta {input_folder} não foi encontrada.")

    if not output_folder.exists():
        output_folder.mkdir(parents=True)

    pdf_files = [file for file in input_folder.rglob('*.pdf')]
    if not pdf_files:
        logging.info("Nenhum arquivo PDF encontrado para processar.")
        print("Nenhum arquivo PDF encontrado para processar.")
        return

    # Ponto de verificação de arquivos processados
    processed_files = set()

    # Carregar logs existentes e identificar arquivos processados
    if os.path.exists('processamento_resumos.log'):
        with open('processamento_resumos.log', 'r') as log_file:
            logs = log_file.readlines()
            for line in logs:
                match = re.search(r'Resumo salvo em: (.+)', line)
                if match:
                    output_path = Path(match.group(1))
                    processed_files.add(output_path.name)

    for pdf_file in tqdm(pdf_files, desc="Processando PDFs", unit="arquivo"):
        output_file = sanitize_filename(f"{theme}_{pdf_file.stem}_resumo.pdf")
        if output_file in processed_files:
            logging.info(f"Resumo já processado: {pdf_file.name}")
            print(f"Resumo já processado: {pdf_file.name}")
            continue

        logging.info(f"Processando arquivo: {pdf_file}")
        text = read_pdf(pdf_file)
        blocks = split_text(text)
        summaries = []
        for block in blocks:
            summary = summarize_block(block)
            summaries.append(summary)
        final_summary = compile_summaries(summaries)
        write_summary_to_pdf(final_summary, output_folder / output_file)
        logging.info(f"Resumo salvo em: {output_folder / output_file}")
        print(f"Resumo salvo em: {output_folder / output_file}")

# Solicitar pastas de entrada e saída e tema do vídeo
input_folder = input("Digite o caminho da pasta de entrada: ")
output_folder = input("Digite o caminho da pasta de saída: ")
theme = input("Digite o tema do vídeo: ")

try:
    process_pdf_files(input_folder, output_folder, theme)
except Exception as e:
    print(f'Não foi possível processar a pasta: {e}')
    logging.error(f'Não foi possível processar a pasta: {e}')

I am experiencing some problems. First, the summary is not as natural and complete as I would like. It is usable, but I believe it could be improved. Also, I am encountering a small error in the middle of the process. Here is the error:

makefile

Copiar código

Não foi possível processar a pasta: Erro ao resumir o texto com a OpenAI após 3 tentativas: Sorry! We've encountered an issue with repetitive patterns in your prompt. Please try again with a different prompt. tem que chamar

Could you please help me improve the summarization quality and resolve this error?E aí tudo isso