Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

1
resposta

[Projeto] Desafio Final - Minha Resposta:

##Desafio Final (usando uma IDE):

##1 - Carregar um arquivo .txt, onde cada linha será um elemento de uma lista do Python

lista_resenhas = []
with open("resenhas.txt","r",encoding="utf-8") as arquivo:
    for linha in arquivo:
        lista_resenhas.append(linha)

##2 - Mandá-la ao modelo que você está rodando localmente para extrair, em formato JSON, onde cada item terá "usuario", "resenha original", "resenha_pt", "avaliacao" (Positiva, Negativa, Neutra)

from openai import OpenAI

client = OpenAI

client_openai = OpenAI(
    base_url="http://127.0.0.1:1234/v1",
    api_key="lm-studio"
)

resposta = client_openai.chat.completions.create(
    model="google/gemma-3n-e4b",
    messages = [
        {"role":"system", "content": "Você é um assistente de IA prestativo"},
        {"role":"user", "content": """Preciso que leia esta lista de resenhas e retorne para mim APENAS, em formato JSON, onde cada item terá 'usuario', 'resenha original', 'resenha_pt', 'avaliacao' (Positiva, Negativa, Neutra), NÃO RETORNE NENHUM OUTRO TIPO DE COMENTÁRIO. 
         use o formato 
         ```json[
            {"usuario": 'conteudo da lista', 'resenha original': 'conteudo da lista', 'resenha_pt': 'conteudo da lista', 'avaliacao': 'conteudo da lista'}
            {"usuario": 'conteudo da lista', 'resenha original': 'conteudo da lista', 'resenha_pt': 'conteudo da lista', 'avaliacao': 'conteudo da lista'}
            ...
         
            {"usuario": 'conteudo da lista', 'resenha original': 'conteudo da lista', 'resenha_pt': 'conteudo da lista', 'avaliacao': 'conteudo da lista'}
         ]```
         segue a lista:""".join(lista_resenhas) }
         ## tive que fazer um pouco de prompt engeniering pra fazer o retorno vir correto rsrs
    ],
    temperature=1.0,
)

resposta = resposta.choices[0].message.content

##3 - Transformar a resposta do modelo em uma lista de dicionários Python

import json
json_de_resenhas_classificadas_limpo = resposta.replace("```json", "").replace("```", "")
dicionario_de_resenhas = json.loads(json_de_resenhas_classificadas_limpo)

##4 - Criar uma função que, dada uma lista de dicionários, percorre a lista faz 2 coisas:

##a) conta a quantidade de avaliações positivas, negativas e neutras;
##b) une cada item dessa lista em uma variável do tipo string com algum separador.
##Ao final, retorna ambas as coisas.

def analisa_resenhas(lista_dics):
    negativas = 0
    positivas = 0
    neutras = 0
    for dicionario in lista_dics:
        if dicionario['avaliacao'] == 'Positiva':
            positivas += 1 
        elif dicionario['avaliacao'] == 'Negativa':
            negativas += 1
        else:
            neutras += 1

    lista_de_dicionarios_str = [str(dicionario) for dicionario in lista_dics]
    textos_unidos = "###".join(lista_de_dicionarios_str)

    return textos_unidos, positivas, negativas, neutras



texto, positivas, negativas, neutras = analisa_resenhas(dicionario_de_resenhas)
print(texto)
print(f"Análise das resenhas\n Positivas: {positivas}\n Negativas: {negativas}\n Neutras: {neutras}")
1 resposta

Olá, Luiz. Como vai?

Parabéns pela conclusão do Desafio Final! A sua solução ficou excelente e demonstra um domínio muito bom na integração de scripts Python com modelos de Linguagem (LLMs) rodando localmente através do LM Studio, além de aplicar com sucesso a manipulação de arquivos e lógica de estruturas de dados.

O prompt engineering que você mencionou no item 2 foi cirúrgico! Forçar o formato esperado através de exemplos estruturados é uma técnica essencial quando trabalhamos com modelos menores locais (como o Gemma), que tendem a ser mais prolixos se não receberem instruções restritivas.

Para agregar ainda mais valor ao seu projeto de conclusão e trazer boas práticas de nível de produção, separei algumas sugestões e aprofundamentos técnicos:

1. Reforçando a Limpeza de Quebras de Linhas na Leitura (Item 1)

No seu primeiro bloco de código, ao percorrer o arquivo .txt linha por linha, o método armazena o texto contendo o caractere invisível de quebra de linha \n no final de cada frase.

for linha in arquivo:
    lista_resenhas.append(linha)
  • Sugestão: Para evitar que esses \n poluam o prompt enviado para a LLM e garantir um envio de texto perfeitamente limpo, o ideal é aplicar o método .strip() ao ler a linha:
for linha in arquivo:
    lista_resenhas.append(linha.strip())

2. Uso do join() na Construção do Prompt (Item 2)

Na construção do conteúdo da mensagem do usuário, você utilizou o método "".join(lista_resenhas) acoplado ao texto do prompt.

  • Ponto de Atenção: Do jeito que foi escrito, o .join() vai usar o texto inteiro do seu prompt como "separador" entre as linhas da lista de resenhas. Isso pode misturar as instruções do prompt no meio de cada resenha que estava no arquivo de texto, confundindo a IA.
  • Forma Ideal: O correto é isolar a concatenação da lista usando um separador simples (como uma quebra de linha \n) e depois somar essa string ao corpo do prompt. Veja como fica mais legível:
texto_das_resenhas = "\n".join(lista_resenhas)

# Dentro de messages:
{"role": "user", "content": f"Sua instrução aqui...\n\nSegue a lista:\n{texto_das_resenhas}"}

3. Extração Segura do Bloco JSON (Item 3)

A sua técnica de fazer .replace("```json", "") funciona muito bem quando o modelo obedece o formato perfeitamente. Contudo, em cenários reais, os modelos podem incluir espaços extras ou textos antes e depois das crases.

Uma excelente alternativa para deixar o seu script blindado contra variações da resposta da LLM é utilizar Expressões Regulares (regex) para capturar tudo o que estiver estritamente entre os colchetes do JSON:

import re

# Encontra tudo que está entre o primeiro [ e o último ]
match = re.search(r'\[.*\]', resposta, re.DOTALL)
if match:
    json_limpo = match.group(0)
    dicionario_de_resenhas = json.loads(json_limpo)

4. Unificação com JSON na Função (Item 4)

Na função analisa_resenhas, você converteu os dicionários individuais para string usando str(dicionario) e aplicou o join com "###".

Essa lógica atende perfeitamente o escopo do desafio. Caso você precise enviar essa string unificada para um banco de dados ou outra API futuramente, uma boa prática de mercado é converter a lista inteira de volta para string usando json.dumps(lista_dics, ensure_ascii=False). Isso mantém o formato do texto padronizado internacionalmente e evita problemas de codificação de caracteres com aspas simples ou acentuações.

Excelente encerramento de curso! Você estruturou um pipeline completo de processamento de linguagem natural local muito poderoso.

Espero que possa ter lhe ajudado!